daigaku 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -3
- data/README.md +1 -1
- data/daigaku.gemspec +23 -26
- data/lib/daigaku.rb +0 -1
- data/lib/daigaku/chapter.rb +3 -4
- data/lib/daigaku/coloring.rb +13 -13
- data/lib/daigaku/configuration.rb +25 -28
- data/lib/daigaku/congratulator.rb +17 -5
- data/lib/daigaku/course.rb +9 -8
- data/lib/daigaku/exceptions.rb +0 -2
- data/lib/daigaku/generator.rb +13 -13
- data/lib/daigaku/github_client.rb +4 -4
- data/lib/daigaku/loadable.rb +11 -15
- data/lib/daigaku/loading/chapters.rb +0 -2
- data/lib/daigaku/loading/courses.rb +0 -2
- data/lib/daigaku/loading/units.rb +0 -2
- data/lib/daigaku/markdown.rb +1 -0
- data/lib/daigaku/markdown/printer.rb +89 -0
- data/lib/daigaku/markdown/ruby_doc.rb +6 -8
- data/lib/daigaku/solution.rb +18 -15
- data/lib/daigaku/storeable.rb +11 -12
- data/lib/daigaku/task.rb +1 -1
- data/lib/daigaku/terminal.rb +3 -4
- data/lib/daigaku/terminal/cli.rb +6 -8
- data/lib/daigaku/terminal/courses.rb +19 -16
- data/lib/daigaku/terminal/output.rb +0 -2
- data/lib/daigaku/terminal/setup.rb +13 -18
- data/lib/daigaku/terminal/solutions.rb +27 -32
- data/lib/daigaku/terminal/welcome.rb +9 -11
- data/lib/daigaku/test.rb +7 -10
- data/lib/daigaku/test_result.rb +13 -16
- data/lib/daigaku/unit.rb +1 -3
- data/lib/daigaku/version.rb +1 -1
- data/lib/daigaku/views.rb +4 -3
- data/lib/daigaku/views/chapters_menu.rb +16 -20
- data/lib/daigaku/views/courses_menu.rb +12 -15
- data/lib/daigaku/views/main_menu.rb +23 -23
- data/lib/daigaku/views/menu.rb +9 -13
- data/lib/daigaku/views/splash.rb +11 -13
- data/lib/daigaku/views/subscriber.rb +38 -0
- data/lib/daigaku/views/task_view.rb +80 -78
- data/lib/daigaku/views/top_bar.rb +4 -10
- data/lib/daigaku/views/units_menu.rb +16 -21
- data/lib/daigaku/window.rb +12 -70
- data/spec/daigaku/chapter_spec.rb +23 -18
- data/spec/daigaku/coloring_spec.rb +0 -1
- data/spec/daigaku/configuration_spec.rb +54 -50
- data/spec/daigaku/congratulator_spec.rb +11 -8
- data/spec/daigaku/course_spec.rb +70 -51
- data/spec/daigaku/generator_spec.rb +24 -25
- data/spec/daigaku/github_client_spec.rb +17 -18
- data/spec/daigaku/loading/chapters_spec.rb +2 -3
- data/spec/daigaku/loading/courses_spec.rb +2 -3
- data/spec/daigaku/loading/units_spec.rb +4 -5
- data/spec/daigaku/markdown/ruby_doc_spec.rb +3 -6
- data/spec/daigaku/reference_solution_spec.rb +8 -10
- data/spec/daigaku/solution_spec.rb +18 -20
- data/spec/daigaku/storeable_spec.rb +12 -10
- data/spec/daigaku/task_spec.rb +3 -4
- data/spec/daigaku/terminal/cli_spec.rb +29 -21
- data/spec/daigaku/terminal/courses_spec.rb +104 -99
- data/spec/daigaku/terminal/output_spec.rb +44 -39
- data/spec/daigaku/terminal/setup_spec.rb +1 -3
- data/spec/daigaku/terminal/solutions_spec.rb +0 -2
- data/spec/daigaku/terminal/welcome_spec.rb +0 -2
- data/spec/daigaku/terminal_spec.rb +5 -7
- data/spec/daigaku/test_example_spec.rb +16 -14
- data/spec/daigaku/test_result_spec.rb +21 -25
- data/spec/daigaku/test_spec.rb +11 -12
- data/spec/daigaku/unit_spec.rb +24 -27
- data/spec/daigaku/views/chapters_menu_spec.rb +0 -1
- data/spec/daigaku/views/courses_menu_spec.rb +0 -1
- data/spec/daigaku/views/menu_spec.rb +1 -2
- data/spec/daigaku/views/task_view_spec.rb +0 -2
- data/spec/daigaku/views/units_menu_spec.rb +0 -1
- data/spec/daigaku/views_spec.rb +0 -1
- data/spec/daigaku_spec.rb +9 -12
- data/spec/path_helpers_spec.rb +11 -12
- data/spec/resource_helpers_spec.rb +11 -12
- data/spec/spec_helper.rb +3 -4
- data/spec/support/macros/content_helpers.rb +16 -17
- data/spec/support/macros/mock_helpers.rb +6 -6
- data/spec/support/macros/path_helpers.rb +15 -15
- data/spec/support/macros/resource_helpers.rb +34 -35
- metadata +12 -10
@@ -1,21 +1,20 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Loading::Units do
|
4
|
-
|
5
|
-
let(:course_name) { course_dir_names.first }
|
4
|
+
let(:course_name) { course_dir_names.first }
|
6
5
|
let(:chapter_path) { chapter_dirs(course_name).first }
|
7
6
|
let(:chapter_name) { File.basename(chapter_path) }
|
8
7
|
|
9
8
|
let(:subjects) { Daigaku::Loading::Units.load(chapter_path) }
|
10
9
|
|
11
|
-
it
|
10
|
+
it 'has the prescribed number of units' do
|
12
11
|
units_count = available_units(course_name, chapter_name).count
|
13
12
|
expect(subjects.count).to eq units_count
|
14
13
|
end
|
15
14
|
|
16
|
-
it
|
15
|
+
it 'loads the available units' do
|
17
16
|
subjects.each_with_index do |unit, index|
|
18
17
|
expect(unit.title).to eq unit_titles[index]
|
19
18
|
end
|
20
19
|
end
|
21
|
-
end
|
20
|
+
end
|
@@ -1,18 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Markdown::RubyDoc do
|
4
|
-
|
5
|
-
|
6
|
-
it "responds to #{class_method}" do
|
7
|
-
expect(Daigaku::Markdown::RubyDoc).to respond_to class_method
|
8
|
-
end
|
4
|
+
it 'responds to .parse' do
|
5
|
+
expect(Daigaku::Markdown::RubyDoc).to respond_to :parse
|
9
6
|
end
|
10
7
|
|
11
8
|
def parse(text)
|
12
9
|
Daigaku::Markdown::RubyDoc.parse(text)
|
13
10
|
end
|
14
11
|
|
15
|
-
describe '
|
12
|
+
describe '.parse' do
|
16
13
|
context 'for a text containing a core doc markup' do
|
17
14
|
let(:base_url) { "http://ruby-doc.org/core-#{RUBY_VERSION}" }
|
18
15
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::ReferenceSolution do
|
4
|
-
|
5
4
|
it { is_expected.to respond_to :code }
|
6
5
|
it { is_expected.to respond_to :path }
|
7
6
|
it { is_expected.to respond_to :code_lines }
|
@@ -13,27 +12,26 @@ describe Daigaku::ReferenceSolution do
|
|
13
12
|
|
14
13
|
subject { Daigaku::ReferenceSolution.new(unit_path) }
|
15
14
|
|
16
|
-
it
|
15
|
+
it 'has the prescribed path' do
|
17
16
|
path = File.join(unit_path, reference_solution_name)
|
18
17
|
expect(subject.path).to eq path
|
19
18
|
end
|
20
19
|
|
21
|
-
describe
|
22
|
-
it
|
20
|
+
describe '#code' do
|
21
|
+
it 'has the prescribed code' do
|
23
22
|
expect(subject.code).to eq solution_content
|
24
23
|
end
|
25
24
|
|
26
|
-
it
|
25
|
+
it 'returns an empty string if the code is not available' do
|
27
26
|
subject.instance_variable_set(:@code, nil)
|
28
|
-
expect(subject.code).to eq
|
27
|
+
expect(subject.code).to eq ''
|
29
28
|
end
|
30
29
|
end
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
it "returns the code split into lines" do
|
31
|
+
describe '#code_lines' do
|
32
|
+
it 'returns the code split into lines' do
|
35
33
|
lines = ['muffin = "sweet"', 'hamburger = "mjummy"']
|
36
|
-
allow(subject).to receive(:code)
|
34
|
+
allow(subject).to receive(:code).and_return(lines.join("\n"))
|
37
35
|
|
38
36
|
expect(subject.code_lines).to eq lines
|
39
37
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Solution do
|
4
|
-
|
5
4
|
it { is_expected.to respond_to :code }
|
6
5
|
it { is_expected.to respond_to :path }
|
7
6
|
it { is_expected.to respond_to :verify! }
|
@@ -14,39 +13,39 @@ describe Daigaku::Solution do
|
|
14
13
|
end
|
15
14
|
|
16
15
|
let(:solution_path) { all_solution_file_paths.first }
|
17
|
-
let(:unit_path)
|
16
|
+
let(:unit_path) { all_unit_dirs.first }
|
18
17
|
|
19
18
|
subject { Daigaku::Solution.new(unit_path) }
|
20
19
|
|
21
|
-
it
|
20
|
+
it 'has the prescribed solution path from the given unit path' do
|
22
21
|
expect(subject.path).to eq solution_path
|
23
22
|
end
|
24
23
|
|
25
|
-
it
|
24
|
+
it 'has the prescribed code' do
|
26
25
|
expect(subject.code).to eq solution_content
|
27
26
|
end
|
28
27
|
|
29
|
-
it
|
28
|
+
it 'loads the verified state from the store on creation' do
|
30
29
|
Daigaku::Solution.new(unit_path).verify!
|
31
30
|
solution = Daigaku::Solution.new(unit_path)
|
32
31
|
|
33
32
|
expect(solution).to be_verified
|
34
33
|
end
|
35
34
|
|
36
|
-
describe
|
37
|
-
it
|
38
|
-
key =
|
35
|
+
describe '#store_key' do
|
36
|
+
it 'returns the appropriate key string for the solution' do
|
37
|
+
key = 'verified/course_a/chapter_a/unit_a'
|
39
38
|
expect(subject.store_key).to eq key
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
|
-
context
|
44
|
-
describe
|
45
|
-
it
|
42
|
+
context 'Verification' do
|
43
|
+
describe '#verify!' do
|
44
|
+
it 'returns a TestResult' do
|
46
45
|
expect(subject.verify!).to be_a Daigaku::TestResult
|
47
46
|
end
|
48
47
|
|
49
|
-
it
|
48
|
+
it 'sets @verified true if Test passed' do
|
50
49
|
QuickStore.store.set(subject.store_key, false)
|
51
50
|
solution = Daigaku::Solution.new(unit_path)
|
52
51
|
|
@@ -55,14 +54,14 @@ describe Daigaku::Solution do
|
|
55
54
|
expect(solution.instance_variable_get(:@verified)).to be_truthy
|
56
55
|
end
|
57
56
|
|
58
|
-
it
|
57
|
+
it 'sets the solution’s state in the store to verified if passed' do
|
59
58
|
subject.verify!
|
60
59
|
mastered = QuickStore.store.get(subject.store_key)
|
61
60
|
|
62
61
|
expect(mastered).to be_truthy
|
63
62
|
end
|
64
63
|
|
65
|
-
it
|
64
|
+
it 'sets the solution’s state in the store to unverified unless passed' do
|
66
65
|
subject.instance_variable_set(:@code, 'puts "I ❤ Daigaku!"')
|
67
66
|
subject.verify!
|
68
67
|
mastered = QuickStore.store.get(subject.store_key)
|
@@ -71,16 +70,15 @@ describe Daigaku::Solution do
|
|
71
70
|
end
|
72
71
|
end
|
73
72
|
|
74
|
-
describe
|
75
|
-
it
|
76
|
-
expect(subject.verified?).to
|
73
|
+
describe '#verified?' do
|
74
|
+
it 'is false by default' do
|
75
|
+
expect(subject.verified?).to be false
|
77
76
|
end
|
78
77
|
|
79
|
-
it
|
78
|
+
it 'returns true if #verify! passed' do
|
80
79
|
subject.verify!
|
81
|
-
expect(subject.verified?).to
|
80
|
+
expect(subject.verified?).to be true
|
82
81
|
end
|
83
82
|
end
|
84
83
|
end
|
85
|
-
|
86
84
|
end
|
@@ -1,35 +1,37 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Storeable do
|
4
|
-
|
5
|
-
it "responds to ::key" do
|
4
|
+
it 'responds to .key' do
|
6
5
|
expect(Daigaku::Storeable).to respond_to :key
|
7
6
|
end
|
8
7
|
|
9
|
-
describe '
|
10
|
-
it
|
8
|
+
describe '.key' do
|
9
|
+
it 'creates a store key from the given string' do
|
11
10
|
key = Daigaku::Storeable.key('1-_Raw content-Title')
|
12
11
|
expect(key).to eq 'raw_content_title'
|
13
12
|
end
|
14
13
|
|
15
|
-
it
|
14
|
+
it 'creates a cleaned up store key from a given path string' do
|
16
15
|
key = Daigaku::Storeable.key('path/to/the/1-_Raw content string')
|
17
16
|
expect(key).to eq 'path/to/the/raw_content_string'
|
18
17
|
end
|
19
18
|
|
20
|
-
it
|
19
|
+
it 'creates a prefixed key when a prefix option is given' do
|
21
20
|
key = Daigaku::Storeable.key('1-_Raw content-Title', prefix: 'courses')
|
22
21
|
expect(key).to eq 'courses/raw_content_title'
|
23
22
|
end
|
24
23
|
|
25
|
-
it
|
24
|
+
it 'creates a suffixed key if a suffix option is given' do
|
26
25
|
key = Daigaku::Storeable.key('1-_Raw content-Title', suffix: '1-author')
|
27
26
|
expect(key).to eq 'raw_content_title/author'
|
28
27
|
end
|
29
28
|
|
30
|
-
it
|
31
|
-
|
29
|
+
it 'creates a multi suffixed key if a suffixes option is given' do
|
30
|
+
suffixes = ['meta', '1-author']
|
31
|
+
title = '1-_Raw content-Title'
|
32
|
+
key = Daigaku::Storeable.key(title, suffixes: suffixes)
|
33
|
+
|
32
34
|
expect(key).to eq 'raw_content_title/meta/author'
|
33
35
|
end
|
34
36
|
end
|
35
|
-
end
|
37
|
+
end
|
data/spec/daigaku/task_spec.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Task do
|
4
|
-
|
5
4
|
it { is_expected.to respond_to :markdown }
|
6
5
|
it { is_expected.to respond_to :path }
|
7
6
|
|
@@ -12,12 +11,12 @@ describe Daigaku::Task do
|
|
12
11
|
|
13
12
|
subject { Daigaku::Task.new(unit_path) }
|
14
13
|
|
15
|
-
it
|
14
|
+
it 'has the prescribed path' do
|
16
15
|
path = File.join(unit_path, task_name)
|
17
16
|
expect(subject.path).to eq path
|
18
17
|
end
|
19
18
|
|
20
|
-
it
|
19
|
+
it 'has the prescribed markdown' do
|
21
20
|
expect(subject.markdown).to eq task_file_content
|
22
21
|
end
|
23
|
-
end
|
22
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Terminal::CLI do
|
4
|
+
before { suppress_print_out }
|
4
5
|
|
5
6
|
it { is_expected.to be_a Thor }
|
6
7
|
it { is_expected.to respond_to :about }
|
@@ -11,40 +12,47 @@ describe Daigaku::Terminal::CLI do
|
|
11
12
|
it { is_expected.to respond_to :solutions }
|
12
13
|
it { is_expected.to respond_to :setup }
|
13
14
|
|
14
|
-
describe
|
15
|
-
|
16
|
-
allow(Daigaku::Loading::Courses).to receive(:load) { [1] }
|
17
|
-
allow(Daigaku).to receive(:start) { true }
|
18
|
-
expect(Daigaku).to receive(:start)
|
15
|
+
describe '#learn' do
|
16
|
+
before { allow(Daigaku).to receive(:start).and_return(true) }
|
19
17
|
|
20
|
-
|
18
|
+
context 'if there are courses' do
|
19
|
+
before do
|
20
|
+
allow(Daigaku::Loading::Courses).to receive(:load).and_return([1])
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'starts the daigaku terminal app' do
|
24
|
+
expect(Daigaku).to receive(:start)
|
25
|
+
subject.learn
|
26
|
+
end
|
21
27
|
end
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
expect(Daigaku).not_to receive(:start)
|
29
|
+
context 'if there are no courses' do
|
30
|
+
before do
|
31
|
+
allow(Daigaku::Loading::Courses).to receive(:load).and_return([])
|
32
|
+
end
|
28
33
|
|
29
|
-
|
34
|
+
it 'does not start the daigaku terminal app' do
|
35
|
+
expect(Daigaku).not_to receive(:start)
|
36
|
+
subject.learn
|
37
|
+
end
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
33
|
-
describe
|
34
|
-
it
|
35
|
-
allow(Daigaku::Terminal::Welcome).to receive(:run)
|
41
|
+
describe '#welcome' do
|
42
|
+
it 'runs the welcome routine' do
|
43
|
+
allow(Daigaku::Terminal::Welcome).to receive(:run).and_return(true)
|
36
44
|
expect(Daigaku::Terminal::Welcome).to receive(:run).once
|
37
|
-
|
38
45
|
subject.welcome
|
39
46
|
end
|
40
47
|
end
|
41
48
|
|
42
|
-
describe
|
43
|
-
it
|
44
|
-
|
45
|
-
|
46
|
-
|
49
|
+
describe '#scaffold' do
|
50
|
+
it 'runs the scaffolding' do
|
51
|
+
allow_any_instance_of(Daigaku::Generator)
|
52
|
+
.to receive(:scaffold)
|
53
|
+
.and_return(true)
|
47
54
|
|
55
|
+
expect_any_instance_of(Daigaku::Generator).to receive(:scaffold).once
|
48
56
|
subject.scaffold
|
49
57
|
end
|
50
58
|
end
|
@@ -1,102 +1,104 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Terminal::Courses do
|
4
|
-
|
5
4
|
before { suppress_print_out }
|
6
5
|
|
7
6
|
it { is_expected.to be_a Thor }
|
8
7
|
|
9
|
-
describe
|
10
|
-
|
11
|
-
|
12
|
-
end
|
8
|
+
describe 'commands' do
|
9
|
+
it { is_expected.to respond_to :list }
|
10
|
+
it { is_expected.to respond_to :download }
|
13
11
|
end
|
14
12
|
|
15
|
-
describe
|
13
|
+
describe '#download' do
|
16
14
|
before do
|
17
15
|
Daigaku.config.courses_path = local_courses_path
|
18
16
|
|
19
|
-
@zip_file_name =
|
20
|
-
@file_content
|
21
|
-
@url
|
17
|
+
@zip_file_name = 'repo.zip'
|
18
|
+
@file_content = prepare_download(@zip_file_name)
|
19
|
+
@url = "https://example.com/#{@zip_file_name}"
|
22
20
|
|
23
21
|
stub_request(:get, @url)
|
24
|
-
.with(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
.with(
|
23
|
+
headers: {
|
24
|
+
'Accept' => '*/*',
|
25
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
26
|
+
'User-Agent' => 'Ruby'
|
27
|
+
}
|
28
|
+
).to_return(status: 200, body: @file_content, headers: {})
|
29
|
+
|
30
|
+
stub_request(:get, 'https://api.github.com/repos/daigaku-ruby/Get_started_with_Ruby')
|
32
31
|
.with(headers: { 'Accept' => '*/*', 'User-Agent' => 'Ruby' })
|
33
|
-
.to_return(status: 200, body:
|
32
|
+
.to_return(status: 200, body: '{}', headers: {})
|
34
33
|
end
|
35
34
|
|
36
35
|
after { cleanup_download(@zip_file_name) }
|
37
36
|
|
38
|
-
it
|
39
|
-
expect{ subject.download(@url) }.not_to raise_error
|
37
|
+
it 'downloads the file from a given url' do
|
38
|
+
expect { subject.download(@url) }.not_to raise_error
|
40
39
|
end
|
41
40
|
|
42
|
-
it
|
41
|
+
it 'uses Courses.unzip to unzip the course' do
|
43
42
|
expect(Daigaku::Course).to receive(:unzip).once
|
44
43
|
subject.download(@url)
|
45
44
|
end
|
46
45
|
|
47
|
-
it
|
46
|
+
it 'creates a new courses folder in the daigaku courses directory' do
|
48
47
|
target_path = File.join(Daigaku.config.courses_path, File.basename(course_dirs.first))
|
49
48
|
dirs = Dir[File.join(Daigaku.config.courses_path, '**')]
|
50
49
|
expect(dirs.include?(target_path)).to be_truthy
|
51
50
|
end
|
52
51
|
|
53
|
-
it
|
52
|
+
it 'raises an error if param is no url' do
|
54
53
|
expect(subject).to receive(:say_warning)
|
55
54
|
subject.download('no-url')
|
56
55
|
end
|
57
56
|
|
58
|
-
it
|
57
|
+
it 'raises an error if param is no url to a zip file' do
|
59
58
|
expect(subject).to receive(:say_warning)
|
60
59
|
subject.download('http://exmaple.com/something-else')
|
61
60
|
end
|
62
61
|
|
63
|
-
describe
|
62
|
+
describe 'stores download data:' do
|
64
63
|
before do
|
65
|
-
@github_url =
|
64
|
+
@github_url = 'https://github.com/user/course_a/archive/master.zip'
|
66
65
|
|
67
66
|
stub_request(:get, @github_url)
|
68
|
-
.with(
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
67
|
+
.with(
|
68
|
+
headers: {
|
69
|
+
'Accept' => '*/*',
|
70
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
71
|
+
'User-Agent' => 'Ruby'
|
72
|
+
}
|
73
|
+
).to_return(status: 200, body: @file_content, headers: {})
|
74
|
+
|
75
|
+
stub_request(:get, 'https://api.github.com/repos/course_a/repo')
|
76
76
|
.with(headers: { 'Accept' => '*/*', 'User-Agent' => 'Ruby' })
|
77
|
-
.to_return(status: 200, body:
|
77
|
+
.to_return(status: 200, body: '{}', headers: {})
|
78
78
|
end
|
79
79
|
|
80
|
-
it
|
80
|
+
it 'stores the course’s author for courses from Github' do
|
81
81
|
subject.download(@github_url)
|
82
82
|
store_key = 'courses/course_a/author'
|
83
83
|
expect(QuickStore.store.get(store_key)).to eq 'user'
|
84
84
|
end
|
85
85
|
|
86
|
-
it
|
86
|
+
it 'stores the course’s repo for courses from Github' do
|
87
87
|
subject.download(@github_url)
|
88
88
|
store_key = 'courses/course_a/github'
|
89
89
|
expect(QuickStore.store.get(store_key)).to eq 'user/course_a'
|
90
90
|
end
|
91
91
|
|
92
|
-
it
|
92
|
+
it 'stores the downloading timestamp' do
|
93
93
|
time = Time.now
|
94
|
-
allow(Time).to receive(:now)
|
94
|
+
allow(Time).to receive(:now).and_return(time)
|
95
95
|
subject.download(@url)
|
96
|
-
|
96
|
+
|
97
|
+
updated_at = QuickStore.store.get('courses/course_a/updated_at')
|
98
|
+
expect(updated_at).to eq time.to_s
|
97
99
|
end
|
98
100
|
|
99
|
-
it
|
101
|
+
it 'stores the course’s download url' do
|
100
102
|
subject.download(@url)
|
101
103
|
expect(QuickStore.store.get('courses/course_a/url')).to eq @url
|
102
104
|
end
|
@@ -107,44 +109,46 @@ describe Daigaku::Terminal::Courses do
|
|
107
109
|
before do
|
108
110
|
Daigaku.config.courses_path = local_courses_path
|
109
111
|
|
110
|
-
@zip_file_name =
|
111
|
-
@file_content
|
112
|
-
@url
|
112
|
+
@zip_file_name = 'repo.zip'
|
113
|
+
@file_content = prepare_download(@zip_file_name)
|
114
|
+
@url = "https://example.com/#{@zip_file_name}"
|
113
115
|
|
114
116
|
stub_request(:get, @url)
|
115
|
-
.with(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
117
|
+
.with(
|
118
|
+
headers: {
|
119
|
+
'Accept' => '*/*',
|
120
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
121
|
+
'User-Agent' => 'Ruby'
|
122
|
+
}
|
123
|
+
).to_return(status: 200, body: @file_content, headers: {})
|
124
|
+
|
125
|
+
stub_request(:get, 'https://api.github.com/repos/daigaku-ruby/Get_started_with_Ruby')
|
123
126
|
.with(headers: { 'Accept' => '*/*', 'User-Agent' => 'Ruby' })
|
124
|
-
.to_return(status: 200, body:
|
127
|
+
.to_return(status: 200, body: '{}', headers: {})
|
125
128
|
|
126
|
-
allow(subject).to receive(:download)
|
127
|
-
allow(Daigaku::GithubClient).to receive(:updated?)
|
129
|
+
allow(subject).to receive(:download).and_return(true)
|
130
|
+
allow(Daigaku::GithubClient).to receive(:updated?).and_return(true)
|
128
131
|
end
|
129
132
|
|
130
133
|
after { cleanup_download(@zip_file_name) }
|
131
134
|
|
132
|
-
it
|
135
|
+
it 'updates a course that is not from Github on each call' do
|
133
136
|
url = 'https://example.com/repo.zip'
|
134
137
|
expect(subject).to receive(:download).with(url, 'updated').once
|
135
138
|
subject.update('Course_A')
|
136
139
|
end
|
137
140
|
|
138
|
-
it
|
139
|
-
url =
|
141
|
+
it 'updates a course from Github if there are new contents' do
|
142
|
+
url = 'https://github.com/user/repo/archive/master.zip'
|
140
143
|
|
141
144
|
stub_request(:get, url)
|
142
|
-
.with(
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
145
|
+
.with(
|
146
|
+
headers: {
|
147
|
+
'Accept' => '*/*',
|
148
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
149
|
+
'User-Agent' => 'Ruby'
|
150
|
+
}
|
151
|
+
).to_return(status: 200, body: @file_content, headers: {})
|
148
152
|
|
149
153
|
QuickStore.store.set('courses/course_a/url', url)
|
150
154
|
|
@@ -152,17 +156,18 @@ describe Daigaku::Terminal::Courses do
|
|
152
156
|
subject.update('Course_A')
|
153
157
|
end
|
154
158
|
|
155
|
-
it
|
156
|
-
allow(Daigaku::GithubClient).to receive(:updated?)
|
157
|
-
url =
|
159
|
+
it 'does not update a course from Github if there are no new contents' do
|
160
|
+
allow(Daigaku::GithubClient).to receive(:updated?).and_return(false)
|
161
|
+
url = 'https://github.com/user/repo/archive/master.zip'
|
158
162
|
|
159
163
|
stub_request(:get, url)
|
160
|
-
.with(
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
164
|
+
.with(
|
165
|
+
headers: {
|
166
|
+
'Accept' => '*/*',
|
167
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
168
|
+
'User-Agent' => 'Ruby'
|
169
|
+
}
|
170
|
+
).to_return(status: 200, body: @file_content, headers: {})
|
166
171
|
|
167
172
|
QuickStore.store.set('courses/course_a/url', url)
|
168
173
|
QuickStore.store.set('courses/course_a/github', 'user/repo')
|
@@ -171,7 +176,7 @@ describe Daigaku::Terminal::Courses do
|
|
171
176
|
subject.update('Course_A')
|
172
177
|
end
|
173
178
|
|
174
|
-
it
|
179
|
+
it 'updates all courses if --all option is given' do
|
175
180
|
file_content = prepare_download(@zip_file_name, multiple_courses: true)
|
176
181
|
|
177
182
|
stub_request(:get, @url)
|
@@ -183,7 +188,7 @@ describe Daigaku::Terminal::Courses do
|
|
183
188
|
}
|
184
189
|
).to_return(status: 200, body: file_content, headers: {})
|
185
190
|
|
186
|
-
allow(subject).to receive(:options)
|
191
|
+
allow(subject).to receive(:options).and_return(all: true)
|
187
192
|
allow(subject).to receive(:download).exactly(course_dirs.count).times
|
188
193
|
|
189
194
|
subject.update
|
@@ -198,49 +203,49 @@ describe Daigaku::Terminal::Courses do
|
|
198
203
|
allow(subject).to receive(:get).and_return('yes')
|
199
204
|
end
|
200
205
|
|
201
|
-
describe
|
202
|
-
it
|
203
|
-
allow(subject).to receive(:options)
|
206
|
+
describe 'confirmation' do
|
207
|
+
it 'is nessecary to delete all courses' do
|
208
|
+
allow(subject).to receive(:options).and_return(all: true)
|
204
209
|
expect(subject).to receive(:get_confirm)
|
205
210
|
subject.delete
|
206
211
|
end
|
207
212
|
|
208
|
-
it
|
213
|
+
it 'is nessecary to delete a certain course' do
|
209
214
|
expect(subject).to receive(:get_confirm)
|
210
215
|
subject.delete(course_dir_names.first)
|
211
216
|
end
|
212
217
|
end
|
213
218
|
|
214
|
-
context
|
215
|
-
it
|
219
|
+
context 'when confirmed:' do
|
220
|
+
it 'deletes the given course' do
|
216
221
|
expect(Dir.exist?(@course_path)).to be_truthy
|
217
222
|
subject.delete(course_dir_names.first)
|
218
223
|
expect(Dir.exist?(@course_path)).to be_falsey
|
219
224
|
end
|
220
225
|
|
221
|
-
it
|
222
|
-
allow(subject).to receive(:options)
|
226
|
+
it 'deletes all courses with option --all' do
|
227
|
+
allow(subject).to receive(:options).and_return(all: true)
|
223
228
|
expect(Dir.exist?(@course_path)).to be_truthy
|
224
229
|
subject.delete
|
225
230
|
|
226
231
|
course_dirs.each do |dir|
|
227
|
-
expect(Dir.exist?(dir)).to
|
232
|
+
expect(Dir.exist?(dir)).to be false
|
228
233
|
end
|
229
234
|
end
|
230
235
|
end
|
231
236
|
|
232
|
-
context
|
237
|
+
context 'when not confirmed:' do
|
233
238
|
before { allow(subject).to receive(:get).and_return('no') }
|
234
239
|
|
235
|
-
it
|
240
|
+
it 'does not delete the given course' do
|
236
241
|
expect(Dir.exist?(@course_path)).to be_truthy
|
237
242
|
subject.delete(course_dir_names.first)
|
238
243
|
expect(Dir.exist?(@course_path)).to be_truthy
|
239
244
|
end
|
240
245
|
|
241
|
-
it
|
242
|
-
allow(subject).to receive(:options)
|
243
|
-
expect(Dir.exist?(@course_path)).to
|
246
|
+
it 'does not delete all courses' do
|
247
|
+
allow(subject).to receive(:options).and_return(all: true)
|
248
|
+
expect(Dir.exist?(@course_path)).to be true
|
244
249
|
subject.delete
|
245
250
|
|
246
251
|
course_dirs.each do |dir|
|
@@ -249,29 +254,30 @@ describe Daigaku::Terminal::Courses do
|
|
249
254
|
end
|
250
255
|
end
|
251
256
|
|
252
|
-
describe
|
253
|
-
it
|
257
|
+
describe 'status information' do
|
258
|
+
it 'is printed when a certain course was deleted' do
|
254
259
|
expect(subject).to receive(:say_info)
|
255
260
|
subject.delete(course_dir_names.first)
|
256
261
|
end
|
257
262
|
|
258
|
-
it
|
259
|
-
allow(subject).to receive(:options)
|
263
|
+
it 'is printed when all courses were deleted' do
|
264
|
+
allow(subject).to receive(:options).and_return(all: true)
|
260
265
|
expect(subject).to receive(:say_info)
|
261
266
|
subject.delete
|
262
267
|
end
|
263
268
|
end
|
264
269
|
|
265
|
-
describe
|
266
|
-
it
|
270
|
+
describe 'QuickStore data' do
|
271
|
+
it 'is deleted for a certain course' do
|
267
272
|
key = Daigaku::Storeable.key(course_dir_names.first, prefix: 'courses')
|
268
273
|
QuickStore.store.set(key, 'some value')
|
269
274
|
subject.delete(course_dir_names.first)
|
275
|
+
|
270
276
|
expect(QuickStore.store.get(key)).to be_nil
|
271
277
|
end
|
272
278
|
|
273
|
-
it
|
274
|
-
allow(subject).to receive(:options)
|
279
|
+
it 'is deleted for all courses when option --all is set' do
|
280
|
+
allow(subject).to receive(:options).and_return(all: true)
|
275
281
|
|
276
282
|
keys = course_dir_names.map do |course_name|
|
277
283
|
Daigaku::Storeable.key(course_name, prefix: 'courses')
|
@@ -283,10 +289,9 @@ describe Daigaku::Terminal::Courses do
|
|
283
289
|
|
284
290
|
subject.delete
|
285
291
|
|
286
|
-
course_dir_names.each_with_index do |
|
292
|
+
course_dir_names.each_with_index do |_, index|
|
287
293
|
expect(QuickStore.store.get(keys[index])).to be_nil
|
288
294
|
end
|
289
|
-
|
290
295
|
end
|
291
296
|
end
|
292
297
|
end
|