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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +25 -0
- data/Rakefile +1 -0
- data/bin/tryruby +21 -0
- data/lib/tryruby.rb +5 -0
- data/lib/tryruby/challenge.rb +28 -0
- data/lib/tryruby/challenge_builder.rb +32 -0
- data/lib/tryruby/colors.rb +43 -0
- data/lib/tryruby/commands.rb +18 -0
- data/lib/tryruby/default_levels.rb +858 -0
- data/lib/tryruby/level.rb +23 -0
- data/lib/tryruby/level_builder.rb +21 -0
- data/lib/tryruby/next_fix.rb +9 -0
- data/lib/tryruby/runner.rb +19 -0
- data/lib/tryruby/shell.rb +122 -0
- data/lib/tryruby/tutorial.rb +53 -0
- data/lib/tryruby/version.rb +4 -0
- data/spec/challenge_buider_spec.rb +39 -0
- data/spec/challenge_spec.rb +91 -0
- data/spec/colors_spec.rb +69 -0
- data/spec/commands_spec.rb +50 -0
- data/spec/level_builder_spec.rb +21 -0
- data/spec/level_spec.rb +30 -0
- data/spec/next_fix_spec.rb +22 -0
- data/spec/shell_spec.rb +205 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/tutorial_spec.rb +74 -0
- data/tryruby.gemspec +27 -0
- metadata +173 -0
@@ -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
|
data/spec/level_spec.rb
ADDED
@@ -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
|
data/spec/shell_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|