belajar 0.1.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.
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