paperclip-fix 4.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.hound.yml +1066 -0
  4. data/.rubocop.yml +1 -0
  5. data/.travis.yml +22 -0
  6. data/Appraisals +11 -0
  7. data/CONTRIBUTING.md +75 -0
  8. data/Gemfile +21 -0
  9. data/LICENSE +24 -0
  10. data/NEWS +420 -0
  11. data/README.md +979 -0
  12. data/RELEASING.md +17 -0
  13. data/Rakefile +44 -0
  14. data/UPGRADING +14 -0
  15. data/cucumber/paperclip_steps.rb +6 -0
  16. data/features/basic_integration.feature +80 -0
  17. data/features/migration.feature +94 -0
  18. data/features/rake_tasks.feature +62 -0
  19. data/features/step_definitions/attachment_steps.rb +110 -0
  20. data/features/step_definitions/html_steps.rb +15 -0
  21. data/features/step_definitions/rails_steps.rb +236 -0
  22. data/features/step_definitions/s3_steps.rb +14 -0
  23. data/features/step_definitions/web_steps.rb +107 -0
  24. data/features/support/env.rb +11 -0
  25. data/features/support/fakeweb.rb +13 -0
  26. data/features/support/file_helpers.rb +34 -0
  27. data/features/support/fixtures/boot_config.txt +15 -0
  28. data/features/support/fixtures/gemfile.txt +5 -0
  29. data/features/support/fixtures/preinitializer.txt +20 -0
  30. data/features/support/paths.rb +28 -0
  31. data/features/support/rails.rb +63 -0
  32. data/features/support/selectors.rb +19 -0
  33. data/gemfiles/3.2.gemfile +19 -0
  34. data/gemfiles/4.1.gemfile +19 -0
  35. data/gemfiles/4.2.gemfile +19 -0
  36. data/lib/generators/paperclip/USAGE +8 -0
  37. data/lib/generators/paperclip/paperclip_generator.rb +30 -0
  38. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
  39. data/lib/paperclip/attachment.rb +608 -0
  40. data/lib/paperclip/attachment_registry.rb +59 -0
  41. data/lib/paperclip/callbacks.rb +40 -0
  42. data/lib/paperclip/content_type_detector.rb +79 -0
  43. data/lib/paperclip/deprecations.rb +42 -0
  44. data/lib/paperclip/errors.rb +32 -0
  45. data/lib/paperclip/file_command_content_type_detector.rb +30 -0
  46. data/lib/paperclip/filename_cleaner.rb +16 -0
  47. data/lib/paperclip/geometry.rb +158 -0
  48. data/lib/paperclip/geometry_detector_factory.rb +48 -0
  49. data/lib/paperclip/geometry_parser_factory.rb +31 -0
  50. data/lib/paperclip/glue.rb +17 -0
  51. data/lib/paperclip/has_attached_file.rb +109 -0
  52. data/lib/paperclip/helpers.rb +56 -0
  53. data/lib/paperclip/interpolations/plural_cache.rb +18 -0
  54. data/lib/paperclip/interpolations.rb +197 -0
  55. data/lib/paperclip/io_adapters/abstract_adapter.rb +47 -0
  56. data/lib/paperclip/io_adapters/attachment_adapter.rb +36 -0
  57. data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
  58. data/lib/paperclip/io_adapters/empty_string_adapter.rb +18 -0
  59. data/lib/paperclip/io_adapters/file_adapter.rb +22 -0
  60. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +15 -0
  61. data/lib/paperclip/io_adapters/identity_adapter.rb +12 -0
  62. data/lib/paperclip/io_adapters/nil_adapter.rb +34 -0
  63. data/lib/paperclip/io_adapters/registry.rb +32 -0
  64. data/lib/paperclip/io_adapters/stringio_adapter.rb +33 -0
  65. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +42 -0
  66. data/lib/paperclip/io_adapters/uri_adapter.rb +63 -0
  67. data/lib/paperclip/locales/de.yml +18 -0
  68. data/lib/paperclip/locales/en.yml +18 -0
  69. data/lib/paperclip/locales/es.yml +18 -0
  70. data/lib/paperclip/locales/ja.yml +18 -0
  71. data/lib/paperclip/locales/pt-BR.yml +18 -0
  72. data/lib/paperclip/locales/zh-CN.yml +18 -0
  73. data/lib/paperclip/locales/zh-HK.yml +18 -0
  74. data/lib/paperclip/locales/zh-TW.yml +18 -0
  75. data/lib/paperclip/logger.rb +21 -0
  76. data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
  77. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +100 -0
  78. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
  79. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +96 -0
  80. data/lib/paperclip/matchers.rb +64 -0
  81. data/lib/paperclip/media_type_spoof_detector.rb +89 -0
  82. data/lib/paperclip/missing_attachment_styles.rb +79 -0
  83. data/lib/paperclip/processor.rb +48 -0
  84. data/lib/paperclip/processor_helpers.rb +50 -0
  85. data/lib/paperclip/rails_environment.rb +25 -0
  86. data/lib/paperclip/railtie.rb +31 -0
  87. data/lib/paperclip/schema.rb +83 -0
  88. data/lib/paperclip/storage/filesystem.rb +90 -0
  89. data/lib/paperclip/storage/fog.rb +241 -0
  90. data/lib/paperclip/storage/s3.rb +440 -0
  91. data/lib/paperclip/storage.rb +3 -0
  92. data/lib/paperclip/style.rb +109 -0
  93. data/lib/paperclip/tempfile.rb +43 -0
  94. data/lib/paperclip/tempfile_factory.rb +23 -0
  95. data/lib/paperclip/thumbnail.rb +121 -0
  96. data/lib/paperclip/url_generator.rb +72 -0
  97. data/lib/paperclip/validators/attachment_content_type_validator.rb +88 -0
  98. data/lib/paperclip/validators/attachment_file_name_validator.rb +80 -0
  99. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +29 -0
  100. data/lib/paperclip/validators/attachment_presence_validator.rb +30 -0
  101. data/lib/paperclip/validators/attachment_size_validator.rb +115 -0
  102. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +27 -0
  103. data/lib/paperclip/validators.rb +74 -0
  104. data/lib/paperclip/version.rb +3 -0
  105. data/lib/paperclip.rb +213 -0
  106. data/lib/tasks/paperclip.rake +127 -0
  107. data/paperclip.gemspec +51 -0
  108. data/shoulda_macros/paperclip.rb +134 -0
  109. data/spec/database.yml +4 -0
  110. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  111. data/spec/paperclip/attachment_processing_spec.rb +82 -0
  112. data/spec/paperclip/attachment_registry_spec.rb +130 -0
  113. data/spec/paperclip/attachment_spec.rb +1494 -0
  114. data/spec/paperclip/content_type_detector_spec.rb +48 -0
  115. data/spec/paperclip/deprecations_spec.rb +65 -0
  116. data/spec/paperclip/file_command_content_type_detector_spec.rb +26 -0
  117. data/spec/paperclip/filename_cleaner_spec.rb +14 -0
  118. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  119. data/spec/paperclip/geometry_parser_spec.rb +73 -0
  120. data/spec/paperclip/geometry_spec.rb +255 -0
  121. data/spec/paperclip/glue_spec.rb +44 -0
  122. data/spec/paperclip/has_attached_file_spec.rb +142 -0
  123. data/spec/paperclip/integration_spec.rb +667 -0
  124. data/spec/paperclip/interpolations_spec.rb +262 -0
  125. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +78 -0
  126. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +139 -0
  127. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +83 -0
  128. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  129. data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
  130. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +104 -0
  131. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  132. data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
  133. data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
  134. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
  135. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
  136. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +127 -0
  137. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  138. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +99 -0
  139. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  140. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  141. data/spec/paperclip/media_type_spoof_detector_spec.rb +79 -0
  142. data/spec/paperclip/meta_class_spec.rb +30 -0
  143. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  144. data/spec/paperclip/paperclip_spec.rb +222 -0
  145. data/spec/paperclip/plural_cache_spec.rb +37 -0
  146. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  147. data/spec/paperclip/processor_spec.rb +26 -0
  148. data/spec/paperclip/rails_environment_spec.rb +33 -0
  149. data/spec/paperclip/rake_spec.rb +103 -0
  150. data/spec/paperclip/schema_spec.rb +248 -0
  151. data/spec/paperclip/storage/filesystem_spec.rb +79 -0
  152. data/spec/paperclip/storage/fog_spec.rb +535 -0
  153. data/spec/paperclip/storage/s3_live_spec.rb +182 -0
  154. data/spec/paperclip/storage/s3_spec.rb +1526 -0
  155. data/spec/paperclip/style_spec.rb +255 -0
  156. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  157. data/spec/paperclip/thumbnail_spec.rb +500 -0
  158. data/spec/paperclip/url_generator_spec.rb +211 -0
  159. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  160. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  161. data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
  162. data/spec/paperclip/validators/attachment_size_validator_spec.rb +229 -0
  163. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +52 -0
  164. data/spec/paperclip/validators_spec.rb +164 -0
  165. data/spec/spec_helper.rb +43 -0
  166. data/spec/support/assertions.rb +71 -0
  167. data/spec/support/deprecations.rb +9 -0
  168. data/spec/support/fake_model.rb +25 -0
  169. data/spec/support/fake_rails.rb +12 -0
  170. data/spec/support/fixtures/12k.png +0 -0
  171. data/spec/support/fixtures/50x50.png +0 -0
  172. data/spec/support/fixtures/5k.png +0 -0
  173. data/spec/support/fixtures/animated +0 -0
  174. data/spec/support/fixtures/animated.gif +0 -0
  175. data/spec/support/fixtures/animated.unknown +0 -0
  176. data/spec/support/fixtures/bad.png +1 -0
  177. data/spec/support/fixtures/empty.html +1 -0
  178. data/spec/support/fixtures/empty.xlsx +0 -0
  179. data/spec/support/fixtures/fog.yml +8 -0
  180. data/spec/support/fixtures/rotated.jpg +0 -0
  181. data/spec/support/fixtures/s3.yml +8 -0
  182. data/spec/support/fixtures/spaced file.jpg +0 -0
  183. data/spec/support/fixtures/spaced file.png +0 -0
  184. data/spec/support/fixtures/text.txt +1 -0
  185. data/spec/support/fixtures/twopage.pdf +0 -0
  186. data/spec/support/fixtures/uppercase.PNG +0 -0
  187. data/spec/support/matchers/accept.rb +5 -0
  188. data/spec/support/matchers/exist.rb +5 -0
  189. data/spec/support/matchers/have_column.rb +23 -0
  190. data/spec/support/mock_attachment.rb +22 -0
  191. data/spec/support/mock_interpolator.rb +24 -0
  192. data/spec/support/mock_url_generator_builder.rb +27 -0
  193. data/spec/support/model_reconstruction.rb +60 -0
  194. data/spec/support/rails_helpers.rb +7 -0
  195. data/spec/support/test_data.rb +13 -0
  196. data/spec/support/version_helper.rb +9 -0
  197. metadata +606 -0
