kt-paperclip 6.2.0

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 (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