kt-paperclip 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (191) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +3 -0
  4. data/.gitignore +19 -0
  5. data/.hound.yml +1050 -0
  6. data/.rubocop.yml +1 -0
  7. data/.travis.yml +47 -0
  8. data/Appraisals +24 -0
  9. data/CONTRIBUTING.md +86 -0
  10. data/Gemfile +18 -0
  11. data/LICENSE +24 -0
  12. data/NEWS +515 -0
  13. data/README.md +1053 -0
  14. data/RELEASING.md +17 -0
  15. data/Rakefile +52 -0
  16. data/UPGRADING +17 -0
  17. data/features/basic_integration.feature +85 -0
  18. data/features/migration.feature +29 -0
  19. data/features/rake_tasks.feature +62 -0
  20. data/features/step_definitions/attachment_steps.rb +110 -0
  21. data/features/step_definitions/html_steps.rb +15 -0
  22. data/features/step_definitions/rails_steps.rb +257 -0
  23. data/features/step_definitions/s3_steps.rb +14 -0
  24. data/features/step_definitions/web_steps.rb +106 -0
  25. data/features/support/env.rb +12 -0
  26. data/features/support/fakeweb.rb +11 -0
  27. data/features/support/file_helpers.rb +34 -0
  28. data/features/support/fixtures/boot_config.txt +15 -0
  29. data/features/support/fixtures/gemfile.txt +5 -0
  30. data/features/support/fixtures/preinitializer.txt +20 -0
  31. data/features/support/paths.rb +28 -0
  32. data/features/support/rails.rb +39 -0
  33. data/features/support/selectors.rb +19 -0
  34. data/gemfiles/4.2.gemfile +20 -0
  35. data/gemfiles/5.0.gemfile +20 -0
  36. data/gemfiles/5.1.gemfile +20 -0
  37. data/gemfiles/5.2.gemfile +20 -0
  38. data/gemfiles/6.0.gemfile +20 -0
  39. data/lib/generators/paperclip/USAGE +8 -0
  40. data/lib/generators/paperclip/paperclip_generator.rb +36 -0
  41. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
  42. data/lib/paperclip.rb +215 -0
  43. data/lib/paperclip/attachment.rb +617 -0
  44. data/lib/paperclip/attachment_registry.rb +60 -0
  45. data/lib/paperclip/callbacks.rb +42 -0
  46. data/lib/paperclip/content_type_detector.rb +80 -0
  47. data/lib/paperclip/errors.rb +34 -0
  48. data/lib/paperclip/file_command_content_type_detector.rb +28 -0
  49. data/lib/paperclip/filename_cleaner.rb +15 -0
  50. data/lib/paperclip/geometry.rb +157 -0
  51. data/lib/paperclip/geometry_detector_factory.rb +45 -0
  52. data/lib/paperclip/geometry_parser_factory.rb +31 -0
  53. data/lib/paperclip/glue.rb +17 -0
  54. data/lib/paperclip/has_attached_file.rb +116 -0
  55. data/lib/paperclip/helpers.rb +60 -0
  56. data/lib/paperclip/interpolations.rb +201 -0
  57. data/lib/paperclip/interpolations/plural_cache.rb +18 -0
  58. data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
  59. data/lib/paperclip/io_adapters/attachment_adapter.rb +47 -0
  60. data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
  61. data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
  62. data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
  63. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
  64. data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
  65. data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
  66. data/lib/paperclip/io_adapters/registry.rb +36 -0
  67. data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
  68. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
  69. data/lib/paperclip/io_adapters/uri_adapter.rb +68 -0
  70. data/lib/paperclip/locales/en.yml +18 -0
  71. data/lib/paperclip/logger.rb +21 -0
  72. data/lib/paperclip/matchers.rb +64 -0
  73. data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
  74. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
  75. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
  76. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
  77. data/lib/paperclip/media_type_spoof_detector.rb +90 -0
  78. data/lib/paperclip/missing_attachment_styles.rb +84 -0
  79. data/lib/paperclip/processor.rb +56 -0
  80. data/lib/paperclip/processor_helpers.rb +52 -0
  81. data/lib/paperclip/rails_environment.rb +21 -0
  82. data/lib/paperclip/railtie.rb +31 -0
  83. data/lib/paperclip/schema.rb +81 -0
  84. data/lib/paperclip/storage.rb +3 -0
  85. data/lib/paperclip/storage/filesystem.rb +99 -0
  86. data/lib/paperclip/storage/fog.rb +252 -0
  87. data/lib/paperclip/storage/s3.rb +461 -0
  88. data/lib/paperclip/style.rb +106 -0
  89. data/lib/paperclip/tempfile.rb +42 -0
  90. data/lib/paperclip/tempfile_factory.rb +22 -0
  91. data/lib/paperclip/thumbnail.rb +131 -0
  92. data/lib/paperclip/url_generator.rb +76 -0
  93. data/lib/paperclip/validators.rb +73 -0
  94. data/lib/paperclip/validators/attachment_content_type_validator.rb +88 -0
  95. data/lib/paperclip/validators/attachment_file_name_validator.rb +75 -0
  96. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
  97. data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
  98. data/lib/paperclip/validators/attachment_size_validator.rb +109 -0
  99. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
  100. data/lib/paperclip/version.rb +3 -0
  101. data/lib/tasks/paperclip.rake +140 -0
  102. data/paperclip.gemspec +50 -0
  103. data/shoulda_macros/paperclip.rb +134 -0
  104. data/spec/database.yml +4 -0
  105. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  106. data/spec/paperclip/attachment_processing_spec.rb +79 -0
  107. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  108. data/spec/paperclip/attachment_spec.rb +1590 -0
  109. data/spec/paperclip/content_type_detector_spec.rb +47 -0
  110. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  111. data/spec/paperclip/filename_cleaner_spec.rb +13 -0
  112. data/spec/paperclip/geometry_detector_spec.rb +38 -0
  113. data/spec/paperclip/geometry_parser_spec.rb +73 -0
  114. data/spec/paperclip/geometry_spec.rb +255 -0
  115. data/spec/paperclip/glue_spec.rb +42 -0
  116. data/spec/paperclip/has_attached_file_spec.rb +78 -0
  117. data/spec/paperclip/integration_spec.rb +702 -0
  118. data/spec/paperclip/interpolations_spec.rb +270 -0
  119. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
  120. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +140 -0
  121. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
  122. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  123. data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
  124. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +137 -0
  125. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  126. data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
  127. data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
  128. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
  129. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
  130. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +221 -0
  131. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  132. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
  133. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  134. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  135. data/spec/paperclip/media_type_spoof_detector_spec.rb +120 -0
  136. data/spec/paperclip/meta_class_spec.rb +30 -0
  137. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
  138. data/spec/paperclip/paperclip_spec.rb +196 -0
  139. data/spec/paperclip/plural_cache_spec.rb +37 -0
  140. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  141. data/spec/paperclip/processor_spec.rb +26 -0
  142. data/spec/paperclip/rails_environment_spec.rb +30 -0
  143. data/spec/paperclip/rake_spec.rb +103 -0
  144. data/spec/paperclip/schema_spec.rb +252 -0
  145. data/spec/paperclip/storage/filesystem_spec.rb +79 -0
  146. data/spec/paperclip/storage/fog_spec.rb +560 -0
  147. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  148. data/spec/paperclip/storage/s3_spec.rb +1695 -0
  149. data/spec/paperclip/style_spec.rb +251 -0
  150. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  151. data/spec/paperclip/tempfile_spec.rb +35 -0
  152. data/spec/paperclip/thumbnail_spec.rb +504 -0
  153. data/spec/paperclip/url_generator_spec.rb +221 -0
  154. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  155. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +159 -0
  156. data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
  157. data/spec/paperclip/validators/attachment_size_validator_spec.rb +235 -0
  158. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
  159. data/spec/paperclip/validators_spec.rb +164 -0
  160. data/spec/spec_helper.rb +45 -0
  161. data/spec/support/assertions.rb +84 -0
  162. data/spec/support/fake_model.rb +24 -0
  163. data/spec/support/fake_rails.rb +12 -0
  164. data/spec/support/fixtures/12k.png +0 -0
  165. data/spec/support/fixtures/50x50.png +0 -0
  166. data/spec/support/fixtures/5k.png +0 -0
  167. data/spec/support/fixtures/animated +0 -0
  168. data/spec/support/fixtures/animated.gif +0 -0
  169. data/spec/support/fixtures/animated.unknown +0 -0
  170. data/spec/support/fixtures/bad.png +1 -0
  171. data/spec/support/fixtures/empty.html +1 -0
  172. data/spec/support/fixtures/empty.xlsx +0 -0
  173. data/spec/support/fixtures/fog.yml +8 -0
  174. data/spec/support/fixtures/rotated.jpg +0 -0
  175. data/spec/support/fixtures/s3.yml +8 -0
  176. data/spec/support/fixtures/spaced file.jpg +0 -0
  177. data/spec/support/fixtures/spaced file.png +0 -0
  178. data/spec/support/fixtures/text.txt +1 -0
  179. data/spec/support/fixtures/twopage.pdf +0 -0
  180. data/spec/support/fixtures/uppercase.PNG +0 -0
  181. data/spec/support/matchers/accept.rb +5 -0
  182. data/spec/support/matchers/exist.rb +5 -0
  183. data/spec/support/matchers/have_column.rb +23 -0
  184. data/spec/support/mock_attachment.rb +24 -0
  185. data/spec/support/mock_interpolator.rb +24 -0
  186. data/spec/support/mock_url_generator_builder.rb +26 -0
  187. data/spec/support/model_reconstruction.rb +72 -0
  188. data/spec/support/reporting.rb +11 -0
  189. data/spec/support/test_data.rb +13 -0
  190. data/spec/support/version_helper.rb +9 -0
  191. metadata +586 -0
