image_resizer 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +45 -0
- data/LICENSE +22 -0
- data/README.md +56 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/image_resizer.gemspec +93 -0
- data/lib/image_resizer/analyzer.rb +51 -0
- data/lib/image_resizer/configurable.rb +206 -0
- data/lib/image_resizer/encoder.rb +55 -0
- data/lib/image_resizer/has_filename.rb +24 -0
- data/lib/image_resizer/loggable.rb +28 -0
- data/lib/image_resizer/processor.rb +220 -0
- data/lib/image_resizer/shell.rb +48 -0
- data/lib/image_resizer/temp_object.rb +216 -0
- data/lib/image_resizer/utils.rb +44 -0
- data/lib/image_resizer.rb +10 -0
- data/samples/DSC02119.JPG +0 -0
- data/samples/a.jp2 +0 -0
- data/samples/beach.jpg +0 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/landscape.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/sample.docx +0 -0
- data/samples/taj.jpg +0 -0
- data/samples/white pixel.png +0 -0
- data/spec/image_resizer/analyzer_spec.rb +78 -0
- data/spec/image_resizer/configurable_spec.rb +479 -0
- data/spec/image_resizer/encoder_spec.rb +41 -0
- data/spec/image_resizer/has_filename_spec.rb +88 -0
- data/spec/image_resizer/loggable_spec.rb +80 -0
- data/spec/image_resizer/processor_spec.rb +590 -0
- data/spec/image_resizer/shell_spec.rb +34 -0
- data/spec/image_resizer/temp_object_spec.rb +442 -0
- data/spec/spec_helper.rb +61 -0
- data/spec/support/argument_matchers.rb +19 -0
- data/spec/support/image_matchers.rb +58 -0
- data/spec/support/simple_matchers.rb +53 -0
- data/tmp/test_file +1 -0
- metadata +147 -0
@@ -0,0 +1,442 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ImageResizer::TempObject do
|
4
|
+
|
5
|
+
####### Helper Methods #######
|
6
|
+
|
7
|
+
def sample_path(filename)
|
8
|
+
SAMPLES_DIR.join(filename)
|
9
|
+
end
|
10
|
+
|
11
|
+
def new_tempfile(data='HELLO')
|
12
|
+
tempfile = Tempfile.new('test')
|
13
|
+
tempfile.write(data)
|
14
|
+
tempfile.rewind
|
15
|
+
tempfile
|
16
|
+
end
|
17
|
+
|
18
|
+
def new_file(data='HELLO', path="tmp/test_file")
|
19
|
+
File.open(path, 'w') do |f|
|
20
|
+
f.write(data)
|
21
|
+
end
|
22
|
+
File.new(path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def new_pathname(data='HELLO', path="tmp/test_file")
|
26
|
+
File.open(path, 'w') do |f|
|
27
|
+
f.write(data)
|
28
|
+
end
|
29
|
+
Pathname.new(path)
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_temp_object(data, klass=ImageResizer::TempObject)
|
33
|
+
klass.new(initialization_object(data))
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialization_object(data)
|
37
|
+
raise NotImplementedError, "This should be implemented in the describe block!"
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_parts(temp_object)
|
41
|
+
parts = []
|
42
|
+
temp_object.each do |bytes|
|
43
|
+
parts << bytes
|
44
|
+
end
|
45
|
+
parts.length.should >= 2 # Sanity check to check that the sample file is adequate for this test
|
46
|
+
parts
|
47
|
+
end
|
48
|
+
|
49
|
+
###############################
|
50
|
+
|
51
|
+
it "should raise an error if initialized with a non-string/file/tempfile" do
|
52
|
+
lambda{
|
53
|
+
ImageResizer::TempObject.new(3)
|
54
|
+
}.should raise_error(ArgumentError)
|
55
|
+
end
|
56
|
+
|
57
|
+
shared_examples_for "common behaviour" do
|
58
|
+
|
59
|
+
describe "simple initialization" do
|
60
|
+
|
61
|
+
before(:each) do
|
62
|
+
@temp_object = new_temp_object('HELLO')
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "data" do
|
66
|
+
it "should return the data correctly" do
|
67
|
+
@temp_object.data.should == 'HELLO'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "file" do
|
72
|
+
it "should return a readable file" do
|
73
|
+
@temp_object.file.should be_a(File)
|
74
|
+
end
|
75
|
+
it "should contain the correct data" do
|
76
|
+
@temp_object.file.read.should == 'HELLO'
|
77
|
+
end
|
78
|
+
it "should yield a file then close it if a block is given" do
|
79
|
+
@temp_object.file do |f|
|
80
|
+
f.read.should == 'HELLO'
|
81
|
+
f.should_receive :close
|
82
|
+
end
|
83
|
+
end
|
84
|
+
it "should return whatever is returned from the block if a block is given" do
|
85
|
+
@temp_object.file do |f|
|
86
|
+
'doogie'
|
87
|
+
end.should == 'doogie'
|
88
|
+
end
|
89
|
+
it "should enable reading the file twice" do
|
90
|
+
@temp_object.file{|f| f.read }.should == "HELLO"
|
91
|
+
@temp_object.file{|f| f.read }.should == "HELLO"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "tempfile" do
|
96
|
+
it "should create a closed tempfile" do
|
97
|
+
@temp_object.tempfile.should be_a(Tempfile)
|
98
|
+
@temp_object.tempfile.should be_closed
|
99
|
+
end
|
100
|
+
it "should contain the correct data" do
|
101
|
+
@temp_object.tempfile.open.read.should == 'HELLO'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "path" do
|
106
|
+
it "should return an absolute file path" do
|
107
|
+
if running_on_windows?
|
108
|
+
@temp_object.path.should =~ %r{^[a-zA-Z]:/\w+}
|
109
|
+
else
|
110
|
+
@temp_object.path.should =~ %r{^/\w+}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "size" do
|
116
|
+
it "should return the size in bytes" do
|
117
|
+
@temp_object.size.should == 5
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "to_file" do
|
122
|
+
before(:each) do
|
123
|
+
@filename = 'tmp/eggnog.txt'
|
124
|
+
FileUtils.rm_f(@filename) if File.exists?(@filename)
|
125
|
+
end
|
126
|
+
after(:each) do
|
127
|
+
FileUtils.rm_f(@filename) if File.exists?(@filename)
|
128
|
+
end
|
129
|
+
it "should write to a file" do
|
130
|
+
@temp_object.to_file(@filename)
|
131
|
+
File.exists?(@filename).should be_true
|
132
|
+
end
|
133
|
+
it "should write the correct data to the file" do
|
134
|
+
@temp_object.to_file(@filename)
|
135
|
+
File.read(@filename).should == 'HELLO'
|
136
|
+
end
|
137
|
+
it "should return a readable file" do
|
138
|
+
file = @temp_object.to_file(@filename)
|
139
|
+
file.should be_a(File)
|
140
|
+
file.read.should == 'HELLO'
|
141
|
+
end
|
142
|
+
it "should have 644 permissions" do
|
143
|
+
@temp_object.to_file(@filename)
|
144
|
+
File::Stat.new(@filename).mode.to_s(8).should =~ /644$/
|
145
|
+
end
|
146
|
+
it "should allow setting different permissions" do
|
147
|
+
@temp_object.to_file(@filename, :mode => 0755)
|
148
|
+
File::Stat.new(@filename).mode.to_s(8).should =~ /755$/
|
149
|
+
end
|
150
|
+
it "should create intermediate subdirs" do
|
151
|
+
filename = 'tmp/gog/mcgee'
|
152
|
+
@temp_object.to_file(filename)
|
153
|
+
File.exists?(filename).should be_true
|
154
|
+
FileUtils.rm_rf('tmp/gog')
|
155
|
+
end
|
156
|
+
it "should allow not creating intermediate subdirs" do
|
157
|
+
filename = 'tmp/gog/mcgee'
|
158
|
+
expect{ @temp_object.to_file(filename, :mkdirs => false) }.to raise_error()
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "each" do
|
165
|
+
it "should yield 8192 bytes each time" do
|
166
|
+
temp_object = new_temp_object(File.read(sample_path('round.gif')))
|
167
|
+
parts = get_parts(temp_object)
|
168
|
+
parts[0...-1].each do |part|
|
169
|
+
part.bytesize.should == 8192
|
170
|
+
end
|
171
|
+
parts.last.bytesize.should <= 8192
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "closing" do
|
176
|
+
before(:each) do
|
177
|
+
@temp_object = new_temp_object("wassup")
|
178
|
+
end
|
179
|
+
it "should delete its tempfile" do
|
180
|
+
tempfile = @temp_object.tempfile
|
181
|
+
path = tempfile.path
|
182
|
+
path.should_not be_empty
|
183
|
+
@temp_object.close
|
184
|
+
File.exist?(path).should be_false
|
185
|
+
end
|
186
|
+
%w(tempfile file data).each do |method|
|
187
|
+
it "should raise error when calling #{method}" do
|
188
|
+
@temp_object.close
|
189
|
+
expect{
|
190
|
+
@temp_object.send(method)
|
191
|
+
}.to raise_error(ImageResizer::TempObject::Closed)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
it "should not report itself as closed to begin with" do
|
195
|
+
@temp_object.should_not be_closed
|
196
|
+
end
|
197
|
+
it "should report itself as closed after closing" do
|
198
|
+
@temp_object.close
|
199
|
+
@temp_object.should be_closed
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "initializing from a string" do
|
206
|
+
|
207
|
+
def initialization_object(data)
|
208
|
+
data
|
209
|
+
end
|
210
|
+
|
211
|
+
it_should_behave_like "common behaviour"
|
212
|
+
|
213
|
+
it "should not create a file when calling each" do
|
214
|
+
temp_object = new_temp_object('HELLO')
|
215
|
+
temp_object.should_not_receive(:tempfile)
|
216
|
+
temp_object.each{}
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should use set the file extension in path from the name" do
|
220
|
+
temp_object = ImageResizer::TempObject.new("hi", :name => 'dark.cloud')
|
221
|
+
temp_object.path.should =~ /\.cloud$/
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe "initializing from a tempfile" do
|
226
|
+
|
227
|
+
def initialization_object(data)
|
228
|
+
new_tempfile(data)
|
229
|
+
end
|
230
|
+
|
231
|
+
it_should_behave_like "common behaviour"
|
232
|
+
|
233
|
+
it "should not create a data string when calling each" do
|
234
|
+
temp_object = new_temp_object('HELLO')
|
235
|
+
temp_object.should_not_receive(:data)
|
236
|
+
temp_object.each{}
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should return the tempfile's path" do
|
240
|
+
temp_object = new_temp_object('HELLO')
|
241
|
+
temp_object.path.should == temp_object.tempfile.path
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe "initializing from a file" do
|
246
|
+
|
247
|
+
def initialization_object(data)
|
248
|
+
new_file(data)
|
249
|
+
end
|
250
|
+
|
251
|
+
it_should_behave_like "common behaviour"
|
252
|
+
|
253
|
+
it "should not create a data string when calling each" do
|
254
|
+
temp_object = new_temp_object('HELLO')
|
255
|
+
temp_object.should_not_receive(:data)
|
256
|
+
temp_object.each{}
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should return the file's path" do
|
260
|
+
file = new_file('HELLO')
|
261
|
+
temp_object = ImageResizer::TempObject.new(file)
|
262
|
+
temp_object.path.should == File.expand_path(file.path)
|
263
|
+
end
|
264
|
+
|
265
|
+
it "should return an absolute path even if the file wasn't instantiated like that" do
|
266
|
+
file = new_file('HELLO', 'tmp/bongo')
|
267
|
+
temp_object = ImageResizer::TempObject.new(file)
|
268
|
+
if running_on_windows?
|
269
|
+
temp_object.path.should =~ %r{^[a-zA-Z]:/\w.*bongo}
|
270
|
+
else
|
271
|
+
temp_object.path.should =~ %r{^/\w.*bongo}
|
272
|
+
end
|
273
|
+
file.close
|
274
|
+
FileUtils.rm(file.path)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "initializing from a pathname" do
|
279
|
+
|
280
|
+
def initialization_object(data)
|
281
|
+
new_pathname(data)
|
282
|
+
end
|
283
|
+
|
284
|
+
it_should_behave_like "common behaviour"
|
285
|
+
|
286
|
+
it "should not create a data string when calling each" do
|
287
|
+
temp_object = new_temp_object('HELLO')
|
288
|
+
temp_object.should_not_receive(:data)
|
289
|
+
temp_object.each{}
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should return the file's path" do
|
293
|
+
pathname = new_pathname('HELLO')
|
294
|
+
temp_object = ImageResizer::TempObject.new(pathname)
|
295
|
+
temp_object.path.should == File.expand_path(pathname.to_s)
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should return an absolute path even if the pathname is relative" do
|
299
|
+
pathname = new_pathname('HELLO', 'tmp/bingo')
|
300
|
+
temp_object = ImageResizer::TempObject.new(pathname)
|
301
|
+
if running_on_windows?
|
302
|
+
temp_object.path.should =~ %r{^[a-zA-Z]:/\w.*bingo}
|
303
|
+
else
|
304
|
+
temp_object.path.should =~ %r{^/\w.*bingo}
|
305
|
+
end
|
306
|
+
pathname.delete
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
describe "initializing from another temp object" do
|
311
|
+
|
312
|
+
def initialization_object(data)
|
313
|
+
ImageResizer::TempObject.new(data)
|
314
|
+
end
|
315
|
+
|
316
|
+
before(:each) do
|
317
|
+
@temp_object1 = ImageResizer::TempObject.new(new_tempfile('hello'))
|
318
|
+
@temp_object2 = ImageResizer::TempObject.new(@temp_object1)
|
319
|
+
end
|
320
|
+
|
321
|
+
it_should_behave_like "common behaviour"
|
322
|
+
|
323
|
+
it "should not be the same object" do
|
324
|
+
@temp_object1.should_not == @temp_object2
|
325
|
+
end
|
326
|
+
it "should have the same data" do
|
327
|
+
@temp_object1.data.should == @temp_object2.data
|
328
|
+
end
|
329
|
+
it "should have the same file path" do
|
330
|
+
@temp_object1.path.should == @temp_object2.path
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
describe "initialize from a Rack::Test::UploadedFile" do
|
335
|
+
def initialization_object(data)
|
336
|
+
# The criteria we're using to determine if an object is a
|
337
|
+
# Rack::Test::UploadedFile is if it responds to path
|
338
|
+
#
|
339
|
+
# We can't just check if it is_a?(Rack::Test::UploadedFile) because that
|
340
|
+
# class may not always be present.
|
341
|
+
uploaded_file = mock("mock_uploadedfile")
|
342
|
+
uploaded_file.stub!(:path).and_return File.expand_path('tmp/test_file')
|
343
|
+
uploaded_file.stub!(:original_filename).and_return('foo.jpg')
|
344
|
+
|
345
|
+
# Create a real file with the contents required at the correct path
|
346
|
+
new_file(data, 'tmp/test_file')
|
347
|
+
|
348
|
+
uploaded_file
|
349
|
+
end
|
350
|
+
|
351
|
+
it_should_behave_like "common behaviour"
|
352
|
+
end
|
353
|
+
|
354
|
+
describe "original_filename" do
|
355
|
+
before(:each) do
|
356
|
+
@obj = new_tempfile
|
357
|
+
end
|
358
|
+
it "should set the original_filename if the initial object responds to 'original filename'" do
|
359
|
+
def @obj.original_filename
|
360
|
+
'jimmy.page'
|
361
|
+
end
|
362
|
+
ImageResizer::TempObject.new(@obj).original_filename.should == 'jimmy.page'
|
363
|
+
end
|
364
|
+
it "should not set the name if the initial object doesn't respond to 'original filename'" do
|
365
|
+
ImageResizer::TempObject.new(@obj).original_filename.should be_nil
|
366
|
+
end
|
367
|
+
it "should set the name if the initial object is a file object" do
|
368
|
+
file = File.new(SAMPLES_DIR.join('round.gif'))
|
369
|
+
temp_object = ImageResizer::TempObject.new(file)
|
370
|
+
temp_object.original_filename.should == 'round.gif'
|
371
|
+
end
|
372
|
+
it "should set the name if the initial object is a pathname" do
|
373
|
+
pathname = Pathname.new(SAMPLES_DIR + '/round.gif')
|
374
|
+
temp_object = ImageResizer::TempObject.new(pathname)
|
375
|
+
temp_object.original_filename.should == 'round.gif'
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
describe "meta" do
|
380
|
+
it "should default to an empty hash" do
|
381
|
+
ImageResizer::TempObject.new('sdf').meta.should == {}
|
382
|
+
end
|
383
|
+
it "should allow setting on initialize" do
|
384
|
+
ImageResizer::TempObject.new('sdf', :dub => 'wub').meta.should == {:dub => 'wub'}
|
385
|
+
end
|
386
|
+
it "should allow setting" do
|
387
|
+
temp_object = ImageResizer::TempObject.new('boo')
|
388
|
+
temp_object.meta = {:far => 'gone'}
|
389
|
+
temp_object.meta.should == {:far => 'gone'}
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
describe "name" do
|
394
|
+
it "should default to nil" do
|
395
|
+
ImageResizer::TempObject.new("HELLO").name.should be_nil
|
396
|
+
end
|
397
|
+
it "should allow setting the name via the meta" do
|
398
|
+
ImageResizer::TempObject.new("HELLO", :name => 'gosh.pig').name.should == "gosh.pig"
|
399
|
+
end
|
400
|
+
it "should fallback to the original filename if not set" do
|
401
|
+
content = "HELLO"
|
402
|
+
content.should_receive(:original_filename).and_return("some.egg")
|
403
|
+
temp_object = ImageResizer::TempObject.new(content)
|
404
|
+
temp_object.name.should == "some.egg"
|
405
|
+
end
|
406
|
+
it "should prefer the specified name to the original filename" do
|
407
|
+
content = "HELLO"
|
408
|
+
content.stub!(:original_filename).and_return("brase.nose")
|
409
|
+
temp_object = ImageResizer::TempObject.new("HELLO", :name => 'some.gug')
|
410
|
+
temp_object.name.should == "some.gug"
|
411
|
+
end
|
412
|
+
it "should allow setting with a setter" do
|
413
|
+
temp_object = ImageResizer::TempObject.new("HELLO")
|
414
|
+
temp_object.name = 'bugs'
|
415
|
+
temp_object.name.should == "bugs"
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
describe "sanity check for using HasFilename" do
|
420
|
+
it "should act like ImageResizer::HasFilename" do
|
421
|
+
temp_object = ImageResizer::TempObject.new('h', :name => 'one.big.park')
|
422
|
+
temp_object.ext = 'smeagol'
|
423
|
+
temp_object.name.should == 'one.big.smeagol'
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
describe "unique_id" do
|
428
|
+
before(:each) do
|
429
|
+
@temp_object = ImageResizer::TempObject.new('hello')
|
430
|
+
end
|
431
|
+
it "should return a unique id" do
|
432
|
+
@temp_object.unique_id.should =~ /^\d+$/
|
433
|
+
end
|
434
|
+
it "should be unique" do
|
435
|
+
@temp_object.unique_id.should_not == ImageResizer::TempObject.new('hello').unique_id
|
436
|
+
end
|
437
|
+
it "should not change" do
|
438
|
+
@temp_object.unique_id.should == @temp_object.unique_id
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
3
|
+
Bundler.setup(:default, :test)
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'rspec'
|
8
|
+
require 'image_resizer'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'pry'
|
11
|
+
require 'pry-nav'
|
12
|
+
require 'pry-stack_explorer'
|
13
|
+
|
14
|
+
# Requires supporting files with custom matchers and macros, etc,
|
15
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
16
|
+
|
17
|
+
SAMPLES_DIR = Pathname.new(File.expand_path(File.dirname(__FILE__) + '/../samples')) unless defined?(SAMPLES_DIR)
|
18
|
+
|
19
|
+
def todo
|
20
|
+
raise "TODO"
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# require 'logger'
|
25
|
+
# LOG_FILE = 'tmp/test.log' unless defined?(LOG_FILE)
|
26
|
+
# FileUtils.rm_rf(LOG_FILE)
|
27
|
+
# def mock_app(extra_stubs={})
|
28
|
+
# mock('app', {
|
29
|
+
# :datastore => mock('datastore', :store => 'some_uid', :retrieve => ["SOME_DATA", {}], :destroy => nil),
|
30
|
+
# :processor => mock('processor', :process => "SOME_PROCESSED_DATA"),
|
31
|
+
# :encoder => mock('encoder', :encode => "SOME_ENCODED_DATA"),
|
32
|
+
# :analyzer => mock('analyzer', :analyse => "some_result", :analysis_methods => Module.new),
|
33
|
+
# :generator => mock('generator', :generate => "SOME_GENERATED_DATA"),
|
34
|
+
# :log => Logger.new(LOG_FILE),
|
35
|
+
# :cache_duration => 10000,
|
36
|
+
# :job_definitions => Module.new
|
37
|
+
# }.merge(extra_stubs)
|
38
|
+
# )
|
39
|
+
# end
|
40
|
+
|
41
|
+
# def test_app
|
42
|
+
# time = Time.now
|
43
|
+
# app = ImageResizer::App.send(:new, "test_#{time.sec}_#{time.usec}".to_sym)
|
44
|
+
# app.log = Logger.new(LOG_FILE)
|
45
|
+
# app.datastore.root_path = 'tmp/file_data_store_test'
|
46
|
+
# app
|
47
|
+
# end
|
48
|
+
|
49
|
+
def suppressing_stderr
|
50
|
+
original_stderr = $stderr.dup
|
51
|
+
tempfile = Tempfile.new('stderr')
|
52
|
+
$stderr.reopen(tempfile) rescue
|
53
|
+
yield
|
54
|
+
ensure
|
55
|
+
tempfile.close!
|
56
|
+
$stderr.reopen(original_stderr)
|
57
|
+
end
|
58
|
+
|
59
|
+
def running_on_windows?
|
60
|
+
ENV['OS'] && ENV['OS'].downcase == 'windows_nt'
|
61
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
def string_matching(regexp)
|
2
|
+
Spec::Mocks::ArgumentMatchers::RegexpMatcher.new(regexp)
|
3
|
+
end
|
4
|
+
|
5
|
+
class TempObjectArgumentMatcher
|
6
|
+
def initialize(data, opts)
|
7
|
+
@data = data
|
8
|
+
@opts = opts
|
9
|
+
end
|
10
|
+
def ==(actual)
|
11
|
+
actual.is_a?(ImageResizer::TempObject) &&
|
12
|
+
actual.data == @data &&
|
13
|
+
@opts.all?{|k,v| actual.send(k) == v }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def a_temp_object_with_data(data, opts={})
|
18
|
+
TempObjectArgumentMatcher.new(data, opts)
|
19
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
def image_properties(image)
|
2
|
+
if image.is_a?(Tempfile)
|
3
|
+
tempfile = image
|
4
|
+
else
|
5
|
+
tempfile = Tempfile.new('image')
|
6
|
+
tempfile.binmode
|
7
|
+
tempfile.write(image.is_a?(ImageResizer::TempObject) ? image.data : image)
|
8
|
+
tempfile.close
|
9
|
+
end
|
10
|
+
details = `identify #{tempfile.path}`
|
11
|
+
# example of details string:
|
12
|
+
# myimage.png PNG 200x100 200x100+0+0 8-bit DirectClass 31.2kb
|
13
|
+
filename, format, geometry, geometry_2, depth, image_class, size = details.split(' ')
|
14
|
+
width, height = geometry.split('x')
|
15
|
+
{
|
16
|
+
:filename => filename,
|
17
|
+
:format => format.downcase,
|
18
|
+
:width => width,
|
19
|
+
:height => height,
|
20
|
+
:depth => depth,
|
21
|
+
:image_class => image_class,
|
22
|
+
:size => size
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
RSpec::Matchers.define :have_width do |width|
|
27
|
+
match do |given|
|
28
|
+
width.should === image_properties(given)[:width].to_i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
RSpec::Matchers.define :have_height do |height|
|
33
|
+
match do |given|
|
34
|
+
height.should === image_properties(given)[:height].to_i
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
RSpec::Matchers.define :have_format do |format|
|
39
|
+
match do |given|
|
40
|
+
image_properties(given)[:format].should == format
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
RSpec::Matchers.define :have_size do |size|
|
45
|
+
match do |given|
|
46
|
+
image_properties(given)[:size].should == size
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
RSpec::Matchers.define :equal_image do |other|
|
51
|
+
match do |given|
|
52
|
+
image_data = given.open.read
|
53
|
+
other_image_data = other.open.read
|
54
|
+
given.close
|
55
|
+
other.close
|
56
|
+
image_data == other_image_data
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
RSpec::Matchers.define :match_url do |url|
|
2
|
+
match do |given|
|
3
|
+
given_path, given_query_string = given.split('?')
|
4
|
+
path, query_string = url.split('?')
|
5
|
+
|
6
|
+
path == given_path && given_query_string.split('&').sort == query_string.split('&').sort
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec::Matchers.define :be_an_empty_directory do
|
11
|
+
match do |given|
|
12
|
+
Dir.entries(given) == ['.','..']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec::Matchers.define :include_hash do |hash|
|
17
|
+
match do |given|
|
18
|
+
given.merge(hash) == given
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def memory_usage
|
23
|
+
GC.start # Garbage collect
|
24
|
+
`ps -o rss= -p #{$$}`.strip.to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec::Matchers.define :leak_memory do
|
28
|
+
match do |given|
|
29
|
+
memory_before = memory_usage
|
30
|
+
given.call
|
31
|
+
memory_after = memory_usage
|
32
|
+
result = memory_after > memory_before
|
33
|
+
puts "#{memory_after} > #{memory_before}" if result
|
34
|
+
result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
RSpec::Matchers.define :match_attachment_classes do |classes|
|
39
|
+
match do |given_classes|
|
40
|
+
given_classes.length == classes.length &&
|
41
|
+
classes.zip(given_classes).all? do |(klass, given)|
|
42
|
+
given.model_class == klass[0] && given.attribute == klass[1] && given.app == klass[2]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
RSpec::Matchers.define :be_a_text_response do
|
48
|
+
match do |given_response|
|
49
|
+
given_response.status.should == 200
|
50
|
+
given_response.body.length.should > 0
|
51
|
+
given_response.content_type.should == 'text/plain'
|
52
|
+
end
|
53
|
+
end
|
data/tmp/test_file
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
wassup
|