fog-dragonfly 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fog-dragonfly might be problematic. Click here for more details.
- data/.specopts +2 -0
- data/.yardopts +23 -0
- data/Gemfile +23 -0
- data/Gemfile.rails.2.3.5 +14 -0
- data/History.md +266 -0
- data/LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +92 -0
- data/VERSION +1 -0
- data/config.ru +13 -0
- data/docs.watchr +1 -0
- data/dragonfly.gemspec +293 -0
- data/extra_docs/Analysers.md +108 -0
- data/extra_docs/Caching.md +23 -0
- data/extra_docs/Configuration.md +138 -0
- data/extra_docs/DataStorage.md +136 -0
- data/extra_docs/Encoding.md +96 -0
- data/extra_docs/GeneralUsage.md +121 -0
- data/extra_docs/Generators.md +102 -0
- data/extra_docs/Heroku.md +50 -0
- data/extra_docs/Index.md +36 -0
- data/extra_docs/MimeTypes.md +40 -0
- data/extra_docs/Models.md +266 -0
- data/extra_docs/Mongo.md +45 -0
- data/extra_docs/Processing.md +130 -0
- data/extra_docs/Rack.md +52 -0
- data/extra_docs/Rails2.md +55 -0
- data/extra_docs/Rails3.md +62 -0
- data/extra_docs/Sinatra.md +25 -0
- data/extra_docs/URLs.md +169 -0
- data/features/3.0.3.feature +8 -0
- data/features/images.feature +47 -0
- data/features/no_processing.feature +14 -0
- data/features/rails_2.3.5.feature +7 -0
- data/features/steps/common_steps.rb +8 -0
- data/features/steps/dragonfly_steps.rb +66 -0
- data/features/steps/rails_steps.rb +39 -0
- data/features/support/env.rb +40 -0
- data/fixtures/files/app/models/album.rb +3 -0
- data/fixtures/files/app/views/albums/new.html.erb +4 -0
- data/fixtures/files/app/views/albums/show.html.erb +4 -0
- data/fixtures/files/config/initializers/dragonfly.rb +4 -0
- data/fixtures/files/features/manage_album_images.feature +12 -0
- data/fixtures/files/features/step_definitions/image_steps.rb +15 -0
- data/fixtures/files/features/support/paths.rb +15 -0
- data/fixtures/files/features/text_images.feature +7 -0
- data/fixtures/rails_2.3.5/template.rb +10 -0
- data/fixtures/rails_3.0.3/template.rb +20 -0
- data/irbrc.rb +17 -0
- data/lib/dragonfly.rb +45 -0
- data/lib/dragonfly/active_model_extensions.rb +13 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +169 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +45 -0
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
- data/lib/dragonfly/active_model_extensions/validations.rb +37 -0
- data/lib/dragonfly/analyser.rb +59 -0
- data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
- data/lib/dragonfly/analysis/image_magick_analyser.rb +47 -0
- data/lib/dragonfly/analysis/r_magick_analyser.rb +63 -0
- data/lib/dragonfly/app.rb +182 -0
- data/lib/dragonfly/config/heroku.rb +19 -0
- data/lib/dragonfly/config/image_magick.rb +41 -0
- data/lib/dragonfly/config/r_magick.rb +46 -0
- data/lib/dragonfly/config/rails.rb +17 -0
- data/lib/dragonfly/configurable.rb +119 -0
- data/lib/dragonfly/core_ext/object.rb +8 -0
- data/lib/dragonfly/core_ext/string.rb +9 -0
- data/lib/dragonfly/core_ext/symbol.rb +9 -0
- data/lib/dragonfly/data_storage.rb +9 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +114 -0
- data/lib/dragonfly/data_storage/mongo_data_store.rb +82 -0
- data/lib/dragonfly/data_storage/s3data_store.rb +115 -0
- data/lib/dragonfly/encoder.rb +13 -0
- data/lib/dragonfly/encoding/image_magick_encoder.rb +57 -0
- data/lib/dragonfly/encoding/r_magick_encoder.rb +61 -0
- data/lib/dragonfly/function_manager.rb +69 -0
- data/lib/dragonfly/generation/hash_with_css_style_keys.rb +23 -0
- data/lib/dragonfly/generation/image_magick_generator.rb +140 -0
- data/lib/dragonfly/generation/r_magick_generator.rb +155 -0
- data/lib/dragonfly/generator.rb +9 -0
- data/lib/dragonfly/image_magick_utils.rb +81 -0
- data/lib/dragonfly/job.rb +371 -0
- data/lib/dragonfly/job_builder.rb +39 -0
- data/lib/dragonfly/job_definitions.rb +26 -0
- data/lib/dragonfly/job_endpoint.rb +15 -0
- data/lib/dragonfly/loggable.rb +28 -0
- data/lib/dragonfly/middleware.rb +34 -0
- data/lib/dragonfly/processing/image_magick_processor.rb +99 -0
- data/lib/dragonfly/processing/r_magick_processor.rb +126 -0
- data/lib/dragonfly/processor.rb +9 -0
- data/lib/dragonfly/r_magick_utils.rb +48 -0
- data/lib/dragonfly/rails/images.rb +22 -0
- data/lib/dragonfly/response.rb +82 -0
- data/lib/dragonfly/routed_endpoint.rb +40 -0
- data/lib/dragonfly/serializer.rb +32 -0
- data/lib/dragonfly/simple_cache.rb +23 -0
- data/lib/dragonfly/simple_endpoint.rb +63 -0
- data/lib/dragonfly/temp_object.rb +220 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/sample.docx +0 -0
- data/samples/taj.jpg +0 -0
- data/spec/argument_matchers.rb +19 -0
- 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_model_extensions/model_spec.rb +723 -0
- 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 +57 -0
- data/spec/dragonfly/analysis/image_magick_analyser_spec.rb +15 -0
- data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +27 -0
- data/spec/dragonfly/analysis/shared_analyser_spec.rb +51 -0
- data/spec/dragonfly/app_spec.rb +280 -0
- data/spec/dragonfly/config/r_magick_spec.rb +25 -0
- data/spec/dragonfly/configurable_spec.rb +220 -0
- data/spec/dragonfly/core_ext/string_spec.rb +17 -0
- data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
- data/spec/dragonfly/data_storage/data_store_spec.rb +76 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +169 -0
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +38 -0
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +94 -0
- data/spec/dragonfly/deprecation_spec.rb +20 -0
- data/spec/dragonfly/encoding/image_magick_encoder_spec.rb +41 -0
- data/spec/dragonfly/encoding/r_magick_encoder_spec.rb +37 -0
- data/spec/dragonfly/function_manager_spec.rb +154 -0
- data/spec/dragonfly/generation/hash_with_css_style_keys_spec.rb +24 -0
- data/spec/dragonfly/generation/image_magick_generator_spec.rb +12 -0
- data/spec/dragonfly/generation/r_magick_generator_spec.rb +24 -0
- data/spec/dragonfly/generation/shared_generator_spec.rb +91 -0
- data/spec/dragonfly/image_magick_utils_spec.rb +16 -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 +120 -0
- data/spec/dragonfly/job_spec.rb +773 -0
- data/spec/dragonfly/loggable_spec.rb +80 -0
- data/spec/dragonfly/middleware_spec.rb +68 -0
- data/spec/dragonfly/processing/image_magick_processor_spec.rb +29 -0
- data/spec/dragonfly/processing/r_magick_processor_spec.rb +26 -0
- data/spec/dragonfly/processing/shared_processing_spec.rb +215 -0
- 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 +89 -0
- data/spec/dragonfly/temp_object_spec.rb +352 -0
- data/spec/image_matchers.rb +47 -0
- data/spec/simple_matchers.rb +44 -0
- data/spec/spec_helper.rb +58 -0
- data/yard/handlers/configurable_attr_handler.rb +38 -0
- data/yard/setup.rb +15 -0
- data/yard/templates/default/fulldoc/html/css/common.css +107 -0
- data/yard/templates/default/layout/html/layout.erb +87 -0
- data/yard/templates/default/module/html/configuration_summary.erb +31 -0
- data/yard/templates/default/module/setup.rb +17 -0
- metadata +550 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Needs: @generator
|
4
|
+
describe "image generator", :shared => true do
|
5
|
+
|
6
|
+
describe "generating an image with the given dimensions" do
|
7
|
+
before(:each) do
|
8
|
+
@image, @extra = @generator.plasma(23,12)
|
9
|
+
end
|
10
|
+
it {@image.should have_width(23)}
|
11
|
+
it {@image.should have_height(12)}
|
12
|
+
it {@image.should have_format('png')}
|
13
|
+
it {@extra.should == {:format => :png, :name => 'plasma.png'}}
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "specifying the format" do
|
17
|
+
before(:each) do
|
18
|
+
@image, @extra = @generator.plasma(23, 12, :gif)
|
19
|
+
end
|
20
|
+
it {@image.should have_format('gif')}
|
21
|
+
it {@extra.should == {:format => :gif, :name => 'plasma.gif'}}
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "text" do
|
25
|
+
before(:each) do
|
26
|
+
@text = "mmm"
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "creating a text image" do
|
30
|
+
before(:each) do
|
31
|
+
@image, @extra = @generator.text(@text, :font_size => 12)
|
32
|
+
end
|
33
|
+
it {@image.should have_width(20..40)} # approximate
|
34
|
+
it {@image.should have_height(10..20)}
|
35
|
+
it {@image.should have_format('png')}
|
36
|
+
it {@extra.should == {:format => :png, :name => 'text.png'}}
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "specifying the format" do
|
40
|
+
before(:each) do
|
41
|
+
@image, @extra = @generator.text(@text, :format => :gif)
|
42
|
+
end
|
43
|
+
it {@image.should have_format('gif')}
|
44
|
+
it {@extra.should == {:format => :gif, :name => 'text.gif'}}
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "padding" do
|
48
|
+
before(:each) do
|
49
|
+
no_padding_text, extra = @generator.text(@text, :font_size => 12)
|
50
|
+
@width = image_properties(no_padding_text)[:width].to_i
|
51
|
+
@height = image_properties(no_padding_text)[:height].to_i
|
52
|
+
end
|
53
|
+
it "1 number shortcut" do
|
54
|
+
image, extra = @generator.text(@text, :padding => '10')
|
55
|
+
image.should have_width(@width + 20)
|
56
|
+
image.should have_height(@height + 20)
|
57
|
+
end
|
58
|
+
it "2 numbers shortcut" do
|
59
|
+
image, extra = @generator.text(@text, :padding => '10 5')
|
60
|
+
image.should have_width(@width + 10)
|
61
|
+
image.should have_height(@height + 20)
|
62
|
+
end
|
63
|
+
it "3 numbers shortcut" do
|
64
|
+
image, extra = @generator.text(@text, :padding => '10 5 8')
|
65
|
+
image.should have_width(@width + 10)
|
66
|
+
image.should have_height(@height + 18)
|
67
|
+
end
|
68
|
+
it "4 numbers shortcut" do
|
69
|
+
image, extra = @generator.text(@text, :padding => '1 2 3 4')
|
70
|
+
image.should have_width(@width + 6)
|
71
|
+
image.should have_height(@height + 4)
|
72
|
+
end
|
73
|
+
it "should override the general padding declaration with the specific one (e.g. 'padding-left')" do
|
74
|
+
image, extra = @generator.text(@text, :padding => '10', 'padding-left' => 9)
|
75
|
+
image.should have_width(@width + 19)
|
76
|
+
image.should have_height(@height + 20)
|
77
|
+
end
|
78
|
+
it "should ignore 'px' suffixes" do
|
79
|
+
image, extra = @generator.text(@text, :padding => '1px 2px 3px 4px')
|
80
|
+
image.should have_width(@width + 6)
|
81
|
+
image.should have_height(@height + 4)
|
82
|
+
end
|
83
|
+
it "bad padding string" do
|
84
|
+
lambda{
|
85
|
+
@generator.text(@text, :padding => '1 2 3 4 5')
|
86
|
+
}.should raise_error(ArgumentError)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::ImageMagickUtils do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@obj = Object.new
|
7
|
+
@obj.extend(Dragonfly::ImageMagickUtils)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should raise an error if the identify command isn't found" do
|
11
|
+
lambda{
|
12
|
+
@obj.send(:run, "non-existent-command")
|
13
|
+
}.should raise_error(Dragonfly::ImageMagickUtils::ShellCommandFailed)
|
14
|
+
end
|
15
|
+
|
16
|
+
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,120 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
3
|
+
|
4
|
+
## General tests for Response go here as it's a pretty simple wrapper around that
|
5
|
+
|
6
|
+
describe Dragonfly::JobEndpoint do
|
7
|
+
|
8
|
+
def make_request(job, opts={})
|
9
|
+
endpoint = Dragonfly::JobEndpoint.new(job)
|
10
|
+
Rack::MockRequest.new(endpoint).get('', opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@app = test_app
|
15
|
+
@app.datastore.stub!(:retrieve).with('egg').and_return(["GUNGLE", {:name => 'gung.txt'}])
|
16
|
+
@job = Dragonfly::Job.new(@app).fetch('egg')
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return a correct response if successful" do
|
20
|
+
response = make_request(@job)
|
21
|
+
response.status.should == 200
|
22
|
+
response['ETag'].should =~ /^"\w+"$/
|
23
|
+
response['Cache-Control'].should == "public, max-age=31536000"
|
24
|
+
response['Content-Type'].should == 'text/plain'
|
25
|
+
response['Content-Length'].should == '6'
|
26
|
+
response['Content-Disposition'].should == 'filename="gung.txt"'
|
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.unique_signature)
|
60
|
+
@job.applied_steps.should be_empty
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "Content Disposition" do
|
65
|
+
before(:each) do
|
66
|
+
@app.encoder.add{|temp_object, format| temp_object }
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "filename" do
|
70
|
+
it "should return the original name" do
|
71
|
+
response = make_request(@job)
|
72
|
+
response['Content-Disposition'].should == 'filename="gung.txt"'
|
73
|
+
end
|
74
|
+
it "should return a filename with a different extension if it's been encoded" do
|
75
|
+
response = make_request(@job.encode(:doogs))
|
76
|
+
response['Content-Disposition'].should == 'filename="gung.doogs"'
|
77
|
+
end
|
78
|
+
it "should not have the filename if name doesn't exist" do
|
79
|
+
response = make_request(@app.new_job("ADFSDF"))
|
80
|
+
response['Content-Disposition'].should be_nil
|
81
|
+
end
|
82
|
+
it "should cope with filenames with no ext" do
|
83
|
+
response = make_request(@app.new_job("ASDF", :name => 'asdf'))
|
84
|
+
response['Content-Disposition'].should == 'filename="asdf"'
|
85
|
+
end
|
86
|
+
it "should uri encode funny characters" do
|
87
|
+
response = make_request(@app.new_job("ASDF", :name => '£@$£ `'))
|
88
|
+
response['Content-Disposition'].should == 'filename="%C2%A3@$%C2%A3%20%60"'
|
89
|
+
end
|
90
|
+
it "should allow for setting the filename using a block" do
|
91
|
+
@app.content_filename = proc{|job, request|
|
92
|
+
job.basename.reverse.upcase + request['a']
|
93
|
+
}
|
94
|
+
response = make_request(@job, 'QUERY_STRING' => 'a=egg')
|
95
|
+
response['Content-Disposition'].should == 'filename="GNUGegg"'
|
96
|
+
end
|
97
|
+
it "should not include the filename if configured to be nil" do
|
98
|
+
@app.content_filename = nil
|
99
|
+
response = make_request(@job)
|
100
|
+
response['Content-Disposition'].should be_nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "content disposition" do
|
105
|
+
it "should use the app's configured content-disposition" do
|
106
|
+
@app.content_disposition = :attachment
|
107
|
+
response = make_request(@job)
|
108
|
+
response['Content-Disposition'].should == 'attachment; filename="gung.txt"'
|
109
|
+
end
|
110
|
+
it "should allow using a block to set the content disposition" do
|
111
|
+
@app.content_disposition = proc{|job, request|
|
112
|
+
job.basename + request['blah']
|
113
|
+
}
|
114
|
+
response = make_request(@job, 'QUERY_STRING' => 'blah=yo')
|
115
|
+
response['Content-Disposition'].should == 'gungyo; filename="gung.txt"'
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
@@ -0,0 +1,773 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
# Matchers
|
4
|
+
Spec::Matchers.define :match_steps do |steps|
|
5
|
+
match 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
|
+
|
180
|
+
it "should allow returning an array with extra attributes from the processor" do
|
181
|
+
@app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return(['hi', {:name => 'hello_20x30.txt', :meta => {:eggs => 'asdf'}}])
|
182
|
+
temp_object = @job.apply.temp_object
|
183
|
+
temp_object.data.should == 'hi'
|
184
|
+
temp_object.name.should == 'hello_20x30.txt'
|
185
|
+
temp_object.meta.should == {:a => :b, :eggs => 'asdf'}
|
186
|
+
temp_object.format.should == :txt
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "encode" do
|
191
|
+
before(:each) do
|
192
|
+
@job.encode!(:gif, :bitrate => 'mumma')
|
193
|
+
end
|
194
|
+
|
195
|
+
it { @job.steps.should match_steps([Dragonfly::Job::Encode]) }
|
196
|
+
|
197
|
+
it "should use the encoder when applied" do
|
198
|
+
@app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return('alo')
|
199
|
+
@job.apply.data.should == 'alo'
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should maintain the temp object attributes (except format)" do
|
203
|
+
@app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return('alo')
|
204
|
+
temp_object = @job.apply.temp_object
|
205
|
+
temp_object.data.should == 'alo'
|
206
|
+
temp_object.name.should == 'hello.txt'
|
207
|
+
temp_object.meta.should == {:a => :b}
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should update the format" do
|
211
|
+
@app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return('alo')
|
212
|
+
@job.apply.temp_object.format.should == :gif
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should allow returning an array with extra attributes form the encoder" do
|
216
|
+
@app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return(['alo', {:name => 'doobie', :meta => {:eggs => 'fish'}}])
|
217
|
+
temp_object = @job.apply.temp_object
|
218
|
+
temp_object.data.should == 'alo'
|
219
|
+
temp_object.name.should == 'doobie'
|
220
|
+
temp_object.meta.should == {:a => :b, :eggs => 'fish'}
|
221
|
+
end
|
222
|
+
|
223
|
+
it "not allow overriding the format" do
|
224
|
+
@app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return(['alo', {:format => :png}])
|
225
|
+
temp_object = @job.apply.temp_object
|
226
|
+
temp_object.format.should == :gif
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "analysis" do
|
232
|
+
before(:each) do
|
233
|
+
@app = test_app
|
234
|
+
@job = Dragonfly::Job.new(@app, Dragonfly::TempObject.new('HELLO'))
|
235
|
+
@app.analyser.add(:num_letters){|temp_object, letter| temp_object.data.count(letter) }
|
236
|
+
end
|
237
|
+
it "should return correctly when calling analyse" do
|
238
|
+
@job.analyse(:num_letters, 'L').should == 2
|
239
|
+
end
|
240
|
+
it "should have mixed in the analyser method" do
|
241
|
+
@job.num_letters('L').should == 2
|
242
|
+
end
|
243
|
+
it "should return nil from analyse if calling any old method" do
|
244
|
+
@job.analyse(:robin_van_persie).should be_nil
|
245
|
+
end
|
246
|
+
it "should not allow calling any old method" do
|
247
|
+
lambda{
|
248
|
+
@job.robin_van_persie
|
249
|
+
}.should raise_error(NoMethodError)
|
250
|
+
end
|
251
|
+
it "should work correctly with chained jobs, applying before analysing" do
|
252
|
+
@app.processor.add(:double){|temp_object| temp_object.data * 2 }
|
253
|
+
@job.process(:double).num_letters('L').should == 4
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe "adding jobs" do
|
258
|
+
|
259
|
+
before(:each) do
|
260
|
+
@app = mock_app
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should raise an error if the app is different" do
|
264
|
+
job1 = Dragonfly::Job.new(@app)
|
265
|
+
job2 = Dragonfly::Job.new(mock_app)
|
266
|
+
lambda {
|
267
|
+
job1 + job2
|
268
|
+
}.should raise_error(Dragonfly::Job::AppDoesNotMatch)
|
269
|
+
end
|
270
|
+
|
271
|
+
describe "both belonging to the same app" do
|
272
|
+
before(:each) do
|
273
|
+
@job1 = Dragonfly::Job.new(@app, Dragonfly::TempObject.new('hello'))
|
274
|
+
@job1.process! :resize
|
275
|
+
@job2 = Dragonfly::Job.new(@app, Dragonfly::TempObject.new('hola'))
|
276
|
+
@job2.encode! :png
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should concatenate jobs" do
|
280
|
+
job3 = @job1 + @job2
|
281
|
+
job3.steps.should match_steps([
|
282
|
+
Dragonfly::Job::Process,
|
283
|
+
Dragonfly::Job::Encode
|
284
|
+
])
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should raise an error if the second job has applied steps" do
|
288
|
+
@job2.apply
|
289
|
+
lambda {
|
290
|
+
@job1 + @job2
|
291
|
+
}.should raise_error(Dragonfly::Job::JobAlreadyApplied)
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should not raise an error if the first job has applied steps" do
|
295
|
+
@job1.apply
|
296
|
+
lambda {
|
297
|
+
@job1 + @job2
|
298
|
+
}.should_not raise_error
|
299
|
+
end
|
300
|
+
|
301
|
+
it "should have the first job's temp_object" do
|
302
|
+
(@job1 + @job2).temp_object.data.should == 'hello'
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should have the correct applied steps" do
|
306
|
+
@job1.apply
|
307
|
+
(@job1 + @job2).applied_steps.should match_steps([
|
308
|
+
Dragonfly::Job::Process
|
309
|
+
])
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should have the correct pending steps" do
|
313
|
+
@job1.apply
|
314
|
+
(@job1 + @job2).pending_steps.should match_steps([
|
315
|
+
Dragonfly::Job::Encode
|
316
|
+
])
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
end
|
321
|
+
|
322
|
+
describe "defining extra steps after applying" do
|
323
|
+
before(:each) do
|
324
|
+
@app = mock_app
|
325
|
+
@job = Dragonfly::Job.new(@app)
|
326
|
+
@job.temp_object = Dragonfly::TempObject.new("hello")
|
327
|
+
@job.process! :resize
|
328
|
+
@job.apply
|
329
|
+
@job.encode! :micky
|
330
|
+
end
|
331
|
+
it "should not call apply on already applied steps" do
|
332
|
+
@job.steps[0].should_not_receive(:apply)
|
333
|
+
@job.apply
|
334
|
+
end
|
335
|
+
it "should call apply on not yet applied steps" do
|
336
|
+
@job.steps[1].should_receive(:apply)
|
337
|
+
@job.apply
|
338
|
+
end
|
339
|
+
it "should return all steps" do
|
340
|
+
@job.steps.should match_steps([
|
341
|
+
Dragonfly::Job::Process,
|
342
|
+
Dragonfly::Job::Encode
|
343
|
+
])
|
344
|
+
end
|
345
|
+
it "should return applied steps" do
|
346
|
+
@job.applied_steps.should match_steps([
|
347
|
+
Dragonfly::Job::Process
|
348
|
+
])
|
349
|
+
end
|
350
|
+
it "should return the pending steps" do
|
351
|
+
@job.pending_steps.should match_steps([
|
352
|
+
Dragonfly::Job::Encode
|
353
|
+
])
|
354
|
+
end
|
355
|
+
it "should not call apply on any steps when already applied" do
|
356
|
+
@job.apply
|
357
|
+
@job.steps[0].should_not_receive(:apply)
|
358
|
+
@job.steps[1].should_not_receive(:apply)
|
359
|
+
@job.apply
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
describe "chaining" do
|
364
|
+
|
365
|
+
before(:each) do
|
366
|
+
@app = mock_app
|
367
|
+
@job = Dragonfly::Job.new(@app)
|
368
|
+
end
|
369
|
+
|
370
|
+
it "should return itself if bang is used" do
|
371
|
+
@job.fetch!('some_uid').should == @job
|
372
|
+
end
|
373
|
+
|
374
|
+
it "should return a new job if bang is not used" do
|
375
|
+
@job.fetch('some_uid').should_not == @job
|
376
|
+
end
|
377
|
+
|
378
|
+
describe "when a chained job is defined" do
|
379
|
+
before(:each) do
|
380
|
+
@job.fetch!('some_uid')
|
381
|
+
@job2 = @job.process(:resize, '30x30')
|
382
|
+
end
|
383
|
+
|
384
|
+
it "should return the correct steps for the original job" do
|
385
|
+
@job.applied_steps.should match_steps([
|
386
|
+
])
|
387
|
+
@job.pending_steps.should match_steps([
|
388
|
+
Dragonfly::Job::Fetch
|
389
|
+
])
|
390
|
+
end
|
391
|
+
|
392
|
+
it "should return the correct data for the original job" do
|
393
|
+
@job.data.should == 'SOME_DATA'
|
394
|
+
end
|
395
|
+
|
396
|
+
it "should return the correct steps for the new job" do
|
397
|
+
@job2.applied_steps.should match_steps([
|
398
|
+
])
|
399
|
+
@job2.pending_steps.should match_steps([
|
400
|
+
Dragonfly::Job::Fetch,
|
401
|
+
Dragonfly::Job::Process
|
402
|
+
])
|
403
|
+
end
|
404
|
+
|
405
|
+
it "should return the correct data for the new job" do
|
406
|
+
@job2.data.should == 'SOME_PROCESSED_DATA'
|
407
|
+
end
|
408
|
+
|
409
|
+
it "should not affect the other one when one is applied" do
|
410
|
+
@job.apply
|
411
|
+
@job.applied_steps.should match_steps([
|
412
|
+
Dragonfly::Job::Fetch
|
413
|
+
])
|
414
|
+
@job.pending_steps.should match_steps([
|
415
|
+
])
|
416
|
+
@job.temp_object.data.should == 'SOME_DATA'
|
417
|
+
@job2.applied_steps.should match_steps([
|
418
|
+
])
|
419
|
+
@job2.pending_steps.should match_steps([
|
420
|
+
Dragonfly::Job::Fetch,
|
421
|
+
Dragonfly::Job::Process
|
422
|
+
])
|
423
|
+
@job2.temp_object.should be_nil
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
end
|
428
|
+
|
429
|
+
describe "to_a" do
|
430
|
+
before(:each) do
|
431
|
+
@app = mock_app
|
432
|
+
end
|
433
|
+
it "should represent all the steps in array form" do
|
434
|
+
job = Dragonfly::Job.new(@app)
|
435
|
+
job.fetch! 'some_uid'
|
436
|
+
job.generate! :plasma # you wouldn't really call this after fetch but still works
|
437
|
+
job.process! :resize, '30x40'
|
438
|
+
job.encode! :gif, :bitrate => 20
|
439
|
+
job.to_a.should == [
|
440
|
+
[:f, 'some_uid'],
|
441
|
+
[:g, :plasma],
|
442
|
+
[:p, :resize, '30x40'],
|
443
|
+
[:e, :gif, {:bitrate => 20}]
|
444
|
+
]
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
describe "from_a" do
|
449
|
+
|
450
|
+
before(:each) do
|
451
|
+
@app = test_app
|
452
|
+
end
|
453
|
+
|
454
|
+
describe "a well-defined array" do
|
455
|
+
before(:each) do
|
456
|
+
@job = Dragonfly::Job.from_a([
|
457
|
+
[:f, 'some_uid'],
|
458
|
+
[:g, :plasma],
|
459
|
+
[:p, :resize, '30x40'],
|
460
|
+
[:e, :gif, {:bitrate => 20}]
|
461
|
+
], @app)
|
462
|
+
end
|
463
|
+
it "should have the correct step types" do
|
464
|
+
@job.steps.should match_steps([
|
465
|
+
Dragonfly::Job::Fetch,
|
466
|
+
Dragonfly::Job::Generate,
|
467
|
+
Dragonfly::Job::Process,
|
468
|
+
Dragonfly::Job::Encode
|
469
|
+
])
|
470
|
+
end
|
471
|
+
it "should have the correct args" do
|
472
|
+
@job.steps[0].args.should == ['some_uid']
|
473
|
+
@job.steps[1].args.should == [:plasma]
|
474
|
+
@job.steps[2].args.should == [:resize, '30x40']
|
475
|
+
@job.steps[3].args.should == [:gif, {:bitrate => 20}]
|
476
|
+
end
|
477
|
+
it "should have no applied steps" do
|
478
|
+
@job.applied_steps.should be_empty
|
479
|
+
end
|
480
|
+
it "should have all steps pending" do
|
481
|
+
@job.steps.should == @job.pending_steps
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
[
|
486
|
+
:f,
|
487
|
+
[:f],
|
488
|
+
[[]],
|
489
|
+
[[:egg]]
|
490
|
+
].each do |object|
|
491
|
+
it "should raise an error if the object passed in is #{object.inspect}" do
|
492
|
+
lambda {
|
493
|
+
Dragonfly::Job.from_a(object, @app)
|
494
|
+
}.should raise_error(Dragonfly::Job::InvalidArray)
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
it "should initialize an empty job if the array is empty" do
|
499
|
+
job = Dragonfly::Job.from_a([], @app)
|
500
|
+
job.steps.should be_empty
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
describe "from_path" do
|
505
|
+
before(:each) do
|
506
|
+
@app = test_app
|
507
|
+
@serialized = @app.fetch('eggs').serialize
|
508
|
+
end
|
509
|
+
it "should work with a simple path" do
|
510
|
+
Dragonfly::Job.from_path("/#{@serialized}", @app).should be_a(Dragonfly::Job)
|
511
|
+
end
|
512
|
+
it "should work with no slash" do
|
513
|
+
Dragonfly::Job.from_path(@serialized, @app).should be_a(Dragonfly::Job)
|
514
|
+
end
|
515
|
+
it "should ignore the app's url_path_prefix" do
|
516
|
+
@app.url_path_prefix = '/images/yo'
|
517
|
+
Dragonfly::Job.from_path("/images/yo/#{@serialized}", @app).should be_a(Dragonfly::Job)
|
518
|
+
end
|
519
|
+
it "should not work with an incorrect url_path_prefix" do
|
520
|
+
@app.url_path_prefix = '/images/yo'
|
521
|
+
lambda{
|
522
|
+
Dragonfly::Job.from_path("/images/#{@serialized}", @app).should be_a(Dragonfly::Job)
|
523
|
+
}.should raise_error(Dragonfly::Serializer::BadString)
|
524
|
+
end
|
525
|
+
it "should ignore any suffix" do
|
526
|
+
Dragonfly::Job.from_path("/#{@serialized}asdfJASKLDF*()!@$%{}|/GGG/.png.your.mum", @app).should be_a(Dragonfly::Job)
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
describe "serialization" do
|
531
|
+
before(:each) do
|
532
|
+
@app = test_app
|
533
|
+
@job = Dragonfly::Job.new(@app).fetch('mumma').process(:resize, '1x50')
|
534
|
+
end
|
535
|
+
it "should serialize itself" do
|
536
|
+
@job.serialize.should =~ /^\w{1,}$/
|
537
|
+
end
|
538
|
+
it "should deserialize to the same as the original" do
|
539
|
+
new_job = Dragonfly::Job.deserialize(@job.serialize, @app)
|
540
|
+
new_job.to_a.should == @job.to_a
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
describe "to_app" do
|
545
|
+
before(:each) do
|
546
|
+
@app = test_app
|
547
|
+
@job = Dragonfly::Job.new(@app)
|
548
|
+
end
|
549
|
+
it "should return an endpoint" do
|
550
|
+
endpoint = @job.to_app
|
551
|
+
endpoint.should be_a(Dragonfly::JobEndpoint)
|
552
|
+
endpoint.job.should == @job
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
describe "url" do
|
557
|
+
before(:each) do
|
558
|
+
@app = mock_app(:url_for => 'hello')
|
559
|
+
@job = Dragonfly::Job.new(@app)
|
560
|
+
end
|
561
|
+
it "should return a url" do
|
562
|
+
@job.generate!(:plasma)
|
563
|
+
@job.url.should == 'hello'
|
564
|
+
end
|
565
|
+
it "should return nil if there are no steps" do
|
566
|
+
@job.url.should be_nil
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
describe "to_fetched_job" do
|
571
|
+
it "should maintain the same temp_object and be already applied" do
|
572
|
+
app = mock_app
|
573
|
+
job = Dragonfly::Job.new(app, Dragonfly::TempObject.new("HELLO"))
|
574
|
+
new_job = job.to_fetched_job('some_uid')
|
575
|
+
new_job.temp_object.data.should == 'HELLO'
|
576
|
+
new_job.to_a.should == [
|
577
|
+
[:f, 'some_uid']
|
578
|
+
]
|
579
|
+
new_job.pending_steps.should be_empty
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
describe "format" do
|
584
|
+
before(:each) do
|
585
|
+
@app = test_app
|
586
|
+
end
|
587
|
+
it "should default to nil" do
|
588
|
+
job = @app.new_job("HELLO")
|
589
|
+
job.format.should be_nil
|
590
|
+
end
|
591
|
+
it "should use the temp_object format if it exists" do
|
592
|
+
job = @app.new_job("HELLO", :format => :txt)
|
593
|
+
job.format.should == :txt
|
594
|
+
end
|
595
|
+
it "should use the analyser format if it exists" do
|
596
|
+
@app.analyser.add :format do |temp_object|
|
597
|
+
:egg
|
598
|
+
end
|
599
|
+
job = @app.new_job("HELLO")
|
600
|
+
job.format.should == :egg
|
601
|
+
end
|
602
|
+
it "should prefer the temp_object format if both exist" do
|
603
|
+
@app.analyser.add :format do |temp_object|
|
604
|
+
:egg
|
605
|
+
end
|
606
|
+
job = @app.new_job("HELLO", :format => :txt)
|
607
|
+
job.format.should == :txt
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
describe "validate_sha!" do
|
612
|
+
before(:each) do
|
613
|
+
@app = test_app
|
614
|
+
@job = @app.fetch('eggs')
|
615
|
+
end
|
616
|
+
it "should raise an error if nothing is given" do
|
617
|
+
lambda{
|
618
|
+
@job.validate_sha!(nil)
|
619
|
+
}.should raise_error(Dragonfly::Job::NoSHAGiven)
|
620
|
+
end
|
621
|
+
it "should raise an error if the wrong SHA is given" do
|
622
|
+
lambda{
|
623
|
+
@job.validate_sha!('asdf')
|
624
|
+
}.should raise_error(Dragonfly::Job::IncorrectSHA)
|
625
|
+
end
|
626
|
+
it "should return self if ok" do
|
627
|
+
@job.validate_sha!(@job.sha).should == @job
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
describe "setting the name" do
|
632
|
+
before(:each) do
|
633
|
+
@app = test_app
|
634
|
+
@job = @app.new_job("HELLO", :name => 'not.me')
|
635
|
+
end
|
636
|
+
it "should allow setting the name" do
|
637
|
+
@job.name = 'wassup.doc'
|
638
|
+
@job.name.should == 'wassup.doc'
|
639
|
+
end
|
640
|
+
end
|
641
|
+
|
642
|
+
describe "setting the meta" do
|
643
|
+
before(:each) do
|
644
|
+
@app = test_app
|
645
|
+
@job = @app.new_job("HiThere", :meta => {:five => 'beans'})
|
646
|
+
end
|
647
|
+
it "should allow setting the meta" do
|
648
|
+
@job.meta = {:doogie => 'ladders'}
|
649
|
+
@job.meta.should == {:doogie => 'ladders'}
|
650
|
+
end
|
651
|
+
it "should allow updating the meta" do
|
652
|
+
@job.meta[:doogie] = 'ladders'
|
653
|
+
@job.meta.should == {:five => 'beans', :doogie => 'ladders'}
|
654
|
+
end
|
655
|
+
end
|
656
|
+
|
657
|
+
describe "b64_data" do
|
658
|
+
before(:each) do
|
659
|
+
@app = test_app
|
660
|
+
end
|
661
|
+
it "should return a string using the data:URI schema" do
|
662
|
+
job = @app.new_job("HELLO", :name => 'text.txt')
|
663
|
+
job.b64_data.should == "data:text/plain;base64,SEVMTE8=\n"
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
describe "querying stuff without applying steps" do
|
668
|
+
before(:each) do
|
669
|
+
@app = test_app
|
670
|
+
end
|
671
|
+
|
672
|
+
describe "fetch_step" do
|
673
|
+
it "should return nil if it doesn't exist" do
|
674
|
+
@app.generate(:ponies).process(:jam).fetch_step.should be_nil
|
675
|
+
end
|
676
|
+
it "should return the fetch step otherwise" do
|
677
|
+
step = @app.fetch('hello').process(:cheese).fetch_step
|
678
|
+
step.should be_a(Dragonfly::Job::Fetch)
|
679
|
+
step.uid.should == 'hello'
|
680
|
+
end
|
681
|
+
end
|
682
|
+
describe "fetched uid" do
|
683
|
+
describe "when there's no fetch step" do
|
684
|
+
before(:each) do
|
685
|
+
@job = @app.new_job("AGG")
|
686
|
+
end
|
687
|
+
it "should return nil for uid" do
|
688
|
+
@job.uid.should be_nil
|
689
|
+
end
|
690
|
+
it "should return nil for uid_basename" do
|
691
|
+
@job.uid_basename.should be_nil
|
692
|
+
end
|
693
|
+
it "should return nil for uid_extname" do
|
694
|
+
@job.uid_extname.should be_nil
|
695
|
+
end
|
696
|
+
end
|
697
|
+
describe "when there is a fetch step" do
|
698
|
+
before(:each) do
|
699
|
+
@job = @app.fetch('gungedin/innit.blud')
|
700
|
+
end
|
701
|
+
it "should return the uid" do
|
702
|
+
@job.uid.should == 'gungedin/innit.blud'
|
703
|
+
end
|
704
|
+
it "should return the uid_basename" do
|
705
|
+
@job.uid_basename.should == 'innit'
|
706
|
+
end
|
707
|
+
it "should return the uid_extname" do
|
708
|
+
@job.uid_extname.should == '.blud'
|
709
|
+
end
|
710
|
+
end
|
711
|
+
end
|
712
|
+
|
713
|
+
describe "fetch_file_step" do
|
714
|
+
it "should return nil if it doesn't exist" do
|
715
|
+
@app.generate(:ponies).process(:jam).fetch_file_step.should be_nil
|
716
|
+
end
|
717
|
+
it "should return the fetch_file step otherwise" do
|
718
|
+
step = @app.fetch_file('/my/file.png').process(:cheese).fetch_file_step
|
719
|
+
step.should be_a(Dragonfly::Job::FetchFile)
|
720
|
+
step.path.should == '/my/file.png'
|
721
|
+
end
|
722
|
+
end
|
723
|
+
|
724
|
+
describe "generate_step" do
|
725
|
+
it "should return nil if it doesn't exist" do
|
726
|
+
@app.fetch('many/ponies').process(:jam).generate_step.should be_nil
|
727
|
+
end
|
728
|
+
it "should return the generate step otherwise" do
|
729
|
+
step = @app.generate(:ponies).process(:cheese).generate_step
|
730
|
+
step.should be_a(Dragonfly::Job::Generate)
|
731
|
+
step.args.should == [:ponies]
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
describe "process_steps" do
|
736
|
+
it "should return the processing steps" do
|
737
|
+
job = @app.fetch('many/ponies').process(:jam).process(:eggs).encode(:gif)
|
738
|
+
job.process_steps.should match_steps([
|
739
|
+
Dragonfly::Job::Process,
|
740
|
+
Dragonfly::Job::Process
|
741
|
+
])
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
describe "encode_step" do
|
746
|
+
it "should return nil if it doesn't exist" do
|
747
|
+
@app.generate(:ponies).encode_step.should be_nil
|
748
|
+
end
|
749
|
+
it "should return the last encode step otherwise" do
|
750
|
+
step = @app.fetch('hello').encode(:smells).encode(:cheese).encode_step
|
751
|
+
step.should be_a(Dragonfly::Job::Encode)
|
752
|
+
step.format.should == :cheese
|
753
|
+
end
|
754
|
+
end
|
755
|
+
describe "encoded_format" do
|
756
|
+
it "should return nil if there's no encode step" do
|
757
|
+
@app.new_job('asdf').encoded_format.should be_nil
|
758
|
+
end
|
759
|
+
it "should return the last encoded format if it exists" do
|
760
|
+
@app.fetch('gungedin').encode(:a).encode(:b).encoded_format.should == :b
|
761
|
+
end
|
762
|
+
end
|
763
|
+
describe "encoded_extname" do
|
764
|
+
it "should return nil if there's no encode step" do
|
765
|
+
@app.new_job('asdf').encoded_extname.should be_nil
|
766
|
+
end
|
767
|
+
it "should return the last encoded format as an extname if it exists" do
|
768
|
+
@app.fetch('gungedin').encode(:a).encode(:b).encoded_extname.should == '.b'
|
769
|
+
end
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
773
|
+
end
|