forked from davejacobs/letters
/
core_ext_spec.rb
279 lines (237 loc) · 8.11 KB
/
core_ext_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
require "spec_helper"
module Letters
describe CoreExt do
let(:hash) { Hash.new }
before do
@old_dir = Dir.getwd
FileUtils.mkdir_p "tmp"
Dir.chdir "tmp"
end
after do
Dir.chdir @old_dir
FileUtils.rm_rf "tmp"
end
it "all letter methods but #e, #k and #n return the original object" do
# Prevent output and debugging
Helpers.should_receive(:call_debugger).any_number_of_times
$stdout.should_receive(:puts).any_number_of_times
hash.should_receive(:system).any_number_of_times
Helpers.should_receive(:change_safety).any_number_of_times
("a".."z").to_a.reject do |letter|
letter =~ /[ekjn]/
end.select do |letter|
hash.respond_to? letter
end.each do |letter|
hash.send(letter).should == hash
end
# Methods that can take a block
hash.j { nil }.should == hash
hash.o { nil }.should == hash
end
describe "#a (assert)" do
it "jumps into the receiver's calling context" do
lambda do
[1, 2, 3].a { count }
end.should_not raise_error
end
it "raises a Letters::AssertionError if the block returns false" do
lambda do
[1, 2, 3].a { count > 3 }
end.should raise_error(Letters::AssertionError)
end
it "raises a Letters::AssertionError if the block returns nil" do
lambda do
[1, 2, 3].a { nil }
end.should raise_error(Letters::AssertionError)
end
it "does nothing if the block returns a truthy value" do
[1, 2, 3].a { count < 4 }.should == [1, 2, 3]
end
end
describe "#c (callstack)" do
it "outputs the current call trace then returns the object" do
$stdout.should_receive(:puts).with kind_of String
hash.c
end
end
describe "#d (debug)" do
it "enters the debugger and then returns the object" do
Helpers.should_receive(:call_debugger)
hash.d
end
end
describe "#d1, #d2 (smart object diff)" do
it "outputs the difference between two arrays" do
arr1, arr2 = [1, 2, 3], [3, 4, 5]
expected_diff = Helpers.diff(arr1, arr2)
$stdout.should_receive(:puts).with(expected_diff.awesome_inspect).once
arr1.d1.should == arr1
arr2.d2.should == arr2
end
end
describe "#e (empty check)" do
it "raises an error if the receiver is empty" do
lambda { "".e }.should raise_error(EmptyError)
end
it "does nothing if the receiver is not empty" do
lambda { "string".e }.should_not raise_error
"string".n.should == "string"
end
end
describe "#f (file)" do
describe "when no filename or output format are given" do
it "writes the object as YAML to a file named 'log'" do
File.exist?("log").should_not be_true
hash.f
File.exist?("log").should be_true
File.read("log").should == hash.to_yaml
end
end
describe "when a file name, but no output format is given" do
it "writes the object as YAML to the named file" do
hash.f(:name => "object")
File.exist?("object").should be_true
File.read("object").should == hash.to_yaml
end
end
describe "when an output format, but no file name is given" do
it "writes the object as that format to a file named 'log'" do
hash.f(:format => :ap)
File.exist?("log").should be_true
File.read("log").chomp.should == hash.awesome_inspect
end
end
describe "when 'log' is a directory" do
before { FileUtils.mkdir "log" }
after { FileUtils.rm_rf "log" }
it "appends the first integer that de-dupes the name" do
File.exist?("log1").should be_false
lambda { hash.f }.should_not raise_error
File.exist?("log1").should be_true
end
end
end
describe "#j (jump)" do
it "jumps into the object's context" do
a = nil
hash.j { a = count }
a.should == 0
end
it "allows for IO, even in object context" do
$stdout.should_receive(:puts).with(0)
hash.j { puts count }
end
end
describe "#k (kill)" do
it 'raises a KillError immediately by default' do
lambda { hash.k }.should raise_error(KillError)
end
it 'does not raises if number of calls are below max' do
lambda{ hash.k(max: 1) }.should_not raise_error
end
it 'raises a KillError if number of calls is above max' do
h, count = hash, 0
lambda{
10.times{ h.k(max: 5); count += 1; }
}.should raise_error(KillError)
count.should eq(5)
end
end
describe "#l (log)" do
it "logs the object if a logger is present and then returns the object" do
logger = double 'logger'
logger.should_receive(:info).with(hash.to_yaml)
hash.should_receive(:logger).and_return(logger)
hash.l
end
it "prints an warning if a logger is not present and then returns the object" do
$stdout.should_receive(:puts).with("[warning] No logger available")
hash.l
end
it "logs the object if a logger is present and then returns the object" do
logger = double 'logger'
logger.should_receive(:info).never
logger.should_receive(:error).with(hash.to_yaml)
hash.should_receive(:logger).and_return(logger)
hash.l(:level => "error")
end
end
describe "#m (mark object as tainted/untainted)" do
it "with no argument or `true`, marks the receiver as tainted" do
lambda do
hash.m
end.should change { hash.tainted? }.from(false).to(true)
end
it "when passed `false`, marks the receiver as untainted" do
hash.taint
lambda do
hash.m(false)
end.should change { hash.tainted? }.from(true).to(false)
end
end
describe "#n (nil check)" do
it "raises an error if the receiver is nil" do
lambda { nil.n }.should raise_error(NilError)
end
it "does nothing if the receiver is not nil" do
lambda { hash.n }.should_not raise_error
end
end
describe "#o (print)" do
describe "when no format is given" do
it "writes the object as awesome_print to STDOUT" do
$stdout.should_receive(:puts).with(hash.awesome_inspect)
hash.o
end
end
describe "when a format is given" do
it "writes the object as that format to STDOUT" do
$stdout.should_receive(:puts).with(hash.to_yaml)
hash.o(:format => :yaml)
end
end
describe "when a block is given" do
it "write the result of the block, executed in the object's context" do
$stdout.should_receive(:puts).with(hash.length.awesome_inspect)
hash.o { length }.should == hash
end
end
end
describe "#r (ri)" do
it "displays RI information for the receiver's class, if available" do
hash.should_receive(:system).with("ri Hash")
hash.r
end
it "can narrow its scope to a single method" do
hash.should_receive(:system).with("ri Hash#new")
hash.r(:new)
end
end
describe "#s (safety)" do
it "without argument, bumps the safety level by one" do
Helpers.should_receive(:change_safety).with(1)
hash.s
end
it "bumps the safety level to the specified level if possible" do
Helpers.should_receive(:change_safety).with(4)
hash.s(4)
end
it "throws an exception if the specified level is invalid" do
# Simulate changing safety level from higher level
Helpers.should_receive(:change_safety).with(3).and_raise
lambda do
hash.s(3)
end.should raise_error
end
end
describe "#t (timestamp)" do
it "without :stream, prints the current time to STDOUT" do
time = Time.now
Timecop.freeze(time) do
$stdout.should_receive(:puts).with(time.to_s(:millis)).twice
{}.t.select {|k,v| k =~ /foo/ }.t
end
end
end
end
end