daigaku 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.travis.yml +7 -4
- data/CODE_OF_CONDUCT.md +77 -0
- data/README.md +11 -11
- data/bin/daigaku +6 -2
- data/daigaku.gemspec +22 -26
- data/lib/daigaku.rb +0 -1
- data/lib/daigaku/chapter.rb +3 -4
- data/lib/daigaku/coloring.rb +22 -27
- 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 -15
- data/lib/daigaku/github_client.rb +5 -5
- data/lib/daigaku/loadable.rb +23 -14
- 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 +15 -15
- data/lib/daigaku/solution.rb +23 -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 +8 -8
- data/lib/daigaku/terminal/courses.rb +22 -19
- data/lib/daigaku/terminal/output.rb +46 -53
- 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 +54 -21
- data/lib/daigaku/unit.rb +2 -4
- data/lib/daigaku/version.rb +1 -1
- data/lib/daigaku/views.rb +29 -33
- 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 +14 -18
- data/lib/daigaku/views/splash.rb +11 -13
- data/lib/daigaku/views/subscriber.rb +38 -0
- data/lib/daigaku/views/task_view.rb +97 -80
- 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 +75 -52
- 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 +12 -6
- data/spec/daigaku/reference_solution_spec.rb +8 -10
- data/spec/daigaku/solution_spec.rb +21 -22
- 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 +32 -44
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Loading::Chapters do
|
4
|
-
|
5
4
|
let(:subjects) { Daigaku::Loading::Chapters.load(course_dirs.first) }
|
6
5
|
|
7
|
-
it
|
6
|
+
it 'has the prescribed number of chapters' do
|
8
7
|
expect(subjects.count).to eq available_chapters(course_dirs.first).count
|
9
8
|
end
|
10
9
|
|
11
|
-
it
|
10
|
+
it 'loads the available chapters' do
|
12
11
|
subjects.each_with_index do |chapter, index|
|
13
12
|
expect(chapter.title).to eq chapter_titles[index]
|
14
13
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Daigaku::Loading::Courses do
|
4
|
-
|
5
4
|
let(:subjects) { Daigaku::Loading::Courses.load(courses_basepath) }
|
6
5
|
|
7
|
-
it
|
6
|
+
it 'has the prescribed number of courses' do
|
8
7
|
expect(subjects.count).to eq available_courses.count
|
9
8
|
end
|
10
9
|
|
11
|
-
it
|
10
|
+
it 'loads the available courses' do
|
12
11
|
subjects.each_with_index do |course, index|
|
13
12
|
expect(course.title).to eq course_titles[index]
|
14
13
|
end
|
@@ -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
|
|
@@ -56,6 +53,15 @@ describe Daigaku::Markdown::RubyDoc do
|
|
56
53
|
expect(parse(markdown)).to eq "#{base_url}/Enumerator/Lazy.html#method-i-flat_map"
|
57
54
|
end
|
58
55
|
|
56
|
+
it 'returns the right link for an instance method not starting with word characters' do
|
57
|
+
markdown = '(ruby-doc core: Array#<<)'
|
58
|
+
expect(parse(markdown)).to eq "#{base_url}/Array.html#method-i-3C-3C"
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns the right link for an instance method with regex characters' do
|
62
|
+
markdown = '(ruby-doc core: Array#any?)'
|
63
|
+
expect(parse(markdown)).to eq "#{base_url}/Array.html#method-i-any-3F"
|
64
|
+
end
|
59
65
|
end
|
60
66
|
|
61
67
|
context 'for a text containing a stdlib doc markup' do
|
@@ -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,32 +54,32 @@ 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
|
66
|
-
|
64
|
+
it 'sets the solution’s state in the store to unverified unless passed' do
|
65
|
+
allow(File).to receive(:read).and_return('puts "I ❤ Daigaku!"')
|
66
|
+
QuickStore.store.set(subject.store_key, true)
|
67
|
+
|
67
68
|
subject.verify!
|
68
69
|
mastered = QuickStore.store.get(subject.store_key)
|
69
|
-
|
70
70
|
expect(mastered).to be_falsey
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
describe
|
75
|
-
it
|
76
|
-
expect(subject.verified?).to
|
74
|
+
describe '#verified?' do
|
75
|
+
it 'is false by default' do
|
76
|
+
expect(subject.verified?).to be false
|
77
77
|
end
|
78
78
|
|
79
|
-
it
|
79
|
+
it 'returns true if #verify! passed' do
|
80
80
|
subject.verify!
|
81
|
-
expect(subject.verified?).to
|
81
|
+
expect(subject.verified?).to be true
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
|
-
|
86
85
|
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
|