ungulate 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/VERSION +1 -1
  2. data/bin/ungulate_server.rb +22 -7
  3. data/features/image_resize.feature +2 -12
  4. data/features/notification_url.feature +14 -0
  5. data/features/resize_then_composite.feature +2 -1
  6. data/features/step_definitions/bucket_steps.rb +4 -0
  7. data/features/step_definitions/command_steps.rb +10 -1
  8. data/features/step_definitions/notification_steps.rb +23 -0
  9. data/features/step_definitions/queue_steps.rb +7 -21
  10. data/features/step_definitions/version_steps.rb +2 -2
  11. data/features/{support.rb → support/config.rb} +4 -0
  12. data/features/support/helpers.rb +21 -0
  13. data/features/support/put_server.rb +22 -0
  14. data/lib/ungulate.rb +64 -0
  15. data/lib/ungulate/blob_processor.rb +34 -0
  16. data/lib/ungulate/curl_http.rb +25 -0
  17. data/lib/ungulate/file_upload.rb +22 -16
  18. data/lib/ungulate/job.rb +23 -143
  19. data/lib/ungulate/rmagick_version_creator.rb +77 -0
  20. data/lib/ungulate/s3_storage.rb +41 -0
  21. data/lib/ungulate/server.rb +27 -7
  22. data/lib/ungulate/sqs_message_queue.rb +38 -0
  23. data/spec/fixtures/chuckle.jpg +0 -0
  24. data/spec/fixtures/chuckle.png +0 -0
  25. data/spec/fixtures/chuckle_converted.png +0 -0
  26. data/spec/fixtures/chuckle_converted_badly.png +0 -0
  27. data/spec/fixtures/chuckle_thumbnail.png +0 -0
  28. data/spec/fixtures/watermark.png +0 -0
  29. data/spec/lib/ungulate/blob_processor_spec.rb +68 -0
  30. data/spec/lib/ungulate/curl_http_spec.rb +20 -0
  31. data/spec/{ungulate → lib/ungulate}/file_upload_spec.rb +10 -27
  32. data/spec/lib/ungulate/job_spec.rb +120 -0
  33. data/spec/lib/ungulate/rmagick_version_creator_spec.rb +97 -0
  34. data/spec/lib/ungulate/s3_storage_spec.rb +74 -0
  35. data/spec/lib/ungulate/server_spec.rb +44 -0
  36. data/spec/lib/ungulate/sqs_message_queue_spec.rb +28 -0
  37. data/spec/{ungulate → lib/ungulate}/view_helpers_spec.rb +1 -1
  38. data/spec/lib/ungulate_spec.rb +24 -0
  39. data/spec/spec_helper.rb +73 -0
  40. metadata +67 -25
  41. data/spec/ungulate/job_spec.rb +0 -386
  42. data/spec/ungulate/server_spec.rb +0 -42
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
  require 'ungulate/view_helpers'
3
3
  require 'active_support/core_ext'
4
4
 
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'ungulate'
3
+
4
+ describe Ungulate do
5
+ describe "configuration" do
6
+ it "returns the same object every time" do
7
+ Ungulate.configuration.should equal(Ungulate.configuration)
8
+ end
9
+
10
+ it "yields the current configuration" do
11
+ Ungulate.configure do |config|
12
+ config.should == Ungulate::configuration
13
+ end
14
+ end
15
+
16
+ it "allows setting and retrieving values" do
17
+ Ungulate.configure do |config|
18
+ config.bob = 'tree'
19
+ end
20
+
21
+ Ungulate.configuration.bob.should == 'tree'
22
+ end
23
+ end
24
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,76 @@
1
1
  require 'ungulate'
2
2
  require 'rspec'
3
3
 