@@ -0,0 +1,251 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::Style do
4
+ context "A style rule" do
5
+ before do
6
+ @attachment = attachment path: ":basename.:extension",
7
+ styles: { foo: { geometry: "100x100#", format: :png } },
8
+ whiny: true
9
+ @style = @attachment.styles[:foo]
10
+ end
11
+
12
+ it "is held as a Style object" do
13
+ expect(@style).to be_a Paperclip::Style
14
+ end
15
+
16
+ it "gets processors from the attachment definition" do
17
+ assert_equal [:thumbnail], @style.processors
18
+ end
19
+
20
+ it "has the right geometry" do
21
+ assert_equal "100x100#", @style.geometry
22
+ end
23
+
24
+ it "is whiny if the attachment is" do
25
+ assert @style.whiny?
26
+ end
27
+
28
+ it "responds to hash notation" do
29
+ assert_equal [:thumbnail], @style[:processors]
30
+ assert_equal "100x100#", @style[:geometry]
31
+ end
32
+
33
+ it "returns the name of the style in processor options" do
34
+ assert_equal :foo, @style.processor_options[:style]
35
+ end
36
+ end
37
+
38
+ context "A style rule with properties supplied as procs" do
39
+ before do
40
+ @attachment = attachment path: ":basename.:extension",
41
+ whiny_thumbnails: true,
42
+ processors: lambda { |_a| [:test] },
43
+ styles: {
44
+ foo: lambda { |_a| "300x300#" },
45
+ bar: {
46
+ geometry: lambda { |_a| "300x300#" },
47
+ convert_options: lambda { |_a| "-do_stuff" },
48
+ source_file_options: lambda { |_a| "-do_extra_stuff" }
49
+ }
50
+ }
51
+ end
52
+
53
+ it "calls procs when they are needed" do
54
+ assert_equal "300x300#", @attachment.styles[:foo].geometry
55
+ assert_equal "300x300#", @attachment.styles[:bar].geometry
56
+ assert_equal [:test], @attachment.styles[:foo].processors
57
+ assert_equal [:test], @attachment.styles[:bar].processors
58
+ assert_equal "-do_stuff", @attachment.styles[:bar].convert_options
59
+ assert_equal "-do_extra_stuff", @attachment.styles[:bar].source_file_options
60
+ end
61
+ end
62
+
63
+ context "An attachment with style rules in various forms" do
64
+ before do
65
+ styles = {}
66
+ styles[:aslist] = ["100x100", :png]
67
+ styles[:ashash] = { geometry: "100x100", format: :png }
68
+ styles[:asstring] = "100x100"
69
+ @attachment = attachment path: ":basename.:extension",
70
+ styles: styles
71
+ end
72
+
73
+ it "has the right number of styles" do
74
+ expect(@attachment.styles).to be_a Hash
75
+ assert_equal 3, @attachment.styles.size
76
+ end
77
+
78
+ it "has styles as Style objects" do
79
+ [:aslist, :ashash, :aslist].each do |s|
80
+ expect(@attachment.styles[s]).to be_a Paperclip::Style
81
+ end
82
+ end
83
+
84
+ it "has the right geometries" do
85
+ [:aslist, :ashash, :aslist].each do |s|
86
+ assert_equal @attachment.styles[s].geometry, "100x100"
87
+ end
88
+ end
89
+
90
+ it "has the right formats" do
91
+ assert_equal @attachment.styles[:aslist].format, :png
92
+ assert_equal @attachment.styles[:ashash].format, :png
93
+ assert_nil @attachment.styles[:asstring].format
94
+ end
95
+
96
+ it "retains order" do
97
+ assert_equal [:aslist, :ashash, :asstring], @attachment.styles.keys
98
+ end
99
+ end
100
+
101
+ context "An attachment with :convert_options" do
102
+ it "does not have called extra_options_for(:thumb/:large) on initialization" do
103
+ @attachment = attachment path: ":basename.:extension",
104
+ styles: { thumb: "100x100", large: "400x400" },
105
+ convert_options: { all: "-do_stuff", thumb: "-thumbnailize" }
106
+ expect(@attachment).to_not receive(:extra_options_for)
107
+ @style = @attachment.styles[:thumb]
108
+ end
109
+
110
+ it "calls extra_options_for(:thumb/:large) when convert options are requested" do
111
+ @attachment = attachment path: ":basename.:extension",
112
+ styles: { thumb: "100x100", large: "400x400" },
113
+ convert_options: { all: "-do_stuff", thumb: "-thumbnailize" }
114
+ @style = @attachment.styles[:thumb]
115
+ @file = StringIO.new("...")
116
+ allow(@file).to receive(:original_filename).and_return("file.jpg")
117
+
118
+ expect(@attachment).to receive(:extra_options_for).with(:thumb)
119
+ @attachment.styles[:thumb].convert_options
120
+ end
121
+ end
122
+
123
+ context "An attachment with :source_file_options" do
124
+ it "does not have called extra_source_file_options_for(:thumb/:large) on initialization" do
125
+ @attachment = attachment path: ":basename.:extension",
126
+ styles: { thumb: "100x100", large: "400x400" },
127
+ source_file_options: { all: "-density 400", thumb: "-depth 8" }
128
+ expect(@attachment).to_not receive(:extra_source_file_options_for)
129
+ @style = @attachment.styles[:thumb]
130
+ end
131
+
132
+ it "calls extra_options_for(:thumb/:large) when convert options are requested" do
133
+ @attachment = attachment path: ":basename.:extension",
134
+ styles: { thumb: "100x100", large: "400x400" },
135
+ source_file_options: { all: "-density 400", thumb: "-depth 8" }
136
+ @style = @attachment.styles[:thumb]
137
+ @file = StringIO.new("...")
138
+ allow(@file).to receive(:original_filename).and_return("file.jpg")
139
+
140
+ expect(@attachment).to receive(:extra_source_file_options_for).with(:thumb)
141
+ @attachment.styles[:thumb].source_file_options
142
+ end
143
+ end
144
+
145
+ context "A style rule with its own :processors" do
146
+ before do
147
+ @attachment = attachment path: ":basename.:extension",
148
+ styles: {
149
+ foo: {
150
+ geometry: "100x100#",
151
+ format: :png,
152
+ processors: [:test]
153
+ }
154
+ },
155
+ processors: [:thumbnail]
156
+ @style = @attachment.styles[:foo]
157
+ end
158
+
159
+ it "does not get processors from the attachment" do
160
+ expect(@attachment).to_not receive(:processors)
161
+ assert_not_equal [:thumbnail], @style.processors
162
+ end
163
+
164
+ it "reports its own processors" do
165
+ assert_equal [:test], @style.processors
166
+ end
167
+ end
168
+
169
+ context "A style rule with :processors supplied as procs" do
170
+ before do
171
+ @attachment = attachment path: ":basename.:extension",
172
+ styles: {
173
+ foo: {
174
+ geometry: "100x100#",
175
+ format: :png,
176
+ processors: lambda { |_a| [:test] }
177
+ }
178
+ },
179
+ processors: [:thumbnail]
180
+ end
181
+
182
+ it "defers processing of procs until they are needed" do
183
+ expect(@attachment.styles[:foo].instance_variable_get("@processors")).to be_a Proc
184
+ end
185
+
186
+ it "calls procs when they are needed" do
187
+ assert_equal [:test], @attachment.styles[:foo].processors
188
+ end
189
+ end
190
+
191
+ context "An attachment with :convert_options and :source_file_options in :styles" do
192
+ before do
193
+ @attachment = attachment path: ":basename.:extension",
194
+ styles: {
195
+ thumb: "100x100",
196
+ large: { geometry: "400x400",
197
+ convert_options: "-do_stuff",
198
+ source_file_options: "-do_extra_stuff" }
199
+ }
200
+ @file = StringIO.new("...")
201
+ allow(@file).to receive(:original_filename).and_return("file.jpg")
202
+ end
203
+
204
+ it "has empty options for :thumb style" do
205
+ assert_equal "", @attachment.styles[:thumb].processor_options[:convert_options]
206
+ assert_equal "", @attachment.styles[:thumb].processor_options[:source_file_options]
207
+ end
208
+
209
+ it "has the right options for :large style" do
210
+ assert_equal "-do_stuff", @attachment.styles[:large].processor_options[:convert_options]
211
+ assert_equal "-do_extra_stuff", @attachment.styles[:large].processor_options[:source_file_options]
212
+ end
213
+ end
214
+
215
+ context "A style rule supplied with default format" do
216
+ before do
217
+ @attachment = attachment default_format: :png,
218
+ styles: {
219
+ asstring: "300x300#",
220
+ aslist: ["300x300#", :jpg],
221
+ ashash: {
222
+ geometry: "300x300#",
223
+ convert_options: "-do_stuff"
224
+ }
225
+ }
226
+ end
227
+
228
+ it "has the right number of styles" do
229
+ expect(@attachment.styles).to be_a Hash
230
+ assert_equal 3, @attachment.styles.size
231
+ end
232
+
233
+ it "has styles as Style objects" do
234
+ [:aslist, :ashash, :aslist].each do |s|
235
+ expect(@attachment.styles[s]).to be_a Paperclip::Style
236
+ end
237
+ end
238
+
239
+ it "has the right geometries" do
240
+ [:aslist, :ashash, :aslist].each do |s|
241
+ assert_equal @attachment.styles[s].geometry, "300x300#"
242
+ end
243
+ end
244
+
245
+ it "has the right formats" do
246
+ assert_equal @attachment.styles[:aslist].format, :jpg
247
+ assert_equal @attachment.styles[:ashash].format, :png
248
+ assert_equal @attachment.styles[:asstring].format, :png
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::TempfileFactory do
4
+ it "is able to generate a tempfile with the right name" do
5
+ file = subject.generate("omg.png")
6
+ assert File.extname(file.path), "png"
7
+ end
8
+
9
+ it "is able to generate a tempfile with the right name with a tilde at the beginning" do
10
+ file = subject.generate("~omg.png")
11
+ assert File.extname(file.path), "png"
12
+ end
13
+
14
+ it "is able to generate a tempfile with the right name with a tilde at the end" do
15
+ file = subject.generate("omg.png~")
16
+ assert File.extname(file.path), "png"
17
+ end
18
+
19
+ it "is able to generate a tempfile from a file with a really long name" do
20
+ filename = "#{'longfilename' * 100}.png"
21
+ file = subject.generate(filename)
22
+ assert File.extname(file.path), "png"
23
+ end
24
+
25
+ it "is able to take nothing as a parameter and not error" do
26
+ file = subject.generate
27
+ assert File.exist?(file.path)
28
+ end
29
+
30
+ it "does not throw Errno::ENAMETOOLONG when it has a really long name" do
31
+ expect { subject.generate("o" * 255) }.to_not raise_error
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::Tempfile do
4
+ context "A Paperclip Tempfile" do
5
+ before do
6
+ @tempfile = described_class.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 = described_class.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
+ end
@@ -0,0 +1,504 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::Thumbnail do
4
+ context "An image" do
5
+ before do
6
+ @file = File.new(fixture_file("5k.png"), "rb")
7
+ end
8
+
9
+ after { @file.close }
10
+
11
+ [["600x600>", "434x66"],
12
+ ["400x400>", "400x61"],
13
+ ["32x32<", "434x66"],
14
+ [nil, "434x66"]].each do |args|
15
+ context "being thumbnailed with a geometry of #{args[0]}" do
16
+ before do
17
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: args[0])
18
+ end
19
+
20
+ it "starts with dimensions of 434x66" do
21
+ cmd = %[identify -format "%wx%h" "#{@file.path}"]
22
+ assert_equal "434x66", `#{cmd}`.chomp
23
+ end
24
+
25
+ it "reports the correct target geometry" do
26
+ assert_equal args[0].to_s, @thumb.target_geometry.to_s
27
+ end
28
+
29
+ context "when made" do
30
+ before do
31
+ @thumb_result = @thumb.make
32
+ end
33
+
34
+ it "is the size we expect it to be" do
35
+ cmd = %[identify -format "%wx%h" "#{@thumb_result.path}"]
36
+ assert_equal args[1], `#{cmd}`.chomp
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ context "being thumbnailed at 100x50 with cropping" do
43
+ before do
44
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#")
45
+ end
46
+
47
+ it "lets us know when a command isn't found versus a processing error" do
48
+ old_path = ENV["PATH"]
49
+ begin
50
+ Terrapin::CommandLine.path = ""
51
+ Paperclip.options[:command_path] = ""
52
+ ENV["PATH"] = ""
53
+ assert_raises(Paperclip::Errors::CommandNotFoundError) do
54
+ silence_stream(STDERR) do
55
+ @thumb.make
56
+ end
57
+ end
58
+ ensure
59
+ ENV["PATH"] = old_path
60
+ end
61
+ end
62
+
63
+ it "reports its correct current and target geometries" do
64
+ assert_equal "100x50#", @thumb.target_geometry.to_s
65
+ assert_equal "434x66", @thumb.current_geometry.to_s
66
+ end
67
+
68
+ it "reports its correct format" do
69
+ assert_nil @thumb.format
70
+ end
71
+
72
+ it "has whiny turned on by default" do
73
+ assert @thumb.whiny
74
+ end
75
+
76
+ it "has convert_options set to nil by default" do
77
+ assert_equal nil, @thumb.convert_options
78
+ end
79
+
80
+ it "has source_file_options set to nil by default" do
81
+ assert_equal nil, @thumb.source_file_options
82
+ end
83
+
84
+ it "sends the right command to convert when sent #make" do
85
+ expect(@thumb).to receive(:convert) do |*arg|
86
+ arg[0] == ':source -auto-orient -resize "x50" -crop "100x50+114+0" +repage :dest' &&
87
+ arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
88
+ end
89
+ @thumb.make
90
+ end
91
+
92
+ it "creates the thumbnail when sent #make" do
93
+ dst = @thumb.make
94
+ assert_match /100x50/, `identify "#{dst.path}"`
95
+ end
96
+ end
97
+
98
+ it "crops a EXIF-rotated image properly" do
99
+ file = File.new(fixture_file("rotated.jpg"))
100
+ thumb = Paperclip::Thumbnail.new(file, geometry: "50x50#")
101
+
102
+ output_file = thumb.make
103
+
104
+ command = Terrapin::CommandLine.new("identify", "-format %wx%h :file")
105
+ assert_equal "50x50", command.run(file: output_file.path).strip
106
+ end
107
+
108
+ context "being thumbnailed with source file options set" do
109
+ before do
110
+ @thumb = Paperclip::Thumbnail.new(@file,
111
+ geometry: "100x50#",
112
+ source_file_options: "-strip")
113
+ end
114
+
115
+ it "has source_file_options value set" do
116
+ assert_equal ["-strip"], @thumb.source_file_options
117
+ end
118
+
119
+ it "sends the right command to convert when sent #make" do
120
+ expect(@thumb).to receive(:convert) do |*arg|
121
+ arg[0] == '-strip :source -auto-orient -resize "x50" -crop "100x50+114+0" +repage :dest' &&
122
+ arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
123
+ end
124
+ @thumb.make
125
+ end
126
+
127
+ it "creates the thumbnail when sent #make" do
128
+ dst = @thumb.make
129
+ assert_match /100x50/, `identify "#{dst.path}"`
130
+ end
131
+
132
+ context "redefined to have bad source_file_options setting" do
133
+ before do
134
+ @thumb = Paperclip::Thumbnail.new(@file,
135
+ geometry: "100x50#",
136
+ source_file_options: "-this-aint-no-option")
137
+ end
138
+
139
+ it "errors when trying to create the thumbnail" do
140
+ assert_raises(Paperclip::Error) do
141
+ silence_stream(STDERR) do
142
+ @thumb.make
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ context "being thumbnailed with convert options set" do
150
+ before do
151
+ @thumb = Paperclip::Thumbnail.new(@file,
152
+ geometry: "100x50#",
153
+ convert_options: "-strip -depth 8")
154
+ end
155
+
156
+ it "has convert_options value set" do
157
+ assert_equal %w"-strip -depth 8", @thumb.convert_options
158
+ end
159
+
160
+ it "sends the right command to convert when sent #make" do
161
+ expect(@thumb).to receive(:convert) do |*arg|
162
+ arg[0] == ':source -auto-orient -resize "x50" -crop "100x50+114+0" +repage -strip -depth 8 :dest' &&
163
+ arg[1][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
164
+ end
165
+ @thumb.make
166
+ end
167
+
168
+ it "creates the thumbnail when sent #make" do
169
+ dst = @thumb.make
170
+ assert_match /100x50/, `identify "#{dst.path}"`
171
+ end
172
+
173
+ context "redefined to have bad convert_options setting" do
174
+ before do
175
+ @thumb = Paperclip::Thumbnail.new(@file,
176
+ geometry: "100x50#",
177
+ convert_options: "-this-aint-no-option")
178
+ end
179
+
180
+ it "errors when trying to create the thumbnail" do
181
+ silence_stream(STDERR) do
182
+ expect do
183
+ @thumb.make
184
+ end.to raise_error(
185
+ Paperclip::Error, /unrecognized option `-this-aint-no-option'/
186
+ )
187
+ end
188
+ end
189
+
190
+ it "lets us know when a command isn't found versus a processing error" do
191
+ old_path = ENV["PATH"]
192
+ begin
193
+ Terrapin::CommandLine.path = ""
194
+ Paperclip.options[:command_path] = ""
195
+ ENV["PATH"] = ""
196
+ assert_raises(Paperclip::Errors::CommandNotFoundError) do
197
+ silence_stream(STDERR) do
198
+ @thumb.make
199
+ end
200
+ end
201
+ ensure
202
+ ENV["PATH"] = old_path
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ context "being thumbnailed with a blank geometry string" do
209
+ before do
210
+ @thumb = Paperclip::Thumbnail.new(@file,
211
+ geometry: "",
212
+ convert_options: "-gravity center -crop \"300x300+0-0\"")
213
+ end
214
+
215
+ it "does not get resized by default" do
216
+ assert !@thumb.transformation_command.include?("-resize")
217
+ end
218
+ end
219
+
220
+ context "being thumbnailed with default animated option (true)" do
221
+ it "calls identify to check for animated images when sent #make" do
222
+ thumb = Paperclip::Thumbnail.new(@file, geometry: "100x50#")
223
+ expect(thumb).to receive(:identify).at_least(1).times do |*arg|
224
+ arg[0] == "-format %m :file" &&
225
+ arg[1][:file] == "#{File.expand_path(thumb.file.path)}[0]"
226
+ end
227
+ thumb.make
228
+ end
229
+ end
230
+
231
+ context "passing a custom file geometry parser" do
232
+ after do
233
+ Object.send(:remove_const, :GeoParser) if Object.const_defined?(:GeoParser)
234
+ end
235
+
236
+ it "produces the appropriate transformation_command" do
237
+ GeoParser = Class.new do
238
+ def self.from_file(_file)
239
+ new
240
+ end
241
+
242
+ def transformation_to(_target, _should_crop)
243
+ ["SCALE", "CROP"]
244
+ end
245
+ end
246
+
247
+ thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", file_geometry_parser: ::GeoParser)
248
+
249
+ transformation_command = thumb.transformation_command
250
+
251
+ assert transformation_command.include?("-crop"),
252
+ %{expected #{transformation_command.inspect} to include '-crop'}
253
+ assert transformation_command.include?('"CROP"'),
254
+ %{expected #{transformation_command.inspect} to include '"CROP"'}
255
+ assert transformation_command.include?("-resize"),
256
+ %{expected #{transformation_command.inspect} to include '-resize'}
257
+ assert transformation_command.include?('"SCALE"'),
258
+ %{expected #{transformation_command.inspect} to include '"SCALE"'}
259
+ end
260
+ end
261
+
262
+ context "passing a custom geometry string 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.parse(_s)
270
+ new
271
+ end
272
+
273
+ def to_s
274
+ "151x167"
275
+ end
276
+ end
277
+
278
+ thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", string_geometry_parser: ::GeoParser)
279
+
280
+ transformation_command = thumb.transformation_command
281
+
282
+ assert transformation_command.include?('"151x167"'),
283
+ %{expected #{transformation_command.inspect} to include '151x167'}
284
+ end
285
+ end
286
+ end
287
+
288
+ context "A multipage PDF" do
289
+ before do
290
+ @file = File.new(fixture_file("twopage.pdf"), "rb")
291
+ end
292
+
293
+ after { @file.close }
294
+
295
+ it "starts with two pages with dimensions 612x792" do
296
+ cmd = %[identify -format "%wx%h" "#{@file.path}"]
297
+ assert_equal "612x792" * 2, `#{cmd}`.chomp
298
+ end
299
+
300
+ context "being thumbnailed at 100x100 with cropping" do
301
+ before do
302
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "100x100#", format: :png)
303
+ end
304
+
305
+ it "reports its correct current and target geometries" do
306
+ assert_equal "100x100#", @thumb.target_geometry.to_s
307
+ assert_equal "612x792", @thumb.current_geometry.to_s
308
+ end
309
+
310
+ it "reports its correct format" do
311
+ assert_equal :png, @thumb.format
312
+ end
313
+
314
+ it "creates the thumbnail when sent #make" do
315
+ dst = @thumb.make
316
+ assert_match /100x100/, `identify "#{dst.path}"`
317
+ end
318
+ end
319
+ end
320
+
321
+ context "An animated gif" do
322
+ before do
323
+ @file = File.new(fixture_file("animated.gif"), "rb")
324
+ end
325
+
326
+ after { @file.close }
327
+
328
+ it "starts with 12 frames with size 100x100" do
329
+ cmd = %[identify -format "%wx%h" "#{@file.path}"]
330
+ assert_equal "100x100" * 12, `#{cmd}`.chomp
331
+ end
332
+
333
+ context "with static output" do
334
+ before do
335
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :jpg)
336
+ end
337
+
338
+ it "creates the single frame thumbnail when sent #make" do
339
+ dst = @thumb.make
340
+ cmd = %[identify -format "%wx%h" "#{dst.path}"]
341
+ assert_equal "50x50", `#{cmd}`.chomp
342
+ end
343
+ end
344
+
345
+ context "with animated output format" do
346
+ before do
347
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :gif)
348
+ end
349
+
350
+ it "creates the 12 frames thumbnail when sent #make" do
351
+ dst = @thumb.make
352
+ cmd = %[identify -format "%wx%h," "#{dst.path}"]
353
+ frames = `#{cmd}`.chomp.split(",")
354
+ assert_equal 12, frames.size
355
+ assert_frame_dimensions (45..50), frames
356
+ end
357
+
358
+ it "uses the -coalesce option" do
359
+ assert_equal @thumb.transformation_command.first, "-coalesce"
360
+ end
361
+
362
+ it "uses the -layers 'optimize' option" do
363
+ assert_equal @thumb.transformation_command.last, '-layers "optimize"'
364
+ end
365
+ end
366
+
367
+ context "with omitted output format" do
368
+ before do
369
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50")
370
+ end
371
+
372
+ it "creates the 12 frames thumbnail when sent #make" do
373
+ dst = @thumb.make
374
+ cmd = %[identify -format "%wx%h," "#{dst.path}"]
375
+ frames = `#{cmd}`.chomp.split(",")
376
+ assert_equal 12, frames.size
377
+ assert_frame_dimensions (45..50), frames
378
+ end
379
+
380
+ it "uses the -coalesce option" do
381
+ assert_equal @thumb.transformation_command.first, "-coalesce"
382
+ end
383
+
384
+ it "uses the -layers 'optimize' option" do
385
+ assert_equal @thumb.transformation_command.last, '-layers "optimize"'
386
+ end
387
+ end
388
+
389
+ context "with unidentified source format" do
390
+ before do
391
+ @unidentified_file = File.new(fixture_file("animated.unknown"), "rb")
392
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "60x60")
393
+ end
394
+
395
+ it "creates the 12 frames thumbnail when sent #make" do
396
+ dst = @thumb.make
397
+ cmd = %[identify -format "%wx%h," "#{dst.path}"]
398
+ frames = `#{cmd}`.chomp.split(",")
399
+ assert_equal 12, frames.size
400
+ assert_frame_dimensions (55..60), frames
401
+ end
402
+
403
+ it "uses the -coalesce option" do
404
+ assert_equal @thumb.transformation_command.first, "-coalesce"
405
+ end
406
+
407
+ it "uses the -layers 'optimize' option" do
408
+ assert_equal @thumb.transformation_command.last, '-layers "optimize"'
409
+ end
410
+ end
411
+
412
+ context "with no source format" do
413
+ before do
414
+ @unidentified_file = File.new(fixture_file("animated"), "rb")
415
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "70x70")
416
+ end
417
+
418
+ it "creates the 12 frames thumbnail when sent #make" do
419
+ dst = @thumb.make
420
+ cmd = %[identify -format "%wx%h," "#{dst.path}"]
421
+ frames = `#{cmd}`.chomp.split(",")
422
+ assert_equal 12, frames.size
423
+ assert_frame_dimensions (60..70), frames
424
+ end
425
+
426
+ it "uses the -coalesce option" do
427
+ assert_equal @thumb.transformation_command.first, "-coalesce"
428
+ end
429
+
430
+ it "uses the -layers 'optimize' option" do
431
+ assert_equal @thumb.transformation_command.last, '-layers "optimize"'
432
+ end
433
+ end
434
+
435
+ context "with animated option set to false" do
436
+ before do
437
+ @thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", animated: false)
438
+ end
439
+
440
+ it "outputs the gif format" do
441
+ dst = @thumb.make
442
+ cmd = %[identify "#{dst.path}"]
443
+ assert_match /GIF/, `#{cmd}`.chomp
444
+ end
445
+
446
+ it "creates the single frame thumbnail when sent #make" do
447
+ dst = @thumb.make
448
+ cmd = %[identify -format "%wx%h" "#{dst.path}"]
449
+ assert_equal "50x50", `#{cmd}`.chomp
450
+ end
451
+ end
452
+
453
+ context "with a specified frame_index" do
454
+ before do
455
+ @thumb = Paperclip::Thumbnail.new(
456
+ @file,
457
+ geometry: "50x50",
458
+ frame_index: 5,
459
+ format: :jpg
460
+ )
461
+ end
462
+
463
+ it "creates the thumbnail from the frame index when sent #make" do
464
+ @thumb.make
465
+ assert_equal 5, @thumb.frame_index
466
+ end
467
+ end
468
+
469
+ context "with a specified frame_index out of bounds" do
470
+ before do
471
+ @thumb = Paperclip::Thumbnail.new(
472
+ @file,
473
+ geometry: "50x50",
474
+ frame_index: 20,
475
+ format: :jpg
476
+ )
477
+ end
478
+
479
+ it "errors when trying to create the thumbnail" do
480
+ assert_raises(Paperclip::Error) do
481
+ silence_stream(STDERR) do
482
+ @thumb.make
483
+ end
484
+ end
485
+ end
486
+ end
487
+ end
488
+
489
+ context "with a really long file name" do
490
+ before do
491
+ tempfile = Tempfile.new("f")
492
+ tempfile_additional_chars = tempfile.path.split("/")[-1].length + 15
493
+ image_file = File.new(fixture_file("5k.png"), "rb")
494
+ @file = Tempfile.new("f" * (255 - tempfile_additional_chars))
495
+ @file.write(image_file.read)
496
+ @file.rewind
497
+ end
498
+
499
+ it "does not throw Errno::ENAMETOOLONG" do
500
+ thumb = Paperclip::Thumbnail.new(@file, geometry: "50x50", format: :gif)
501
+ expect { thumb.make }.to_not raise_error
502
+ end
503
+ end
504
+ end