oahu-dragonfly 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. data/.rspec +1 -0
  2. data/.yardopts +24 -0
  3. data/Gemfile +30 -0
  4. data/History.md +323 -0
  5. data/LICENSE +20 -0
  6. data/README.md +88 -0
  7. data/Rakefile +50 -0
  8. data/VERSION +1 -0
  9. data/config.ru +14 -0
  10. data/docs.watchr +1 -0
  11. data/dragonfly.gemspec +297 -0
  12. data/extra_docs/Analysers.md +66 -0
  13. data/extra_docs/Caching.md +23 -0
  14. data/extra_docs/Configuration.md +124 -0
  15. data/extra_docs/Couch.md +49 -0
  16. data/extra_docs/DataStorage.md +153 -0
  17. data/extra_docs/Encoding.md +67 -0
  18. data/extra_docs/GeneralUsage.md +121 -0
  19. data/extra_docs/Generators.md +60 -0
  20. data/extra_docs/Heroku.md +50 -0
  21. data/extra_docs/ImageMagick.md +125 -0
  22. data/extra_docs/Index.md +33 -0
  23. data/extra_docs/MimeTypes.md +40 -0
  24. data/extra_docs/Models.md +272 -0
  25. data/extra_docs/Mongo.md +45 -0
  26. data/extra_docs/Processing.md +77 -0
  27. data/extra_docs/Rack.md +52 -0
  28. data/extra_docs/Rails2.md +57 -0
  29. data/extra_docs/Rails3.md +62 -0
  30. data/extra_docs/Sinatra.md +25 -0
  31. data/extra_docs/URLs.md +169 -0
  32. data/features/images.feature +47 -0
  33. data/features/no_processing.feature +14 -0
  34. data/features/rails_3.0.5.feature +8 -0
  35. data/features/steps/common_steps.rb +8 -0
  36. data/features/steps/dragonfly_steps.rb +66 -0
  37. data/features/steps/rails_steps.rb +28 -0
  38. data/features/support/env.rb +13 -0
  39. data/features/support/setup.rb +32 -0
  40. data/fixtures/rails_3.0.5/files/app/models/album.rb +7 -0
  41. data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
  42. data/fixtures/rails_3.0.5/files/app/views/albums/show.html.erb +6 -0
  43. data/fixtures/rails_3.0.5/files/config/initializers/dragonfly.rb +4 -0
  44. data/fixtures/rails_3.0.5/files/features/manage_album_images.feature +38 -0
  45. data/fixtures/rails_3.0.5/files/features/step_definitions/helper_steps.rb +7 -0
  46. data/fixtures/rails_3.0.5/files/features/step_definitions/image_steps.rb +25 -0
  47. data/fixtures/rails_3.0.5/files/features/support/paths.rb +17 -0
  48. data/fixtures/rails_3.0.5/files/features/text_images.feature +7 -0
  49. data/fixtures/rails_3.0.5/template.rb +20 -0
  50. data/irbrc.rb +18 -0
  51. data/lib/dragonfly.rb +55 -0
  52. data/lib/dragonfly/active_model_extensions.rb +13 -0
  53. data/lib/dragonfly/active_model_extensions/attachment.rb +250 -0
  54. data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +148 -0
  55. data/lib/dragonfly/active_model_extensions/class_methods.rb +95 -0
  56. data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
  57. data/lib/dragonfly/active_model_extensions/validations.rb +41 -0
  58. data/lib/dragonfly/analyser.rb +58 -0
  59. data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
  60. data/lib/dragonfly/analysis/image_magick_analyser.rb +6 -0
  61. data/lib/dragonfly/app.rb +172 -0
  62. data/lib/dragonfly/config/heroku.rb +19 -0
  63. data/lib/dragonfly/config/image_magick.rb +6 -0
  64. data/lib/dragonfly/config/rails.rb +20 -0
  65. data/lib/dragonfly/configurable.rb +207 -0
  66. data/lib/dragonfly/core_ext/array.rb +7 -0
  67. data/lib/dragonfly/core_ext/hash.rb +7 -0
  68. data/lib/dragonfly/core_ext/object.rb +12 -0
  69. data/lib/dragonfly/core_ext/string.rb +9 -0
  70. data/lib/dragonfly/core_ext/symbol.rb +9 -0
  71. data/lib/dragonfly/data_storage.rb +9 -0
  72. data/lib/dragonfly/data_storage/couch_data_store.rb +64 -0
  73. data/lib/dragonfly/data_storage/file_data_store.rb +141 -0
  74. data/lib/dragonfly/data_storage/mongo_data_store.rb +86 -0
  75. data/lib/dragonfly/data_storage/s3data_store.rb +145 -0
  76. data/lib/dragonfly/encoder.rb +13 -0
  77. data/lib/dragonfly/encoding/image_magick_encoder.rb +6 -0
  78. data/lib/dragonfly/function_manager.rb +71 -0
  79. data/lib/dragonfly/generation/image_magick_generator.rb +6 -0
  80. data/lib/dragonfly/generator.rb +9 -0
  81. data/lib/dragonfly/hash_with_css_style_keys.rb +21 -0
  82. data/lib/dragonfly/image_magick/analyser.rb +51 -0
  83. data/lib/dragonfly/image_magick/config.rb +41 -0
  84. data/lib/dragonfly/image_magick/encoder.rb +57 -0
  85. data/lib/dragonfly/image_magick/generator.rb +145 -0
  86. data/lib/dragonfly/image_magick/processor.rb +99 -0
  87. data/lib/dragonfly/image_magick/utils.rb +72 -0
  88. data/lib/dragonfly/image_magick_utils.rb +4 -0
  89. data/lib/dragonfly/job.rb +451 -0
  90. data/lib/dragonfly/job_builder.rb +39 -0
  91. data/lib/dragonfly/job_definitions.rb +26 -0
  92. data/lib/dragonfly/job_endpoint.rb +15 -0
  93. data/lib/dragonfly/loggable.rb +28 -0
  94. data/lib/dragonfly/middleware.rb +20 -0
  95. data/lib/dragonfly/processing/image_magick_processor.rb +6 -0
  96. data/lib/dragonfly/processor.rb +9 -0
  97. data/lib/dragonfly/rails/images.rb +27 -0
  98. data/lib/dragonfly/response.rb +97 -0
  99. data/lib/dragonfly/routed_endpoint.rb +40 -0
  100. data/lib/dragonfly/serializer.rb +32 -0
  101. data/lib/dragonfly/server.rb +113 -0
  102. data/lib/dragonfly/simple_cache.rb +23 -0
  103. data/lib/dragonfly/temp_object.rb +175 -0
  104. data/lib/dragonfly/url_mapper.rb +78 -0
  105. data/samples/beach.png +0 -0
  106. data/samples/egg.png +0 -0
  107. data/samples/round.gif +0 -0
  108. data/samples/sample.docx +0 -0
  109. data/samples/taj.jpg +0 -0
  110. data/spec/dragonfly/active_model_extensions/model_spec.rb +1426 -0
  111. data/spec/dragonfly/active_model_extensions/spec_helper.rb +91 -0
  112. data/spec/dragonfly/analyser_spec.rb +123 -0
  113. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +48 -0
  114. data/spec/dragonfly/app_spec.rb +135 -0
  115. data/spec/dragonfly/configurable_spec.rb +461 -0
  116. data/spec/dragonfly/core_ext/array_spec.rb +19 -0
  117. data/spec/dragonfly/core_ext/hash_spec.rb +19 -0
  118. data/spec/dragonfly/core_ext/string_spec.rb +17 -0
  119. data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
  120. data/spec/dragonfly/data_storage/couch_data_store_spec.rb +76 -0
  121. data/spec/dragonfly/data_storage/file_data_store_spec.rb +296 -0
  122. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +57 -0
  123. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +258 -0
  124. data/spec/dragonfly/data_storage/shared_data_store_examples.rb +77 -0
  125. data/spec/dragonfly/function_manager_spec.rb +154 -0
  126. data/spec/dragonfly/hash_with_css_style_keys_spec.rb +24 -0
  127. data/spec/dragonfly/image_magick/analyser_spec.rb +64 -0
  128. data/spec/dragonfly/image_magick/encoder_spec.rb +41 -0
  129. data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
  130. data/spec/dragonfly/image_magick/processor_spec.rb +233 -0
  131. data/spec/dragonfly/image_magick/utils_spec.rb +18 -0
  132. data/spec/dragonfly/job_builder_spec.rb +37 -0
  133. data/spec/dragonfly/job_definitions_spec.rb +35 -0
  134. data/spec/dragonfly/job_endpoint_spec.rb +173 -0
  135. data/spec/dragonfly/job_spec.rb +1046 -0
  136. data/spec/dragonfly/loggable_spec.rb +80 -0
  137. data/spec/dragonfly/middleware_spec.rb +47 -0
  138. data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
  139. data/spec/dragonfly/serializer_spec.rb +61 -0
  140. data/spec/dragonfly/server_spec.rb +278 -0
  141. data/spec/dragonfly/simple_cache_spec.rb +27 -0
  142. data/spec/dragonfly/temp_object_spec.rb +306 -0
  143. data/spec/dragonfly/url_mapper_spec.rb +126 -0
  144. data/spec/functional/deprecations_spec.rb +51 -0
  145. data/spec/functional/image_magick_app_spec.rb +27 -0
  146. data/spec/functional/model_urls_spec.rb +85 -0
  147. data/spec/functional/remote_on_the_fly_spec.rb +51 -0
  148. data/spec/functional/to_response_spec.rb +31 -0
  149. data/spec/spec_helper.rb +51 -0
  150. data/spec/support/argument_matchers.rb +19 -0
  151. data/spec/support/image_matchers.rb +47 -0
  152. data/spec/support/simple_matchers.rb +53 -0
  153. data/yard/handlers/configurable_attr_handler.rb +38 -0
  154. data/yard/setup.rb +15 -0
  155. data/yard/templates/default/fulldoc/html/css/common.css +107 -0
  156. data/yard/templates/default/layout/html/layout.erb +89 -0
  157. data/yard/templates/default/module/html/configuration_summary.erb +31 -0
  158. data/yard/templates/default/module/setup.rb +17 -0
  159. metadata +544 -0
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dragonfly::ImageMagick::Utils do
4
+
5
+ before(:each) do
6
+ @obj = Object.new
7
+ @obj.extend(Dragonfly::ImageMagick::Utils)
8
+ end
9
+
10
+ it "should raise an error if the identify command isn't found" do
11
+ suppressing_stderr do
12
+ lambda{
13
+ @obj.send(:run, "non-existent-command")
14
+ }.should raise_error(Dragonfly::ImageMagick::Utils::ShellCommandFailed)
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,37 @@
1
+ require '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 '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,173 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ ## General tests for Response go here as it's a pretty simple wrapper around that
5
+
6
+ describe "Dragonfly::JobEndpoint Rack::Lint tests" do
7
+ before(:each) do
8
+ @app = test_app
9
+ @app.generator.add(:test_data){ "Test Data" }
10
+ @job = @app.generate(:test_data)
11
+ @endpoint = Rack::Lint.new(Dragonfly::JobEndpoint.new(@job))
12
+ end
13
+
14
+ it "should pass for HEAD requests" do
15
+ Rack::MockRequest.new(@endpoint).request("HEAD", '')
16
+ end
17
+
18
+ it "should pass for GET requests" do
19
+ Rack::MockRequest.new(@endpoint).request("GET", '')
20
+ end
21
+
22
+ it "should pass for POST requests" do
23
+ Rack::MockRequest.new(@endpoint).request("POST", '')
24
+ end
25
+
26
+ it "should pass for PUT requests" do
27
+ Rack::MockRequest.new(@endpoint).request("PUT", '')
28
+ end
29
+
30
+ it "should pass for DELETE requests" do
31
+ Rack::MockRequest.new(@endpoint).request("DELETE", '')
32
+ end
33
+ end
34
+
35
+ describe Dragonfly::JobEndpoint do
36
+
37
+ def make_request(job, opts={})
38
+ endpoint = Dragonfly::JobEndpoint.new(job)
39
+ method = (opts.delete(:method) || :get).to_s.upcase
40
+ Rack::MockRequest.new(endpoint).request(method, '', opts)
41
+ end
42
+
43
+ before(:each) do
44
+ @app = test_app
45
+ @app.datastore.stub!(:retrieve).with('egg').and_return(["GUNGLE", {:name => 'gung.txt'}])
46
+ @job = @app.new_job.fetch('egg')
47
+ end
48
+
49
+ it "should return a correct response to a successful GET request" do
50
+ response = make_request(@job)
51
+ response.status.should == 200
52
+ response['ETag'].should =~ /^"\w+"$/
53
+ response['Cache-Control'].should == "public, max-age=31536000"
54
+ response['Content-Type'].should == 'text/plain'
55
+ response['Content-Length'].should == '6'
56
+ response['Content-Disposition'].should == 'filename="gung.txt"'
57
+ response.body.should == 'GUNGLE'
58
+ end
59
+
60
+ it "should return the correct headers and no content to a successful HEAD request" do
61
+ response = make_request(@job, :method => :head)
62
+ response.status.should == 200
63
+ response['ETag'].should =~ /^"\w+"$/
64
+ response['Cache-Control'].should == "public, max-age=31536000"
65
+ response['Content-Type'].should == 'text/plain'
66
+ response['Content-Length'].should == '6'
67
+ response['Content-Disposition'].should == 'filename="gung.txt"'
68
+ response.body.should == ''
69
+ end
70
+
71
+ %w(POST PUT DELETE CUSTOM_METHOD).each do |method|
72
+
73
+ it "should return a 405 error for a #{method} request" do
74
+ response = make_request(@job, :method => method)
75
+ response.status.should == 405
76
+ response['Allow'].should == "GET, HEAD"
77
+ response['Content-Type'].should == 'text/plain'
78
+ response.body.should == "#{method} method not allowed"
79
+ end
80
+
81
+ end
82
+
83
+ it "should return 404 if the datastore raises data not found" do
84
+ @job.should_receive(:apply).and_raise(Dragonfly::DataStorage::DataNotFound)
85
+ response = make_request(@job)
86
+ response.status.should == 404
87
+ end
88
+
89
+ describe "ETag" do
90
+ it "should return an ETag" do
91
+ response = make_request(@job)
92
+ response.headers['ETag'].should =~ /^"\w+"$/
93
+ end
94
+
95
+ [
96
+ "dingle",
97
+ "dingle, eggheads",
98
+ '"dingle", "eggheads"',
99
+ '*'
100
+ ].each do |header|
101
+ it "should return a 304 if the correct ETag is specified in HTTP_IF_NONE_MATCH header e.g. #{header}" do
102
+ @job.should_receive(:unique_signature).at_least(:once).and_return('dingle')
103
+ response = make_request(@job, 'HTTP_IF_NONE_MATCH' => header)
104
+ response.status.should == 304
105
+ response['ETag'].should == '"dingle"'
106
+ response['Cache-Control'].should == "public, max-age=31536000"
107
+ response.body.should be_empty
108
+ end
109
+ end
110
+
111
+ it "should not have applied any steps if the correct ETag is specified in HTTP_IF_NONE_MATCH header" do
112
+ response = make_request(@job, 'HTTP_IF_NONE_MATCH' => @job.unique_signature)
113
+ @job.applied_steps.should be_empty
114
+ end
115
+ end
116
+
117
+ describe "Content Disposition" do
118
+ before(:each) do
119
+ @app.encoder.add{|temp_object, format| temp_object }
120
+ end
121
+
122
+ describe "filename" do
123
+ it "should return the original name" do
124
+ response = make_request(@job)
125
+ response['Content-Disposition'].should == 'filename="gung.txt"'
126
+ end
127
+ it "should return a filename with a different extension if it's been encoded" do
128
+ response = make_request(@job.encode(:doogs))
129
+ response['Content-Disposition'].should == 'filename="gung.doogs"'
130
+ end
131
+ it "should not have the filename if name doesn't exist" do
132
+ response = make_request(@app.new_job("ADFSDF"))
133
+ response['Content-Disposition'].should be_nil
134
+ end
135
+ it "should cope with filenames with no ext" do
136
+ response = make_request(@app.new_job("ASDF", :name => 'asdf'))
137
+ response['Content-Disposition'].should == 'filename="asdf"'
138
+ end
139
+ it "should uri encode funny characters" do
140
+ response = make_request(@app.new_job("ASDF", :name => '£@$£ `'))
141
+ response['Content-Disposition'].should == 'filename="%C2%A3@$%C2%A3%20%60"'
142
+ end
143
+ it "should allow for setting the filename using a block" do
144
+ @app.content_filename = proc{|job, request|
145
+ job.basename.reverse.upcase + request['a']
146
+ }
147
+ response = make_request(@job, 'QUERY_STRING' => 'a=egg')
148
+ response['Content-Disposition'].should == 'filename="GNUGegg"'
149
+ end
150
+ it "should not include the filename if configured to be nil" do
151
+ @app.content_filename = nil
152
+ response = make_request(@job)
153
+ response['Content-Disposition'].should be_nil
154
+ end
155
+ end
156
+
157
+ describe "content disposition" do
158
+ it "should use the app's configured content-disposition" do
159
+ @app.content_disposition = :attachment
160
+ response = make_request(@job)
161
+ response['Content-Disposition'].should == 'attachment; filename="gung.txt"'
162
+ end
163
+ it "should allow using a block to set the content disposition" do
164
+ @app.content_disposition = proc{|job, request|
165
+ job.basename + request['blah']
166
+ }
167
+ response = make_request(@job, 'QUERY_STRING' => 'blah=yo')
168
+ response['Content-Disposition'].should == 'gungyo; filename="gung.txt"'
169
+ end
170
+ end
171
+ end
172
+
173
+ end
@@ -0,0 +1,1046 @@
1
+ require 'spec_helper'
2
+
3
+ # Matchers
4
+ RSpec::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
+ Dragonfly::Job::FetchUrl => :fetch_url
21
+ }.each do |klass, step_name|
22
+ it "should return the correct step name for #{klass}" do
23
+ klass.step_name.should == step_name
24
+ end
25
+ end
26
+
27
+ {
28
+ Dragonfly::Job::Fetch => :f,
29
+ Dragonfly::Job::Process => :p,
30
+ Dragonfly::Job::Encode => :e,
31
+ Dragonfly::Job::Generate => :g,
32
+ Dragonfly::Job::FetchFile => :ff,
33
+ Dragonfly::Job::FetchUrl => :fu
34
+ }.each do |klass, abbreviation|
35
+ it "should return the correct abbreviation for #{klass}" do
36
+ klass.abbreviation.should == abbreviation
37
+ end
38
+ end
39
+
40
+ describe "step_names" do
41
+ it "should return the available step names" do
42
+ Dragonfly::Job.step_names.should == [:fetch, :process, :encode, :generate, :fetch_file, :fetch_url]
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ describe "without content" do
49
+
50
+ before(:each) do
51
+ @app = mock_app
52
+ @job = Dragonfly::Job.new(@app)
53
+ end
54
+
55
+ it "should allow initializing with content" do
56
+ job = Dragonfly::Job.new(@app, 'eggheads')
57
+ job.data.should == 'eggheads'
58
+ end
59
+
60
+ describe "fetch" do
61
+ before(:each) do
62
+ @job.fetch!('some_uid')
63
+ end
64
+
65
+ it { @job.steps.should match_steps([Dragonfly::Job::Fetch]) }
66
+
67
+ it "should retrieve from the app's datastore when applied" do
68
+ @app.datastore.should_receive(:retrieve).with('some_uid').and_return('HELLO')
69
+ @job.data.should == 'HELLO'
70
+ end
71
+
72
+ it "should set extra data if returned from the datastore" do
73
+ @app.datastore.should_receive(:retrieve).with('some_uid').and_return(['HELLO', {:name => 'test.txt'}])
74
+ @job.data.should == 'HELLO'
75
+ @job.meta.should == {:name => 'test.txt'}
76
+ end
77
+ end
78
+
79
+ describe "process" do
80
+ it "should raise an error when applying" do
81
+ @job.process!(:resize, '20x30')
82
+ lambda{
83
+ @job.apply
84
+ }.should raise_error(Dragonfly::Job::NothingToProcess)
85
+ end
86
+ end
87
+
88
+ describe "encode" do
89
+ it "should raise an error when applying" do
90
+ @job.encode!(:gif)
91
+ lambda{
92
+ @job.apply
93
+ }.should raise_error(Dragonfly::Job::NothingToEncode)
94
+ end
95
+ end
96
+
97
+ describe "analyse" do
98
+ it "should raise an error" do
99
+ lambda{
100
+ @job.analyse(:width)
101
+ }.should raise_error(Dragonfly::Job::NothingToAnalyse)
102
+ end
103
+ end
104
+
105
+ describe "generate" do
106
+ before(:each) do
107
+ @job.generate!(:plasma, 20, 30)
108
+ end
109
+
110
+ it { @job.steps.should match_steps([Dragonfly::Job::Generate]) }
111
+
112
+ it "should use the generator when applied" do
113
+ @app.generator.should_receive(:generate).with(:plasma, 20, 30).and_return('hi')
114
+ @job.data.should == 'hi'
115
+ end
116
+
117
+ it "should save extra data if the generator returns it" do
118
+ @app.generator.should_receive(:generate).with(:plasma, 20, 30).and_return(['hi', {:name => 'plasma.png'}])
119
+ @job.data.should == 'hi'
120
+ @job.meta.should == {:name => 'plasma.png'}
121
+ end
122
+ end
123
+
124
+ describe "fetch_file" do
125
+ before(:each) do
126
+ @job.fetch_file!(File.dirname(__FILE__) + '/../../samples/egg.png')
127
+ end
128
+
129
+ it { @job.steps.should match_steps([Dragonfly::Job::FetchFile]) }
130
+
131
+ it "should fetch the specified file when applied" do
132
+ @job.size.should == 62664
133
+ end
134
+
135
+ it "should set the name" do
136
+ @job.meta[:name].should == 'egg.png'
137
+ end
138
+ end
139
+
140
+ describe "fetch_url" do
141
+ before(:each) do
142
+ stub_request(:get, 'http://some.place.com').to_return(:body => 'result!')
143
+ stub_request(:get, 'https://some.place.com').to_return(:body => 'secure result!')
144
+ end
145
+
146
+ it {
147
+ @job.fetch_url!('some.url')
148
+ @job.steps.should match_steps([Dragonfly::Job::FetchUrl])
149
+ }
150
+
151
+ it "should fetch the specified url when applied" do
152
+ @job.fetch_url!('http://some.place.com')
153
+ @job.data.should == "result!"
154
+ end
155
+
156
+ it "should default to http" do
157
+ @job.fetch_url!('some.place.com')
158
+ @job.data.should == "result!"
159
+ end
160
+
161
+ it "should also work with https" do
162
+ @job.fetch_url!('https://some.place.com')
163
+ @job.data.should == "secure result!"
164
+ end
165
+
166
+ it "should set the name if there is one" do
167
+ @job.fetch_url!('some.place.com/dung.beetle')
168
+ @job.meta[:name].should == 'dung.beetle'
169
+ end
170
+
171
+ ["some.place.com", "some.place.com/", "some.place.com/eggs/"].each do |url|
172
+ it "should not set the name if there isn't one, e.g. #{url}" do
173
+ @job.fetch_url!(url)
174
+ @job.meta[:name].should be_nil
175
+ end
176
+ end
177
+ end
178
+
179
+ end
180
+
181
+ describe "with content already there" do
182
+
183
+ before(:each) do
184
+ @app = mock_app
185
+ @job = Dragonfly::Job.new(@app, 'HELLO', :name => 'hello.txt', :a => :b)
186
+ @temp_object = @job.temp_object
187
+ end
188
+
189
+ describe "apply" do
190
+ it "should return itself" do
191
+ @job.apply.should == @job
192
+ end
193
+ end
194
+
195
+ describe "process" do
196
+ before(:each) do
197
+ @job.process!(:resize, '20x30')
198
+ end
199
+
200
+ it { @job.steps.should match_steps([Dragonfly::Job::Process]) }
201
+
202
+ it "should use the processor when applied" do
203
+ @app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return('hi')
204
+ @job.data.should == 'hi'
205
+ end
206
+
207
+ it "should maintain the meta attributes" do
208
+ @app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return('hi')
209
+ @job.data.should == 'hi'
210
+ @job.meta.should == {:name => 'hello.txt', :a => :b}
211
+ end
212
+
213
+ it "should allow returning an array with extra attributes from the processor" do
214
+ @app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return(['hi', {:name => 'hello_20x30.txt', :eggs => 'asdf'}])
215
+ @job.data.should == 'hi'
216
+ @job.meta.should == {:name => 'hello_20x30.txt', :a => :b, :eggs => 'asdf'}
217
+ end
218
+ end
219
+
220
+ describe "encode" do
221
+ before(:each) do
222
+ @job.encode!(:gif, :bitrate => 'mumma')
223
+ end
224
+
225
+ it { @job.steps.should match_steps([Dragonfly::Job::Encode]) }
226
+
227
+ it "should use the encoder when applied" do
228
+ @app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return('alo')
229
+ @job.data.should == 'alo'
230
+ end
231
+
232
+ it "should maintain the meta and update the format" do
233
+ @app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return('alo')
234
+ @job.data.should == 'alo'
235
+ @job.meta.should == {:name => 'hello.txt', :a => :b, :format => :gif}
236
+ end
237
+
238
+ it "should update the format even when not applied" do
239
+ @app.encoder.should_not_receive(:encode)
240
+ @job.meta[:format].should == :gif
241
+ end
242
+
243
+ it "should allow returning an array with extra attributes form the encoder" do
244
+ @app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return(['alo', {:name => 'doobie', :eggs => 'fish'}])
245
+ @job.data.should == 'alo'
246
+ @job.meta.should == {:name => 'doobie', :a => :b, :eggs => 'fish', :format => :gif}
247
+ end
248
+
249
+ it "not allow overriding the format" do
250
+ @app.encoder.should_receive(:encode).with(@temp_object, :gif, :bitrate => 'mumma').and_return(['alo', {:format => :png}])
251
+ @job.apply.meta[:format].should == :gif
252
+ end
253
+ end
254
+ end
255
+
256
+ describe "analysis" do
257
+ before(:each) do
258
+ @app = test_app
259
+ @job = @app.new_job('HELLO')
260
+ @app.analyser.add(:num_letters){|temp_object, letter| temp_object.data.count(letter) }
261
+ end
262
+ it "should return correctly when calling analyse" do
263
+ @job.analyse(:num_letters, 'L').should == 2
264
+ end
265
+ it "should have mixed in the analyser method" do
266
+ @job.num_letters('L').should == 2
267
+ end
268
+ it "should return nil from analyse if calling any old method" do
269
+ @job.analyse(:robin_van_persie).should be_nil
270
+ end
271
+ it "should not allow calling any old method" do
272
+ lambda{
273
+ @job.robin_van_persie
274
+ }.should raise_error(NoMethodError)
275
+ end
276
+ it "should work correctly with chained jobs, applying before analysing" do
277
+ @app.processor.add(:double){|temp_object| temp_object.data * 2 }
278
+ @job.process(:double).num_letters('L').should == 4
279
+ end
280
+ end
281
+
282
+ describe "defining extra steps after applying" do
283
+ before(:each) do
284
+ @app = mock_app
285
+ @job = Dragonfly::Job.new(@app)
286
+ @job.temp_object = Dragonfly::TempObject.new("hello")
287
+ @job.process! :resize
288
+ @job.apply
289
+ @job.encode! :micky
290
+ end
291
+ it "should not call apply on already applied steps" do
292
+ @job.steps[0].should_not_receive(:apply)
293
+ @job.apply
294
+ end
295
+ it "should call apply on not yet applied steps" do
296
+ @job.steps[1].should_receive(:apply)
297
+ @job.apply
298
+ end
299
+ it "should return all steps" do
300
+ @job.steps.should match_steps([
301
+ Dragonfly::Job::Process,
302
+ Dragonfly::Job::Encode
303
+ ])
304
+ end
305
+ it "should return applied steps" do
306
+ @job.applied_steps.should match_steps([
307
+ Dragonfly::Job::Process
308
+ ])
309
+ end
310
+ it "should return the pending steps" do
311
+ @job.pending_steps.should match_steps([
312
+ Dragonfly::Job::Encode
313
+ ])
314
+ end
315
+ it "should not call apply on any steps when already applied" do
316
+ @job.apply
317
+ @job.steps[0].should_not_receive(:apply)
318
+ @job.steps[1].should_not_receive(:apply)
319
+ @job.apply
320
+ end
321
+ end
322
+
323
+ describe "chaining" do
324
+
325
+ before(:each) do
326
+ @app = mock_app
327
+ @job = Dragonfly::Job.new(@app)
328
+ end
329
+
330
+ it "should return itself if bang is used" do
331
+ @job.fetch!('some_uid').should == @job
332
+ end
333
+
334
+ it "should return a new job if bang is not used" do
335
+ @job.fetch('some_uid').should_not == @job
336
+ end
337
+
338
+ describe "when a chained job is defined" do
339
+ before(:each) do
340
+ @job.fetch!('some_uid')
341
+ @job2 = @job.process(:resize, '30x30')
342
+ end
343
+
344
+ it "should return the correct steps for the original job" do
345
+ @job.applied_steps.should match_steps([
346
+ ])
347
+ @job.pending_steps.should match_steps([
348
+ Dragonfly::Job::Fetch
349
+ ])
350
+ end
351
+
352
+ it "should return the correct data for the original job" do
353
+ @job.data.should == 'SOME_DATA'
354
+ end
355
+
356
+ it "should return the correct steps for the new job" do
357
+ @job2.applied_steps.should match_steps([
358
+ ])
359
+ @job2.pending_steps.should match_steps([
360
+ Dragonfly::Job::Fetch,
361
+ Dragonfly::Job::Process
362
+ ])
363
+ end
364
+
365
+ it "should return the correct data for the new job" do
366
+ @job2.data.should == 'SOME_PROCESSED_DATA'
367
+ end
368
+
369
+ it "should not affect the other one when one is applied" do
370
+ @job.apply
371
+ @job.applied_steps.should match_steps([
372
+ Dragonfly::Job::Fetch
373
+ ])
374
+ @job.pending_steps.should match_steps([
375
+ ])
376
+ @job.temp_object.data.should == 'SOME_DATA'
377
+ @job2.applied_steps.should match_steps([
378
+ ])
379
+ @job2.pending_steps.should match_steps([
380
+ Dragonfly::Job::Fetch,
381
+ Dragonfly::Job::Process
382
+ ])
383
+ @job2.temp_object.should be_nil
384
+ end
385
+ end
386
+
387
+ end
388
+
389
+ describe "applied?" do
390
+ before(:each) do
391
+ @app = test_app
392
+ end
393
+ it "should return true when empty" do
394
+ @app.new_job.should be_applied
395
+ end
396
+ it "should return false when not applied" do
397
+ @app.fetch('eggs').should_not be_applied
398
+ end
399
+ it "should return true when applied" do
400
+ @app.datastore.should_receive(:retrieve).with('eggs').and_return("cracked")
401
+ job = @app.fetch('eggs').apply
402
+ job.should be_applied
403
+ end
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 "serialization" do
482
+ before(:each) do
483
+ @app = test_app
484
+ @job = Dragonfly::Job.new(@app).fetch('uid').process(:resize_and_crop, :width => 270, :height => 92, :gravity => 'n')
485
+ end
486
+ it "should serialize itself" do
487
+ @job.serialize.should =~ /^\w{1,}$/
488
+ end
489
+ it "should deserialize to the same as the original" do
490
+ new_job = Dragonfly::Job.deserialize(@job.serialize, @app)
491
+ new_job.to_a.should == @job.to_a
492
+ end
493
+ it "should correctly deserialize a string serialized with ruby 1.8.7" do
494
+ job = Dragonfly::Job.deserialize('BAhbB1sHOgZmSSIIdWlkBjoGRVRbCDoGcDoUcmVzaXplX2FuZF9jcm9wewg6CndpZHRoaQIOAToLaGVpZ2h0aWE6DGdyYXZpdHlJIgZuBjsGVA', @app)
495
+ job.to_a.should == @job.to_a
496
+ end
497
+ it "should correctly deserialize a string serialized with ruby 1.9.2" do
498
+ job = Dragonfly::Job.deserialize('BAhbB1sHOgZmIgh1aWRbCDoGcDoUcmVzaXplX2FuZF9jcm9wewg6CndpZHRoaQIOAToLaGVpZ2h0aWE6DGdyYXZpdHkiBm4', @app)
499
+ job.to_a.should == @job.to_a
500
+ end
501
+ end
502
+
503
+ describe "to_app" do
504
+ before(:each) do
505
+ @app = test_app
506
+ @job = Dragonfly::Job.new(@app)
507
+ end
508
+ it "should return an endpoint" do
509
+ endpoint = @job.to_app
510
+ endpoint.should be_a(Dragonfly::JobEndpoint)
511
+ endpoint.job.should == @job
512
+ end
513
+ end
514
+
515
+ describe "url" do
516
+ before(:each) do
517
+ @app = test_app
518
+ @job = Dragonfly::Job.new(@app)
519
+ end
520
+
521
+ it "should return nil if there are no steps" do
522
+ @job.url.should be_nil
523
+ end
524
+
525
+ describe "using meta in the url" do
526
+ before(:each) do
527
+ @app.server.url_format = '/media/:job/:zoo'
528
+ @job.generate!(:fish)
529
+ end
530
+ it "should act as per usual if no params given" do
531
+ @job.url.should == "/media/#{@job.serialize}"
532
+ end
533
+ it "should add given params" do
534
+ @job.url(:zoo => 'jokes', :on => 'me').should == "/media/#{@job.serialize}/jokes?on=me"
535
+ end
536
+ it "should use the meta if it exists" do
537
+ @job.meta[:zoo] = 'hair'
538
+ @job.url.should == "/media/#{@job.serialize}/hair"
539
+ end
540
+ it "should not add an meta that isn't needed" do
541
+ @job.meta[:gump] = 'flub'
542
+ @job.url.should == "/media/#{@job.serialize}"
543
+ end
544
+ it "should override if a param is passed in" do
545
+ @job.meta[:zoo] = 'hair'
546
+ @job.url(:zoo => 'dare').should == "/media/#{@job.serialize}/dare"
547
+ end
548
+
549
+ describe "basename" do
550
+ before(:each) do
551
+ @app.server.url_format = '/:job/:basename'
552
+ @job.meta = {:name => 'hello.egg', :basename => 'hi'}
553
+ end
554
+ it "should use the meta if it exists" do
555
+ @job.url.should == "/#{@job.serialize}/hi"
556
+ end
557
+ it "should use the name if basename meta doesn't exist" do
558
+ @job.meta.delete(:basename)
559
+ @job.url.should == "/#{@job.serialize}/hello"
560
+ end
561
+ it "should not set if neither exist" do
562
+ @job.meta = {}
563
+ @job.url.should == "/#{@job.serialize}"
564
+ end
565
+ end
566
+
567
+ describe "ext" do
568
+ before(:each) do
569
+ @app.server.url_format = '/:job.:ext'
570
+ @job.meta = {:name => 'hello.egg', :ext => 'hi'}
571
+ end
572
+ it "should use the meta if it exists" do
573
+ @job.url.should == "/#{@job.serialize}.hi"
574
+ end
575
+ it "should use the name if ext meta doesn't exist" do
576
+ @job.meta.delete(:ext)
577
+ @job.url.should == "/#{@job.serialize}.egg"
578
+ end
579
+ it "should not set if neither exist" do
580
+ @job.meta = {}
581
+ @job.url.should == "/#{@job.serialize}"
582
+ end
583
+ end
584
+
585
+ describe "format" do
586
+ before(:each) do
587
+ @app.server.url_format = '/:job.:format'
588
+ @job.stub!(:ext).and_return("hi")
589
+ end
590
+ it "should use the meta if it exists" do
591
+ @job.meta = {:format => :txt}
592
+ @job.url.should == "/#{@job.serialize}.txt"
593
+ end
594
+ it "should use the ext if format meta doesn't exist" do
595
+ @job.url.should == "/#{@job.serialize}.hi"
596
+ end
597
+ it "should not use the ext if format meta doesn't exist and trust_file_extensions is switched off" do
598
+ @app.trust_file_extensions = false
599
+ @job.url.should == "/#{@job.serialize}"
600
+ end
601
+ it "should not set if neither exist" do
602
+ @job.should_receive(:ext).and_return nil
603
+ @job.url.should == "/#{@job.serialize}"
604
+ end
605
+ end
606
+ end
607
+ end
608
+
609
+ describe "to_fetched_job" do
610
+ before(:each) do
611
+ @app = test_app
612
+ @job = @app.create("HELLO")
613
+ end
614
+ it "should maintain the same temp_object and be already applied" do
615
+ new_job = @job.to_fetched_job('some_uid')
616
+ new_job.data.should == 'HELLO'
617
+ new_job.to_a.should == [
618
+ [:f, 'some_uid']
619
+ ]
620
+ new_job.pending_steps.should be_empty
621
+ end
622
+ it "should maintain the meta" do
623
+ @job.meta = {:right => 'said fred'}
624
+ new_job = @job.to_fetched_job('some_uid')
625
+ new_job.meta.should == {:right => 'said fred'}
626
+ end
627
+ end
628
+
629
+ describe "to_unique_s" do
630
+ it "should use the arrays of args to create the string" do
631
+ job = test_app.fetch('uid').process(:gug, 4, :some => 'arg', :and => 'more')
632
+ job.to_unique_s.should == 'fuidpgug4andmoresomearg'
633
+ end
634
+ end
635
+
636
+ describe "sha" do
637
+ before(:each) do
638
+ @app = test_app
639
+ @job = @app.fetch('eggs')
640
+ end
641
+
642
+ it "should be of the correct format" do
643
+ @job.sha.should =~ /^\w{8}$/
644
+ end
645
+
646
+ it "should be the same for the same job steps" do
647
+ @app.fetch('eggs').sha.should == @job.sha
648
+ end
649
+
650
+ it "should be different for different jobs" do
651
+ @app.fetch('figs').sha.should_not == @job.sha
652
+ end
653
+ end
654
+
655
+ describe "validate_sha!" do
656
+ before(:each) do
657
+ @app = test_app
658
+ @job = @app.fetch('eggs')
659
+ end
660
+ it "should raise an error if nothing is given" do
661
+ lambda{
662
+ @job.validate_sha!(nil)
663
+ }.should raise_error(Dragonfly::Job::NoSHAGiven)
664
+ end
665
+ it "should raise an error if the wrong SHA is given" do
666
+ lambda{
667
+ @job.validate_sha!('asdf')
668
+ }.should raise_error(Dragonfly::Job::IncorrectSHA)
669
+ end
670
+ it "should return self if ok" do
671
+ @job.validate_sha!(@job.sha).should == @job
672
+ end
673
+ end
674
+
675
+ describe "setting the name" do
676
+ before(:each) do
677
+ @app = test_app
678
+ @job = @app.new_job("HELLO", :name => 'not.me')
679
+ end
680
+ it "should allow setting the name" do
681
+ @job.name = 'wassup.doc'
682
+ @job.name.should == 'wassup.doc'
683
+ end
684
+ end
685
+
686
+ describe "setting the meta" do
687
+ before(:each) do
688
+ @app = test_app
689
+ @job = @app.new_job("HiThere", :five => 'beans')
690
+ end
691
+ it "should allow setting the meta" do
692
+ @job.meta = {:doogie => 'ladders'}
693
+ @job.meta.should == {:doogie => 'ladders'}
694
+ end
695
+ it "should allow updating the meta" do
696
+ @job.meta[:doogie] = 'ladders'
697
+ @job.meta.should == {:five => 'beans', :doogie => 'ladders'}
698
+ end
699
+ end
700
+
701
+ describe "b64_data" do
702
+ before(:each) do
703
+ @app = test_app
704
+ end
705
+ it "should return a string using the data:URI schema" do
706
+ job = @app.new_job("HELLO", :name => 'text.txt')
707
+ job.b64_data.should == "data:text/plain;base64,SEVMTE8=\n"
708
+ end
709
+ end
710
+
711
+ describe "querying stuff without applying steps" do
712
+ before(:each) do
713
+ @app = test_app
714
+ end
715
+
716
+ describe "fetch_step" do
717
+ it "should return nil if it doesn't exist" do
718
+ @app.generate(:ponies).process(:jam).fetch_step.should be_nil
719
+ end
720
+ it "should return the fetch step otherwise" do
721
+ step = @app.fetch('hello').process(:cheese).fetch_step
722
+ step.should be_a(Dragonfly::Job::Fetch)
723
+ step.uid.should == 'hello'
724
+ end
725
+ end
726
+ describe "fetched uid" do
727
+ describe "when there's no fetch step" do
728
+ before(:each) do
729
+ @job = @app.new_job("AGG")
730
+ end
731
+ it "should return nil for uid" do
732
+ @job.uid.should be_nil
733
+ end
734
+ it "should return nil for uid_basename" do
735
+ @job.uid_basename.should be_nil
736
+ end
737
+ it "should return nil for uid_extname" do
738
+ @job.uid_extname.should be_nil
739
+ end
740
+ end
741
+ describe "when there is a fetch step" do
742
+ before(:each) do
743
+ @job = @app.fetch('gungedin/innit.blud')
744
+ end
745
+ it "should return the uid" do
746
+ @job.uid.should == 'gungedin/innit.blud'
747
+ end
748
+ it "should return the uid_basename" do
749
+ @job.uid_basename.should == 'innit'
750
+ end
751
+ it "should return the uid_extname" do
752
+ @job.uid_extname.should == '.blud'
753
+ end
754
+ end
755
+ end
756
+
757
+ describe "fetch_file_step" do
758
+ it "should return nil if it doesn't exist" do
759
+ @app.generate(:ponies).process(:jam).fetch_file_step.should be_nil
760
+ end
761
+ it "should return the fetch_file step otherwise" do
762
+ step = @app.fetch_file('/my/file.png').process(:cheese).fetch_file_step
763
+ step.should be_a(Dragonfly::Job::FetchFile)
764
+ step.path.should == '/my/file.png'
765
+ end
766
+ end
767
+
768
+ describe "fetch_url_step" do
769
+ it "should return nil if it doesn't exist" do
770
+ @app.generate(:ponies).fetch_url_step.should be_nil
771
+ end
772
+ it "should return the fetch_url step otherwise" do
773
+ step = @app.fetch_url('egg.heads').process(:cheese).fetch_url_step
774
+ step.should be_a(Dragonfly::Job::FetchUrl)
775
+ step.url.should == 'http://egg.heads'
776
+ end
777
+ end
778
+
779
+ describe "generate_step" do
780
+ it "should return nil if it doesn't exist" do
781
+ @app.fetch('many/ponies').process(:jam).generate_step.should be_nil
782
+ end
783
+ it "should return the generate step otherwise" do
784
+ step = @app.generate(:ponies).process(:cheese).generate_step
785
+ step.should be_a(Dragonfly::Job::Generate)
786
+ step.args.should == [:ponies]
787
+ end
788
+ end
789
+
790
+ describe "process_steps" do
791
+ it "should return the processing steps" do
792
+ job = @app.fetch('many/ponies').process(:jam).process(:eggs).encode(:gif)
793
+ job.process_steps.should match_steps([
794
+ Dragonfly::Job::Process,
795
+ Dragonfly::Job::Process
796
+ ])
797
+ end
798
+ end
799
+
800
+ describe "encode_step" do
801
+ it "should return nil if it doesn't exist" do
802
+ @app.generate(:ponies).encode_step.should be_nil
803
+ end
804
+ it "should return the last encode step otherwise" do
805
+ step = @app.fetch('hello').encode(:smells).encode(:cheese).encode_step
806
+ step.should be_a(Dragonfly::Job::Encode)
807
+ step.format.should == :cheese
808
+ end
809
+ end
810
+ describe "encoded_format" do
811
+ it "should return nil if there's no encode step" do
812
+ @app.new_job('asdf').encoded_format.should be_nil
813
+ end
814
+ it "should return the last encoded format if it exists" do
815
+ @app.fetch('gungedin').encode(:a).encode(:b).encoded_format.should == :b
816
+ end
817
+ end
818
+ describe "encoded_extname" do
819
+ it "should return nil if there's no encode step" do
820
+ @app.new_job('asdf').encoded_extname.should be_nil
821
+ end
822
+ it "should return the last encoded format as an extname if it exists" do
823
+ @app.fetch('gungedin').encode(:a).encode(:b).encoded_extname.should == '.b'
824
+ end
825
+ end
826
+ end
827
+
828
+ describe "meta" do
829
+ before(:each) do
830
+ @app = test_app
831
+ @job = @app.new_job
832
+ end
833
+ it "should default meta to an empty hash" do
834
+ @job.meta.should == {}
835
+ end
836
+ it "should allow setting" do
837
+ @job.meta = {:a => :b}
838
+ @job.meta.should == {:a => :b}
839
+ end
840
+ it "should not allow setting as anything other than a hash" do
841
+ lambda{
842
+ @job.meta = 3
843
+ }.should raise_error(ArgumentError)
844
+ end
845
+ it "should allow setting on initialize" do
846
+ job = @app.new_job('asdf', :b => :c)
847
+ job.meta.should == {:b => :c}
848
+ end
849
+ it "should keep them when chained" do
850
+ @job.meta[:darn] = 'it'
851
+ @job.generate(:gollum).meta.should == {:darn => 'it'}
852
+ end
853
+ end
854
+
855
+ describe "name" do
856
+ before(:each) do
857
+ @app = test_app
858
+ end
859
+ it "should default to nil" do
860
+ job = @app.new_job('HELLO')
861
+ job.name.should be_nil
862
+ end
863
+ it "should use the meta" do
864
+ job = @app.new_job('HELLO')
865
+ job.meta[:name] = 'monkey.egg'
866
+ job.name.should == 'monkey.egg'
867
+ end
868
+ it "should allow setting" do
869
+ job = @app.new_job('HELLO')
870
+ job.name = "jonny.briggs"
871
+ job.meta[:name].should == 'jonny.briggs'
872
+ end
873
+
874
+ describe "ext" do
875
+ before(:each) do
876
+ @job = @app.new_job('asdf')
877
+ end
878
+ it "should use the correct extension from name" do
879
+ @job.name = 'hello.there.mate'
880
+ @job.ext.should == 'mate'
881
+ end
882
+ it "should be nil if name has none" do
883
+ @job.name = 'hello'
884
+ @job.ext.should be_nil
885
+ end
886
+ it "should be nil if name is nil" do
887
+ @job.name = nil
888
+ @job.ext.should be_nil
889
+ end
890
+ it "should use the meta first if set" do
891
+ @job.meta[:ext] = 'duggs'
892
+ @job.name = 'hello.there.mate'
893
+ @job.ext.should == 'duggs'
894
+ end
895
+ end
896
+
897
+ describe "basename" do
898
+ before(:each) do
899
+ @job = @app.new_job('asdf')
900
+ end
901
+ it "should use the correct basename from name" do
902
+ @job.name = 'hello.there.mate'
903
+ @job.basename.should == 'hello.there'
904
+ end
905
+ it "should be the name if it has no ext" do
906
+ @job.name = 'hello'
907
+ @job.basename.should == 'hello'
908
+ end
909
+ it "should be nil if name is nil" do
910
+ @job.name = nil
911
+ @job.basename.should be_nil
912
+ end
913
+ it "should use the meta first if set" do
914
+ @job.meta[:basename] = 'duggs'
915
+ @job.name = 'hello.there.mate'
916
+ @job.basename.should == 'duggs'
917
+ end
918
+ end
919
+
920
+ describe "format" do
921
+ before(:each) do
922
+ @app = test_app
923
+ end
924
+ it "should default to nil" do
925
+ job = @app.new_job("HELLO")
926
+ job.format.should be_nil
927
+ end
928
+ it "should use the meta format if it exists" do
929
+ job = @app.new_job("HELLO")
930
+ job.meta[:format] = :txt
931
+ job.format.should == :txt
932
+ end
933
+ it "should use the analyser format if it exists" do
934
+ @app.analyser.add :format do |temp_object|
935
+ :egg
936
+ end
937
+ job = @app.new_job("HELLO")
938
+ job.format.should == :egg
939
+ end
940
+ it "should use the file extension if it has no format" do
941
+ @job = @app.new_job("HIMATE", :name => 'test.pdf')
942
+ @job.format.should == :pdf
943
+ end
944
+ it "should not use the file extension if it's been switched off" do
945
+ @app.trust_file_extensions = false
946
+ @job = @app.new_job("HIMATE", :name => 'test.pdf')
947
+ @job.format.should be_nil
948
+ end
949
+ it "should prefer the set format over the file extension" do
950
+ job = @app.new_job("HELLO", :name => 'test.pdf', :format => :txt)
951
+ job.format.should == :txt
952
+ end
953
+ it "should prefer the file extension over the analysed format" do
954
+ @app.analyser.add :format do |temp_object|
955
+ :egg
956
+ end
957
+ job = @app.new_job("HELLO", :name => 'test.pdf')
958
+ job.format.should == :pdf
959
+ end
960
+ it "should apply the job" do
961
+ @app.generator.add(:test){ ["skid marks", {:name => 'terry.burton'}] }
962
+ job = @app.generate(:test)
963
+ job.format.should == :burton
964
+ job.should be_applied
965
+ end
966
+ end
967
+
968
+ describe "mime_type" do
969
+ before(:each) do
970
+ @app = test_app
971
+ end
972
+ it "should return the correct mime_type if the format is given" do
973
+ @job = @app.new_job("HIMATE")
974
+ @job.should_receive(:format).and_return(:tiff)
975
+ @job.mime_type.should == 'image/tiff'
976
+ end
977
+ it "should fall back to the mime_type analyser if the format is nil" do
978
+ @app.analyser.add :mime_type do |temp_object|
979
+ 'image/jpeg'
980
+ end
981
+ @job = @app.new_job("HIMATE")
982
+ @job.mime_type.should == 'image/jpeg'
983
+ end
984
+ it "should fall back to the fallback mime_type if neither format or analyser exist" do
985
+ @app.new_job("HIMATE").mime_type.should == 'application/octet-stream'
986
+ end
987
+ end
988
+
989
+ end
990
+
991
+ describe "store" do
992
+ before(:each) do
993
+ @app = test_app
994
+ @app.generator.add(:test){ ["Toes", {:name => 'doogie.txt'}] }
995
+ @job = @app.generate(:test)
996
+ end
997
+ it "should store its data along with the meta" do
998
+ @job.meta[:eggs] = 'doolally'
999
+ @app.datastore.should_receive(:store).with(a_temp_object_with_data("Toes"), :meta => {:name => 'doogie.txt', :eggs => 'doolally'})
1000
+ @job.store
1001
+ end
1002
+ it "should add extra opts" do
1003
+ @app.datastore.should_receive(:store).with(a_temp_object_with_data("Toes"), :meta => {:name => 'doogie.txt'}, :path => 'blah')
1004
+ @job.store(:path => 'blah')
1005
+ end
1006
+ end
1007
+
1008
+ describe "dealing with original_filename" do
1009
+ before(:each) do
1010
+ @string = "terry"
1011
+ @string.stub!(:original_filename).and_return("gum.tree")
1012
+ @app = test_app
1013
+ @app.generator.add(:test){ @string }
1014
+ end
1015
+ it "should set it as the name" do
1016
+ @app.create(@string).name.should == 'gum.tree'
1017
+ end
1018
+ it "should prefer the initialized name over the original_filename" do
1019
+ @app.create(@string, :name => 'doo.berry').name.should == 'doo.berry'
1020
+ end
1021
+ it "should work with e.g. generators" do
1022
+ @app.generate(:test).apply.name.should == 'gum.tree'
1023
+ end
1024
+ it "should favour an e.g. generator returned name" do
1025
+ @app.generator.add(:test2){ [@string, {:name => 'gen.ome'}] }
1026
+ @app.generate(:test2).apply.name.should == 'gen.ome'
1027
+ end
1028
+ it "should not overwrite a set name" do
1029
+ job = @app.generate(:test)
1030
+ job.name = 'egg.mumma'
1031
+ job.apply.name.should == 'egg.mumma'
1032
+ end
1033
+ end
1034
+
1035
+ describe "deprecated meta format" do
1036
+ before(:each) do
1037
+ @app = test_app
1038
+ end
1039
+ it "should still work if the datastore/whatever returns meta nested in :meta key" do
1040
+ @app.datastore.should_receive(:retrieve).with('some_uid').and_return(['HELLO', {:name => 'test.txt', :meta => {:some => 'meta'}}])
1041
+ job = @app.fetch('some_uid').apply
1042
+ job.meta.should == {:name => 'test.txt', :some => 'meta'}
1043
+ end
1044
+ end
1045
+
1046
+ end