tryruby 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.
@@ -0,0 +1,50 @@
1
+ require_relative 'spec_helper'
2
+ require 'ripl'
3
+ require_relative '../lib/tryruby/commands'
4
+ require_relative '../lib/tryruby/next_fix'
5
+
6
+ # mocking shell
7
+ module TestShellModule
8
+ class << self; attr_reader :called; end
9
+ @called = {}
10
+
11
+ def next_challenge
12
+ TestShellModule.called[:next_challenge] = true
13
+ end
14
+
15
+ def prev_challenge
16
+ TestShellModule.called[:prev_challenge] = true
17
+ end
18
+
19
+ def help_challenge
20
+ TestShellModule.called[:help_challenge] = true
21
+ end
22
+ end
23
+
24
+ Ripl::Shell.include TestShellModule
25
+ Ripl::Shell.include Tryruby::NextFix
26
+ Ripl::Commands.include Tryruby::Commands
27
+ Ripl.shell.before_loop
28
+
29
+ describe Tryruby::Commands do
30
+ let(:input) { nil }
31
+ before(:each) do
32
+ TestShellModule.called.clear
33
+ Ripl.shell.eval_input(input)
34
+ end
35
+ subject { TestShellModule.called }
36
+ describe '#next' do
37
+ let(:input) { 'next' }
38
+ it { is_expected.to eq next_challenge: true }
39
+ end
40
+
41
+ describe '#back' do
42
+ let(:input) { 'back' }
43
+ it { is_expected.to eq prev_challenge: true }
44
+ end
45
+
46
+ describe '#help' do
47
+ let(:input) { 'help' }
48
+ it { is_expected.to eq help_challenge: true }
49
+ end
50
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'spec_helper'
2
+ require_relative '../lib/tryruby/level_builder'
3
+
4
+ describe Tryruby::LevelBuilder do
5
+ subject { described_class.new }
6
+
7
+ describe '#challenge' do
8
+ it 'adds challenges' do
9
+ subject.challenge do
10
+ help 'first'
11
+ end
12
+ subject.challenge do
13
+ help 'second'
14
+ end
15
+ level = subject.level
16
+ expect(level[0].help).to eq 'first'
17
+ expect(level[1].help).to eq 'second'
18
+ expect(level.length).to eq 2
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ require_relative 'spec_helper'
2
+ require_relative '../lib/tryruby/level'
3
+ require_relative '../lib/tryruby/challenge'
4
+
5
+ describe Tryruby::Level do
6
+ let(:a) { Tryruby::Challenge.new('a') }
7
+ let(:b) { Tryruby::Challenge.new('b') }
8
+ subject { described_class.new(a, b) }
9
+
10
+ describe '#[]' do
11
+ it 'returns proper item' do
12
+ expect(subject[0]).to eq a
13
+ expect(subject[1]).to eq b
14
+ end
15
+ end
16
+
17
+ describe '#each' do
18
+ it 'iterates through items' do
19
+ yielded = []
20
+ subject.each { |i| yielded << i }
21
+ expect(yielded).to eq [a, b]
22
+ end
23
+ end
24
+
25
+ describe '#length' do
26
+ it 'returns number of items' do
27
+ expect(subject.length).to eq 2
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'spec_helper'
2
+ require_relative '../lib/tryruby/next_fix'
3
+
4
+ describe Tryruby::NextFix do
5
+ # mocking module to properly inherit
6
+ module API
7
+ def loop_eval(str)
8
+ str
9
+ end
10
+ end
11
+
12
+ include API
13
+ include described_class
14
+
15
+ it 'converts next to self.next' do
16
+ expect(loop_eval('next')).to eq 'self.next'
17
+ end
18
+
19
+ it 'does not convert "next"' do
20
+ expect(loop_eval('"next"')).to eq '"next"'
21
+ end
22
+ end
@@ -0,0 +1,205 @@
1
+ require_relative 'spec_helper'
2
+ require_relative '../lib/tryruby/shell'
3
+ require_relative '../lib/tryruby/challenge'
4
+
5
+ # mocking shell
6
+ class TestShell
7
+ class << self; public :include; end
8
+
9
+ def initialize
10
+ @binding = create_binding
11
+ @result = false
12
+ end
13
+
14
+ # mocking module to properly inherit
15
+ module API
16
+ def before_loop
17
+ end
18
+
19
+ def loop_once
20
+ end
21
+ end
22
+
23
+ def create_binding
24
+ foo = 42
25
+ bar = 24
26
+ binding
27
+ end
28
+
29
+ include API
30
+ end
31
+
32
+ TestShell.include Tryruby::Shell
33
+
34
+ describe Tryruby::Shell do
35
+ called = []
36
+ let(:test) do
37
+ proc do |result, vars, output|
38
+ called << [:test, self, result, vars.dup, output]
39
+ result
40
+ end
41
+ end
42
+ let(:setup) do
43
+ proc do |vars|
44
+ called << [:setup, self, vars.dup]
45
+ vars[:test_var] ||= 0
46
+ vars[:test_var] += 1
47
+ end
48
+ end
49
+ let(:a) { Tryruby::Challenge.new('a', test, setup) }
50
+ let(:b) { Tryruby::Challenge.new('b', nil, setup) }
51
+ let(:c) { Tryruby::Challenge.new('c', test) }
52
+ let(:levels) { [[a, b], [], [c]] }
53
+ let(:shell) { TestShell.new.tap { |sh| sh.levels = levels } }
54
+
55
+ def test_var
56
+ eval('test_var', shell.instance_eval('@binding'))
57
+ end
58
+
59
+ subject { shell.challenge }
60
+
61
+ before(:each) do
62
+ called = []
63
+ shell.before_loop
64
+ end
65
+
66
+ describe '#before_loop' do
67
+ it 'prints help and calls setup' do
68
+ is_expected.to eq a
69
+ expect(called).to eq [[:setup, shell, { foo: 42, bar: 24 }]]
70
+ expect(test_var).to eq 1
71
+ end
72
+ end
73
+
74
+ describe '#next_challenge' do
75
+ let(:test) {}
76
+ it 'prints helps and calls setups' do
77
+ expect do
78
+ shell.next_challenge
79
+ shell.loop_once
80
+ end.to match_stdout('b')
81
+ expect(shell.challenge).to eq b
82
+ expect(test_var).to eq 2
83
+ expect do
84
+ shell.next_challenge
85
+ shell.loop_once
86
+ end.to match_stdout('c')
87
+ expect(shell.challenge).to eq c
88
+ expect(test_var).to eq 2
89
+ expect do
90
+ shell.next_challenge
91
+ shell.loop_once
92
+ end.to throw_symbol(:ripl_exit)
93
+ expect(shell.challenge).to eq nil
94
+ expect(test_var).to eq 2
95
+ expect(called).to eq [
96
+ [:setup, shell, { foo: 42, bar: 24 }],
97
+ [:setup, shell, { foo: 42, bar: 24, test_var: 1 }]
98
+ ]
99
+ end
100
+ end
101
+
102
+ describe '#prev_challenge' do
103
+ let(:test) {}
104
+ it 'prints helps and calls setups' do
105
+ 2.times do
106
+ shell.next_challenge
107
+ shell.loop_once
108
+ end
109
+ expect(shell.challenge).to eq c
110
+ expect(test_var).to eq 2
111
+ expect do
112
+ shell.prev_challenge
113
+ shell.loop_once
114
+ end.to match_stdout('b')
115
+ expect(shell.challenge).to eq b
116
+ expect(test_var).to eq 3
117
+ expect do
118
+ shell.prev_challenge
119
+ shell.loop_once
120
+ end.to match_stdout('a')
121
+ expect(shell.challenge).to eq a
122
+ expect(test_var).to eq 4
123
+ expect do
124
+ shell.prev_challenge
125
+ shell.loop_once
126
+ end.to match_stdout('')
127
+ expect(shell.challenge).to eq a
128
+ expect(test_var).to eq 4
129
+ expect(called).to eq [
130
+ [:setup, shell, { foo: 42, bar: 24 }],
131
+ [:setup, shell, { foo: 42, bar: 24, test_var: 1 }],
132
+ [:setup, shell, { foo: 42, bar: 24, test_var: 2 }],
133
+ [:setup, shell, { foo: 42, bar: 24, test_var: 3 }]
134
+ ]
135
+ end
136
+ end
137
+
138
+ describe '#loop_once' do
139
+ context 'with fulfilled test' do
140
+ let(:test) do
141
+ proc do |result, vars, output|
142
+ called << [:test, self, result, vars, output]
143
+ !result
144
+ end
145
+ end
146
+ it 'goes to next challenge' do
147
+ expect { shell.loop_once }.to match_stdout('Success!')
148
+ expect(called).to eq [
149
+ [:setup, shell, { foo: 42, bar: 24 }],
150
+ [:test, shell, false, { foo: 42, bar: 24, test_var: 1 }, ''],
151
+ [:setup, shell, { foo: 42, bar: 24, test_var: 1 }]
152
+ ]
153
+ expect(shell.challenge).to eq b
154
+ end
155
+ end
156
+ context 'with failed test' do
157
+ it 'does not go to next challenge' do
158
+ expect { shell.loop_once }.to match_stdout('')
159
+ expect(called).to eq [
160
+ [:setup, shell, { foo: 42, bar: 24 }],
161
+ [:test, shell, false, { foo: 42, bar: 24, test_var: 1 }, '']
162
+ ]
163
+ expect(shell.challenge).to eq a
164
+ end
165
+ end
166
+ end
167
+
168
+ describe '#level' do
169
+ it 'returns current level\'s challenges' do
170
+ expect(shell.level).to eq [a, b]
171
+ end
172
+ end
173
+
174
+ describe '#challenge' do
175
+ it 'returns current challenge' do
176
+ is_expected.to eq a
177
+ end
178
+ end
179
+
180
+ describe '#help_challenge' do
181
+ it 'prints help' do
182
+ expect { shell.help_challenge }.to match_stdout('a')
183
+ end
184
+ end
185
+
186
+ context 'without challenge' do
187
+ let(:levels) { [] }
188
+
189
+ describe '#loop_once' do
190
+ it { expect { shell.loop_once }.to throw_symbol(:ripl_exit) }
191
+ end
192
+
193
+ describe '#level' do
194
+ it { expect(shell.level).to eq nil }
195
+ end
196
+
197
+ describe '#challenge' do
198
+ it { is_expected.to eq nil }
199
+ end
200
+
201
+ describe '#help_challenge' do
202
+ it { expect { shell.help_challenge }.to match_stdout('') }
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'stringio'
4
+ $LOAD_PATH << '../lib/tryruby'
5
+
6
+ RSpec.configure do |c|
7
+ c.color = true
8
+ c.formatter = :documentation
9
+ c.tty = true
10
+ end
11
+
12
+ # mtm @ http://stackoverflow.com/questions/6372763/rspec-how-do-i-write-a-test-that-expects-certain-output-but-doesnt-care-about
13
+ RSpec::Matchers.define :match_stdout do |check|
14
+ @capture = nil
15
+
16
+ match do |block|
17
+ begin
18
+ stdout_saved = $stdout
19
+ $stdout = StringIO.new
20
+ block.call
21
+ ensure
22
+ @capture = $stdout
23
+ $stdout = stdout_saved
24
+ end
25
+
26
+ @capture.string.match check
27
+ end
28
+
29
+ failure_message do
30
+ "expected to #{description}"
31
+ end
32
+ failure_message_when_negated do
33
+ "expected not to #{description}"
34
+ end
35
+ description do
36
+ "match [#{check}] on stdout [#{@capture.string}]"
37
+ end
38
+
39
+ def supports_block_expectations?
40
+ true
41
+ end
42
+ end
@@ -0,0 +1,74 @@
1
+ require_relative 'spec_helper'
2
+ require_relative '../lib/tryruby/tutorial'
3
+
4
+ describe Tryruby::Tutorial do
5
+ subject { described_class.new }
6
+
7
+ describe '#[]' do
8
+ it { expect(subject[0]).to eq nil }
9
+ end
10
+
11
+ describe '#each' do
12
+ it 'returns Enumerator without block' do
13
+ expect(subject.each.class).to be Enumerator
14
+ end
15
+ it 'iterates through levels' do
16
+ yielded = []
17
+ subject.each { |i| yielded << i }
18
+ expect(yielded).to eq []
19
+ end
20
+ end
21
+
22
+ describe '#length' do
23
+ it { expect(subject.length).to eq 0 }
24
+ end
25
+
26
+ describe '#commands' do
27
+ it 'return Commands module' do
28
+ expect(subject.commands).to eq described_class::Commands
29
+ end
30
+ end
31
+
32
+ context 'subclass' do
33
+ # Tutorial subclass
34
+ class TestTutorial < described_class
35
+ # Test commands
36
+ module Commands
37
+ def test
38
+ 'test'
39
+ end
40
+ end
41
+ level do
42
+ end
43
+ end
44
+
45
+ subject { TestTutorial.new }
46
+
47
+ describe '#[]' do
48
+ it { expect(subject[0].class).to eq Tryruby::Level }
49
+ end
50
+
51
+ describe '#each' do
52
+ it 'returns Enumerator without block' do
53
+ expect(subject.each.class).to be Enumerator
54
+ end
55
+ it 'iterates through levels' do
56
+ yielded = []
57
+ subject.each { |i| yielded << i.class }
58
+ expect(yielded).to eq [Tryruby::Level]
59
+ end
60
+ end
61
+
62
+ describe '#length' do
63
+ it { expect(subject.length).to eq 1 }
64
+ end
65
+
66
+ describe '#commands' do
67
+ it 'return Commands module' do
68
+ expect(subject.commands).to eq TestTutorial::Commands
69
+ expect(subject.commands.instance_methods).to eq [:test]
70
+ expect(described_class.new.commands.instance_methods).to eq []
71
+ end
72
+ end
73
+ end
74
+ end