ungulate 0.1.4 → 0.2.0

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.
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