pry 0.9.7.4-i386-mingw32 → 0.9.8-i386-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -3
- data/CHANGELOG +43 -0
- data/README.markdown +3 -1
- data/Rakefile +51 -32
- data/bin/pry +2 -80
- data/lib/pry.rb +33 -26
- data/lib/pry/cli.rb +152 -0
- data/lib/pry/code.rb +351 -0
- data/lib/pry/command.rb +422 -0
- data/lib/pry/command_set.rb +259 -129
- data/lib/pry/commands.rb +0 -1
- data/lib/pry/config.rb +43 -9
- data/lib/pry/default_commands/context.rb +109 -92
- data/lib/pry/default_commands/documentation.rb +174 -63
- data/lib/pry/default_commands/easter_eggs.rb +26 -2
- data/lib/pry/default_commands/gems.rb +65 -37
- data/lib/pry/default_commands/input.rb +175 -243
- data/lib/pry/default_commands/introspection.rb +173 -112
- data/lib/pry/default_commands/ls.rb +96 -114
- data/lib/pry/default_commands/shell.rb +175 -70
- data/lib/pry/helpers/base_helpers.rb +7 -2
- data/lib/pry/helpers/command_helpers.rb +71 -77
- data/lib/pry/helpers/options_helpers.rb +10 -41
- data/lib/pry/helpers/text.rb +24 -4
- data/lib/pry/history.rb +55 -17
- data/lib/pry/history_array.rb +2 -0
- data/lib/pry/hooks.rb +252 -0
- data/lib/pry/indent.rb +9 -5
- data/lib/pry/method.rb +149 -50
- data/lib/pry/plugins.rb +12 -4
- data/lib/pry/pry_class.rb +69 -26
- data/lib/pry/pry_instance.rb +187 -115
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +73 -0
- data/man/pry.1 +195 -0
- data/man/pry.1.html +204 -0
- data/man/pry.1.ronn +141 -0
- data/pry.gemspec +29 -32
- data/test/helper.rb +32 -36
- data/test/test_cli.rb +78 -0
- data/test/test_code.rb +201 -0
- data/test/test_command.rb +327 -0
- data/test/test_command_integration.rb +512 -0
- data/test/test_command_set.rb +338 -12
- data/test/test_completion.rb +1 -1
- data/test/test_default_commands.rb +1 -2
- data/test/test_default_commands/test_context.rb +27 -5
- data/test/test_default_commands/test_documentation.rb +20 -8
- data/test/test_default_commands/test_input.rb +84 -45
- data/test/test_default_commands/test_introspection.rb +74 -17
- data/test/test_default_commands/test_ls.rb +9 -36
- data/test/test_default_commands/test_shell.rb +240 -13
- data/test/test_hooks.rb +490 -0
- data/test/test_indent.rb +2 -0
- data/test/test_method.rb +60 -0
- data/test/test_pry.rb +29 -904
- data/test/test_pry_defaults.rb +380 -0
- data/test/test_pry_history.rb +24 -24
- data/test/test_syntax_checking.rb +63 -0
- data/test/test_wrapped_module.rb +71 -0
- metadata +50 -39
- data/lib/pry/command_context.rb +0 -53
- data/lib/pry/command_processor.rb +0 -181
- data/lib/pry/extended_commands/user_command_api.rb +0 -65
- data/test/test_command_processor.rb +0 -176
@@ -1,38 +1,5 @@
|
|
1
1
|
require 'helper'
|
2
2
|
describe "ls" do
|
3
|
-
describe "class_name" do
|
4
|
-
extend Pry::DefaultCommands::Ls.helper_module
|
5
|
-
it "should use the name of the class if it exists" do
|
6
|
-
class_name(Object).should == "Object"
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should use the name of the module if it exists" do
|
10
|
-
class_name(Kernel).should == "Kernel"
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should use Foo.self for singleton classes of classes" do
|
14
|
-
class_name(class << Object; self; end).should == "Object.self"
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should use Foo.self for singleton methods of modules" do
|
18
|
-
class_name(class << Kernel; self; end).should == "Kernel.self"
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should default to the .to_s if that's not possible" do
|
22
|
-
cls = Class.new
|
23
|
-
class_name(cls).should == cls.to_s
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should default to .to_s.self" do
|
27
|
-
cls = Class.new
|
28
|
-
class_name(class << cls; self; end).should == "#{cls.to_s}.self"
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should just be self for singleton classes of normal objects" do
|
32
|
-
class_name(class << "hi"; self; end).should == "self"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
3
|
describe "below ceiling" do
|
37
4
|
it "should stop before Object by default" do
|
38
5
|
mock_pry("cd Class.new{ def goo; end }.new", "ls").should.not =~ /Object/
|
@@ -55,7 +22,13 @@ describe "ls" do
|
|
55
22
|
end
|
56
23
|
end
|
57
24
|
|
58
|
-
describe "
|
25
|
+
describe "help" do
|
26
|
+
it 'should show help with -h' do
|
27
|
+
mock_pry("ls -h").should =~ /Usage: ls/
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "methods" do
|
59
32
|
it "should show public methods by default" do
|
60
33
|
mock_pry("ls Class.new{ def goo; end }.new").should =~ /goo/
|
61
34
|
end
|
@@ -77,7 +50,7 @@ describe "ls" do
|
|
77
50
|
it "should work for objects with an overridden method method" do
|
78
51
|
require 'net/http'
|
79
52
|
# This doesn't actually touch the network, promise!
|
80
|
-
mock_pry("ls Net::HTTP::Get.new('localhost')").should =~ /Net::HTTPGenericRequest
|
53
|
+
mock_pry("ls Net::HTTP::Get.new('localhost')").should =~ /Net::HTTPGenericRequest#methods/
|
81
54
|
end
|
82
55
|
end
|
83
56
|
|
@@ -119,7 +92,7 @@ describe "ls" do
|
|
119
92
|
describe "when no arguments given" do
|
120
93
|
describe "when at the top-level" do
|
121
94
|
# rubinius has a bug that means local_variables of "main" aren't reported inside eval()
|
122
|
-
unless
|
95
|
+
unless Pry::Helpers::BaseHelpers.rbx?
|
123
96
|
it "should show local variables" do
|
124
97
|
mock_pry("ls").should =~ /_pry_/
|
125
98
|
mock_pry("arbitrar = 1", "ls").should =~ /arbitrar/
|
@@ -1,18 +1,243 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe "Pry::DefaultCommands::Shell" do
|
4
|
+
describe "save-file" do
|
5
|
+
before do
|
6
|
+
@tf = Tempfile.new(["pry", ".py"])
|
7
|
+
@path = @tf.path
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
@tf.close(true)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "-f" do
|
15
|
+
it 'should save a file to a file' do
|
16
|
+
f = Tempfile.new(["pry", ".py"])
|
17
|
+
path = f.path
|
18
|
+
f.write ":cute_horse"
|
19
|
+
|
20
|
+
redirect_pry_io(InputTester.new("save-file -f #{path} #{@path}",
|
21
|
+
"exit-all")) do
|
22
|
+
Pry.start(@o)
|
23
|
+
end
|
24
|
+
File.read(@path).should == File.read(path)
|
25
|
+
|
26
|
+
f.close(true)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "-i" do
|
31
|
+
it 'should save input expressions to a file (single expression)' do
|
32
|
+
redirect_pry_io(InputTester.new(":horse_nostrils",
|
33
|
+
"save-file -i 1 #{@path}",
|
34
|
+
"exit-all")) do
|
35
|
+
Pry.start(@o)
|
36
|
+
end
|
37
|
+
File.read(@path).should == ":horse_nostrils\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should save input expressions to a file (range)' do
|
41
|
+
redirect_pry_io(InputTester.new(":horse_nostrils",
|
42
|
+
":sucking_up_all_the_oxygen",
|
43
|
+
"save-file -i 1..2 #{@path}",
|
44
|
+
"exit-all")) do
|
45
|
+
Pry.start(@o)
|
46
|
+
end
|
47
|
+
File.read(@path).should == ":horse_nostrils\n:sucking_up_all_the_oxygen\n"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "-m" do
|
52
|
+
before do
|
53
|
+
@o = Object.new
|
54
|
+
def @o.baby
|
55
|
+
:baby
|
56
|
+
end
|
57
|
+
def @o.bang
|
58
|
+
:bang
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "single method" do
|
63
|
+
it 'should save a method to a file' do
|
64
|
+
redirect_pry_io(InputTester.new("save-file #{@path} -m baby",
|
65
|
+
"exit-all")) do
|
66
|
+
Pry.start(@o)
|
67
|
+
end
|
68
|
+
File.read(@path).should == Pry::Method.from_obj(@o, :baby).source
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should save a method to a file truncated by --lines' do
|
72
|
+
redirect_pry_io(InputTester.new("save-file #{@path} -m baby --lines 2..4",
|
73
|
+
"exit-all")) do
|
74
|
+
Pry.start(@o)
|
75
|
+
end
|
76
|
+
|
77
|
+
# must add 1 as first line of method is 1
|
78
|
+
File.read(@path).should == Pry::Method.from_obj(@o, :baby).source.lines.to_a[1..5].join
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "multiple method" do
|
83
|
+
it 'should save multiple methods to a file' do
|
84
|
+
redirect_pry_io(InputTester.new("save-file #{@path} -m baby -m bang",
|
85
|
+
"exit-all")) do
|
86
|
+
Pry.start(@o)
|
87
|
+
end
|
88
|
+
File.read(@path).should == Pry::Method.from_obj(@o, :baby).source +
|
89
|
+
Pry::Method.from_obj(@o, :bang).source
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should save multiple methods to a file trucated by --lines' do
|
93
|
+
redirect_pry_io(InputTester.new("save-file #{@path} -m baby -m bang --lines 2..-2",
|
94
|
+
"exit-all")) do
|
95
|
+
Pry.start(@o)
|
96
|
+
end
|
97
|
+
|
98
|
+
# must add 1 as first line of method is 1
|
99
|
+
File.read(@path).should == (Pry::Method.from_obj(@o, :baby).source +
|
100
|
+
Pry::Method.from_obj(@o, :bang).source).lines.to_a[1..-2].join
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should save multiple methods to a file trucated by --lines 1 (single parameter, not range)' do
|
104
|
+
redirect_pry_io(InputTester.new("save-file #{@path} -m baby -m bang --lines 1",
|
105
|
+
"exit-all")) do
|
106
|
+
Pry.start(@o)
|
107
|
+
end
|
108
|
+
|
109
|
+
# must add 1 as first line of method is 1
|
110
|
+
File.read(@path).should == (Pry::Method.from_obj(@o, :baby).source +
|
111
|
+
Pry::Method.from_obj(@o, :bang).source).lines.to_a[0]
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "overwrite by default (no --append)" do
|
119
|
+
it 'should overwrite specified file with new input' do
|
120
|
+
redirect_pry_io(InputTester.new(":horse_nostrils",
|
121
|
+
"save-file -i 1 #{@path}",
|
122
|
+
"exit-all")) do
|
123
|
+
Pry.start(@o)
|
124
|
+
end
|
125
|
+
|
126
|
+
redirect_pry_io(InputTester.new(":sucking_up_all_the_oxygen",
|
127
|
+
"save-file -i 1 #{@path}",
|
128
|
+
"exit-all")) do
|
129
|
+
Pry.start(@o)
|
130
|
+
end
|
131
|
+
|
132
|
+
File.read(@path).should == ":sucking_up_all_the_oxygen\n"
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "--append" do
|
138
|
+
it 'should append to end of specified file' do
|
139
|
+
redirect_pry_io(InputTester.new(":horse_nostrils",
|
140
|
+
"save-file -i 1 #{@path}",
|
141
|
+
"exit-all")) do
|
142
|
+
Pry.start(@o)
|
143
|
+
end
|
144
|
+
|
145
|
+
redirect_pry_io(InputTester.new(":sucking_up_all_the_oxygen",
|
146
|
+
"save-file -i 1 #{@path} -a",
|
147
|
+
"exit-all")) do
|
148
|
+
Pry.start(@o)
|
149
|
+
end
|
150
|
+
|
151
|
+
File.read(@path).should == ":horse_nostrils\n:sucking_up_all_the_oxygen\n"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "-c" do
|
156
|
+
it 'should save a command to a file' do
|
157
|
+
redirect_pry_io(InputTester.new("save-file #{@path} -c show-method",
|
158
|
+
"exit-all")) do
|
159
|
+
Pry.start(@o)
|
160
|
+
end
|
161
|
+
cmd = Pry::Method.new(Pry.commands.find_command("show-method").block)
|
162
|
+
File.read(@path).should == Pry::Code.from_method(cmd).to_s
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "combined options" do
|
167
|
+
before do
|
168
|
+
@o = Object.new
|
169
|
+
def @o.baby
|
170
|
+
:baby
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should save input cache and a method to a file (in that order)' do
|
175
|
+
redirect_pry_io(InputTester.new(":horse_nostrils",
|
176
|
+
"save-file -i 1 -m baby #{@path}",
|
177
|
+
"exit-all")) do
|
178
|
+
Pry.start(@o)
|
179
|
+
end
|
180
|
+
File.read(@path).should == ":horse_nostrils\n" + Pry::Method.from_obj(@o, :baby).source
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should select a portion to save using --lines' do
|
184
|
+
redirect_pry_io(InputTester.new(":horse_nostrils",
|
185
|
+
"save-file -i 1 -m baby #{@path} --lines 2..-2",
|
186
|
+
"exit-all")) do
|
187
|
+
Pry.start(@o)
|
188
|
+
end
|
189
|
+
File.read(@path).should == (":horse_nostrils\n" + Pry::Method.from_obj(@o, :baby).source).lines.to_a[1..-2].join
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
4
194
|
describe "cat" do
|
5
195
|
|
6
196
|
describe "on receiving a file that does not exist" do
|
7
197
|
it 'should display an error message' do
|
8
|
-
mock_pry("cat supercalifragilicious66").should =~ /
|
198
|
+
mock_pry("cat supercalifragilicious66").should =~ /Cannot open/
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "with --in" do
|
203
|
+
it 'should display the last few expressions with indices' do
|
204
|
+
output = mock_pry("10", "20", "cat --in")
|
205
|
+
output.should =~ /^1:/
|
206
|
+
output.should =~ /^ 10/
|
207
|
+
output.should =~ /^2:/
|
208
|
+
output.should =~ /^ 20/
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "with --in 1" do
|
213
|
+
it 'should display the first expression with no index' do
|
214
|
+
output = mock_pry("10", "20", "cat --in 1")
|
215
|
+
output.should.not =~ /^\d+:/
|
216
|
+
output.should =~ /^10/
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "with --in -1" do
|
221
|
+
it 'should display the last expression with no index' do
|
222
|
+
output = mock_pry("10", "20", "cat --in -1")
|
223
|
+
output.should.not =~ /^\d+:/
|
224
|
+
output.should =~ /^20/
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "with --in 1..2" do
|
229
|
+
it 'should display the given range with indices, omitting nils' do
|
230
|
+
output = mock_pry("10", "20", "cat --ex", ":hello", "cat --in 1..4")
|
231
|
+
output.should =~ /^1:/
|
232
|
+
output.should.not =~ /^3:/
|
233
|
+
output.should =~ /^ :hello/
|
9
234
|
end
|
10
235
|
end
|
11
236
|
|
12
237
|
# this doesnt work so well on rbx due to differences in backtrace
|
13
238
|
# so we currently skip rbx until we figure out a workaround
|
14
239
|
describe "with --ex" do
|
15
|
-
if !rbx?
|
240
|
+
if !Pry::Helpers::BaseHelpers.rbx?
|
16
241
|
it 'cat --ex should correctly display code that generated exception even if raised in repl' do
|
17
242
|
mock_pry("this raises error", "cat --ex").should =~ /\d+:(\s*) this raises error/
|
18
243
|
end
|
@@ -30,7 +255,7 @@ describe "Pry::DefaultCommands::Shell" do
|
|
30
255
|
temp_file do |f|
|
31
256
|
f << "bt number 1"
|
32
257
|
f.flush
|
33
|
-
pry_instance.last_exception =
|
258
|
+
pry_instance.last_exception = mock_exception("#{f.path}:1", "x", "x")
|
34
259
|
pry_instance.rep(self)
|
35
260
|
end
|
36
261
|
|
@@ -43,7 +268,7 @@ describe "Pry::DefaultCommands::Shell" do
|
|
43
268
|
temp_file do |f|
|
44
269
|
f << "bt number 1"
|
45
270
|
f.flush
|
46
|
-
pry_instance.last_exception =
|
271
|
+
pry_instance.last_exception = mock_exception("#{f.path}:1", "x", "x")
|
47
272
|
pry_instance.rep(self)
|
48
273
|
end
|
49
274
|
|
@@ -56,37 +281,37 @@ describe "Pry::DefaultCommands::Shell" do
|
|
56
281
|
temp_file do |f|
|
57
282
|
f << "bt number 2"
|
58
283
|
f.flush
|
59
|
-
pry_instance.last_exception =
|
284
|
+
pry_instance.last_exception = mock_exception("x", "#{f.path}:1", "x")
|
60
285
|
pry_instance.rep(self)
|
61
286
|
end
|
62
287
|
|
63
288
|
str_output.string.should =~ /bt number 2/
|
64
289
|
end
|
65
290
|
|
66
|
-
it 'should cat third level of backtrace when --ex 2 used
|
291
|
+
it 'should cat third level of backtrace when --ex 2 used' do
|
67
292
|
pry_instance = Pry.new(:input => StringIO.new("cat --ex 2"), :output => str_output = StringIO.new)
|
68
293
|
|
69
294
|
temp_file do |f|
|
70
295
|
f << "bt number 3"
|
71
296
|
f.flush
|
72
|
-
pry_instance.last_exception =
|
297
|
+
pry_instance.last_exception = mock_exception("x", "x", "#{f.path}:1")
|
73
298
|
pry_instance.rep(self)
|
74
299
|
end
|
75
300
|
|
76
301
|
str_output.string.should =~ /bt number 3/
|
77
302
|
end
|
78
303
|
|
79
|
-
it 'should show error when backtrace level out of bounds
|
304
|
+
it 'should show error when backtrace level out of bounds' do
|
80
305
|
pry_instance = Pry.new(:input => StringIO.new("cat --ex 3"), :output => str_output = StringIO.new)
|
81
|
-
pry_instance.last_exception =
|
306
|
+
pry_instance.last_exception = mock_exception("x", "x", "x")
|
82
307
|
pry_instance.rep(self)
|
83
|
-
str_output.string.should =~ /
|
308
|
+
str_output.string.should =~ /out of bounds/
|
84
309
|
end
|
85
310
|
|
86
311
|
it 'each successive cat --ex should show the next level of backtrace, and going past the final level should return to the first' do
|
87
312
|
temp_files = []
|
88
313
|
3.times do |i|
|
89
|
-
temp_files << Tempfile.new(['
|
314
|
+
temp_files << Tempfile.new(['pry', '*.rb'])
|
90
315
|
temp_files.last << "bt number #{i}"
|
91
316
|
temp_files.last.flush
|
92
317
|
end
|
@@ -94,7 +319,7 @@ describe "Pry::DefaultCommands::Shell" do
|
|
94
319
|
pry_instance = Pry.new(:input => StringIO.new("cat --ex\n" * 4),
|
95
320
|
:output => (str_output = StringIO.new))
|
96
321
|
|
97
|
-
pry_instance.last_exception =
|
322
|
+
pry_instance.last_exception = mock_exception(*temp_files.map { |f| "#{f.path}:1" })
|
98
323
|
|
99
324
|
3.times do |i|
|
100
325
|
pry_instance.rep(self)
|
@@ -105,7 +330,9 @@ describe "Pry::DefaultCommands::Shell" do
|
|
105
330
|
pry_instance.rep(self)
|
106
331
|
str_output.string.should =~ /bt number 0/
|
107
332
|
|
108
|
-
temp_files.each
|
333
|
+
temp_files.each do |file|
|
334
|
+
file.close(true)
|
335
|
+
end
|
109
336
|
end
|
110
337
|
|
111
338
|
end
|
data/test/test_hooks.rb
ADDED
@@ -0,0 +1,490 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Pry::Hooks do
|
4
|
+
before do
|
5
|
+
@hooks = Pry::Hooks.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "adding a new hook" do
|
9
|
+
it 'should not execute hook while adding it' do
|
10
|
+
run = false
|
11
|
+
@hooks.add_hook(:test_hook, :my_name) { run = true }
|
12
|
+
run.should == false
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should not allow adding of a hook with a duplicate name' do
|
16
|
+
@hooks.add_hook(:test_hook, :my_name) {}
|
17
|
+
|
18
|
+
lambda { @hooks.add_hook(:test_hook, :my_name) {} }.should.raise ArgumentError
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should create a new hook with a block' do
|
22
|
+
@hooks.add_hook(:test_hook, :my_name) { }
|
23
|
+
@hooks.hook_count(:test_hook).should == 1
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should create a new hook with a callable' do
|
27
|
+
@hooks.add_hook(:test_hook, :my_name, proc { })
|
28
|
+
@hooks.hook_count(:test_hook).should == 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should use block if given both block and callable' do
|
32
|
+
run = false
|
33
|
+
foo = false
|
34
|
+
@hooks.add_hook(:test_hook, :my_name, proc { foo = true }) { run = true }
|
35
|
+
@hooks.hook_count(:test_hook).should == 1
|
36
|
+
@hooks.exec_hook(:test_hook)
|
37
|
+
run.should == true
|
38
|
+
foo.should == false
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should raise if not given a block or any other object' do
|
42
|
+
lambda { @hooks.add_hook(:test_hook, :my_name) }.should.raise ArgumentError
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should create multiple hooks for an event' do
|
46
|
+
@hooks.add_hook(:test_hook, :my_name) {}
|
47
|
+
@hooks.add_hook(:test_hook, :my_name2) {}
|
48
|
+
@hooks.hook_count(:test_hook).should == 2
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should return a count of 0 for an empty hook' do
|
52
|
+
@hooks.hook_count(:test_hook).should == 0
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "Pry::Hooks#merge" do
|
57
|
+
describe "merge!" do
|
58
|
+
it 'should merge in the Pry::Hooks' do
|
59
|
+
h1 = Pry::Hooks.new.add_hook(:test_hook, :testing) {}
|
60
|
+
h2 = Pry::Hooks.new
|
61
|
+
|
62
|
+
h2.merge!(h1)
|
63
|
+
h2.get_hook(:test_hook, :testing).should == h1.get_hook(:test_hook, :testing)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should not share merged elements with original' do
|
67
|
+
h1 = Pry::Hooks.new.add_hook(:test_hook, :testing) {}
|
68
|
+
h2 = Pry::Hooks.new
|
69
|
+
|
70
|
+
h2.merge!(h1)
|
71
|
+
h2.add_hook(:test_hook, :testing2) {}
|
72
|
+
h2.get_hook(:test_hook, :testing2).should.not == h1.get_hook(:test_hook, :testing2)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should NOT overwrite hooks belonging to shared event in receiver' do
|
76
|
+
h1 = Pry::Hooks.new.add_hook(:test_hook, :testing) {}
|
77
|
+
callable = proc {}
|
78
|
+
h2 = Pry::Hooks.new.add_hook(:test_hook, :testing2, callable)
|
79
|
+
|
80
|
+
h2.merge!(h1)
|
81
|
+
h2.get_hook(:test_hook, :testing2).should == callable
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should overwrite identical hook in receiver' do
|
85
|
+
callable1 = proc { :one }
|
86
|
+
h1 = Pry::Hooks.new.add_hook(:test_hook, :testing, callable1)
|
87
|
+
callable2 = proc { :two }
|
88
|
+
h2 = Pry::Hooks.new.add_hook(:test_hook, :testing, callable2)
|
89
|
+
|
90
|
+
h2.merge!(h1)
|
91
|
+
h2.get_hook(:test_hook, :testing).should == callable1
|
92
|
+
h2.hook_count(:test_hook).should == 1
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should preserve hook order' do
|
96
|
+
name = ""
|
97
|
+
h1 = Pry::Hooks.new
|
98
|
+
h1.add_hook(:test_hook, :testing3) { name << "h" }
|
99
|
+
h1.add_hook(:test_hook, :testing4) { name << "n" }
|
100
|
+
|
101
|
+
h2 = Pry::Hooks.new
|
102
|
+
h2.add_hook(:test_hook, :testing1) { name << "j" }
|
103
|
+
h2.add_hook(:test_hook, :testing2) { name << "o" }
|
104
|
+
|
105
|
+
h2.merge!(h1)
|
106
|
+
h2.exec_hook(:test_hook)
|
107
|
+
|
108
|
+
name.should == "john"
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "merge" do
|
112
|
+
it 'should return a fresh, independent instance' do
|
113
|
+
h1 = Pry::Hooks.new.add_hook(:test_hook, :testing) {}
|
114
|
+
h2 = Pry::Hooks.new
|
115
|
+
|
116
|
+
h3 = h2.merge(h1)
|
117
|
+
h3.should.not == h1
|
118
|
+
h3.should.not == h2
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should contain hooks from original instance' do
|
122
|
+
h1 = Pry::Hooks.new.add_hook(:test_hook, :testing) {}
|
123
|
+
h2 = Pry::Hooks.new.add_hook(:test_hook2, :testing) {}
|
124
|
+
|
125
|
+
h3 = h2.merge(h1)
|
126
|
+
h3.get_hook(:test_hook, :testing).should == h1.get_hook(:test_hook, :testing)
|
127
|
+
h3.get_hook(:test_hook2, :testing).should == h2.get_hook(:test_hook2, :testing)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should not affect original instances when new hooks are added' do
|
131
|
+
h1 = Pry::Hooks.new.add_hook(:test_hook, :testing) {}
|
132
|
+
h2 = Pry::Hooks.new.add_hook(:test_hook2, :testing) {}
|
133
|
+
|
134
|
+
h3 = h2.merge(h1)
|
135
|
+
h3.add_hook(:test_hook3, :testing) {}
|
136
|
+
|
137
|
+
h1.get_hook(:test_hook3, :testing).should == nil
|
138
|
+
h2.get_hook(:test_hook3, :testing).should == nil
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "dupping a Pry::Hooks instance" do
|
146
|
+
it 'should share hooks with original' do
|
147
|
+
@hooks.add_hook(:test_hook, :testing) do
|
148
|
+
:none_such
|
149
|
+
end
|
150
|
+
|
151
|
+
hooks_dup = @hooks.dup
|
152
|
+
hooks_dup.get_hook(:test_hook, :testing).should == @hooks.get_hook(:test_hook, :testing)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'adding a new event to dupped instance should not affect original' do
|
156
|
+
@hooks.add_hook(:test_hook, :testing) { :none_such }
|
157
|
+
hooks_dup = @hooks.dup
|
158
|
+
|
159
|
+
hooks_dup.add_hook(:other_test_hook, :testing) { :okay_man }
|
160
|
+
|
161
|
+
hooks_dup.get_hook(:other_test_hook, :testing).should.not == @hooks.get_hook(:other_test_hook, :testing)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'adding a new hook to dupped instance should not affect original' do
|
165
|
+
@hooks.add_hook(:test_hook, :testing) { :none_such }
|
166
|
+
hooks_dup = @hooks.dup
|
167
|
+
|
168
|
+
hooks_dup.add_hook(:test_hook, :testing2) { :okay_man }
|
169
|
+
|
170
|
+
hooks_dup.get_hook(:test_hook, :testing2).should.not == @hooks.get_hook(:test_hook, :testing2)
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "getting hooks" do
|
176
|
+
describe "get_hook" do
|
177
|
+
it 'should return the correct requested hook' do
|
178
|
+
run = false
|
179
|
+
fun = false
|
180
|
+
@hooks.add_hook(:test_hook, :my_name) { run = true }
|
181
|
+
@hooks.add_hook(:test_hook, :my_name2) { fun = true }
|
182
|
+
@hooks.get_hook(:test_hook, :my_name).call
|
183
|
+
run.should == true
|
184
|
+
fun.should == false
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'should return nil if hook does not exist' do
|
188
|
+
@hooks.get_hook(:test_hook, :my_name).should == nil
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "get_hooks" do
|
193
|
+
it 'should return a hash of hook names/hook functions for an event' do
|
194
|
+
hook1 = proc { 1 }
|
195
|
+
hook2 = proc { 2 }
|
196
|
+
@hooks.add_hook(:test_hook, :my_name1, hook1)
|
197
|
+
@hooks.add_hook(:test_hook, :my_name2, hook2)
|
198
|
+
hash = @hooks.get_hooks(:test_hook)
|
199
|
+
hash.size.should == 2
|
200
|
+
hash[:my_name1].should == hook1
|
201
|
+
hash[:my_name2].should == hook2
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'should return an empty hash if no hooks defined' do
|
205
|
+
@hooks.get_hooks(:test_hook).should == {}
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "clearing all hooks for an event" do
|
211
|
+
it 'should clear all hooks' do
|
212
|
+
@hooks.add_hook(:test_hook, :my_name) { }
|
213
|
+
@hooks.add_hook(:test_hook, :my_name2) { }
|
214
|
+
@hooks.add_hook(:test_hook, :my_name3) { }
|
215
|
+
@hooks.clear(:test_hook)
|
216
|
+
@hooks.hook_count(:test_hook).should == 0
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "deleting a hook" do
|
221
|
+
it 'should successfully delete a hook' do
|
222
|
+
@hooks.add_hook(:test_hook, :my_name) {}
|
223
|
+
@hooks.delete_hook(:test_hook, :my_name)
|
224
|
+
@hooks.hook_count(:test_hook).should == 0
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'should return the deleted hook' do
|
228
|
+
run = false
|
229
|
+
@hooks.add_hook(:test_hook, :my_name) { run = true }
|
230
|
+
@hooks.delete_hook(:test_hook, :my_name).call
|
231
|
+
run.should == true
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should return nil if hook does not exist' do
|
235
|
+
@hooks.delete_hook(:test_hook, :my_name).should == nil
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "executing a hook" do
|
240
|
+
it 'should execute block hook' do
|
241
|
+
run = false
|
242
|
+
@hooks.add_hook(:test_hook, :my_name) { run = true }
|
243
|
+
@hooks.exec_hook(:test_hook)
|
244
|
+
run.should == true
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'should execute proc hook' do
|
248
|
+
run = false
|
249
|
+
@hooks.add_hook(:test_hook, :my_name, proc { run = true })
|
250
|
+
@hooks.exec_hook(:test_hook)
|
251
|
+
run.should == true
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'should execute a general callable hook' do
|
255
|
+
callable = Object.new.tap do |obj|
|
256
|
+
obj.instance_variable_set(:@test_var, nil)
|
257
|
+
class << obj
|
258
|
+
attr_accessor :test_var
|
259
|
+
def call() @test_var = true; end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
@hooks.add_hook(:test_hook, :my_name, callable)
|
264
|
+
@hooks.exec_hook(:test_hook)
|
265
|
+
callable.test_var.should == true
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'should execute all hooks for an event if more than one is defined' do
|
269
|
+
x = nil
|
270
|
+
y = nil
|
271
|
+
@hooks.add_hook(:test_hook, :my_name1) { y = true }
|
272
|
+
@hooks.add_hook(:test_hook, :my_name2) { x = true }
|
273
|
+
@hooks.exec_hook(:test_hook)
|
274
|
+
x.should == true
|
275
|
+
y.should == true
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should execute hooks in order' do
|
279
|
+
array = []
|
280
|
+
@hooks.add_hook(:test_hook, :my_name1) { array << 1 }
|
281
|
+
@hooks.add_hook(:test_hook, :my_name2) { array << 2 }
|
282
|
+
@hooks.add_hook(:test_hook, :my_name3) { array << 3 }
|
283
|
+
@hooks.exec_hook(:test_hook)
|
284
|
+
array.should == [1, 2, 3]
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'return value of exec_hook should be that of last executed hook' do
|
288
|
+
@hooks.add_hook(:test_hook, :my_name1) { 1 }
|
289
|
+
@hooks.add_hook(:test_hook, :my_name2) { 2 }
|
290
|
+
@hooks.add_hook(:test_hook, :my_name3) { 3 }
|
291
|
+
@hooks.exec_hook(:test_hook).should == 3
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'should add exceptions to the errors array' do
|
295
|
+
@hooks.add_hook(:test_hook, :foo1) { raise 'one' }
|
296
|
+
@hooks.add_hook(:test_hook, :foo2) { raise 'two' }
|
297
|
+
@hooks.add_hook(:test_hook, :foo3) { raise 'three' }
|
298
|
+
@hooks.exec_hook(:test_hook)
|
299
|
+
@hooks.errors.map(&:message).should == ['one', 'two', 'three']
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'should return the last exception raised as the return value' do
|
303
|
+
@hooks.add_hook(:test_hook, :foo1) { raise 'one' }
|
304
|
+
@hooks.add_hook(:test_hook, :foo2) { raise 'two' }
|
305
|
+
@hooks.add_hook(:test_hook, :foo3) { raise 'three' }
|
306
|
+
@hooks.exec_hook(:test_hook).should == @hooks.errors.last
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
describe "integration tests" do
|
311
|
+
describe "when_started hook" do
|
312
|
+
it 'should yield options to the hook' do
|
313
|
+
options = nil
|
314
|
+
Pry.config.hooks.add_hook(:when_started, :test_hook) { |target, opt, _| options = opt }
|
315
|
+
|
316
|
+
redirect_pry_io(StringIO.new("exit"), out=StringIO.new) do
|
317
|
+
Pry.start binding, :hello => :baby
|
318
|
+
end
|
319
|
+
options[:hello].should == :baby
|
320
|
+
|
321
|
+
Pry.config.hooks.delete_hook(:when_started, :test_hook)
|
322
|
+
end
|
323
|
+
|
324
|
+
describe "target" do
|
325
|
+
|
326
|
+
it 'should yield the target, as a binding ' do
|
327
|
+
b = nil
|
328
|
+
Pry.config.hooks.add_hook(:when_started, :test_hook) { |target, opt, _| b = target }
|
329
|
+
|
330
|
+
redirect_pry_io(StringIO.new("exit"), out=StringIO.new) do
|
331
|
+
Pry.start 5, :hello => :baby
|
332
|
+
end
|
333
|
+
|
334
|
+
b.is_a?(Binding).should == true
|
335
|
+
Pry.config.hooks.delete_hook(:when_started, :test_hook)
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'should yield the target to the hook' do
|
339
|
+
b = nil
|
340
|
+
Pry.config.hooks.add_hook(:when_started, :test_hook) { |target, opt, _| b = target }
|
341
|
+
|
342
|
+
redirect_pry_io(StringIO.new("exit"), out=StringIO.new) do
|
343
|
+
Pry.start 5, :hello => :baby
|
344
|
+
end
|
345
|
+
|
346
|
+
b.eval('self').should == 5
|
347
|
+
Pry.config.hooks.delete_hook(:when_started, :test_hook)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'should allow overriding of target (and binding_stack)' do
|
352
|
+
options = nil
|
353
|
+
o = Object.new
|
354
|
+
class << o; attr_accessor :value; end
|
355
|
+
|
356
|
+
Pry.config.hooks.add_hook(:when_started, :test_hook) { |target, opt, _pry_| _pry_.binding_stack = [Pry.binding_for(o)] }
|
357
|
+
|
358
|
+
redirect_pry_io(InputTester.new("@value = true","exit-all")) do
|
359
|
+
Pry.start binding, :hello => :baby
|
360
|
+
end
|
361
|
+
|
362
|
+
o.value.should == true
|
363
|
+
Pry.config.hooks.delete_hook(:when_started, :test_hook)
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
|
368
|
+
describe "after_session hook" do
|
369
|
+
it 'should always run, even if uncaught exception bubbles out of repl' do
|
370
|
+
o = OpenStruct.new
|
371
|
+
o.great_escape = Class.new(StandardError)
|
372
|
+
|
373
|
+
old_ew = Pry.config.exception_whitelist
|
374
|
+
Pry.config.exception_whitelist << o.great_escape
|
375
|
+
|
376
|
+
array = [1, 2, 3, 4, 5]
|
377
|
+
|
378
|
+
begin
|
379
|
+
redirect_pry_io(StringIO.new("raise great_escape"), out=StringIO.new) do
|
380
|
+
Pry.start o, :hooks => Pry::Hooks.new.add_hook(:after_session, :cleanup) { array = nil }
|
381
|
+
end
|
382
|
+
rescue => ex
|
383
|
+
exception = ex
|
384
|
+
end
|
385
|
+
|
386
|
+
# ensure that an exception really was raised and it broke out
|
387
|
+
# of the repl
|
388
|
+
exception.is_a?(o.great_escape).should == true
|
389
|
+
|
390
|
+
# check that after_session hook ran
|
391
|
+
array.should == nil
|
392
|
+
|
393
|
+
# cleanup after test
|
394
|
+
Pry.config.exception_whitelist = old_ew
|
395
|
+
end
|
396
|
+
|
397
|
+
describe "exceptions" do
|
398
|
+
before do
|
399
|
+
Pry.config.hooks.add_hook(:after_eval, :baddums){ raise "Baddums" }
|
400
|
+
Pry.config.hooks.add_hook(:after_eval, :simbads){ raise "Simbads" }
|
401
|
+
end
|
402
|
+
|
403
|
+
after do
|
404
|
+
Pry.config.hooks.delete_hook(:after_eval, :baddums)
|
405
|
+
Pry.config.hooks.delete_hook(:after_eval, :simbads)
|
406
|
+
end
|
407
|
+
it "should not raise exceptions" do
|
408
|
+
lambda{
|
409
|
+
mock_pry("1", "2", "3")
|
410
|
+
}.should.not.raise
|
411
|
+
end
|
412
|
+
|
413
|
+
it "should print out a notice for each exception raised" do
|
414
|
+
mock_pry("1").should =~ /after_eval hook failed: RuntimeError: Baddums\n.*after_eval hook failed: RuntimeError: Simbads/m
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
describe "anonymous hooks" do
|
421
|
+
it 'should allow adding of hook without a name' do
|
422
|
+
@hooks.add_hook(:test_hook, nil) {}
|
423
|
+
@hooks.hook_count(:test_hook).should == 1
|
424
|
+
end
|
425
|
+
|
426
|
+
it 'should only allow one anonymous hook to exist' do
|
427
|
+
@hooks.add_hook(:test_hook, nil) { }
|
428
|
+
@hooks.add_hook(:test_hook, nil) { }
|
429
|
+
@hooks.hook_count(:test_hook).should == 1
|
430
|
+
end
|
431
|
+
|
432
|
+
it 'should execute most recently added anonymous hook' do
|
433
|
+
x = nil
|
434
|
+
y = nil
|
435
|
+
@hooks.add_hook(:test_hook, nil) { y = 1 }
|
436
|
+
@hooks.add_hook(:test_hook, nil) { x = 2 }
|
437
|
+
@hooks.exec_hook(:test_hook)
|
438
|
+
y.should == nil
|
439
|
+
x.should == 2
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
describe "deprecated hash-based API" do
|
444
|
+
after do
|
445
|
+
Pry.config.hooks.clear_all if Pry.config.hooks
|
446
|
+
end
|
447
|
+
|
448
|
+
describe "Pry.config.hooks" do
|
449
|
+
it 'should allow a hash-assignment' do
|
450
|
+
Pry.config.hooks = { :before_session => proc { :hello } }
|
451
|
+
Pry.config.hooks.get_hook(:before_session, nil).call.should == :hello
|
452
|
+
end
|
453
|
+
|
454
|
+
describe "Pry.config.hooks[]" do
|
455
|
+
it 'should return the only anonymous hook' do
|
456
|
+
Pry.config.hooks = { :before_session => proc { :hello } }
|
457
|
+
Pry.config.hooks[:before_session].call.should == :hello
|
458
|
+
end
|
459
|
+
|
460
|
+
it 'should add an anonymous hook when using Pry.config.hooks[]=' do
|
461
|
+
Pry.config.hooks[:before_session] = proc { :bing }
|
462
|
+
Pry.config.hooks.hook_count(:before_session).should == 1
|
463
|
+
end
|
464
|
+
|
465
|
+
it 'should add overwrite previous anonymous hooks with new one when calling Pry.config.hooks[]= multiple times' do
|
466
|
+
x = nil
|
467
|
+
Pry.config.hooks[:before_session] = proc { x = 1 }
|
468
|
+
Pry.config.hooks[:before_session] = proc { x = 2 }
|
469
|
+
|
470
|
+
Pry.config.hooks.exec_hook(:before_session)
|
471
|
+
Pry.config.hooks.hook_count(:before_session).should == 1
|
472
|
+
x.should == 2
|
473
|
+
end
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
describe "Pry.start" do
|
478
|
+
it 'should accept a hash for :hooks parameter' do
|
479
|
+
|
480
|
+
redirect_pry_io(InputTester.new("exit-all"), out=StringIO.new) do
|
481
|
+
Pry.start binding, :hooks => { :before_session => proc { |output, _, _| output.puts 'hello friend' } }
|
482
|
+
end
|
483
|
+
|
484
|
+
out.string.should =~ /hello friend/
|
485
|
+
end
|
486
|
+
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
end
|