dragonfly 0.6.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of dragonfly might be problematic. Click here for more details.
- data/.gitignore +2 -0
- data/.specopts +2 -0
- data/.yardopts +11 -5
- data/Gemfile +22 -0
- data/Gemfile.rails.2.3.5 +13 -0
- data/History.md +49 -0
- data/README.md +18 -28
- data/Rakefile +24 -36
- data/VERSION +1 -1
- data/config.ru +4 -1
- data/dragonfly.gemspec +85 -99
- data/extra_docs/Analysers.md +66 -30
- data/extra_docs/Caching.md +22 -0
- data/extra_docs/Configuration.md +116 -0
- data/extra_docs/DataStorage.md +114 -14
- data/extra_docs/Encoding.md +62 -37
- data/extra_docs/GeneralUsage.md +118 -0
- data/extra_docs/Generators.md +92 -0
- data/extra_docs/Heroku.md +51 -0
- data/extra_docs/Index.md +8 -9
- data/extra_docs/MimeTypes.md +18 -17
- data/extra_docs/Models.md +251 -0
- data/extra_docs/Processing.md +94 -70
- data/extra_docs/Rack.md +53 -0
- data/extra_docs/Rails2.md +44 -0
- data/extra_docs/Rails3.md +51 -0
- data/extra_docs/Sinatra.md +21 -0
- data/extra_docs/URLs.md +114 -0
- data/features/images.feature +6 -7
- data/features/no_processing.feature +0 -6
- data/features/rails_2.3.5.feature +1 -1
- data/features/rails_3.0.0.rc.feature +8 -0
- data/features/steps/dragonfly_steps.rb +14 -12
- data/features/steps/rails_steps.rb +20 -9
- data/features/support/env.rb +10 -11
- data/fixtures/files/app/views/albums/new.html.erb +4 -4
- data/fixtures/files/app/views/albums/show.html.erb +1 -1
- data/fixtures/files/features/manage_album_images.feature +1 -1
- data/fixtures/files/features/step_definitions/{album_steps.rb → image_steps.rb} +4 -3
- data/fixtures/files/features/support/paths.rb +2 -0
- data/fixtures/files/features/text_images.feature +7 -0
- data/fixtures/rails_3.0.0.rc/template.rb +21 -0
- data/irbrc.rb +2 -1
- data/lib/dragonfly.rb +4 -16
- data/lib/dragonfly/{active_record_extensions.rb → active_model_extensions.rb} +1 -1
- data/lib/dragonfly/active_model_extensions/attachment.rb +146 -0
- data/lib/dragonfly/{active_record_extensions → active_model_extensions}/class_methods.rb +5 -6
- data/lib/dragonfly/{active_record_extensions → active_model_extensions}/instance_methods.rb +1 -1
- data/lib/dragonfly/{active_record_extensions → active_model_extensions}/validations.rb +5 -9
- data/lib/dragonfly/analyser.rb +59 -0
- data/lib/dragonfly/analysis/file_command_analyser.rb +1 -1
- data/lib/dragonfly/analysis/r_magick_analyser.rb +46 -31
- data/lib/dragonfly/app.rb +138 -173
- data/lib/dragonfly/config/heroku.rb +19 -0
- data/lib/dragonfly/config/r_magick.rb +37 -0
- data/lib/dragonfly/config/{rails_defaults.rb → rails.rb} +6 -7
- data/lib/dragonfly/configurable.rb +30 -27
- data/lib/dragonfly/core_ext/object.rb +1 -1
- data/lib/dragonfly/data_storage/file_data_store.rb +59 -26
- data/lib/dragonfly/data_storage/mongo_data_store.rb +65 -0
- data/lib/dragonfly/data_storage/s3data_store.rb +31 -12
- data/lib/dragonfly/encoder.rb +13 -0
- data/lib/dragonfly/encoding/r_magick_encoder.rb +10 -19
- data/lib/dragonfly/endpoint.rb +43 -0
- data/lib/dragonfly/function_manager.rb +65 -0
- data/lib/dragonfly/{processing/r_magick_text_processor.rb → generation/r_magick_generator.rb} +25 -11
- data/lib/dragonfly/generator.rb +9 -0
- data/lib/dragonfly/job.rb +290 -0
- data/lib/dragonfly/job_builder.rb +39 -0
- data/lib/dragonfly/job_definitions.rb +26 -0
- data/lib/dragonfly/job_endpoint.rb +17 -0
- data/lib/dragonfly/loggable.rb +28 -0
- data/lib/dragonfly/middleware.rb +21 -14
- data/lib/dragonfly/processing/r_magick_processor.rb +71 -48
- data/lib/dragonfly/processor.rb +9 -0
- data/lib/dragonfly/r_magick_utils.rb +24 -0
- data/lib/dragonfly/rails/images.rb +10 -7
- data/lib/dragonfly/routed_endpoint.rb +42 -0
- data/lib/dragonfly/serializer.rb +32 -0
- data/lib/dragonfly/simple_cache.rb +23 -0
- data/lib/dragonfly/simple_endpoint.rb +64 -0
- data/lib/dragonfly/temp_object.rb +77 -45
- data/spec/argument_matchers.rb +7 -17
- data/spec/dragonfly/active_model_extensions/active_model_setup.rb +97 -0
- data/spec/dragonfly/active_model_extensions/active_record_setup.rb +85 -0
- data/spec/dragonfly/{active_record_extensions → active_model_extensions}/model_spec.rb +282 -244
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +11 -0
- data/spec/dragonfly/analyser_spec.rb +123 -0
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +2 -2
- data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +10 -1
- data/spec/dragonfly/app_spec.rb +175 -69
- data/spec/dragonfly/configurable_spec.rb +14 -0
- data/spec/dragonfly/data_storage/data_store_spec.rb +36 -9
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +61 -38
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +18 -0
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +34 -39
- data/spec/dragonfly/deprecation_spec.rb +20 -0
- data/spec/dragonfly/function_manager_spec.rb +154 -0
- data/spec/dragonfly/generation/r_magick_generator_spec.rb +119 -0
- data/spec/dragonfly/job_builder_spec.rb +37 -0
- data/spec/dragonfly/job_definitions_spec.rb +35 -0
- data/spec/dragonfly/job_endpoint_spec.rb +66 -0
- data/spec/dragonfly/job_spec.rb +605 -0
- data/spec/dragonfly/loggable_spec.rb +80 -0
- data/spec/dragonfly/middleware_spec.rb +37 -17
- data/spec/dragonfly/processing/r_magick_processor_spec.rb +182 -166
- data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
- data/spec/dragonfly/serializer_spec.rb +61 -0
- data/spec/dragonfly/simple_cache_spec.rb +27 -0
- data/spec/dragonfly/simple_endpoint_spec.rb +78 -0
- data/spec/dragonfly/temp_object_spec.rb +154 -119
- data/spec/simple_matchers.rb +22 -0
- data/spec/spec_helper.rb +28 -4
- data/yard/templates/default/layout/html/layout.erb +18 -11
- metadata +89 -190
- data/config.rb +0 -5
- data/extra_docs/ActiveRecord.md +0 -196
- data/extra_docs/ExampleUseCases.md +0 -189
- data/extra_docs/GettingStarted.md +0 -114
- data/extra_docs/Shortcuts.md +0 -118
- data/extra_docs/UsingWithRails.md +0 -81
- data/features/rails_3.0.0.beta3.feature +0 -7
- data/fixtures/rails_3.0.0.beta3/template.rb +0 -16
- data/lib/dragonfly/active_record_extensions/attachment.rb +0 -170
- data/lib/dragonfly/analyser_list.rb +0 -9
- data/lib/dragonfly/analysis/base.rb +0 -10
- data/lib/dragonfly/belongs_to_app.rb +0 -24
- data/lib/dragonfly/config/heroku_rails_images.rb +0 -23
- data/lib/dragonfly/config/r_magick_images.rb +0 -69
- data/lib/dragonfly/config/r_magick_text.rb +0 -25
- data/lib/dragonfly/config/rails_images.rb +0 -13
- data/lib/dragonfly/data_storage/base.rb +0 -21
- data/lib/dragonfly/data_storage/base64_data_store.rb +0 -23
- data/lib/dragonfly/data_storage/transparent_data_store.rb +0 -21
- data/lib/dragonfly/delegatable.rb +0 -14
- data/lib/dragonfly/delegator.rb +0 -62
- data/lib/dragonfly/encoder_list.rb +0 -9
- data/lib/dragonfly/encoding/base.rb +0 -14
- data/lib/dragonfly/encoding/transparent_encoder.rb +0 -14
- data/lib/dragonfly/extended_temp_object.rb +0 -120
- data/lib/dragonfly/parameters.rb +0 -163
- data/lib/dragonfly/processing/base.rb +0 -10
- data/lib/dragonfly/processor_list.rb +0 -9
- data/lib/dragonfly/url_handler.rb +0 -147
- data/spec/dragonfly/active_record_extensions/attachment_spec.rb +0 -8
- data/spec/dragonfly/active_record_extensions/migration.rb +0 -42
- data/spec/dragonfly/active_record_extensions/models.rb +0 -6
- data/spec/dragonfly/active_record_extensions/spec_helper.rb +0 -24
- data/spec/dragonfly/belongs_to_app_spec.rb +0 -55
- data/spec/dragonfly/delegatable_spec.rb +0 -32
- data/spec/dragonfly/delegator_spec.rb +0 -145
- data/spec/dragonfly/extended_temp_object_spec.rb +0 -71
- data/spec/dragonfly/parameters_spec.rb +0 -298
- data/spec/dragonfly/processing/r_magick_text_processor_spec.rb +0 -84
- data/spec/dragonfly/url_handler_spec.rb +0 -247
- data/spec/dragonfly_spec.rb +0 -16
- data/spec/ginger_scenarios.rb +0 -13
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::Generation::RMagickGenerator do
|
4
|
+
|
5
|
+
describe "plasma" do
|
6
|
+
before(:each) do
|
7
|
+
@generator = Dragonfly::Generation::RMagickGenerator.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "generating an image with the given dimensions" do
|
11
|
+
before(:each) do
|
12
|
+
@image, @extra = @generator.plasma(23,12)
|
13
|
+
end
|
14
|
+
it {@image.should have_width(23)}
|
15
|
+
it {@image.should have_height(12)}
|
16
|
+
it {@image.should have_format('png')}
|
17
|
+
it {@extra.should == {:format => :png, :name => 'plasma.png'}}
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "specifying the format" do
|
21
|
+
before(:each) do
|
22
|
+
@image, @extra = @generator.plasma(23, 12, :gif)
|
23
|
+
end
|
24
|
+
it {@image.should have_format('gif')}
|
25
|
+
it {@extra.should == {:format => :gif, :name => 'plasma.gif'}}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "text" do
|
30
|
+
before(:each) do
|
31
|
+
@generator = Dragonfly::Generation::RMagickGenerator.new
|
32
|
+
@text = "mmm"
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "creating a text image" do
|
36
|
+
before(:each) do
|
37
|
+
@image, @extra = @generator.text(@text, :font_size => 12)
|
38
|
+
end
|
39
|
+
it {@image.should have_width(20..40)} # approximate
|
40
|
+
it {@image.should have_height(10..20)}
|
41
|
+
it {@image.should have_format('png')}
|
42
|
+
it {@extra.should == {:format => :png, :name => 'text.png'}}
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "specifying the format" do
|
46
|
+
before(:each) do
|
47
|
+
@image, @extra = @generator.text(@text, :format => :gif)
|
48
|
+
end
|
49
|
+
it {@image.should have_format('gif')}
|
50
|
+
it {@extra.should == {:format => :gif, :name => 'text.gif'}}
|
51
|
+
end
|
52
|
+
|
53
|
+
# it "should ignore percent characters used by rmagick"
|
54
|
+
|
55
|
+
describe "padding" do
|
56
|
+
before(:each) do
|
57
|
+
no_padding_text, extra = @generator.text(@text, :font_size => 12)
|
58
|
+
@width = image_properties(no_padding_text)[:width].to_i
|
59
|
+
@height = image_properties(no_padding_text)[:height].to_i
|
60
|
+
end
|
61
|
+
it "1 number shortcut" do
|
62
|
+
image, extra = @generator.text(@text, :padding => '10')
|
63
|
+
image.should have_width(@width + 20)
|
64
|
+
image.should have_height(@height + 20)
|
65
|
+
end
|
66
|
+
it "2 numbers shortcut" do
|
67
|
+
image, extra = @generator.text(@text, :padding => '10 5')
|
68
|
+
image.should have_width(@width + 10)
|
69
|
+
image.should have_height(@height + 20)
|
70
|
+
end
|
71
|
+
it "3 numbers shortcut" do
|
72
|
+
image, extra = @generator.text(@text, :padding => '10 5 8')
|
73
|
+
image.should have_width(@width + 10)
|
74
|
+
image.should have_height(@height + 18)
|
75
|
+
end
|
76
|
+
it "4 numbers shortcut" do
|
77
|
+
image, extra = @generator.text(@text, :padding => '1 2 3 4')
|
78
|
+
image.should have_width(@width + 6)
|
79
|
+
image.should have_height(@height + 4)
|
80
|
+
end
|
81
|
+
it "should override the general padding declaration with the specific one (e.g. 'padding-left')" do
|
82
|
+
image, extra = @generator.text(@text, :padding => '10', 'padding-left' => 9)
|
83
|
+
image.should have_width(@width + 19)
|
84
|
+
image.should have_height(@height + 20)
|
85
|
+
end
|
86
|
+
it "should ignore 'px' suffixes" do
|
87
|
+
image, extra = @generator.text(@text, :padding => '1px 2px 3px 4px')
|
88
|
+
image.should have_width(@width + 6)
|
89
|
+
image.should have_height(@height + 4)
|
90
|
+
end
|
91
|
+
it "bad padding string" do
|
92
|
+
lambda{
|
93
|
+
@generator.text(@text, :padding => '1 2 3 4 5')
|
94
|
+
}.should raise_error(ArgumentError)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe Dragonfly::Generation::RMagickGenerator::HashWithCssStyleKeys do
|
100
|
+
before(:each) do
|
101
|
+
@hash = Dragonfly::Generation::RMagickGenerator::HashWithCssStyleKeys[
|
102
|
+
:font_style => 'normal',
|
103
|
+
:'font-weight' => 'bold',
|
104
|
+
'font_colour' => 'white',
|
105
|
+
'font-size' => 23,
|
106
|
+
:hello => 'there'
|
107
|
+
]
|
108
|
+
end
|
109
|
+
describe "accessing using underscore symbol style" do
|
110
|
+
it{ @hash[:font_style].should == 'normal' }
|
111
|
+
it{ @hash[:font_weight].should == 'bold' }
|
112
|
+
it{ @hash[:font_colour].should == 'white' }
|
113
|
+
it{ @hash[:font_size].should == 23 }
|
114
|
+
it{ @hash[:hello].should == 'there' }
|
115
|
+
it{ @hash[:non_existent_key].should be_nil }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::JobBuilder do
|
4
|
+
|
5
|
+
describe "a multi-step job" do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@job_builder = Dragonfly::JobBuilder.new do |size, format|
|
9
|
+
process :thumb, size
|
10
|
+
encode format unless format.nil?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should correctly call job steps" do
|
15
|
+
job = mock
|
16
|
+
job.should_receive(:process).with(:thumb, '30x30#').and_return(job2=mock)
|
17
|
+
job2.should_receive(:encode).with(:jpg).and_return(job3=mock)
|
18
|
+
@job_builder.build(job, '30x30#', :jpg).should == job3
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should work consistently with bang methods" do
|
22
|
+
job = mock
|
23
|
+
job.should_receive(:process!).with(:thumb, '30x30#').and_return(job)
|
24
|
+
job.should_receive(:encode!).with(:jpg).and_return(job)
|
25
|
+
@job_builder.build!(job, '30x30#', :jpg).should == job
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should yield nil if the arg isn't passed in" do
|
29
|
+
job = mock
|
30
|
+
job.should_receive(:process).with(:thumb, '30x30#').and_return(job2=mock)
|
31
|
+
job2.should_not_receive(:encode)
|
32
|
+
@job_builder.build(job, '30x30#').should == job2
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::JobDefinitions do
|
4
|
+
|
5
|
+
describe "defining jobs" do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@job_definitions = Dragonfly::JobDefinitions.new
|
9
|
+
@object = Object.new
|
10
|
+
@object.extend @job_definitions
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "a simple job" do
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
@job_definitions.add :thumb do |size|
|
17
|
+
process :thumb, size
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "correctly call job steps" do
|
22
|
+
@object.should_receive(:process).with(:thumb, '30x30#').and_return(job=mock)
|
23
|
+
@object.thumb('30x30#').should == job
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should correctly call job steps when bang is given" do
|
27
|
+
@object.should_receive(:process!).with(:thumb, '30x30#').and_return(@object)
|
28
|
+
@object.thumb!('30x30#').should == @object
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
## General tests for Endpoint module go here as it's a pretty simple wrapper around that
|
4
|
+
|
5
|
+
describe Dragonfly::JobEndpoint do
|
6
|
+
|
7
|
+
def make_request(job, opts={})
|
8
|
+
endpoint = Dragonfly::JobEndpoint.new(job)
|
9
|
+
Rack::MockRequest.new(endpoint).get('', opts)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "errors" do
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
@app = test_app
|
16
|
+
@app.datastore.stub!(:retrieve).with('egg').and_return(["GUNGLE", {:name => 'gung.txt'}])
|
17
|
+
@job = Dragonfly::Job.new(@app).fetch('egg')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return a correct response if successful" do
|
21
|
+
response = make_request(@job)
|
22
|
+
response.status.should == 200
|
23
|
+
response['ETag'].should =~ /^"\w+"$/
|
24
|
+
response['Cache-Control'].should == "public, max-age=31536000"
|
25
|
+
response['Content-Type'].should == 'text/plain'
|
26
|
+
response['Content-Length'].should == '6'
|
27
|
+
response.body.should == 'GUNGLE'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return 404 if the datastore raises data not found" do
|
31
|
+
@job.should_receive(:apply).and_raise(Dragonfly::DataStorage::DataNotFound)
|
32
|
+
response = make_request(@job)
|
33
|
+
response.status.should == 404
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "ETag" do
|
37
|
+
it "should return an ETag" do
|
38
|
+
response = make_request(@job)
|
39
|
+
response.headers['ETag'].should =~ /^"\w+"$/
|
40
|
+
end
|
41
|
+
|
42
|
+
[
|
43
|
+
"dingle",
|
44
|
+
"dingle, eggheads",
|
45
|
+
'"dingle", "eggheads"',
|
46
|
+
'*'
|
47
|
+
].each do |header|
|
48
|
+
it "should return a 304 if the correct ETag is specified in HTTP_IF_NONE_MATCH header e.g. #{header}" do
|
49
|
+
@job.should_receive(:unique_signature).at_least(:once).and_return('dingle')
|
50
|
+
response = make_request(@job, 'HTTP_IF_NONE_MATCH' => header)
|
51
|
+
response.status.should == 304
|
52
|
+
response['ETag'].should == '"dingle"'
|
53
|
+
response['Cache-Control'].should == "public, max-age=31536000"
|
54
|
+
response.body.should be_empty
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should not have applied any steps if the correct ETag is specified in HTTP_IF_NONE_MATCH header" do
|
59
|
+
response = make_request(@job, 'HTTP_IF_NONE_MATCH' => @job.serialize)
|
60
|
+
@job.applied_steps.should be_empty
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,605 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
# Matchers
|
4
|
+
def match_steps(steps)
|
5
|
+
simple_matcher("match steps #{steps.inspect}") do |given|
|
6
|
+
given.map{|step| step.class } == steps
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Dragonfly::Job do
|
11
|
+
|
12
|
+
describe "Step types" do
|
13
|
+
|
14
|
+
{
|
15
|
+
Dragonfly::Job::Fetch => :fetch,
|
16
|
+
Dragonfly::Job::Process => :process,
|
17
|
+
Dragonfly::Job::Encode => :encode,
|
18
|
+
Dragonfly::Job::Generate => :generate,
|
19
|
+
Dragonfly::Job::FetchFile => :fetch_file
|
20
|
+
}.each do |klass, step_name|
|
21
|
+
it "should return the correct step name for #{klass}" do
|
22
|
+
klass.step_name.should == step_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
{
|
27
|
+
Dragonfly::Job::Fetch => :f,
|
28
|
+
Dragonfly::Job::Process => :p,
|
29
|
+
Dragonfly::Job::Encode => :e,
|
30
|
+
Dragonfly::Job::Generate => :g,
|
31
|
+
Dragonfly::Job::FetchFile => :ff
|
32
|
+
}.each do |klass, abbreviation|
|
33
|
+
it "should return the correct abbreviation for #{klass}" do
|
34
|
+
klass.abbreviation.should == abbreviation
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "step_names" do
|
39
|
+
it "should return the available step names" do
|
40
|
+
Dragonfly::Job.step_names.should == [:fetch, :process, :encode, :generate, :fetch_file]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "without temp_object" do
|
47
|
+
|
48
|
+
before(:each) do
|
49
|
+
@app = mock_app
|
50
|
+
@job = Dragonfly::Job.new(@app)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should allow initializing with content" do
|
54
|
+
job = Dragonfly::Job.new(@app, Dragonfly::TempObject.new('eggheads'))
|
55
|
+
job.temp_object.data.should == 'eggheads'
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "fetch" do
|
59
|
+
before(:each) do
|
60
|
+
@job.fetch!('some_uid')
|
61
|
+
end
|
62
|
+
|
63
|
+
it { @job.steps.should match_steps([Dragonfly::Job::Fetch]) }
|
64
|
+
|
65
|
+
it "should retrieve from the app's datastore when applied" do
|
66
|
+
@app.datastore.should_receive(:retrieve).with('some_uid').and_return('HELLO')
|
67
|
+
@job.apply
|
68
|
+
@job.temp_object.data.should == 'HELLO'
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should set extra data if returned from the datastore" do
|
72
|
+
@app.datastore.should_receive(:retrieve).with('some_uid').and_return(['HELLO', {:name => 'test.txt', :meta => {1=>2}}])
|
73
|
+
@job.apply
|
74
|
+
@job.temp_object.data.should == 'HELLO'
|
75
|
+
@job.temp_object.name.should == 'test.txt'
|
76
|
+
@job.temp_object.meta.should == {1 => 2}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "process" do
|
81
|
+
it "should raise an error when applying" do
|
82
|
+
@job.process!(:resize, '20x30')
|
83
|
+
lambda{
|
84
|
+
@job.apply
|
85
|
+
}.should raise_error(Dragonfly::Job::NothingToProcess)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "encode" do
|
90
|
+
it "should raise an error when applying" do
|
91
|
+
@job.encode!(:gif)
|
92
|
+
lambda{
|
93
|
+
@job.apply
|
94
|
+
}.should raise_error(Dragonfly::Job::NothingToEncode)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "analyse" do
|
99
|
+
it "should raise an error" do
|
100
|
+
lambda{
|
101
|
+
@job.analyse(:width)
|
102
|
+
}.should raise_error(Dragonfly::Job::NothingToAnalyse)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "generate" do
|
107
|
+
before(:each) do
|
108
|
+
@job.generate!(:plasma, 20, 30)
|
109
|
+
end
|
110
|
+
|
111
|
+
it { @job.steps.should match_steps([Dragonfly::Job::Generate]) }
|
112
|
+
|
113
|
+
it "should use the generator when applied" do
|
114
|
+
@app.generator.should_receive(:generate).with(:plasma, 20, 30).and_return('hi')
|
115
|
+
@job.apply.data.should == 'hi'
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should save extra data if the generator returns it" do
|
119
|
+
@app.generator.should_receive(:generate).with(:plasma, 20, 30).and_return(['hi', {:name => 'plasma.png', :format => :png, :meta => {:a => :b}}])
|
120
|
+
@job.apply
|
121
|
+
@job.temp_object.data.should == 'hi'
|
122
|
+
@job.temp_object.name.should == 'plasma.png'
|
123
|
+
@job.temp_object.format.should == :png
|
124
|
+
@job.temp_object.meta.should == {:a => :b}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "fetch_file" do
|
129
|
+
before(:each) do
|
130
|
+
@job.fetch_file!(File.dirname(__FILE__) + '/../../samples/egg.png')
|
131
|
+
end
|
132
|
+
|
133
|
+
it { @job.steps.should match_steps([Dragonfly::Job::FetchFile]) }
|
134
|
+
|
135
|
+
it "should fetch the specified file when applied" do
|
136
|
+
@job.apply
|
137
|
+
@job.temp_object.size.should == 62664
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "with temp_object already there" do
|
145
|
+
|
146
|
+
before(:each) do
|
147
|
+
@app = mock_app
|
148
|
+
@temp_object = Dragonfly::TempObject.new('HELLO', :name => 'hello.txt', :meta => {:a => :b}, :format => :txt)
|
149
|
+
@job = Dragonfly::Job.new(@app)
|
150
|
+
@job.temp_object = @temp_object
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "apply" do
|
154
|
+
it "should return itself" do
|
155
|
+
@job.apply.should == @job
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "process" do
|
160
|
+
before(:each) do
|
161
|
+
@job.process!(:resize, '20x30')
|
162
|
+
end
|
163
|
+
|
164
|
+
it { @job.steps.should match_steps([Dragonfly::Job::Process]) }
|
165
|
+
|
166
|
+
it "should use the processor when applied" do
|
167
|
+
@app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return('hi')
|
168
|
+
@job.apply.data.should == 'hi'
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should maintain the temp object attributes" do
|
172
|
+
@app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return('hi')
|
173
|
+
temp_object = @job.apply.temp_object
|
174
|
+
temp_object.data.should == 'hi'
|
175
|
+
temp_object.name.should == 'hello.txt'
|
176
|
+
temp_object.meta.should == {:a => :b}
|
177
|
+
temp_object.format.should == :txt
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "encode" do
|
182
|
+
before(:each) do
|
183
|
+
@job.encode!(:gif, :bitrate => 'mumma')
|
184
|
+
end
|
185
|
+
|
186
|
+
it { @job.steps.should match_steps([Dragonfly::Job::Encode]) }
|
187
|
+
|
188
|
+
it "should use the encoder when applied" do
|
189
|
+
@app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return('alo')
|
190
|
+
@job.apply.data.should == 'alo'
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should maintain the temp object attributes (except format)" do
|
194
|
+
@app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return('alo')
|
195
|
+
temp_object = @job.apply.temp_object
|
196
|
+
temp_object.data.should == 'alo'
|
197
|
+
temp_object.name.should == 'hello.txt'
|
198
|
+
temp_object.meta.should == {:a => :b}
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should update the format" do
|
202
|
+
@app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return('alo')
|
203
|
+
@job.apply.temp_object.format.should == :gif
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "analysis" do
|
209
|
+
before(:each) do
|
210
|
+
@app = test_app
|
211
|
+
@job = Dragonfly::Job.new(@app, Dragonfly::TempObject.new('HELLO'))
|
212
|
+
@app.analyser.add(:num_letters){|temp_object, letter| temp_object.data.count(letter) }
|
213
|
+
end
|
214
|
+
it "should return correctly when calling analyse" do
|
215
|
+
@job.analyse(:num_letters, 'L').should == 2
|
216
|
+
end
|
217
|
+
it "should have mixed in the analyser method" do
|
218
|
+
@job.num_letters('L').should == 2
|
219
|
+
end
|
220
|
+
it "should return nil from analyse if calling any old method" do
|
221
|
+
@job.analyse(:robin_van_persie).should be_nil
|
222
|
+
end
|
223
|
+
it "should not allow calling any old method" do
|
224
|
+
lambda{
|
225
|
+
@job.robin_van_persie
|
226
|
+
}.should raise_error(NoMethodError)
|
227
|
+
end
|
228
|
+
it "should work correctly with chained jobs, applying before analysing" do
|
229
|
+
@app.processor.add(:double){|temp_object| temp_object.data * 2 }
|
230
|
+
@job.process(:double).num_letters('L').should == 4
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe "adding jobs" do
|
235
|
+
|
236
|
+
before(:each) do
|
237
|
+
@app = mock_app
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should raise an error if the app is different" do
|
241
|
+
job1 = Dragonfly::Job.new(@app)
|
242
|
+
job2 = Dragonfly::Job.new(mock_app)
|
243
|
+
lambda {
|
244
|
+
job1 + job2
|
245
|
+
}.should raise_error(Dragonfly::Job::AppDoesNotMatch)
|
246
|
+
end
|
247
|
+
|
248
|
+
describe "both belonging to the same app" do
|
249
|
+
before(:each) do
|
250
|
+
@job1 = Dragonfly::Job.new(@app, Dragonfly::TempObject.new('hello'))
|
251
|
+
@job1.process! :resize
|
252
|
+
@job2 = Dragonfly::Job.new(@app, Dragonfly::TempObject.new('hola'))
|
253
|
+
@job2.encode! :png
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should concatenate jobs" do
|
257
|
+
job3 = @job1 + @job2
|
258
|
+
job3.steps.should match_steps([
|
259
|
+
Dragonfly::Job::Process,
|
260
|
+
Dragonfly::Job::Encode
|
261
|
+
])
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should raise an error if the second job has applied steps" do
|
265
|
+
@job2.apply
|
266
|
+
lambda {
|
267
|
+
@job1 + @job2
|
268
|
+
}.should raise_error(Dragonfly::Job::JobAlreadyApplied)
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should not raise an error if the first job has applied steps" do
|
272
|
+
@job1.apply
|
273
|
+
lambda {
|
274
|
+
@job1 + @job2
|
275
|
+
}.should_not raise_error
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should have the first job's temp_object" do
|
279
|
+
(@job1 + @job2).temp_object.data.should == 'hello'
|
280
|
+
end
|
281
|
+
|
282
|
+
it "should have the correct applied steps" do
|
283
|
+
@job1.apply
|
284
|
+
(@job1 + @job2).applied_steps.should match_steps([
|
285
|
+
Dragonfly::Job::Process
|
286
|
+
])
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should have the correct pending steps" do
|
290
|
+
@job1.apply
|
291
|
+
(@job1 + @job2).pending_steps.should match_steps([
|
292
|
+
Dragonfly::Job::Encode
|
293
|
+
])
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
describe "defining extra steps after applying" do
|
300
|
+
before(:each) do
|
301
|
+
@app = mock_app
|
302
|
+
@job = Dragonfly::Job.new(@app)
|
303
|
+
@job.temp_object = Dragonfly::TempObject.new("hello")
|
304
|
+
@job.process! :resize
|
305
|
+
@job.apply
|
306
|
+
@job.encode! :micky
|
307
|
+
end
|
308
|
+
it "should not call apply on already applied steps" do
|
309
|
+
@job.steps[0].should_not_receive(:apply)
|
310
|
+
@job.apply
|
311
|
+
end
|
312
|
+
it "should call apply on not yet applied steps" do
|
313
|
+
@job.steps[1].should_receive(:apply)
|
314
|
+
@job.apply
|
315
|
+
end
|
316
|
+
it "should return all steps" do
|
317
|
+
@job.steps.should match_steps([
|
318
|
+
Dragonfly::Job::Process,
|
319
|
+
Dragonfly::Job::Encode
|
320
|
+
])
|
321
|
+
end
|
322
|
+
it "should return applied steps" do
|
323
|
+
@job.applied_steps.should match_steps([
|
324
|
+
Dragonfly::Job::Process
|
325
|
+
])
|
326
|
+
end
|
327
|
+
it "should return the pending steps" do
|
328
|
+
@job.pending_steps.should match_steps([
|
329
|
+
Dragonfly::Job::Encode
|
330
|
+
])
|
331
|
+
end
|
332
|
+
it "should not call apply on any steps when already applied" do
|
333
|
+
@job.apply
|
334
|
+
@job.steps[0].should_not_receive(:apply)
|
335
|
+
@job.steps[1].should_not_receive(:apply)
|
336
|
+
@job.apply
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
describe "chaining" do
|
341
|
+
|
342
|
+
before(:each) do
|
343
|
+
@app = mock_app
|
344
|
+
@job = Dragonfly::Job.new(@app)
|
345
|
+
end
|
346
|
+
|
347
|
+
it "should return itself if bang is used" do
|
348
|
+
@job.fetch!('some_uid').should == @job
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should return a new job if bang is not used" do
|
352
|
+
@job.fetch('some_uid').should_not == @job
|
353
|
+
end
|
354
|
+
|
355
|
+
describe "when a chained job is defined" do
|
356
|
+
before(:each) do
|
357
|
+
@job.fetch!('some_uid')
|
358
|
+
@job2 = @job.process(:resize, '30x30')
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should return the correct steps for the original job" do
|
362
|
+
@job.applied_steps.should match_steps([
|
363
|
+
])
|
364
|
+
@job.pending_steps.should match_steps([
|
365
|
+
Dragonfly::Job::Fetch
|
366
|
+
])
|
367
|
+
end
|
368
|
+
|
369
|
+
it "should return the correct data for the original job" do
|
370
|
+
@job.data.should == 'SOME_DATA'
|
371
|
+
end
|
372
|
+
|
373
|
+
it "should return the correct steps for the new job" do
|
374
|
+
@job2.applied_steps.should match_steps([
|
375
|
+
])
|
376
|
+
@job2.pending_steps.should match_steps([
|
377
|
+
Dragonfly::Job::Fetch,
|
378
|
+
Dragonfly::Job::Process
|
379
|
+
])
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should return the correct data for the new job" do
|
383
|
+
@job2.data.should == 'SOME_PROCESSED_DATA'
|
384
|
+
end
|
385
|
+
|
386
|
+
it "should not affect the other one when one is applied" do
|
387
|
+
@job.apply
|
388
|
+
@job.applied_steps.should match_steps([
|
389
|
+
Dragonfly::Job::Fetch
|
390
|
+
])
|
391
|
+
@job.pending_steps.should match_steps([
|
392
|
+
])
|
393
|
+
@job.temp_object.data.should == 'SOME_DATA'
|
394
|
+
@job2.applied_steps.should match_steps([
|
395
|
+
])
|
396
|
+
@job2.pending_steps.should match_steps([
|
397
|
+
Dragonfly::Job::Fetch,
|
398
|
+
Dragonfly::Job::Process
|
399
|
+
])
|
400
|
+
@job2.temp_object.should be_nil
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
end
|
405
|
+
|
406
|
+
describe "to_a" do
|
407
|
+
before(:each) do
|
408
|
+
@app = mock_app
|
409
|
+
end
|
410
|
+
it "should represent all the steps in array form" do
|
411
|
+
job = Dragonfly::Job.new(@app)
|
412
|
+
job.fetch! 'some_uid'
|
413
|
+
job.generate! :plasma # you wouldn't really call this after fetch but still works
|
414
|
+
job.process! :resize, '30x40'
|
415
|
+
job.encode! :gif, :bitrate => 20
|
416
|
+
job.to_a.should == [
|
417
|
+
[:f, 'some_uid'],
|
418
|
+
[:g, :plasma],
|
419
|
+
[:p, :resize, '30x40'],
|
420
|
+
[:e, :gif, {:bitrate => 20}]
|
421
|
+
]
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
describe "from_a" do
|
426
|
+
|
427
|
+
before(:each) do
|
428
|
+
@app = test_app
|
429
|
+
end
|
430
|
+
|
431
|
+
describe "a well-defined array" do
|
432
|
+
before(:each) do
|
433
|
+
@job = Dragonfly::Job.from_a([
|
434
|
+
[:f, 'some_uid'],
|
435
|
+
[:g, :plasma],
|
436
|
+
[:p, :resize, '30x40'],
|
437
|
+
[:e, :gif, {:bitrate => 20}]
|
438
|
+
], @app)
|
439
|
+
end
|
440
|
+
it "should have the correct step types" do
|
441
|
+
@job.steps.should match_steps([
|
442
|
+
Dragonfly::Job::Fetch,
|
443
|
+
Dragonfly::Job::Generate,
|
444
|
+
Dragonfly::Job::Process,
|
445
|
+
Dragonfly::Job::Encode
|
446
|
+
])
|
447
|
+
end
|
448
|
+
it "should have the correct args" do
|
449
|
+
@job.steps[0].args.should == ['some_uid']
|
450
|
+
@job.steps[1].args.should == [:plasma]
|
451
|
+
@job.steps[2].args.should == [:resize, '30x40']
|
452
|
+
@job.steps[3].args.should == [:gif, {:bitrate => 20}]
|
453
|
+
end
|
454
|
+
it "should have no applied steps" do
|
455
|
+
@job.applied_steps.should be_empty
|
456
|
+
end
|
457
|
+
it "should have all steps pending" do
|
458
|
+
@job.steps.should == @job.pending_steps
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
[
|
463
|
+
:f,
|
464
|
+
[:f],
|
465
|
+
[[]],
|
466
|
+
[[:egg]]
|
467
|
+
].each do |object|
|
468
|
+
it "should raise an error if the object passed in is #{object.inspect}" do
|
469
|
+
lambda {
|
470
|
+
Dragonfly::Job.from_a(object, @app)
|
471
|
+
}.should raise_error(Dragonfly::Job::InvalidArray)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
it "should initialize an empty job if the array is empty" do
|
476
|
+
job = Dragonfly::Job.from_a([], @app)
|
477
|
+
job.steps.should be_empty
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
describe "from_path" do
|
482
|
+
before(:each) do
|
483
|
+
@app = test_app
|
484
|
+
@serialized = @app.fetch('eggs').serialize
|
485
|
+
end
|
486
|
+
it "should work with a simple path" do
|
487
|
+
Dragonfly::Job.from_path("/#{@serialized}", @app).should be_a(Dragonfly::Job)
|
488
|
+
end
|
489
|
+
it "should work with no slash" do
|
490
|
+
Dragonfly::Job.from_path(@serialized, @app).should be_a(Dragonfly::Job)
|
491
|
+
end
|
492
|
+
it "should ignore the app's url_path_prefix" do
|
493
|
+
@app.url_path_prefix = '/images/yo'
|
494
|
+
Dragonfly::Job.from_path("/images/yo/#{@serialized}", @app).should be_a(Dragonfly::Job)
|
495
|
+
end
|
496
|
+
it "should not work with an incorrect url_path_prefix" do
|
497
|
+
@app.url_path_prefix = '/images/yo'
|
498
|
+
lambda{
|
499
|
+
Dragonfly::Job.from_path("/images/#{@serialized}", @app).should be_a(Dragonfly::Job)
|
500
|
+
}.should raise_error(Dragonfly::Serializer::BadString)
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
describe "serialization" do
|
505
|
+
before(:each) do
|
506
|
+
@app = test_app
|
507
|
+
@job = Dragonfly::Job.new(@app).fetch('mumma').process(:resize, '1x50')
|
508
|
+
end
|
509
|
+
it "should serialize itself" do
|
510
|
+
@job.serialize.should =~ /^\w{1,}$/
|
511
|
+
end
|
512
|
+
it "should deserialize to the same as the original" do
|
513
|
+
new_job = Dragonfly::Job.deserialize(@job.serialize, @app)
|
514
|
+
new_job.to_a.should == @job.to_a
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
describe "to_app" do
|
519
|
+
before(:each) do
|
520
|
+
@app = test_app
|
521
|
+
@job = Dragonfly::Job.new(@app)
|
522
|
+
end
|
523
|
+
it "should return an endpoint" do
|
524
|
+
endpoint = @job.to_app
|
525
|
+
endpoint.should be_a(Dragonfly::JobEndpoint)
|
526
|
+
endpoint.job.should == @job
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
describe "url" do
|
531
|
+
before(:each) do
|
532
|
+
@app = mock_app(:url_for => 'hello')
|
533
|
+
@job = Dragonfly::Job.new(@app)
|
534
|
+
end
|
535
|
+
it "should return a url" do
|
536
|
+
@job.generate!(:plasma)
|
537
|
+
@job.url.should == 'hello'
|
538
|
+
end
|
539
|
+
it "should return nil if there are no steps" do
|
540
|
+
@job.url.should be_nil
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
describe "to_fetched_job" do
|
545
|
+
it "should maintain the same temp_object and be already applied" do
|
546
|
+
app = mock_app
|
547
|
+
job = Dragonfly::Job.new(app, Dragonfly::TempObject.new("HELLO"))
|
548
|
+
new_job = job.to_fetched_job('some_uid')
|
549
|
+
new_job.temp_object.data.should == 'HELLO'
|
550
|
+
new_job.to_a.should == [
|
551
|
+
[:f, 'some_uid']
|
552
|
+
]
|
553
|
+
new_job.pending_steps.should be_empty
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
describe "format" do
|
558
|
+
before(:each) do
|
559
|
+
@app = test_app
|
560
|
+
end
|
561
|
+
it "should default to nil" do
|
562
|
+
job = @app.new_job("HELLO")
|
563
|
+
job.format.should be_nil
|
564
|
+
end
|
565
|
+
it "should use the temp_object format if it exists" do
|
566
|
+
job = @app.new_job("HELLO", :format => :txt)
|
567
|
+
job.format.should == :txt
|
568
|
+
end
|
569
|
+
it "should use the analyser format if it exists" do
|
570
|
+
@app.analyser.add :format do |temp_object|
|
571
|
+
:egg
|
572
|
+
end
|
573
|
+
job = @app.new_job("HELLO")
|
574
|
+
job.format.should == :egg
|
575
|
+
end
|
576
|
+
it "should prefer the temp_object format if both exist" do
|
577
|
+
@app.analyser.add :format do |temp_object|
|
578
|
+
:egg
|
579
|
+
end
|
580
|
+
job = @app.new_job("HELLO", :format => :txt)
|
581
|
+
job.format.should == :txt
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
describe "validate_sha!" do
|
586
|
+
before(:each) do
|
587
|
+
@app = test_app
|
588
|
+
@job = @app.fetch('eggs')
|
589
|
+
end
|
590
|
+
it "should raise an error if nothing is given" do
|
591
|
+
lambda{
|
592
|
+
@job.validate_sha!(nil)
|
593
|
+
}.should raise_error(Dragonfly::Job::NoSHAGiven)
|
594
|
+
end
|
595
|
+
it "should raise an error if the wrong SHA is given" do
|
596
|
+
lambda{
|
597
|
+
@job.validate_sha!('asdf')
|
598
|
+
}.should raise_error(Dragonfly::Job::IncorrectSHA)
|
599
|
+
end
|
600
|
+
it "should return self if ok" do
|
601
|
+
@job.validate_sha!(@job.sha).should == @job
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
end
|