belajar 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +5 -0
  6. data/README.md +5 -0
  7. data/Rakefile +5 -0
  8. data/belajar.gemspec +38 -0
  9. data/bin/belajar +12 -0
  10. data/lib/belajar.rb +24 -0
  11. data/lib/belajar/chapter.rb +23 -0
  12. data/lib/belajar/configuration.rb +89 -0
  13. data/lib/belajar/congratulator.rb +13 -0
  14. data/lib/belajar/course.rb +80 -0
  15. data/lib/belajar/exceptions.rb +19 -0
  16. data/lib/belajar/generator.rb +60 -0
  17. data/lib/belajar/github_client.rb +30 -0
  18. data/lib/belajar/loadable.rb +23 -0
  19. data/lib/belajar/loading/chapters.rb +9 -0
  20. data/lib/belajar/loading/courses.rb +9 -0
  21. data/lib/belajar/loading/units.rb +9 -0
  22. data/lib/belajar/reference_solution.rb +18 -0
  23. data/lib/belajar/solution.rb +53 -0
  24. data/lib/belajar/storeable.rb +32 -0
  25. data/lib/belajar/task.rb +10 -0
  26. data/lib/belajar/terminal.rb +12 -0
  27. data/lib/belajar/terminal/cli.rb +59 -0
  28. data/lib/belajar/terminal/courses.rb +179 -0
  29. data/lib/belajar/terminal/output.rb +78 -0
  30. data/lib/belajar/terminal/setup.rb +115 -0
  31. data/lib/belajar/terminal/solutions.rb +46 -0
  32. data/lib/belajar/terminal/texts/about.txt +19 -0
  33. data/lib/belajar/terminal/texts/congratulations.txt +12 -0
  34. data/lib/belajar/terminal/texts/courses_empty.txt +3 -0
  35. data/lib/belajar/terminal/texts/hint_course_download.txt +13 -0
  36. data/lib/belajar/terminal/texts/welcome.txt +12 -0
  37. data/lib/belajar/terminal/welcome.rb +98 -0
  38. data/lib/belajar/test.rb +46 -0
  39. data/lib/belajar/test_result.rb +86 -0
  40. data/lib/belajar/unit.rb +28 -0
  41. data/lib/belajar/version.rb +3 -0
  42. data/lib/belajar/views.rb +51 -0
  43. data/lib/belajar/views/chapters_menu.rb +60 -0
  44. data/lib/belajar/views/courses_menu.rb +52 -0
  45. data/lib/belajar/views/main_menu.rb +37 -0
  46. data/lib/belajar/views/menu.rb +89 -0
  47. data/lib/belajar/views/splash.rb +57 -0
  48. data/lib/belajar/views/task_view.rb +236 -0
  49. data/lib/belajar/views/top_bar.rb +40 -0
  50. data/lib/belajar/views/units_menu.rb +61 -0
  51. data/lib/belajar/window.rb +215 -0
  52. data/spec/belajar/chapter_spec.rb +76 -0
  53. data/spec/belajar/configuration_spec.rb +161 -0
  54. data/spec/belajar/congratulator_spec.rb +24 -0
  55. data/spec/belajar/course_spec.rb +201 -0
  56. data/spec/belajar/generator_spec.rb +82 -0
  57. data/spec/belajar/github_client_spec.rb +53 -0
  58. data/spec/belajar/loading/chapters_spec.rb +16 -0
  59. data/spec/belajar/loading/courses_spec.rb +16 -0
  60. data/spec/belajar/loading/units_spec.rb +21 -0
  61. data/spec/belajar/reference_solution_spec.rb +41 -0
  62. data/spec/belajar/solution_spec.rb +86 -0
  63. data/spec/belajar/storeable_spec.rb +35 -0
  64. data/spec/belajar/task_spec.rb +23 -0
  65. data/spec/belajar/terminal/cli_spec.rb +51 -0
  66. data/spec/belajar/terminal/courses_spec.rb +293 -0
  67. data/spec/belajar/terminal/output_spec.rb +151 -0
  68. data/spec/belajar/terminal/setup_spec.rb +10 -0
  69. data/spec/belajar/terminal/solutions_spec.rb +8 -0
  70. data/spec/belajar/terminal/welcome_spec.rb +12 -0
  71. data/spec/belajar/terminal_spec.rb +24 -0
  72. data/spec/belajar/test_example_spec.rb +54 -0
  73. data/spec/belajar/test_result_spec.rb +91 -0
  74. data/spec/belajar/test_spec.rb +48 -0
  75. data/spec/belajar/unit_spec.rb +85 -0
  76. data/spec/belajar/views/chapters_menu_spec.rb +6 -0
  77. data/spec/belajar/views/courses_menu_spec.rb +6 -0
  78. data/spec/belajar/views/menu_spec.rb +19 -0
  79. data/spec/belajar/views/task_view_spec.rb +7 -0
  80. data/spec/belajar/views/units_menu_spec.rb +6 -0
  81. data/spec/belajar/views_spec.rb +21 -0
  82. data/spec/belajar_spec.rb +51 -0
  83. data/spec/path_helpers_spec.rb +60 -0
  84. data/spec/resource_helpers_spec.rb +33 -0
  85. data/spec/spec_helper.rb +28 -0
  86. data/spec/support/macros/content_helpers.rb +129 -0
  87. data/spec/support/macros/mock_helpers.rb +25 -0
  88. data/spec/support/macros/path_helpers.rb +139 -0
  89. data/spec/support/macros/resource_helpers.rb +157 -0
  90. data/spec/support/macros/test_helpers.rb +6 -0
  91. metadata +385 -0
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+
3
+ describe Belajar::Terminal::Output do
4
+
5
+ subject do
6
+ require 'thor'
7
+ class Test < Thor
8
+ include Belajar::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
+ :get_confirm
27
+ ].each do |method|
28
+ it "has the private method #{method}" do
29
+ expect(subject.private_methods.include?(method)).to be_truthy
30
+ end
31
+ end
32
+
33
+ describe "::say" do
34
+ it "prints the prescribed output to the $stdout" do
35
+ line = "line"
36
+ expect($stdout).to receive(:puts).with("\t#{line}")
37
+ subject.send(:say, line)
38
+ end
39
+
40
+ it "adds the line start in case of multiline inputs" do
41
+ lines = "first line\nsecond line\nthird line\n"
42
+ out_lines = lines.split("\n").map {|l| "\t#{l}" }.join("\n")
43
+ expect($stdout).to receive(:puts).with(out_lines)
44
+ subject.send(:say, lines)
45
+ end
46
+ end
47
+
48
+ describe "::empty_line" do
49
+ it "prints an empty line to the $stdout" do
50
+ expect($stdout).to receive(:puts).with('')
51
+ subject.send(:empty_line)
52
+ end
53
+ end
54
+
55
+ describe "::get" do
56
+ it "prints a string to $stdout to get a line on $stdin" do
57
+ printed = 'printed'
58
+ received = 'received'
59
+
60
+ allow($stdin).to receive(:gets) { received }
61
+ expect($stdout).to receive(:print).with("\n\t#{printed} ")
62
+ expect($stdin).to receive(:gets)
63
+ subject.send(:get, printed)
64
+ end
65
+ end
66
+
67
+ describe "::say_info" do
68
+ it "prints the prescribed output to the $stdout" do
69
+ line = "line"
70
+ expect($stdout).to receive(:puts).exactly(4).times.with("")
71
+ expect($stdout).to receive(:puts).with("\t" + " ℹ #{line}".light_blue)
72
+ expect($stdout).to receive(:puts).twice.times.with("\t" + ('-' * 70).light_blue)
73
+ subject.send(:say_info, line)
74
+ end
75
+ end
76
+
77
+ describe "::say_warning" do
78
+ it "prints the prescribed output to the $stdout" do
79
+ line = "line"
80
+ expect($stdout).to receive(:puts).exactly(4).times.with("")
81
+ expect($stdout).to receive(:puts).with("\t" + "⚠ #{line}".light_red)
82
+ expect($stdout).to receive(:puts).twice.times.with("\t" + ('-' * 70).light_red)
83
+ subject.send(:say_warning, line)
84
+ end
85
+ end
86
+
87
+ describe "::get_command" do
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 "writes 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
+ describe "::get_confirm" do
124
+ before do
125
+ @description = 'description'
126
+ allow($stdin).to receive(:gets).and_return('yes')
127
+ end
128
+
129
+ it "prints a warning with the given description" do
130
+ expect(subject).to receive(:say_warning).once.with(@description)
131
+ subject.send(:get_confirm, @description)
132
+ end
133
+
134
+ it "gets a command from the $stdin" do
135
+ expect($stdin).to receive(:gets)
136
+ subject.send(:get_confirm, @description)
137
+ end
138
+
139
+ it "takes a block to run when confirmed" do
140
+ allow(subject).to receive(:mocked_method).and_return('mocked method')
141
+ expect(subject).to receive(:mocked_method)
142
+ subject.send(:get_confirm, @description) { subject.mocked_method }
143
+ end
144
+
145
+ it "does not run the given block if not confirmed" do
146
+ allow(subject).to receive(:get).and_return('no')
147
+ expect(subject).not_to receive(:mocked_method)
148
+ subject.send(:get_confirm, @description) { subject.mocked_method }
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Belajar::Terminal::Setup do
4
+
5
+ it { is_expected.to be_a Thor }
6
+ it { is_expected.to respond_to :list }
7
+ it { is_expected.to respond_to :set }
8
+ it { is_expected.to respond_to :init }
9
+
10
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Belajar::Terminal::Solutions do
4
+
5
+ it { is_expected.to be_a Thor }
6
+ it { is_expected.to respond_to :open }
7
+
8
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Belajar::Terminal::Welcome do
4
+
5
+ [:run, :about].each do |method|
6
+ it "has the singleton method ::#{method}" do
7
+ singleton_methods = Belajar::Terminal::Welcome.singleton_methods
8
+ expect(singleton_methods.include?(method)).to be_truthy
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Belajar::Terminal do
4
+
5
+ it { is_expected.to respond_to :text }
6
+
7
+ describe "::text" do
8
+ it "loads a text from a file in the terminal/texts" do
9
+ text = Belajar::Terminal.text(:welcome)
10
+ expect(text).to be_a String
11
+ end
12
+
13
+ it "returns an empty string if the file does not exist" do
14
+ text = Belajar::Terminal.text(:non_existent_text)
15
+ expect(text).to eq ''
16
+ end
17
+
18
+ it "returns an empty string if the file has no content" do
19
+ allow(File).to receive(:read) { '' }
20
+ expect(Belajar::Terminal.text(:congratulations)).to eq ''
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Belajar::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 { Belajar::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
+ Belajar::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,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe Belajar::TestResult do
4
+
5
+ subject { Belajar::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
+ it { is_expected.to respond_to :summary_lines }
13
+
14
+ context "with passed input:" do
15
+
16
+ subject { Belajar::TestResult.new(test_passed_json) }
17
+
18
+ it "is marked passed" do
19
+ expect(subject.passed?).to be_truthy
20
+ end
21
+
22
+ it "has a default summary" do
23
+ expect(subject.summary).to include test_passed_summary
24
+ end
25
+ end
26
+
27
+ context "with failed input:" do
28
+
29
+ subject { Belajar::TestResult.new(test_failed_json) }
30
+
31
+ it "is not marked passed" do
32
+ expect(subject.passed?).to be_falsey
33
+ end
34
+
35
+ it "has the prescribed example count" do
36
+ example_count = test_failed_json_parsed[:summary][:example_count]
37
+ expect(subject.example_count).to eq example_count
38
+ end
39
+
40
+ it "has the prescribed failure count" do
41
+ failure_count = test_failed_json_parsed[:summary][:failure_count]
42
+ expect(subject.failure_count).to eq failure_count
43
+ end
44
+
45
+ describe "#examples" do
46
+ it "returns the prescribed number of examples" do
47
+ examples_count = test_failed_json_parsed[:examples].count
48
+ expect(subject.examples.count).to eq examples_count
49
+ end
50
+
51
+ it "returns examples of type Belajar::TestExample" do
52
+ subject.examples.each do |example|
53
+ expect(example).to be_a Belajar::TestExample
54
+ end
55
+ end
56
+
57
+ it "return examples with the prescribed info" do
58
+ subject.examples.each_with_index do |example, index|
59
+ description = test_failed_json_parsed[:examples][index][:full_description]
60
+ status = test_failed_json_parsed[:examples][index][:status]
61
+ exception = test_failed_json_parsed[:examples][index][:exception]
62
+ message = exception ? exception[:message] : example_passed_message
63
+
64
+ expect(example.description).to eq description
65
+ expect(example.status).to eq status
66
+ expect(example.message).to include message
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#summary" do
72
+ it "returns a string having all example infos" do
73
+ subject.examples.each do |example|
74
+ expect(subject.summary).to include example.description
75
+ expect(subject.summary).to include example.message
76
+ expect(subject.summary).to include example.status
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "#summary_lines" do
83
+ it "returns the summary split into lines" do
84
+ lines = ['This', 'is', 'summary', 'for', 'a', 'test']
85
+ allow(subject).to receive(:summary) { lines.join("\n") }
86
+
87
+ expect(subject.summary_lines).to eq lines
88
+ end
89
+ end
90
+
91
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Belajar::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
+ Belajar.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 { Belajar::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 Belajar::TestResult" do
31
+ expect(subject.run(@code)).to be_a Belajar::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 Belajar::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 { Belajar::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 Belajar::Task" do
23
+ expect(subject.task).to be_a Belajar::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 Belajar::ReferenceSolution" do
40
+ expect(subject.reference_solution).to be_a Belajar::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 Belajar::Solution" do
59
+ expect(subject.solution).to be_a Belajar::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(Belajar::Solution).to receive(:verified?) { true }
82
+ expect(subject.mastered?).to be_truthy
83
+ end
84
+ end
85
+ end