4
+ RSpec.configure do |config|
5
+ def fixture_path(filename)
6
+ File.expand_path("fixtures/#{filename}", File.dirname(__FILE__))
7
+ end
8
+
9
+ def fixture(filename)
10
+ File.read fixture_path(filename)
11
+ end
12
+
13
+ def clear(queue)
14
+ puts "CLEAR"
15
+ (1..240).each do
16
+ queue.clear
17
+ size = queue.size
18
+ puts "queue size: #{size}"
19
+ return if size.zero?
20
+ sleep 1
21
+ puts "slept 1 second"
22
+ end
23
+ queue.size.should be_zero
24
+ end
25
+
26
+ def wait_for_non_empty(queue)
27
+ puts "WAIT FOR NON EMPTY"
28
+ (1..240).each do
29
+ size = queue.size
30
+ puts "queue size: #{size}"
31
+ return if size > 0
32
+ sleep 1
33
+ puts "slept 1 second"
34
+ end
35
+ queue.size.should_not be_zero
36
+ end
37
+
38
+ shared_examples_for "a message queue" do
39
+ it "has a name" do
40
+ new_queue.name.should be_present
41
+ end
42
+
43
+ it "can send and receive one deletable message at a time" do
44
+ queue = new_queue
45
+ clear(queue)
46
+
47
+ sent_bodies = Set.new %w(hello there how are you)
48
+
49
+ sent_bodies.each do |message|
50
+ puts "pushing #{message}"
51
+ queue.push(message)
52
+ end
53
+
54
+ queue = nil
55
+
56
+ new_queue_instance = new_queue
57
+ wait_for_non_empty(new_queue_instance)
58
+
59
+ received_bodies = Set.new
60
+
61
+ iterations = 0
62
+ messages = []
63
+ while (received_bodies != sent_bodies) && iterations < 30 do
64
+ messages << new_queue_instance.receive
65
+ bodies = messages.map(&:to_s)
66
+ received_bodies += bodies.select(&:present?)
67
+ iterations += 1
68
+ puts "iteration: #{iterations} :: messages: #{received_bodies.to_a.join(',')}"
69
+ end
70
+
71
+ messages.compact.each(&:delete)
72
+
73
+ received_bodies.should == sent_bodies
74
+ end
75
+ end
76
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ungulate
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 4
10
- version: 0.1.4
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Bruce
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-09-19 00:00:00 +01:00
18
+ date: 2011-10-28 00:00:00 +01:00
19
19
  default_executable: ungulate_server.rb
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -98,9 +98,25 @@ dependencies:
98
98
  type: :runtime
99
99
  version_requirements: *id005
100
100
  - !ruby/object:Gem::Dependency
101
- name: rake
101
+ name: hashie
102
102
  prerelease: false
103
103
  requirement: &id006 !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ hash: 31
109
+ segments:
110
+ - 1
111
+ - 2
112
+ - 0
113
+ version: 1.2.0
114
+ type: :runtime
115
+ version_requirements: *id006
116
+ - !ruby/object:Gem::Dependency
117
+ name: rake
118
+ prerelease: false
119
+ requirement: &id007 !ruby/object:Gem::Requirement
104
120
  none: false
105
121
  requirements:
106
122
  - - ">="
@@ -110,11 +126,11 @@ dependencies:
110
126
  - 0
111
127
  version: "0"
112
128
  type: :development
113
- version_requirements: *id006
129
+ version_requirements: *id007
114
130
  - !ruby/object:Gem::Dependency
115
131
  name: rspec
116
132
  prerelease: false
117
- requirement: &id007 !ruby/object:Gem::Requirement
133
+ requirement: &id008 !ruby/object:Gem::Requirement
118
134
  none: false
119
135
  requirements:
120
136
  - - ">="
@@ -126,11 +142,11 @@ dependencies:
126
142
  - 0
127
143
  version: 2.4.0
128
144
  type: :development
129
- version_requirements: *id007
145
+ version_requirements: *id008
130
146
  - !ruby/object:Gem::Dependency
131
147
  name: cucumber
132
148
  prerelease: false
133
- requirement: &id008 !ruby/object:Gem::Requirement
149
+ requirement: &id009 !ruby/object:Gem::Requirement
134
150
  none: false
135
151
  requirements:
136
152
  - - ">="
@@ -142,11 +158,11 @@ dependencies:
142
158
  - 0
143
159
  version: 0.10.0
144
160
  type: :development
145
- version_requirements: *id008
161
+ version_requirements: *id009
146
162
  - !ruby/object:Gem::Dependency
147
163
  name: i18n
148
164
  prerelease: false
149
- requirement: &id009 !ruby/object:Gem::Requirement
165
+ requirement: &id010 !ruby/object:Gem::Requirement
150
166
  none: false
151
167
  requirements:
152
168
  - - ">="
@@ -158,11 +174,11 @@ dependencies:
158
174
  - 0
159
175
  version: 0.5.0
160
176
  type: :development