@@ -0,0 +1,500 @@
1
+ require 'spec_helper'
2
+
3
+ describe Paperclip::Thumbnail do
4
+ context "A Paperclip Tempfile" do
5
+ before do
6
+ @tempfile = Paperclip::Tempfile.new(["file", ".jpg"])
7
+ end
8
+
9
+ after { @tempfile.close }
10
+
11
+ it "has its path contain a real extension" do
12
+ assert_equal ".jpg", File.extname(@tempfile.path)
13
+ end
14
+
15
+ it "is a real Tempfile" do
16
+ assert @tempfile.is_a?(::Tempfile)
17
+ end
18
+ end
19
+
20
+ context "Another Paperclip Tempfile" do
21
+ before do
22
+ @tempfile = Paperclip::Tempfile.new("file")
23
+ end
24
+
25
+ after { @tempfile.close }
26
+
27
+ it "does not have an extension if not given one" do
28
+ assert_equal "", File.extname(@tempfile.path)
29
+ end
30
+
31
+ it "is a real Tempfile" do
32
+ assert @tempfile.is_a?(::Tempfile)
33
+ end
34
+ end
35
+
36
+ context "An image" do
37
+ before do
38
+ @file = File.new(fixture_file("5k.png"), 'rb')
39
+ end
40
+
41
+ after { @file.close }
42
+
43
+ [["600x600>", "434x66"],
44
+ ["400x400>", "400x61"],
45
+ ["32x32<", "434x66"],
46
+ [nil, "434x66"]
47
+ ].each do |args|
48
+ context "being thumbnailed with a geometry of #{args[0]}" do
49
+ before do
50
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: args[0])
51
+ end
52
+
53
+ it "starts with dimensions of 434x66" do
54
+ cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
55
+ assert_equal "434x66", `#{cmd}`.chomp
56
+ end
57
+
58
+ it "reports the correct target geometry" do
59
+ assert_equal args[0].to_s, @thumb.target_geometry.to_s
60
+ end
61
+
62
+ context "when made" do
63
+ before do
64
+ @thumb_result = @thumb.make
65
+ end
66
+
67
+ it "is the size we expect it to be" do
68
+ cmd = %Q[identify -format "%wx%h" "#{@thumb_result.path}"]
69
+ assert_equal args[1], `#{cmd}`.chomp
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ context "being thumbnailed at 100x50 with cropping" do
76
+ before do
77
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#")
78
+ end
79
+
80
+ it "lets us know when a command isn't found versus a processing error" do
81
+ old_path = ENV['PATH']
82
+ begin
83
+ Cocaine::CommandLine.path = ''
84
+ Paperclip.options[:command_path] = ''
85
+ ENV['PATH'] = ''
86
+ assert_raises(Paperclip::Errors::CommandNotFoundError) do
87
+ silence_stream(STDERR) do
88
+ @thumb.make
89
+ end
90
+ end
91
+ ensure
92
+ ENV['PATH'] = old_path
93
+ end
94
+ end
95
+
96
+ it "reports its correct current and target geometries" do
97
+ assert_equal "100x50#", @thumb.target_geometry.to_s
98
+ assert_equal "434x66", @thumb.current_geometry.to_s
99
+ end
100
+
101
+ it "reports its correct format" do
102
+ assert_nil @thumb.format
103
+ end
104
+
105
+ it "has whiny turned on by default" do
106
+ assert @thumb.whiny
107
+ end
108
+
109
+ it "has convert_options set to nil by default" do
110
+ assert_equal nil, @thumb.convert_options
111
+ end
112
+
113
+ it "has source_file_options set to nil by default" do
114
+ assert_equal nil, @thumb.source_file_options
115
+ end
116
+
117
+ it "sends the right command to convert when sent #make" do
118
+ @thumb.expects(:convert).with do |*arg|
119
+ arg[0] == ':source -auto-orient -resize "x50" -crop "100x50+114+0" +repage :dest' &&
120
+ arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
121
+ end
122
+ @thumb.make
123
+ end
124
+
125
+ it "creates the thumbnail when sent #make" do
126
+ dst = @thumb.make
127
+ assert_match /100x50/, `identify "#{dst.path}"`
128
+ end
129
+ end
130
+
131
+ it 'crops a EXIF-rotated image properly' do
132
+ file = File.new(fixture_file('rotated.jpg'))
133
+ thumb = Paperclip::Thumbnail.new(file, geometry: "50x50#")
134
+
135
+ output_file = thumb.make
136
+
137
+ command = Cocaine::CommandLine.new("identify", "-format %wx%h :file")
138
+ assert_equal "50x50", command.run(file: output_file.path).strip
139
+ end
140
+
141
+ context "being thumbnailed with source file options set" do
142
+ before do
143
+ @thumb = Paperclip::Thumbnail.new(@file,
144
+ geometry: "100x50#",
145
+ source_file_options: "-strip")
146
+ end
147
+
148
+ it "has source_file_options value set" do
149
+ assert_equal ["-strip"], @thumb.source_file_options
150
+ end
151
+
152
+ it "sends the right command to convert when sent #make" do
153
+ @thumb.expects(:convert).with do |*arg|
154
+ arg[0] == '-strip :source -auto-orient -resize "x50" -crop "100x50+114+0" +repage :dest' &&
155
+ arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
156
+ end
157
+ @thumb.make
158
+ end
159
+
160
+ it "creates the thumbnail when sent #make" do
161
+ dst = @thumb.make
162
+ assert_match /100x50/, `identify "#{dst.path}"`
163
+ end
164
+
165
+ context "redefined to have bad source_file_options setting" do
166
+ before do
167
+ @thumb = Paperclip::Thumbnail.new(@file,
168
+ geometry: "100x50#",
169
+ source_file_options: "-this-aint-no-option")
170
+ end
171
+
172
+ it "errors when trying to create the thumbnail" do
173
+ assert_raises(Paperclip::Error) do
174
+ silence_stream(STDERR) do
175
+ @thumb.make
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ context "being thumbnailed with convert options set" do
183
+ before do
184
+ @thumb = Paperclip::Thumbnail.new(@file,
185
+ geometry: "100x50#",
186
+ convert_options: "-strip -depth 8")
187
+ end
188
+
189
+ it "has convert_options value set" do
190
+ assert_equal %w"-strip -depth 8", @thumb.convert_options
191
+ end
192
+
193
+ it "sends the right command to convert when sent #make" do
194
+ @thumb.expects(:convert).with do |*arg|
195
+ arg[0] == ':source -auto-orient -resize "x50" -crop "100x50+114+0" +repage -strip -depth 8 :dest' &&
196
+ arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
197
+ end
198
+ @thumb.make
199
+ end
200
+
201
+ it "creates the thumbnail when sent #make" do
202
+ dst = @thumb.make
203
+ assert_match /100x50/, `identify "#{dst.path}"`
204
+ end
205
+
206
+ context "redefined to have bad convert_options setting" do
207
+ before do
208
+ @thumb = Paperclip::Thumbnail.new(@file,
209
+ geometry: "100x50#",
210
+ convert_options: "-this-aint-no-option")
211
+ end
212
+
213
+ it "errors when trying to create the thumbnail" do
214
+ assert_raises(Paperclip::Error) do
215
+ silence_stream(STDERR) do
216
+ @thumb.make
217
+ end
218
+ end
219
+ end
220
+
221
+ it "lets us know when a command isn't found versus a processing error" do
222
+ old_path = ENV['PATH']
223
+ begin
224
+ Cocaine::CommandLine.path = ''
225
+ Paperclip.options[:command_path] = ''
226
+ ENV['PATH'] = ''
227
+ assert_raises(Paperclip::Errors::CommandNotFoundError) do
228
+ silence_stream(STDERR) do
229
+ @thumb.make
230
+ end
231
+ end
232
+ ensure
233
+ ENV['PATH'] = old_path
234
+ end
235
+ end
236
+ end
237
+ end
238
+
239
+ context "being thumbnailed with a blank geometry string" do
240
+ before do
241
+ @thumb = Paperclip::Thumbnail.new(@file,
242
+ geometry: "",
243
+ convert_options: "-gravity center -crop \"300x300+0-0\"")
244
+ end
245
+
246
+ it "does not get resized by default" do
247
+ assert !@thumb.transformation_command.include?("-resize")
248
+ end
249
+ end
250
+
251
+ context "being thumbnailed with default animated option (true)" do
252
+ it "calls identify to check for animated images when sent #make" do
253
+ thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#")
254
+ thumb.expects(:identify).at_least_once.with do |*arg|
255
+ arg[0] == '-format %m :file' &&
256
+ arg[1][:file] == "#{File.expand_path(thumb.file.path)}[0]"
257
+ end
258
+ thumb.make
259
+ end
260
+ end
261
+
262
+ context "passing a custom file geometry parser" do
263
+ after do
264
+ Object.send(:remove_const, :GeoParser) if Object.const_defined?(:GeoParser)
265
+ end
266
+
267
+ it "produces the appropriate transformation_command" do
268
+ GeoParser = Class.new do
269
+ def self.from_file(file)
270
+ new
271
+ end
272
+
273
+ def transformation_to(target, should_crop)
274
+ ["SCALE", "CROP"]
275
+ end
276
+ end
277
+
278
+ thumb = Paperclip::Thumbnail.new(@file, geometry: '50x50', file_geometry_parser: ::GeoParser)
279
+
280
+ transformation_command = thumb.transformation_command
281
+
282
+ assert transformation_command.include?('-crop'),
283
+ %{expected #{transformation_command.inspect} to include '-crop'}
284
+ assert transformation_command.include?('"CROP"'),
285
+ %{expected #{transformation_command.inspect} to include '"CROP"'}
286
+ assert transformation_command.include?('-resize'),
287
+ %{expected #{transformation_command.inspect} to include '-resize'}
288
+ assert transformation_command.include?('"SCALE"'),
289
+ %{expected #{transformation_command.inspect} to include '"SCALE"'}
290
+ end
291
+ end
292
+
293
+ context "passing a custom geometry string parser" do
294
+ after do
295
+ Object.send(:remove_const, :GeoParser) if Object.const_defined?(:GeoParser)
296
+ end
297
+
298
+ it "produces the appropriate transformation_command" do
299
+ GeoParser = Class.new do
300
+ def self.parse(s)
301
+ new
302
+ end
303
+
304
+ def to_s
305
+ "151x167"
306
+ end
307
+ end
308
+
309
+ thumb = Paperclip::Thumbnail.new(@file, geometry: '50x50', string_geometry_parser: ::GeoParser)
310
+
311
+ transformation_command = thumb.transformation_command
312
+
313
+ assert transformation_command.include?('"151x167"'),
314
+ %{expected #{transformation_command.inspect} to include '151x167'}
315
+ end
316
+ end
317
+ end
318
+
319
+ context "A multipage PDF" do
320
+ before do
321
+ @file = File.new(fixture_file("twopage.pdf"), 'rb')
322
+ end
323
+
324
+ after { @file.close }
325
+
326
+ it "starts with two pages with dimensions 612x792" do
327
+ cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
328
+ assert_equal "612x792"*2, `#{cmd}`.chomp
329
+ end
330
+
331
+ context "being thumbnailed at 100x100 with cropping" do
332
+ before do
333
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x100#", format: :png)
334
+ end
335
+
336
+ it "reports its correct current and target geometries" do
337
+ assert_equal "100x100#", @thumb.target_geometry.to_s
338
+ assert_equal "612x792", @thumb.current_geometry.to_s
339
+ end
340
+
341
+ it "reports its correct format" do
342
+ assert_equal :png, @thumb.format
343
+ end
344
+
345
+ it "creates the thumbnail when sent #make" do
346
+ dst = @thumb.make
347
+ assert_match /100x100/, `identify "#{dst.path}"`
348
+ end
349
+ end
350
+ end
351
+
352
+ context "An animated gif" do
353
+ before do
354
+ @file = File.new(fixture_file("animated.gif"), 'rb')
355
+ end
356
+
357
+ after { @file.close }
358
+
359
+ it "starts with 12 frames with size 100x100" do
360
+ cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
361
+ assert_equal "100x100"*12, `#{cmd}`.chomp
362
+ end
363
+
364
+ context "with static output" do
365
+ before do
366
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :jpg)
367
+ end
368
+
369
+ it "creates the single frame thumbnail when sent #make" do
370
+ dst = @thumb.make
371
+ cmd = %Q[identify -format "%wx%h" "#{dst.path}"]
372
+ assert_equal "50x50", `#{cmd}`.chomp
373
+ end
374
+ end
375
+
376
+ context "with animated output format" do
377
+ before do
378
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :gif)
379
+ end
380
+
381
+ it "creates the 12 frames thumbnail when sent #make" do
382
+ dst = @thumb.make
383
+ cmd = %Q[identify -format "%wx%h," "#{dst.path}"]
384
+ frames = `#{cmd}`.chomp.split(',')
385
+ assert_equal 12, frames.size
386
+ assert_frame_dimensions (45..50), frames
387
+ end
388
+
389
+ it "uses the -coalesce option" do
390
+ assert_equal @thumb.transformation_command.first, "-coalesce"
391
+ end
392
+
393
+ it "uses the -layers 'optimize' option" do
394
+ assert_equal @thumb.transformation_command.last, '-layers "optimize"'
395
+ end
396
+ end
397
+
398
+ context "with omitted output format" do
399
+ before do
400
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50")
401
+ end
402
+
403
+ it "creates the 12 frames thumbnail when sent #make" do
404
+ dst = @thumb.make
405
+ cmd = %Q[identify -format "%wx%h," "#{dst.path}"]
406
+ frames = `#{cmd}`.chomp.split(',')
407
+ assert_equal 12, frames.size
408
+ assert_frame_dimensions (45..50), frames
409
+ end
410
+
411
+ it "uses the -coalesce option" do
412
+ assert_equal @thumb.transformation_command.first, "-coalesce"
413
+ end
414
+
415
+ it "uses the -layers 'optimize' option" do
416
+ assert_equal @thumb.transformation_command.last, '-layers "optimize"'
417
+ end
418
+ end
419
+
420
+ context "with unidentified source format" do
421
+ before do
422
+ @unidentified_file = File.new(fixture_file("animated.unknown"), 'rb')
423
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "60x60")
424
+ end
425
+
426
+ it "creates the 12 frames thumbnail when sent #make" do
427
+ dst = @thumb.make
428
+ cmd = %Q[identify -format "%wx%h," "#{dst.path}"]
429
+ frames = `#{cmd}`.chomp.split(',')
430
+ assert_equal 12, frames.size
431
+ assert_frame_dimensions (55..60), frames
432
+ end
433
+
434
+ it "uses the -coalesce option" do
435
+ assert_equal @thumb.transformation_command.first, "-coalesce"
436
+ end
437
+
438
+ it "uses the -layers 'optimize' option" do
439
+ assert_equal @thumb.transformation_command.last, '-layers "optimize"'
440
+ end
441
+ end
442
+
443
+ context "with no source format" do
444
+ before do
445
+ @unidentified_file = File.new(fixture_file("animated"), 'rb')
446
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "70x70")
447
+ end
448
+
449
+ it "creates the 12 frames thumbnail when sent #make" do
450
+ dst = @thumb.make
451
+ cmd = %Q[identify -format "%wx%h," "#{dst.path}"]
452
+ frames = `#{cmd}`.chomp.split(',')
453
+ assert_equal 12, frames.size
454
+ assert_frame_dimensions (60..70), frames
455
+ end
456
+
457
+ it "uses the -coalesce option" do
458
+ assert_equal @thumb.transformation_command.first, "-coalesce"
459
+ end
460
+
461
+ it "uses the -layers 'optimize' option" do
462
+ assert_equal @thumb.transformation_command.last, '-layers "optimize"'
463
+ end
464
+ end
465
+
466
+ context "with animated option set to false" do
467
+ before do
468
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", animated: false)
469
+ end
470
+
471
+ it "outputs the gif format" do
472
+ dst = @thumb.make
473
+ cmd = %Q[identify "#{dst.path}"]
474
+ assert_match /GIF/, `#{cmd}`.chomp
475
+ end
476
+
477
+ it "creates the single frame thumbnail when sent #make" do
478
+ dst = @thumb.make
479
+ cmd = %Q[identify -format "%wx%h" "#{dst.path}"]
480
+ assert_equal "50x50", `#{cmd}`.chomp
481
+ end
482
+ end
483
+ end
484
+
485
+ context "with a really long file name" do
486
+ before do
487
+ tempfile = Tempfile.new("f")
488
+ tempfile_additional_chars = tempfile.path.split("/")[-1].length + 15
489
+ image_file = File.new(fixture_file("5k.png"), "rb")
490
+ @file = Tempfile.new("f" * (255 - tempfile_additional_chars))
491
+ @file.write(image_file.read)
492
+ @file.rewind
493
+ end
494
+
495
+ it "does not throw Errno::ENAMETOOLONG" do
496
+ thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :gif)
497
+ expect { thumb.make }.to_not raise_error
498
+ end
499
+ end
500
+ end
@@ -0,0 +1,211 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Paperclip::UrlGenerator do
5
+ it "uses the given interpolator" do
6
+ expected = "the expected result"
7
+ mock_attachment = MockAttachment.new
8
+ mock_interpolator = MockInterpolator.new(result: expected)
9
+
10
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment,
11
+ { interpolator: mock_interpolator })
12
+ result = url_generator.for(:style_name, {})
13
+
14
+ assert_equal expected, result
15
+ assert mock_interpolator.has_interpolated_attachment?(mock_attachment)
16
+ assert mock_interpolator.has_interpolated_style_name?(:style_name)
17
+ end
18
+
19
+ it "uses the default URL when no file is assigned" do
20
+ mock_attachment = MockAttachment.new
21
+ mock_interpolator = MockInterpolator.new
22
+ default_url = "the default url"
23
+ options = { interpolator: mock_interpolator, default_url: default_url}
24
+
25
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
26
+ url_generator.for(:style_name, {})
27
+
28
+ assert mock_interpolator.has_interpolated_pattern?(default_url),
29
+ "expected the interpolator to be passed #{default_url.inspect} but it wasn't"
30
+ end
31
+
32
+ it "executes the default URL lambda when no file is assigned" do
33
+ mock_attachment = MockAttachment.new
34
+ mock_interpolator = MockInterpolator.new
35
+ default_url = lambda {|attachment| "the #{attachment.class.name} default url" }
36
+ options = { interpolator: mock_interpolator, default_url: default_url}
37
+
38
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
39
+ url_generator.for(:style_name, {})
40
+
41
+ assert mock_interpolator.has_interpolated_pattern?("the MockAttachment default url"),
42
+ %{expected the interpolator to be passed "the MockAttachment default url", but it wasn't}
43
+ end
44
+
45
+ it "executes the method named by the symbol as the default URL when no file is assigned" do
46
+ mock_model = FakeModel.new
47
+ mock_attachment = MockAttachment.new(model: mock_model)
48
+ mock_interpolator = MockInterpolator.new
49
+ default_url = :to_s
50
+ options = { interpolator: mock_interpolator, default_url: default_url}
51
+
52
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
53
+ url_generator.for(:style_name, {})
54
+
55
+ assert mock_interpolator.has_interpolated_pattern?(mock_model.to_s),
56
+ %{expected the interpolator to be passed #{mock_model.to_s}, but it wasn't}
57
+ end
58
+
59
+ it "URL-escapes spaces if asked to" do
60
+ expected = "the expected result"
61
+ mock_attachment = MockAttachment.new
62
+ mock_interpolator = MockInterpolator.new(result: expected)
63
+ options = { interpolator: mock_interpolator }
64
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
65
+
66
+ result = url_generator.for(:style_name, {escape: true})
67
+
68
+ assert_equal "the%20expected%20result", result
69
+ end
70
+
71
+ it "escapes the result of the interpolator using a method on the object, if asked to escape" do
72
+ expected = Class.new do
73
+ def escape
74
+ "the escaped result"
75
+ end
76
+ end.new
77
+ mock_attachment = MockAttachment.new
78
+ mock_interpolator = MockInterpolator.new(result: expected)
79
+ options = { interpolator: mock_interpolator }
80
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
81
+
82
+ result = url_generator.for(:style_name, {escape: true})
83
+
84
+ assert_equal "the escaped result", result
85
+ end
86
+
87
+ it "leaves spaces unescaped as asked to" do
88
+ expected = "the expected result"
89
+ mock_attachment = MockAttachment.new
90
+ mock_interpolator = MockInterpolator.new(result: expected)
91
+ options = { interpolator: mock_interpolator }
92
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
93
+
94
+ result = url_generator.for(:style_name, {escape: false})
95
+
96
+ assert_equal "the expected result", result
97
+ end
98
+
99
+ it "defaults to leaving spaces unescaped" do
100
+ expected = "the expected result"
101
+ mock_attachment = MockAttachment.new
102
+ mock_interpolator = MockInterpolator.new(result: expected)
103
+ options = { interpolator: mock_interpolator }
104
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
105
+
106
+ result = url_generator.for(:style_name, {})
107
+
108
+ assert_equal "the expected result", result
109
+ end
110
+
111
+ it "produces URLs without the updated_at value when the object does not respond to updated_at" do
112
+ expected = "the expected result"
113
+ mock_interpolator = MockInterpolator.new(result: expected)
114
+ mock_attachment = MockAttachment.new(responds_to_updated_at: false)
115
+ options = { interpolator: mock_interpolator }
116
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
117
+
118
+ result = url_generator.for(:style_name, {timestamp: true})
119
+
120
+ assert_equal expected, result
121
+ end
122
+
123
+ it "produces URLs without the updated_at value when the updated_at value is nil" do
124
+ expected = "the expected result"
125
+ mock_interpolator = MockInterpolator.new(result: expected)
126
+ mock_attachment = MockAttachment.new(responds_to_updated_at: true, updated_at: nil)
127
+ options = { interpolator: mock_interpolator }
128
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
129
+
130
+ result = url_generator.for(:style_name, {timestamp: true})
131
+
132
+ assert_equal expected, result
133
+ end
134
+
135
+ it "produces URLs with the updated_at when it exists" do
136
+ expected = "the expected result"
137
+ updated_at = 1231231234
138
+ mock_interpolator = MockInterpolator.new(result: expected)
139
+ mock_attachment = MockAttachment.new(updated_at: updated_at)
140
+ options = { interpolator: mock_interpolator }
141
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
142
+
143
+ result = url_generator.for(:style_name, {timestamp: true})
144
+
145
+ assert_equal "#{expected}?#{updated_at}", result
146
+ end
147
+
148
+ it "produces URLs with the updated_at when it exists, separated with a & if a ? follow by = already exists" do
149
+ expected = "the?expected=result"
150
+ updated_at = 1231231234
151
+ mock_interpolator = MockInterpolator.new(result: expected)
152
+ mock_attachment = MockAttachment.new(updated_at: updated_at)
153
+ options = { interpolator: mock_interpolator }
154
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
155
+
156
+ result = url_generator.for(:style_name, {timestamp: true})
157
+
158
+ assert_equal "#{expected}&#{updated_at}", result
159
+ end
160
+
161
+ it "produces URLs without the updated_at when told to do as much" do
162
+ expected = "the expected result"
163
+ updated_at = 1231231234
164
+ mock_interpolator = MockInterpolator.new(result: expected)
165
+ mock_attachment = MockAttachment.new(updated_at: updated_at)
166
+ options = { interpolator: mock_interpolator }
167
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
168
+
169
+ result = url_generator.for(:style_name, {timestamp: false})
170
+
171
+ assert_equal expected, result
172
+ end
173
+
174
+ it "produces the correct URL when the instance has a file name" do
175
+ expected = "the expected result"
176
+ mock_attachment = MockAttachment.new(original_filename: 'exists')
177
+ mock_interpolator = MockInterpolator.new
178
+ options = { interpolator: mock_interpolator, url: expected}
179
+
180
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
181
+ url_generator.for(:style_name, {})
182
+
183
+ assert mock_interpolator.has_interpolated_pattern?(expected),
184
+ "expected the interpolator to be passed #{expected.inspect} but it wasn't"
185
+ end
186
+
187
+ describe "should be able to escape (, ), [, and ]." do
188
+ def generate(expected, updated_at=nil)
189
+ mock_attachment = MockAttachment.new(updated_at: updated_at)
190
+ mock_interpolator = MockInterpolator.new(result: expected)
191
+ options = { interpolator: mock_interpolator }
192
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment, options)
193
+ def url_generator.respond_to(params)
194
+ false if params == :escape
195
+ end
196
+ url_generator.for(:style_name, {escape: true, timestamp: !!updated_at})
197
+ end
198
+
199
+ it "not timestamp" do
200
+ expected = "the(expected)result[]"
201
+ assert_equal "the%28expected%29result%5B%5D", generate(expected)
202
+ end
203
+
204
+ it "timestamp" do
205
+ expected = "the(expected)result[]"
206
+ updated_at = 1231231234
207
+ assert_equal "the%28expected%29result%5B%5D?#{updated_at}",
208
+ generate(expected, updated_at)
209
+ end
210
+ end
211
+ end