daigaku 0.0.1
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 +7 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/README.md +62 -0
- data/Rakefile +2 -0
- data/bin/daigaku +12 -0
- data/daigaku.gemspec +37 -0
- data/lib/daigaku.rb +27 -0
- data/lib/daigaku/chapter.rb +23 -0
- data/lib/daigaku/configuration.rb +86 -0
- data/lib/daigaku/course.rb +23 -0
- data/lib/daigaku/database.rb +64 -0
- data/lib/daigaku/exceptions.rb +19 -0
- data/lib/daigaku/generator.rb +53 -0
- data/lib/daigaku/loadable.rb +23 -0
- data/lib/daigaku/loading/chapters.rb +9 -0
- data/lib/daigaku/loading/courses.rb +9 -0
- data/lib/daigaku/loading/units.rb +9 -0
- data/lib/daigaku/reference_solution.rb +10 -0
- data/lib/daigaku/solution.rb +42 -0
- data/lib/daigaku/task.rb +10 -0
- data/lib/daigaku/terminal.rb +11 -0
- data/lib/daigaku/terminal/cli.rb +59 -0
- data/lib/daigaku/terminal/courses.rb +114 -0
- data/lib/daigaku/terminal/output.rb +72 -0
- data/lib/daigaku/terminal/setup.rb +115 -0
- data/lib/daigaku/terminal/solutions.rb +46 -0
- data/lib/daigaku/terminal/texts/about.txt +19 -0
- data/lib/daigaku/terminal/texts/courses_empty.txt +3 -0
- data/lib/daigaku/terminal/texts/hint_course_download.txt +13 -0
- data/lib/daigaku/terminal/texts/welcome.txt +12 -0
- data/lib/daigaku/terminal/welcome.rb +98 -0
- data/lib/daigaku/test.rb +46 -0
- data/lib/daigaku/test_result.rb +69 -0
- data/lib/daigaku/unit.rb +28 -0
- data/lib/daigaku/version.rb +3 -0
- data/lib/daigaku/views.rb +59 -0
- data/lib/daigaku/views/chapters_menu.rb +91 -0
- data/lib/daigaku/views/courses_menu.rb +87 -0
- data/lib/daigaku/views/main_menu.rb +37 -0
- data/lib/daigaku/views/splash.rb +57 -0
- data/lib/daigaku/views/task_view.rb +206 -0
- data/lib/daigaku/views/top_bar.rb +48 -0
- data/lib/daigaku/views/units_menu.rb +92 -0
- data/lib/daigaku/window.rb +160 -0
- data/spec/daigaku/chapter_spec.rb +76 -0
- data/spec/daigaku/configuration_spec.rb +161 -0
- data/spec/daigaku/course_spec.rb +75 -0
- data/spec/daigaku/database_spec.rb +79 -0
- data/spec/daigaku/generator_spec.rb +82 -0
- data/spec/daigaku/loading/chapters_spec.rb +16 -0
- data/spec/daigaku/loading/courses_spec.rb +16 -0
- data/spec/daigaku/loading/units_spec.rb +21 -0
- data/spec/daigaku/reference_solution_spec.rb +23 -0
- data/spec/daigaku/solution_spec.rb +79 -0
- data/spec/daigaku/task_spec.rb +23 -0
- data/spec/daigaku/terminal/cli_spec.rb +51 -0
- data/spec/daigaku/terminal/courses_spec.rb +60 -0
- data/spec/daigaku/terminal/output_spec.rb +123 -0
- data/spec/daigaku/terminal/setup_spec.rb +10 -0
- data/spec/daigaku/terminal/solutions_spec.rb +8 -0
- data/spec/daigaku/terminal/welcome_spec.rb +12 -0
- data/spec/daigaku/terminal_spec.rb +14 -0
- data/spec/daigaku/test_example_spec.rb +54 -0
- data/spec/daigaku/test_result_spec.rb +81 -0
- data/spec/daigaku/test_spec.rb +48 -0
- data/spec/daigaku/unit_spec.rb +85 -0
- data/spec/daigaku/views/chapters_menu_spec.rb +8 -0
- data/spec/daigaku/views/courses_menu_spec.rb +8 -0
- data/spec/daigaku/views/task_view_spec.rb +7 -0
- data/spec/daigaku/views/units_menu_spec.rb +8 -0
- data/spec/daigaku/views_spec.rb +23 -0
- data/spec/daigaku_spec.rb +57 -0
- data/spec/path_helpers_spec.rb +60 -0
- data/spec/resource_helpers_spec.rb +33 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/support/macros/content_helpers.rb +129 -0
- data/spec/support/macros/mock_helpers.rb +20 -0
- data/spec/support/macros/path_helpers.rb +133 -0
- data/spec/support/macros/resource_helpers.rb +119 -0
- data/spec/support/macros/test_helpers.rb +6 -0
- metadata +361 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Daigaku::Terminal::Output do
|
4
|
+
|
5
|
+
subject do
|
6
|
+
require 'thor'
|
7
|
+
class Test < Thor
|
8
|
+
include Daigaku::Terminal::Output
|
9
|
+
end
|
10
|
+
|
11
|
+
Test.new
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow($stdout).to receive(:puts) { |string| string }
|
16
|
+
allow($stdout).to receive(:print) { |string| string }
|
17
|
+
end
|
18
|
+
|
19
|
+
[
|
20
|
+
:say,
|
21
|
+
:empty_line,
|
22
|
+
:get,
|
23
|
+
:say_info,
|
24
|
+
:say_warning,
|
25
|
+
:get_command
|
26
|
+
].each do |method|
|
27
|
+
it "has the private method #{method}" do
|
28
|
+
expect(subject.private_methods.include?(method)).to be_truthy
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "::say" do
|
33
|
+
it "prints the prescribed output to the $stdout" do
|
34
|
+
line = "line"
|
35
|
+
expect($stdout).to receive(:puts).with("\t#{line}")
|
36
|
+
subject.send(:say, line)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "adds the line start in case of multiline inputs" do
|
40
|
+
lines = "first line\nsecond line\nthird line\n"
|
41
|
+
out_lines = lines.split("\n").map {|l| "\t#{l}" }.join("\n")
|
42
|
+
expect($stdout).to receive(:puts).with(out_lines)
|
43
|
+
subject.send(:say, lines)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "::empty_line" do
|
48
|
+
it "prints an empty line to the $stdout" do
|
49
|
+
expect($stdout).to receive(:puts).with('')
|
50
|
+
subject.send(:empty_line)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "::get" do
|
55
|
+
it "prints a string to $stdout to get a line on $stdin" do
|
56
|
+
printed = 'printed'
|
57
|
+
received = 'received'
|
58
|
+
|
59
|
+
allow($stdin).to receive(:gets) { received }
|
60
|
+
expect($stdout).to receive(:print).with("\n\t#{printed} ")
|
61
|
+
expect($stdin).to receive(:gets)
|
62
|
+
subject.send(:get, printed)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "::say_info" do
|
67
|
+
it "prints the prescribed output to the $stdout" do
|
68
|
+
line = "line"
|
69
|
+
expect($stdout).to receive(:puts).exactly(4).times.with("")
|
70
|
+
expect($stdout).to receive(:puts).with("\t" + " ℹ #{line}".light_blue)
|
71
|
+
expect($stdout).to receive(:puts).twice.times.with("\t" + ('-' * 70).light_blue)
|
72
|
+
subject.send(:say_info, line)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "::say_warning" do
|
77
|
+
it "prints the prescribed output to the $stdout" do
|
78
|
+
line = "line"
|
79
|
+
expect($stdout).to receive(:puts).exactly(4).times.with("")
|
80
|
+
expect($stdout).to receive(:puts).with("\t" + "⚠ #{line}".light_red)
|
81
|
+
expect($stdout).to receive(:puts).twice.times.with("\t" + ('-' * 70).light_red)
|
82
|
+
subject.send(:say_warning, line)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "::get_command" do
|
87
|
+
|
88
|
+
before do
|
89
|
+
@correct_command = 'correct command'
|
90
|
+
@description = 'description'
|
91
|
+
allow($stdin).to receive(:gets).and_return(@correct_command)
|
92
|
+
allow(Kernel).to receive(:system) { '' }
|
93
|
+
end
|
94
|
+
|
95
|
+
it "prints a description" do
|
96
|
+
expect($stdout).to receive(:puts).once.with("\t#{@description}")
|
97
|
+
subject.send(:get_command, @correct_command, @description)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "gets a command from the $stdin" do
|
101
|
+
expect($stdin).to receive(:gets)
|
102
|
+
subject.send(:get_command, @correct_command, @description)
|
103
|
+
end
|
104
|
+
|
105
|
+
context "with the right command typed in:" do
|
106
|
+
it "gets a specified command from the user" do
|
107
|
+
subject.send(:get_command, @correct_command, @description)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "with a wrong command typed in:" do
|
112
|
+
it "writed a hint" do
|
113
|
+
wrong_command = 'wrong command'
|
114
|
+
error = "This was something else. Try \"#{@correct_command}\"."
|
115
|
+
allow($stdin).to receive(:gets).and_return(wrong_command, @correct_command)
|
116
|
+
|
117
|
+
expect($stdout).to receive(:puts).once.with("\t#{error}")
|
118
|
+
subject.send(:get_command, @correct_command, @description)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Daigaku::Terminal::Welcome do
|
4
|
+
|
5
|
+
[:run, :about].each do |method|
|
6
|
+
it "has the singleton method ::#{method}" do
|
7
|
+
singleton_methods = Daigaku::Terminal::Welcome.singleton_methods
|
8
|
+
expect(singleton_methods.include?(method)).to be_truthy
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Daigaku::Terminal do
|
4
|
+
|
5
|
+
it { is_expected.to respond_to :text }
|
6
|
+
|
7
|
+
describe "::load_text" do
|
8
|
+
it "loads a text from a file in the cli/texts" do
|
9
|
+
text = Daigaku::Terminal.text(:welcome)
|
10
|
+
expect(text).to be_a String
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Daigaku::TestExample do
|
4
|
+
|
5
|
+
it { is_expected.to respond_to :description }
|
6
|
+
it { is_expected.to respond_to :status }
|
7
|
+
it { is_expected.to respond_to :message }
|
8
|
+
|
9
|
+
context "when passed:" do
|
10
|
+
let(:description) { test_passed_json_parsed[:examples].first[:description] }
|
11
|
+
let(:status) { test_passed_json_parsed[:examples].first[:status] }
|
12
|
+
|
13
|
+
subject { Daigaku::TestExample.new(description: description, status: status) }
|
14
|
+
|
15
|
+
it "has the prescribed description" do
|
16
|
+
expect(subject.description).to eq description
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has the prescribed status" do
|
20
|
+
expect(subject.status).to eq status
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has the prescribed message" do
|
24
|
+
expect(subject.message).to eq example_passed_message
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when failed:" do
|
29
|
+
let(:description) { test_failed_json_parsed[:examples].first[:description] }
|
30
|
+
let(:status) { test_failed_json_parsed[:examples].first[:status] }
|
31
|
+
let(:message) { test_failed_json_parsed[:examples].first[:exception][:message] }
|
32
|
+
|
33
|
+
subject do
|
34
|
+
Daigaku::TestExample.new(
|
35
|
+
description: description,
|
36
|
+
status: status,
|
37
|
+
message: message
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "has the prescribed description" do
|
42
|
+
expect(subject.description).to eq description
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has the prescribed status" do
|
46
|
+
expect(subject.status).to eq status
|
47
|
+
end
|
48
|
+
|
49
|
+
it "has the prescribed message" do
|
50
|
+
expect(subject.message).to eq message
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Daigaku::TestResult do
|
4
|
+
|
5
|
+
subject { Daigaku::TestResult.new(test_passed_json) }
|
6
|
+
|
7
|
+
it { is_expected.to respond_to :example_count }
|
8
|
+
it { is_expected.to respond_to :failure_count }
|
9
|
+
it { is_expected.to respond_to :examples }
|
10
|
+
it { is_expected.to respond_to :passed? }
|
11
|
+
it { is_expected.to respond_to :summary }
|
12
|
+
|
13
|
+
context "with passed input:" do
|
14
|
+
|
15
|
+
subject { Daigaku::TestResult.new(test_passed_json) }
|
16
|
+
|
17
|
+
it "is marked passed" do
|
18
|
+
expect(subject.passed?).to be_truthy
|
19
|
+
end
|
20
|
+
|
21
|
+
it "has a default summary" do
|
22
|
+
expect(subject.summary).to eq test_passed_summary
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "with failed input:" do
|
27
|
+
|
28
|
+
subject { Daigaku::TestResult.new(test_failed_json) }
|
29
|
+
|
30
|
+
it "is not marked passed" do
|
31
|
+
expect(subject.passed?).to be_falsey
|
32
|
+
end
|
33
|
+
|
34
|
+
it "has the prescribed example count" do
|
35
|
+
example_count = test_failed_json_parsed[:summary][:example_count]
|
36
|
+
expect(subject.example_count).to eq example_count
|
37
|
+
end
|
38
|
+
|
39
|
+
it "has the prescribed failure count" do
|
40
|
+
failure_count = test_failed_json_parsed[:summary][:failure_count]
|
41
|
+
expect(subject.failure_count).to eq failure_count
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#examples" do
|
45
|
+
it "returns the prescribed number of examples" do
|
46
|
+
examples_count = test_failed_json_parsed[:examples].count
|
47
|
+
expect(subject.examples.count).to eq examples_count
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns examples of type Daigaku::TestExample" do
|
51
|
+
subject.examples.each do |example|
|
52
|
+
expect(example).to be_a Daigaku::TestExample
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "return examples with the prescribed info" do
|
57
|
+
subject.examples.each_with_index do |example, index|
|
58
|
+
description = test_failed_json_parsed[:examples][index][:full_description]
|
59
|
+
status = test_failed_json_parsed[:examples][index][:status]
|
60
|
+
exception = test_failed_json_parsed[:examples][index][:exception]
|
61
|
+
message = exception ? exception[:message] : example_passed_message
|
62
|
+
|
63
|
+
expect(example.description).to eq description
|
64
|
+
expect(example.status).to eq status
|
65
|
+
expect(example.message).to eq message
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#summary" do
|
71
|
+
it "returns a string having all example infos" do
|
72
|
+
subject.examples.each do |example|
|
73
|
+
expect(subject.summary).to include example.description
|
74
|
+
expect(subject.summary).to include example.message
|
75
|
+
expect(subject.summary).to include example.status
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Daigaku::Test do
|
4
|
+
|
5
|
+
it { is_expected.to respond_to :path }
|
6
|
+
it { is_expected.to respond_to :run }
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
prepare_solutions
|
10
|
+
Daigaku.config.solutions_path = solutions_basepath
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:unit_path) { all_unit_dirs.first }
|
14
|
+
let(:test_path) { all_test_file_paths.first }
|
15
|
+
|
16
|
+
subject { Daigaku::Test.new(unit_path) }
|
17
|
+
|
18
|
+
it "has the appropriate path" do
|
19
|
+
expect(subject.path).to eq test_path
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#run" do
|
23
|
+
before do
|
24
|
+
course_name = course_dir_names.first
|
25
|
+
chapter_name = chapter_dir_names.first
|
26
|
+
unit_name = unit_dir_names.first
|
27
|
+
@code = available_solution(course_name, chapter_name, unit_name).code
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns a Daigaku::TestResult" do
|
31
|
+
expect(subject.run(@code)).to be_a Daigaku::TestResult
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when passing" do
|
35
|
+
it "returns a passing result" do
|
36
|
+
expect(subject.run(@code).passed?).to be_truthy
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when failing" do
|
41
|
+
it "returns a failing result" do
|
42
|
+
code = "print 'BYE WORLD'"
|
43
|
+
expect(subject.run(code).passed?).to be_falsey
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Daigaku::Unit do
|
4
|
+
|
5
|
+
it { is_expected.to respond_to :title }
|
6
|
+
it { is_expected.to respond_to :task }
|
7
|
+
it { is_expected.to respond_to :solution }
|
8
|
+
it { is_expected.to respond_to :reference_solution }
|
9
|
+
it { is_expected.to respond_to :mastered? }
|
10
|
+
|
11
|
+
let(:course_name) { course_dir_names.first }
|
12
|
+
let(:chapter_name) { chapter_dir_names.first }
|
13
|
+
let(:unit_name) { unit_dir_names.first }
|
14
|
+
|
15
|
+
subject { Daigaku::Unit.new(unit_dirs(course_name).first[0]) }
|
16
|
+
|
17
|
+
it "has the prescribed title" do
|
18
|
+
expect(subject.title).to eq unit_titles.first
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#task" do
|
22
|
+
it "returns an object of type Daigaku::Task" do
|
23
|
+
expect(subject.task).to be_a Daigaku::Task
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns the unit's appropriate task" do
|
27
|
+
task = available_task(course_name, chapter_name, unit_name).first
|
28
|
+
expect(subject.task.markdown).to eq task.markdown
|
29
|
+
end
|
30
|
+
|
31
|
+
it "lazy-loads the task" do
|
32
|
+
expect(subject.instance_variable_get(:@task)).to be_nil
|
33
|
+
subject.task
|
34
|
+
expect(subject.instance_variable_get(:@task)).not_to be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#reference_solution" do
|
39
|
+
it "returns an object of type Daigaku::ReferenceSolution" do
|
40
|
+
expect(subject.reference_solution).to be_a Daigaku::ReferenceSolution
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns the units appropriate predefined reference solution" do
|
44
|
+
reference_solution = available_reference_solution(course_name,
|
45
|
+
chapter_name,
|
46
|
+
unit_name).first
|
47
|
+
expect(subject.reference_solution.code).to eq reference_solution.code
|
48
|
+
end
|
49
|
+
|
50
|
+
it "lazy-loads the reference solution" do
|
51
|
+
expect(subject.instance_variable_get(:@reference_solution)).to be_nil
|
52
|
+
subject.reference_solution
|
53
|
+
expect(subject.instance_variable_get(:@reference_solution)).not_to be_nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#solution" do
|
58
|
+
it "returns an object of type Daigaku::Solution" do
|
59
|
+
expect(subject.solution).to be_a Daigaku::Solution
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns the units appropriate solution provided by the user" do
|
63
|
+
expect(subject.solution.code).to eq available_solution(course_name,
|
64
|
+
chapter_name,
|
65
|
+
unit_name).code
|
66
|
+
end
|
67
|
+
|
68
|
+
it "lazy-loads the reference solution" do
|
69
|
+
expect(subject.instance_variable_get(:@solution)).to be_nil
|
70
|
+
subject.solution
|
71
|
+
expect(subject.instance_variable_get(:@solution)).not_to be_nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#mastered?" do
|
76
|
+
it "returns false by default" do
|
77
|
+
expect(subject.mastered?).to be_falsey
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns true if the solution has been verified" do
|
81
|
+
allow_any_instance_of(Daigaku::Solution).to receive(:verified?) { true }
|
82
|
+
expect(subject.mastered?).to be_truthy
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|