161
- version_requirements: *id009
177
+ version_requirements: *id010
162
178
  - !ruby/object:Gem::Dependency
163
179
  name: ruby-debug
164
180
  prerelease: false
165
- requirement: &id010 !ruby/object:Gem::Requirement
181
+ requirement: &id011 !ruby/object:Gem::Requirement
166
182
  none: false
167
183
  requirements:
168
184
  - - ">="
@@ -172,7 +188,7 @@ dependencies:
172
188
  - 0
173
189
  version: "0"
174
190
  type: :development
175
- version_requirements: *id010
191
+ version_requirements: *id011
176
192
  description: |
177
193
  = Ungulate
178
194
 
@@ -225,22 +241,44 @@ files:
225
241
  - features/camels.jpg
226
242
  - features/cope_with_empty_queue.feature
227
243
  - features/image_resize.feature
244
+ - features/notification_url.feature
228
245
  - features/resize_then_composite.feature
246
+ - features/step_definitions/bucket_steps.rb
229
247
  - features/step_definitions/command_steps.rb
248
+ - features/step_definitions/notification_steps.rb
230
249
  - features/step_definitions/queue_steps.rb
231
250
  - features/step_definitions/version_steps.rb
232
251
  - features/superhugwatermark.png
233
- - features/support.rb
252
+ - features/support/config.rb
253
+ - features/support/helpers.rb
254
+ - features/support/put_server.rb
255
+ - lib/ungulate/blob_processor.rb
256
+ - lib/ungulate/curl_http.rb
234
257
  - lib/ungulate/file_upload.rb
235
258
  - lib/ungulate/job.rb
259
+ - lib/ungulate/rmagick_version_creator.rb
260
+ - lib/ungulate/s3_storage.rb
236
261
  - lib/ungulate/server.rb
262
+ - lib/ungulate/sqs_message_queue.rb
237
263
  - lib/ungulate/view_helpers.rb
238
264
  - lib/ungulate.rb
265
+ - spec/fixtures/chuckle.jpg
266
+ - spec/fixtures/chuckle.png
267
+ - spec/fixtures/chuckle_converted.png
268
+ - spec/fixtures/chuckle_converted_badly.png
269
+ - spec/fixtures/chuckle_thumbnail.png
270
+ - spec/fixtures/watermark.png
271
+ - spec/lib/ungulate/blob_processor_spec.rb
272
+ - spec/lib/ungulate/curl_http_spec.rb
273
+ - spec/lib/ungulate/file_upload_spec.rb
274
+ - spec/lib/ungulate/job_spec.rb
275
+ - spec/lib/ungulate/rmagick_version_creator_spec.rb
276
+ - spec/lib/ungulate/s3_storage_spec.rb
277
+ - spec/lib/ungulate/server_spec.rb
278
+ - spec/lib/ungulate/sqs_message_queue_spec.rb
279
+ - spec/lib/ungulate/view_helpers_spec.rb
280
+ - spec/lib/ungulate_spec.rb
239
281
  - spec/spec_helper.rb
240
- - spec/ungulate/file_upload_spec.rb
241
- - spec/ungulate/job_spec.rb
242
- - spec/ungulate/server_spec.rb
243
- - spec/ungulate/view_helpers_spec.rb
244
282
  has_rdoc: true
245
283
  homepage: http://github.com/camelpunch/ungulate
246
284
  licenses: []
@@ -276,8 +314,12 @@ signing_key:
276
314
  specification_version: 3
277
315
  summary: Process images using Amazon SQS and S3
278
316
  test_files:
279
- - spec/spec_helper.rb
280
- - spec/ungulate/file_upload_spec.rb
281
- - spec/ungulate/job_spec.rb
282
- - spec/ungulate/server_spec.rb
283
- - spec/ungulate/view_helpers_spec.rb
317
+ - spec/lib/ungulate/file_upload_spec.rb
318
+ - spec/lib/ungulate/job_spec.rb
319
+ - spec/lib/ungulate/server_spec.rb
320
+ - spec/lib/ungulate/blob_processor_spec.rb
321
+ - spec/lib/ungulate/curl_http_spec.rb
322
+ - spec/lib/ungulate/rmagick_version_creator_spec.rb
323
+ - spec/lib/ungulate/s3_storage_spec.rb
324
+ - spec/lib/ungulate/sqs_message_queue_spec.rb
325
+ - spec/lib/ungulate/view_helpers_spec.rb
@@ -1,386 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
- require 'ungulate/job'
3
-
4
- module Ungulate
5
- describe Job do
6
- let(:source_image) { stub('Source Image', :destroy! => nil) }
7
- let(:processed_image_1) { stub('Image 1', :destroy! => nil) }
8
- let(:processed_image_2) { stub('Image 2', :destroy! => nil) }
9
- let(:curl_easy) { stub('Curl::Easy', :body_str => body_str) }
10
-
11
- before do
12
- ENV['AMAZON_ACCESS_KEY_ID'] = 'test-key-id'
13
- ENV['AMAZON_SECRET_ACCESS_KEY'] = 'test-secret'
14
- @bucket = mock('Bucket', :put => nil)
15
- @sqs = mock('SqsGen2')
16
- @s3 = mock('S3')
17
- @q = mock('Queue')
18
- @versions = {
19
- :thumb => [ :resize_to_fit, 100, 200 ],
20
- :large => [ :resize_to_fit, 200, 300 ],
21
- }
22
-
23
- Curl::Easy.stub(:http_get)
24
- end
25
-
26
- its(:versions) { should == [] }
27
-
28
- describe :sqs do
29
- before do
30
- RightAws::SqsGen2.stub(:new).with('test-key-id', 'test-secret').and_return(@sqs)
31
- end
32
-
33
- it "should return a SqsGen2 instance using environment variables" do
34
- Job.sqs.should == @sqs
35
- end
36
-
37
- it "should memoize" do
38
- Job.instance_variable_set('@sqs', :cache)
39
- Job.sqs.should == :cache
40
- end
41
- end
42
-
43
- describe :pop do
44
- before do
45
- @job_attributes = {
46
- :bucket => 'test-bucket',
47
- :key => 'test-key',
48
- :versions => @versions
49
- }
50
-
51
- @sqs.stub(:queue).with('test-queue').and_return(@q)
52
-
53
- message = mock('Message', :to_s => :message_data)
54
-
55
- @q.stub(:pop).and_return(message)
56
- YAML.stub(:load).with(:message_data).and_return(:attributes)
57
-
58
- Job.stub(:sqs).and_return(@sqs)
59
- Job.stub(:s3).and_return(@s3)
60
-
61
- @job = mock('Job', :attributes= => nil, :queue= => nil, :queue => @q)
62
- Job.stub(:new).and_return(@job)
63
- end
64
-
65
- after { Job.pop('test-queue') }
66
-
67
- it "should set attributes" do
68
- @job.should_receive(:attributes=).with(:attributes)
69
- end
70
-
71
- it "should set the queue" do
72
- @job.should_receive(:queue=).with(@q)
73
- end
74
-
75
- context "when YAML.load returns false" do
76
- before do
77
- YAML.stub(:load).with(:message_data).and_return(false)
78
- end
79
-
80
- it "should not set attributes" do
81
- @job.should_not_receive(:attributes=)
82
- end
83
- end
84
- end
85
-
86
- describe :s3 do
87
- before do
88
- RightAws::S3.stub(:new).with('test-key-id', 'test-secret').and_return(@s3)
89
- end
90
-
91
- it "should return a S3 instance using environment variables" do
92
- Job.s3.should == @s3
93
- end
94
-
95
- it "should memoize" do
96
- Job.instance_variable_set('@s3', :cache)
97
- Job.s3.should == :cache
98
- end
99
- end
100
-
101
- describe :attributes= do
102
- subject do
103
- Job.stub_chain(:s3, :bucket).with('hello').and_return(@bucket)
104
-
105
- job = Job.new
106
- job.attributes = {
107
- :bucket => 'hello',
108
- :key => 'path/to/filename.gif',
109
- :versions => @versions,
110
- :notification_url => 'http://some.host/with/simple/path',
111
- }
112
- job
113
- end
114
-
115
- its(:bucket) { should == @bucket }
116
- its(:key) { should == 'path/to/filename.gif' }
117
- its(:versions) { should == @versions }
118
- its(:notification_url) { should == 'http://some.host/with/simple/path' }
119
- end
120
-
121
- describe :source do
122
- subject do
123
- job = Job.new
124
- job.stub(:key).and_return('test-key')
125
- job.stub_chain(:bucket, :get).with('test-key').and_return(:s3_data)
126
- job.source
127
- end
128
-
129
- it { should == :s3_data }
130
-
131
- it "should memoize" do
132
- job = Job.new
133
- job.instance_variable_set('@source', :cache)
134
- job.source.should == :cache
135
- end
136
- end
137
-
138
- describe :image do
139
- let(:blob) { 'asdf' }
140
-
141
- it "returns a Magick::Image from the source" do
142
- subject.stub(:source).and_return(blob)
143
- Magick::Image.should_receive(:from_blob).with(blob).and_return([source_image])
144
- subject.source_image.should == source_image
145
- end
146
- end
147
-
148
- describe :image_from_instruction do
149
- let(:instruction) { [ :composite, url, arg1, arg2 ] }
150
- let(:overlay) { stub('Overlay', :destroy! => nil) }
151
- let(:arg1) { 1 }
152
- let(:arg2) { 2 }
153
- let(:url) { 'https://www.some.url/' }
154
- let(:body_str) { 'blob' }
155
-
156
- before do
157
- Curl::Easy.stub(:http_get).and_return(curl_easy)
158
- Magick::Image.stub(:from_blob).and_return([overlay])
159
- source_image.stub(:composite).and_return(processed_image_1)
160
- end
161
-
162
- context "when an argument is a URL" do
163
- it "converts the URL to an Image" do
164
- Curl::Easy.should_receive(:http_get).with(url).and_return(curl_easy)
165
- Magick::Image.should_receive(:from_blob).with('blob').and_return([overlay])
166
- source_image.should_receive(:composite).
167
- with(overlay, arg1, arg2).
168
- and_return(processed_image_1)
169
-
170
- subject.image_from_instruction(source_image, instruction).
171
- should == processed_image_1
172
- end
173
-
174
- it "caches the image blob in a hash for later reuse" do
175
- subject.image_from_instruction(source_image, instruction)
176
- Ungulate::Job.blobs_from_urls[url].should == 'blob'
177
- end
178
-
179
- context "image is already cached" do
180
- it "reuses the cached image" do
181
- subject.class.blobs_from_urls[url] = 'cachedblob'
182
- Magick::Image.should_receive(:from_blob).with('cachedblob').and_return([overlay])
183
- subject.image_from_instruction(source_image, instruction)
184
- end
185
- end
186
- end
187
-
188
- context "when argument isn't a valid http URL" do
189
- let(:url) { 'somethingwithhttpinit' }
190
-
191
- it "passes the argument through to the method" do
192
- source_image.should_receive(:composite).
193
- with(url, arg1, arg2).
194
- and_return(processed_image_1)
195
-
196
- subject.image_from_instruction(source_image, instruction)
197
- end
198
- end
199
-
200
- context "when arguments are symbols" do
201
- let(:arg1) { :center_gravity }
202
- let(:arg2) { :soft_light_composite_op }
203
-
204
- it "converts the symbols to Magick::XxXx constants" do
205
- source_image.should_receive(:composite).
206
- with(anything, Magick::CenterGravity, Magick::SoftLightCompositeOp).
207
- and_return(processed_image_1)
208
-
209
- subject.image_from_instruction(source_image, instruction)
210
- end
211
- end
212
- end
213
-
214
- describe :processed_versions do
215
- let(:versions) do
216
- {
217
- :large => [ :resize_to_fit, 100, 200 ],
218
- :small => [ :resize_to_fill, 64, 64 ],
219
- }
220
- end
221
-
222
- before do
223
- subject.stub(:versions).and_return(versions)
224
- subject.stub(:key).and_return('someimage.jpg')
225
- subject.stub(:source_image).and_return(source_image)
226
-
227
- source_image.stub(:resize_to_fit).with(100, 200).and_return(processed_image_1)
228
- source_image.stub(:resize_to_fill).with(64, 64).and_return(processed_image_2)
229
- end
230
-
231
- it "processes multiple versions" do
232
- subject.processed_versions.should include([:large, processed_image_1])
233
- subject.processed_versions.should include([:small, processed_image_2])
234
- end
235
-
236
- it "destroys the image object" do
237
- source_image.should_receive(:destroy!)
238
- subject.processed_versions
239
- end
240
-
241
- it "memoizes" do
242
- subject.instance_variable_set('@processed_versions', :cache)
243
- subject.processed_versions.should == :cache
244
- end
245
-
246
- context "with three 'method' arguments" do
247
- let(:versions) do
248
- { :large => [ :some_method, 'some-value', 1, 2 ] }
249
- end
250
-
251
- it "passes each value" do
252
- source_image.should_receive(:some_method).
253
- with('some-value', 1, 2).
254
- and_return(processed_image_1)
255
- subject.processed_versions.should == [[:large, processed_image_1]]
256
- end
257
- end
258
-
259
- context "with multiple instructions in a version" do
260
- let(:versions) do
261
- {
262
- :large => [
263
- [ :method_1, 'value-1' ],
264
- [ :method_2, 'value-2' ]
265
- ]
266
- }
267
- end
268
-
269
- before do
270
- source_image.stub(:method_1).and_return(processed_image_1)
271
- processed_image_1.stub(:method_2).and_return(processed_image_2)
272
- end
273
-
274
- it "chains the processing" do
275
- subject.processed_versions.should == [[:large, processed_image_2]]
276
- end
277
-
278
- it "destroys intermediate images" do
279
- processed_image_1.should_receive(:destroy!)
280
- subject.processed_versions
281
- end
282
- end
283
- end
284
-
285
- describe :process do
286
- before do
287
- @big = mock('Image', :destroy! => nil, :to_blob => 'bigdata', :format => 'JPEG')
288
- @little = mock('Image', :destroy! => nil, :to_blob => 'littledata', :format => 'JPEG')
289
- @mime_type = mock('MimeType', :to_s => 'image/jpeg')
290
- MIME::Types.stub(:type_for).with('JPEG').and_return(@mime_type)
291
- end
292
-
293
- subject do
294
- job = Job.new
295
- job.stub(:processed_versions).and_return([[:big, @big], [:little, @little]])
296
- job.stub(:bucket).and_return(@bucket)
297
- job.stub(:version_key).with(:big).and_return('path/to/someimage_big.jpg')
298
- job.stub(:version_key).with(:little).and_return('path/to/someimage_little.jpg')
299
- job.stub(:send_notification)
300
- job
301
- end
302
-
303
- it "should destroy the image objects" do
304
- @big.should_receive(:destroy!)
305
- @little.should_receive(:destroy!)
306
- subject.process
307
- end
308
-
309
- it "should send each processed version to S3" do
310
- expected_headers = {
311
- 'Content-Type' => 'image/jpeg',
312
- 'Cache-Control' => 'max-age=2629743',
313
- }
314
-
315
- @bucket.should_receive(:put).with('path/to/someimage_big.jpg',
316
- 'bigdata',
317
- {},
318
- 'public-read',
319
- expected_headers)
320
- @bucket.should_receive(:put).with('path/to/someimage_little.jpg',
321
- 'littledata',
322
- {},
323
- 'public-read',
324
- expected_headers)
325
- subject.process
326
- end
327
-
328
- it "should notify" do
329
- subject.should_receive(:send_notification)
330
- subject.process
331
- end
332
-
333
- context "send_notification returns false" do
334
- before do
335
- subject.stub(:send_notification).and_return(false)
336
- end
337
-
338
- it "should return true" do
339
- subject.process.should be_true
340
- end
341
- end
342
-
343
- context "empty array" do
344
- before do
345
- subject.stub(:processed_versions).and_return([])
346
- end
347
-
348
- it "should not break" do
349
- subject.process
350
- end
351
- end
352
- end
353
-
354
- describe :send_notification do
355
- let(:url) { 'https://some-url' }
356
-
357
- context "notification URL provided" do
358
- it "should PUT to the URL" do
359
- subject.stub(:notification_url).and_return(url)
360
- Curl::Easy.should_receive(:http_put).with(url, '')
361
- subject.send_notification
362
- end
363
- end
364
- end
365
-
366
- describe :version_key do
367
- subject do
368
- job = Job.new
369
- job.stub(:key).and_return('path/to/some/file_name.png')
370
- job.version_key(:extra_large)
371
- end
372
-
373
- it { should == 'path/to/some/file_name_extra_large.png' }
374
-
375
- context "no leading path" do
376
- subject do
377
- job = Job.new
378
- job.stub(:key).and_return('file_name.png')
379
- job.version_key(:extra_large)
380
- end
381
-
382
- it { should == 'file_name_extra_large.png' }
383
- end
384
- end
385
- end
386
- end