jr-paperclip 7.3.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 (200) hide show
  1. checksums.yaml +7 -0
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. data/.github/ISSUE_TEMPLATE/custom.md +10 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.github/workflows/reviewdog.yml +23 -0
  7. data/.github/workflows/test.yml +46 -0
  8. data/.gitignore +19 -0
  9. data/.qlty/.gitignore +7 -0
  10. data/.qlty/qlty.toml +89 -0
  11. data/.rubocop.yml +1060 -0
  12. data/Appraisals +29 -0
  13. data/CONTRIBUTING.md +85 -0
  14. data/Gemfile +17 -0
  15. data/LICENSE +25 -0
  16. data/NEWS +567 -0
  17. data/README.md +1083 -0
  18. data/RELEASING.md +17 -0
  19. data/Rakefile +52 -0
  20. data/bin/console +11 -0
  21. data/features/basic_integration.feature +85 -0
  22. data/features/migration.feature +29 -0
  23. data/features/rake_tasks.feature +62 -0
  24. data/features/step_definitions/attachment_steps.rb +121 -0
  25. data/features/step_definitions/html_steps.rb +15 -0
  26. data/features/step_definitions/rails_steps.rb +271 -0
  27. data/features/step_definitions/s3_steps.rb +16 -0
  28. data/features/step_definitions/web_steps.rb +106 -0
  29. data/features/support/env.rb +12 -0
  30. data/features/support/file_helpers.rb +34 -0
  31. data/features/support/fixtures/boot_config.txt +15 -0
  32. data/features/support/fixtures/gemfile.txt +5 -0
  33. data/features/support/fixtures/preinitializer.txt +20 -0
  34. data/features/support/paths.rb +28 -0
  35. data/features/support/rails.rb +39 -0
  36. data/features/support/selectors.rb +19 -0
  37. data/features/support/webmock_setup.rb +8 -0
  38. data/gemfiles/7.0.gemfile +20 -0
  39. data/gemfiles/7.1.gemfile +20 -0
  40. data/gemfiles/7.2.gemfile +20 -0
  41. data/gemfiles/8.0.gemfile +20 -0
  42. data/gemfiles/8.1.gemfile +20 -0
  43. data/lib/generators/paperclip/USAGE +8 -0
  44. data/lib/generators/paperclip/paperclip_generator.rb +36 -0
  45. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
  46. data/lib/jr-paperclip.rb +1 -0
  47. data/lib/paperclip/attachment.rb +634 -0
  48. data/lib/paperclip/attachment_registry.rb +60 -0
  49. data/lib/paperclip/callbacks.rb +42 -0
  50. data/lib/paperclip/content_type_detector.rb +85 -0
  51. data/lib/paperclip/errors.rb +34 -0
  52. data/lib/paperclip/file_command_content_type_detector.rb +28 -0
  53. data/lib/paperclip/filename_cleaner.rb +15 -0
  54. data/lib/paperclip/geometry.rb +157 -0
  55. data/lib/paperclip/geometry_detector_factory.rb +45 -0
  56. data/lib/paperclip/geometry_parser_factory.rb +31 -0
  57. data/lib/paperclip/glue.rb +18 -0
  58. data/lib/paperclip/has_attached_file.rb +116 -0
  59. data/lib/paperclip/helpers.rb +60 -0
  60. data/lib/paperclip/interpolations/plural_cache.rb +18 -0
  61. data/lib/paperclip/interpolations.rb +205 -0
  62. data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
  63. data/lib/paperclip/io_adapters/attachment_adapter.rb +56 -0
  64. data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
  65. data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
  66. data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
  67. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
  68. data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
  69. data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
  70. data/lib/paperclip/io_adapters/registry.rb +36 -0
  71. data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
  72. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
  73. data/lib/paperclip/io_adapters/uri_adapter.rb +78 -0
  74. data/lib/paperclip/locales/en.yml +18 -0
  75. data/lib/paperclip/locales/fr.yml +18 -0
  76. data/lib/paperclip/locales/gd.yml +20 -0
  77. data/lib/paperclip/logger.rb +21 -0
  78. data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
  79. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
  80. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
  81. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
  82. data/lib/paperclip/matchers.rb +64 -0
  83. data/lib/paperclip/media_type_spoof_detector.rb +93 -0
  84. data/lib/paperclip/missing_attachment_styles.rb +84 -0
  85. data/lib/paperclip/processor.rb +56 -0
  86. data/lib/paperclip/processor_helpers.rb +52 -0
  87. data/lib/paperclip/rails_environment.rb +21 -0
  88. data/lib/paperclip/railtie.rb +31 -0
  89. data/lib/paperclip/schema.rb +104 -0
  90. data/lib/paperclip/storage/filesystem.rb +99 -0
  91. data/lib/paperclip/storage/fog.rb +262 -0
  92. data/lib/paperclip/storage/s3.rb +497 -0
  93. data/lib/paperclip/storage.rb +3 -0
  94. data/lib/paperclip/style.rb +106 -0
  95. data/lib/paperclip/tempfile.rb +42 -0
  96. data/lib/paperclip/tempfile_factory.rb +22 -0
  97. data/lib/paperclip/thumbnail.rb +131 -0
  98. data/lib/paperclip/url_generator.rb +83 -0
  99. data/lib/paperclip/validators/attachment_content_type_validator.rb +95 -0
  100. data/lib/paperclip/validators/attachment_file_name_validator.rb +82 -0
  101. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
  102. data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
  103. data/lib/paperclip/validators/attachment_size_validator.rb +126 -0
  104. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
  105. data/lib/paperclip/validators.rb +73 -0
  106. data/lib/paperclip/version.rb +3 -0
  107. data/lib/paperclip.rb +215 -0
  108. data/lib/tasks/paperclip.rake +140 -0
  109. data/paperclip.gemspec +51 -0
  110. data/shoulda_macros/paperclip.rb +134 -0
  111. data/spec/database.yml +4 -0
  112. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  113. data/spec/paperclip/attachment_processing_spec.rb +79 -0
  114. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  115. data/spec/paperclip/attachment_spec.rb +1617 -0
  116. data/spec/paperclip/content_type_detector_spec.rb +58 -0
  117. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  118. data/spec/paperclip/filename_cleaner_spec.rb +13 -0
  119. data/spec/paperclip/geometry_detector_spec.rb +47 -0
  120. data/spec/paperclip/geometry_parser_spec.rb +73 -0
  121. data/spec/paperclip/geometry_spec.rb +267 -0
  122. data/spec/paperclip/glue_spec.rb +63 -0
  123. data/spec/paperclip/has_attached_file_spec.rb +78 -0
  124. data/spec/paperclip/integration_spec.rb +702 -0
  125. data/spec/paperclip/interpolations_spec.rb +270 -0
  126. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
  127. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +167 -0
  128. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
  129. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  130. data/spec/paperclip/io_adapters/file_adapter_spec.rb +134 -0
  131. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +142 -0
  132. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  133. data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
  134. data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
  135. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
  136. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
  137. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +231 -0
  138. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  139. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
  140. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  141. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  142. data/spec/paperclip/media_type_spoof_detector_spec.rb +126 -0
  143. data/spec/paperclip/meta_class_spec.rb +30 -0
  144. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
  145. data/spec/paperclip/paperclip_spec.rb +196 -0
  146. data/spec/paperclip/plural_cache_spec.rb +37 -0
  147. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  148. data/spec/paperclip/processor_spec.rb +26 -0
  149. data/spec/paperclip/rails_environment_spec.rb +30 -0
  150. data/spec/paperclip/rake_spec.rb +103 -0
  151. data/spec/paperclip/schema_spec.rb +298 -0
  152. data/spec/paperclip/storage/filesystem_spec.rb +102 -0
  153. data/spec/paperclip/storage/fog_spec.rb +606 -0
  154. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  155. data/spec/paperclip/storage/s3_spec.rb +1974 -0
  156. data/spec/paperclip/style_spec.rb +251 -0
  157. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  158. data/spec/paperclip/tempfile_spec.rb +35 -0
  159. data/spec/paperclip/thumbnail_spec.rb +504 -0
  160. data/spec/paperclip/url_generator_spec.rb +231 -0
  161. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +410 -0
  162. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +249 -0
  163. data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
  164. data/spec/paperclip/validators/attachment_size_validator_spec.rb +325 -0
  165. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
  166. data/spec/paperclip/validators_spec.rb +179 -0
  167. data/spec/spec_helper.rb +52 -0
  168. data/spec/support/assertions.rb +84 -0
  169. data/spec/support/fake_model.rb +24 -0
  170. data/spec/support/fake_rails.rb +12 -0
  171. data/spec/support/fixtures/12k.png +0 -0
  172. data/spec/support/fixtures/50x50.png +0 -0
  173. data/spec/support/fixtures/5k.png +0 -0
  174. data/spec/support/fixtures/animated +0 -0
  175. data/spec/support/fixtures/animated.gif +0 -0
  176. data/spec/support/fixtures/animated.unknown +0 -0
  177. data/spec/support/fixtures/aws_s3.yml +13 -0
  178. data/spec/support/fixtures/bad.png +1 -0
  179. data/spec/support/fixtures/empty.html +1 -0
  180. data/spec/support/fixtures/empty.xlsx +0 -0
  181. data/spec/support/fixtures/fog.yml +8 -0
  182. data/spec/support/fixtures/rotated.jpg +0 -0
  183. data/spec/support/fixtures/s3.yml +8 -0
  184. data/spec/support/fixtures/sample.xlsm +0 -0
  185. data/spec/support/fixtures/spaced file.jpg +0 -0
  186. data/spec/support/fixtures/spaced file.png +0 -0
  187. data/spec/support/fixtures/text.txt +1 -0
  188. data/spec/support/fixtures/twopage.pdf +0 -0
  189. data/spec/support/fixtures/uppercase.PNG +0 -0
  190. data/spec/support/matchers/accept.rb +5 -0
  191. data/spec/support/matchers/exist.rb +5 -0
  192. data/spec/support/matchers/have_column.rb +23 -0
  193. data/spec/support/mock_attachment.rb +24 -0
  194. data/spec/support/mock_interpolator.rb +24 -0
  195. data/spec/support/mock_url_generator_builder.rb +26 -0
  196. data/spec/support/model_reconstruction.rb +72 -0
  197. data/spec/support/reporting.rb +11 -0
  198. data/spec/support/test_data.rb +13 -0
  199. data/spec/support/version_helper.rb +9 -0
  200. metadata +702 -0
@@ -0,0 +1,231 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::UrlGenerator do
4
+ it "uses the given interpolator" do
5
+ expected = "the expected result"
6
+ mock_interpolator = MockInterpolator.new(result: expected)
7
+ mock_attachment = MockAttachment.new(interpolator: mock_interpolator)
8
+
9
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
10
+ result = url_generator.for(:style_name, {})
11
+
12
+ assert_equal expected, result
13
+ assert mock_interpolator.has_interpolated_attachment?(mock_attachment)
14
+ assert mock_interpolator.has_interpolated_style_name?(:style_name)
15
+ end
16
+
17
+ it "uses the default URL when no file is assigned" do
18
+ mock_interpolator = MockInterpolator.new
19
+ default_url = "the default url"
20
+ options = { interpolator: mock_interpolator, default_url: default_url }
21
+ mock_attachment = MockAttachment.new(options)
22
+
23
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
24
+ url_generator.for(:style_name, {})
25
+
26
+ assert mock_interpolator.has_interpolated_pattern?(default_url),
27
+ "expected the interpolator to be passed #{default_url.inspect} but it wasn't"
28
+ end
29
+
30
+ it "executes the default URL lambda when no file is assigned" do
31
+ mock_interpolator = MockInterpolator.new
32
+ default_url = lambda { |attachment| "the #{attachment.class.name} default url" }
33
+ options = { interpolator: mock_interpolator, default_url: default_url }
34
+ mock_attachment = MockAttachment.new(options)
35
+
36
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
37
+ url_generator.for(:style_name, {})
38
+
39
+ assert mock_interpolator.has_interpolated_pattern?("the MockAttachment default url"),
40
+ %{expected the interpolator to be passed "the MockAttachment default url", but it wasn't}
41
+ end
42
+
43
+ it "executes the method named by the symbol as the default URL when no file is assigned" do
44
+ mock_model = FakeModel.new
45
+ default_url = :to_s
46
+ mock_interpolator = MockInterpolator.new
47
+ options = {
48
+ interpolator: mock_interpolator,
49
+ default_url: default_url,
50
+ model: mock_model,
51
+ }
52
+ mock_attachment = MockAttachment.new(options)
53
+
54
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
55
+ url_generator.for(:style_name, {})
56
+
57
+ assert mock_interpolator.has_interpolated_pattern?(mock_model.to_s),
58
+ %{expected the interpolator to be passed #{mock_model}, but it wasn't}
59
+ end
60
+
61
+ it "URL-escapes spaces if asked to" do
62
+ expected = "the expected result"
63
+ mock_interpolator = MockInterpolator.new(result: expected)
64
+ options = { interpolator: mock_interpolator }
65
+ mock_attachment = MockAttachment.new(options)
66
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
67
+
68
+ result = url_generator.for(:style_name, escape: true)
69
+
70
+ assert_equal "the%20expected%20result", result
71
+ end
72
+
73
+ it "escapes the result of the interpolator using a method on the object, if asked to escape" do
74
+ expected = Class.new do
75
+ def escape
76
+ "the escaped result"
77
+ end
78
+ end.new
79
+ mock_interpolator = MockInterpolator.new(result: expected)
80
+ options = { interpolator: mock_interpolator }
81
+ mock_attachment = MockAttachment.new(options)
82
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
83
+
84
+ result = url_generator.for(:style_name, escape: true)
85
+
86
+ assert_equal "the escaped result", result
87
+ end
88
+
89
+ it "leaves spaces unescaped as asked to" do
90
+ expected = "the expected result"
91
+ mock_interpolator = MockInterpolator.new(result: expected)
92
+ options = { interpolator: mock_interpolator }
93
+ mock_attachment = MockAttachment.new(options)
94
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
95
+
96
+ result = url_generator.for(:style_name, escape: false)
97
+
98
+ assert_equal "the expected result", result
99
+ end
100
+
101
+ it "defaults to leaving spaces unescaped" do
102
+ expected = "the expected result"
103
+ mock_interpolator = MockInterpolator.new(result: expected)
104
+ options = { interpolator: mock_interpolator }
105
+ mock_attachment = MockAttachment.new(options)
106
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
107
+
108
+ result = url_generator.for(:style_name, {})
109
+
110
+ assert_equal "the expected result", result
111
+ end
112
+
113
+ it "produces URLs without the updated_at value when the object does not respond to updated_at" do
114
+ expected = "the expected result"
115
+ mock_interpolator = MockInterpolator.new(result: expected)
116
+ options = { interpolator: mock_interpolator, responds_to_updated_at: false }
117
+ mock_attachment = MockAttachment.new(options)
118
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
119
+
120
+ result = url_generator.for(:style_name, timestamp: true)
121
+
122
+ assert_equal expected, result
123
+ end
124
+
125
+ it "produces URLs without the updated_at value when the updated_at value is nil" do
126
+ expected = "the expected result"
127
+ mock_interpolator = MockInterpolator.new(result: expected)
128
+ options = {
129
+ responds_to_updated_at: true,
130
+ updated_at: nil,
131
+ interpolator: mock_interpolator,
132
+ }
133
+ mock_attachment = MockAttachment.new(options)
134
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
135
+
136
+ result = url_generator.for(:style_name, timestamp: true)
137
+
138
+ assert_equal expected, result
139
+ end
140
+
141
+ it "produces URLs with the updated_at when it exists" do
142
+ expected = "the expected result"
143
+ updated_at = 1231231234
144
+ mock_interpolator = MockInterpolator.new(result: expected)
145
+ options = { interpolator: mock_interpolator, updated_at: updated_at }
146
+ mock_attachment = MockAttachment.new(options)
147
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
148
+
149
+ result = url_generator.for(:style_name, timestamp: true)
150
+
151
+ assert_equal "#{expected}?#{updated_at}", result
152
+ end
153
+
154
+ it "produces URLs with the updated_at when it exists, separated with a & if a ? follow by = already exists" do
155
+ expected = "the?expected=result"
156
+ updated_at = 1231231234
157
+ mock_interpolator = MockInterpolator.new(result: expected)
158
+ options = { interpolator: mock_interpolator, updated_at: updated_at }
159
+ mock_attachment = MockAttachment.new(options)
160
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
161
+
162
+ result = url_generator.for(:style_name, timestamp: true)
163
+
164
+ assert_equal "#{expected}&#{updated_at}", result
165
+ end
166
+
167
+ it "produces URLs without the updated_at when told to do as much" do
168
+ expected = "the expected result"
169
+ updated_at = 1231231234
170
+ mock_interpolator = MockInterpolator.new(result: expected)
171
+ options = { interpolator: mock_interpolator, updated_at: updated_at }
172
+ mock_attachment = MockAttachment.new(options)
173
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
174
+
175
+ result = url_generator.for(:style_name, timestamp: false)
176
+
177
+ assert_equal expected, result
178
+ end
179
+
180
+ it "produces the correct URL when the instance has a file name" do
181
+ expected = "the expected result"
182
+ mock_interpolator = MockInterpolator.new
183
+ options = {
184
+ interpolator: mock_interpolator,
185
+ url: expected,
186
+ original_filename: "exists",
187
+ }
188
+ mock_attachment = MockAttachment.new(options)
189
+
190
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
191
+ url_generator.for(:style_name, {})
192
+
193
+ assert mock_interpolator.has_interpolated_pattern?(expected),
194
+ "expected the interpolator to be passed #{expected.inspect} but it wasn't"
195
+ end
196
+
197
+ it "doesn't emit deprecation warnings" do
198
+ expected = "the expected result"
199
+ mock_interpolator = MockInterpolator.new(result: expected)
200
+ options = { interpolator: mock_interpolator }
201
+ mock_attachment = MockAttachment.new(options)
202
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
203
+
204
+ expect { url_generator.for(:style_name, escape: true) }.to_not(output(/URI\.(un)?escape is obsolete/).to_stderr)
205
+ end
206
+
207
+ describe "should be able to escape (, ), [, and ]." do
208
+ def generate(expected, updated_at = nil)
209
+ mock_interpolator = MockInterpolator.new(result: expected)
210
+ options = { interpolator: mock_interpolator, updated_at: updated_at }
211
+ mock_attachment = MockAttachment.new(options)
212
+ url_generator = Paperclip::UrlGenerator.new(mock_attachment)
213
+ def url_generator.respond_to(params)
214
+ false if params == :escape
215
+ end
216
+ url_generator.for(:style_name, escape: true, timestamp: !!updated_at)
217
+ end
218
+
219
+ it "not timestamp" do
220
+ expected = "the(expected)result[]"
221
+ assert_equal "the%28expected%29result%5B%5D", generate(expected)
222
+ end
223
+
224
+ it "timestamp" do
225
+ expected = "the(expected)result[]"
226
+ updated_at = 1231231234
227
+ assert_equal "the%28expected%29result%5B%5D?#{updated_at}",
228
+ generate(expected, updated_at)
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,410 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::Validators::AttachmentContentTypeValidator do
4
+ before do
5
+ rebuild_model
6
+ @dummy = Dummy.new
7
+ end
8
+
9
+ def build_validator(options)
10
+ @validator = Paperclip::Validators::AttachmentContentTypeValidator.new(options.merge(
11
+ attributes: :avatar
12
+ ))
13
+ end
14
+
15
+ context "with a nil content type" do
16
+ before do
17
+ build_validator content_type: "image/jpg"
18
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
19
+ @validator.validate(@dummy)
20
+ end
21
+
22
+ it "does not set an error message" do
23
+ assert @dummy.errors[:avatar_content_type].blank?
24
+ end
25
+ end
26
+
27
+ context "with :allow_nil option" do
28
+ context "as true" do
29
+ before do
30
+ build_validator content_type: "image/png", allow_nil: true
31
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
32
+ @validator.validate(@dummy)
33
+ end
34
+
35
+ it "allows avatar_content_type as nil" do
36
+ assert @dummy.errors[:avatar_content_type].blank?
37
+ end
38
+ end
39
+
40
+ context "as false" do
41
+ before do
42
+ build_validator content_type: "image/png", allow_nil: false
43
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
44
+ @validator.validate(@dummy)
45
+ end
46
+
47
+ it "does not allow avatar_content_type as nil" do
48
+ assert @dummy.errors[:avatar_content_type].present?
49
+ end
50
+ end
51
+ end
52
+
53
+ context "with a failing validation" do
54
+ before do
55
+ build_validator content_type: "image/png", allow_nil: false
56
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
57
+ @validator.validate(@dummy)
58
+ end
59
+
60
+ it "adds error to the base object" do
61
+ assert @dummy.errors[:avatar].present?,
62
+ "Error not added to base attribute"
63
+ end
64
+
65
+ it "adds error to base object as a string" do
66
+ expect(@dummy.errors[:avatar].first).to be_a String
67
+ end
68
+ end
69
+
70
+ context "with add_validation_errors_to not set (implicitly :both)" do
71
+ it "adds error to both attribute and base" do
72
+ build_validator content_type: "image/png", allow_nil: false
73
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
74
+ @validator.validate(@dummy)
75
+
76
+ assert @dummy.errors[:avatar_content_type].present?,
77
+ "Error not added to attribute"
78
+
79
+ assert @dummy.errors[:avatar].present?,
80
+ "Error not added to base attribute"
81
+ end
82
+ end
83
+
84
+ context "with add_validation_errors_to set to :attribute globally" do
85
+ before do
86
+ Paperclip.options[:add_validation_errors_to] = :attribute
87
+ end
88
+
89
+ after do
90
+ Paperclip.options[:add_validation_errors_to] = :both
91
+ end
92
+
93
+ it "only adds error to attribute not base" do
94
+ build_validator content_type: "image/png", allow_nil: false
95
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
96
+ @validator.validate(@dummy)
97
+
98
+ assert @dummy.errors[:avatar_content_type].present?,
99
+ "Error not added to attribute"
100
+
101
+ assert @dummy.errors[:avatar].blank?,
102
+ "Error added to base attribute"
103
+ end
104
+ end
105
+
106
+ context "with add_validation_errors_to set to :base globally" do
107
+ before do
108
+ Paperclip.options[:add_validation_errors_to] = :base
109
+ end
110
+
111
+ after do
112
+ Paperclip.options[:add_validation_errors_to] = :both
113
+ end
114
+
115
+ it "only adds error to base not attribute" do
116
+ build_validator content_type: "image/png", allow_nil: false
117
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
118
+ @validator.validate(@dummy)
119
+
120
+ assert @dummy.errors[:avatar].present?,
121
+ "Error not added to base attribute"
122
+
123
+ assert @dummy.errors[:avatar_content_type].blank?,
124
+ "Error added to attribute"
125
+ end
126
+ end
127
+
128
+ context "with add_validation_errors_to set to :attribute" do
129
+ it "only adds error to attribute not base" do
130
+ build_validator content_type: "image/png", allow_nil: false,
131
+ add_validation_errors_to: :attribute
132
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
133
+ @validator.validate(@dummy)
134
+
135
+ assert @dummy.errors[:avatar_content_type].present?,
136
+ "Error not added to attribute"
137
+
138
+ assert @dummy.errors[:avatar].blank?,
139
+ "Error added to base attribute"
140
+ end
141
+ end
142
+
143
+ context "with add_validation_errors_to set to :base" do
144
+ it "only adds error to base not attribute" do
145
+ build_validator content_type: "image/png", allow_nil: false,
146
+ add_validation_errors_to: :base
147
+ allow(@dummy).to receive_messages(avatar_content_type: nil)
148
+ @validator.validate(@dummy)
149
+
150
+ assert @dummy.errors[:avatar].present?,
151
+ "Error not added to base attribute"
152
+
153
+ assert @dummy.errors[:avatar_content_type].blank?,
154
+ "Error added to attribute"
155
+ end
156
+ end
157
+
158
+ context "with a successful validation" do
159
+ before do
160
+ build_validator content_type: "image/png", allow_nil: false
161
+ allow(@dummy).to receive_messages(avatar_content_type: "image/png")
162
+ @validator.validate(@dummy)
163
+ end
164
+
165
+ it "does not add error to the base object" do
166
+ assert @dummy.errors[:avatar].blank?,
167
+ "Error was added to base attribute"
168
+ end
169
+ end
170
+
171
+ context "with :allow_blank option" do
172
+ context "as true" do
173
+ before do
174
+ build_validator content_type: "image/png", allow_blank: true
175
+ allow(@dummy).to receive_messages(avatar_content_type: "")
176
+ @validator.validate(@dummy)
177
+ end
178
+
179
+ it "allows avatar_content_type as blank" do
180
+ assert @dummy.errors[:avatar_content_type].blank?
181
+ end
182
+ end
183
+
184
+ context "as false" do
185
+ before do
186
+ build_validator content_type: "image/png", allow_blank: false
187
+ allow(@dummy).to receive_messages(avatar_content_type: "")
188
+ @validator.validate(@dummy)
189
+ end
190
+
191
+ it "does not allow avatar_content_type as blank" do
192
+ assert @dummy.errors[:avatar_content_type].present?
193
+ end
194
+ end
195
+ end
196
+
197
+ context "whitelist format" do
198
+ context "with an allowed type" do
199
+ context "as a string" do
200
+ before do
201
+ build_validator content_type: "image/jpg"
202
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
203
+ @validator.validate(@dummy)
204
+ end
205
+
206
+ it "does not set an error message" do
207
+ assert @dummy.errors[:avatar_content_type].blank?
208
+ end
209
+ end
210
+
211
+ context "as an regexp" do
212
+ before do
213
+ build_validator content_type: /^image\/.*/
214
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
215
+ @validator.validate(@dummy)
216
+ end
217
+
218
+ it "does not set an error message" do
219
+ assert @dummy.errors[:avatar_content_type].blank?
220
+ end
221
+ end
222
+
223
+ context "as a list" do
224
+ before do
225
+ build_validator content_type: ["image/png", "image/jpg", "image/jpeg"]
226
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
227
+ @validator.validate(@dummy)
228
+ end
229
+
230
+ it "does not set an error message" do
231
+ assert @dummy.errors[:avatar_content_type].blank?
232
+ end
233
+ end
234
+ end
235
+
236
+ context "with a disallowed type" do
237
+ context "as a string" do
238
+ before do
239
+ build_validator content_type: "image/png"
240
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
241
+ @validator.validate(@dummy)
242
+ end
243
+
244
+ it "sets a correct default error message" do
245
+ assert @dummy.errors[:avatar_content_type].present?
246
+ expect(@dummy.errors[:avatar_content_type]).to include "is invalid"
247
+ end
248
+ end
249
+
250
+ context "as a regexp" do
251
+ before do
252
+ build_validator content_type: /^text\/.*/
253
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
254
+ @validator.validate(@dummy)
255
+ end
256
+
257
+ it "sets a correct default error message" do
258
+ assert @dummy.errors[:avatar_content_type].present?
259
+ expect(@dummy.errors[:avatar_content_type]).to include "is invalid"
260
+ end
261
+ end
262
+
263
+ context "with :message option" do
264
+ context "without interpolation" do
265
+ before do
266
+ build_validator content_type: "image/png", message: "should be a PNG image"
267
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
268
+ @validator.validate(@dummy)
269
+ end
270
+
271
+ it "sets a correct error message" do
272
+ expect(@dummy.errors[:avatar_content_type]).to include "should be a PNG image"
273
+ end
274
+ end
275
+
276
+ context "with interpolation" do
277
+ before do
278
+ build_validator content_type: "image/png", message: "should have content type %{types}"
279
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
280
+ @validator.validate(@dummy)
281
+ end
282
+
283
+ it "sets a correct error message" do
284
+ expect(@dummy.errors[:avatar_content_type]).to include "should have content type image/png"
285
+ end
286
+ end
287
+ end
288
+ end
289
+ end
290
+
291
+ context "blacklist format" do
292
+ context "with an allowed type" do
293
+ context "as a string" do
294
+ before do
295
+ build_validator not: "image/gif"
296
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
297
+ @validator.validate(@dummy)
298
+ end
299
+
300
+ it "does not set an error message" do
301
+ assert @dummy.errors[:avatar_content_type].blank?
302
+ end
303
+ end
304
+
305
+ context "as an regexp" do
306
+ before do
307
+ build_validator not: /^text\/.*/
308
+ allow(@dummy).to receive_messages(avatar_content_type: "image/jpg")
309
+ @validator.validate(@dummy)
310
+ end
311
+
312
+ it "does not set an error message" do
313
+ assert @dummy.errors[:avatar_content_type].blank?
314
+ end
315
+ end
316
+
317
+ context "as a list" do
318
+ before do
319
+ build_validator not: ["image/png", "image/jpg", "image/jpeg"]
320
+ allow(@dummy).to receive_messages(avatar_content_type: "image/gif")
321
+ @validator.validate(@dummy)
322
+ end
323
+
324
+ it "does not set an error message" do
325
+ assert @dummy.errors[:avatar_content_type].blank?
326
+ end
327
+ end
328
+ end
329
+
330
+ context "with a disallowed type" do
331
+ context "as a string" do
332
+ before do
333
+ build_validator not: "image/png"
334
+ allow(@dummy).to receive_messages(avatar_content_type: "image/png")
335
+ @validator.validate(@dummy)
336
+ end
337
+
338
+ it "sets a correct default error message" do
339
+ assert @dummy.errors[:avatar_content_type].present?
340
+ expect(@dummy.errors[:avatar_content_type]).to include "is invalid"
341
+ end
342
+ end
343
+
344
+ context "as a regexp" do
345
+ before do
346
+ build_validator not: /^text\/.*/
347
+ allow(@dummy).to receive_messages(avatar_content_type: "text/plain")
348
+ @validator.validate(@dummy)
349
+ end
350
+
351
+ it "sets a correct default error message" do
352
+ assert @dummy.errors[:avatar_content_type].present?
353
+ expect(@dummy.errors[:avatar_content_type]).to include "is invalid"
354
+ end
355
+ end
356
+
357
+ context "with :message option" do
358
+ context "without interpolation" do
359
+ before do
360
+ build_validator not: "image/png", message: "should not be a PNG image"
361
+ allow(@dummy).to receive_messages(avatar_content_type: "image/png")
362
+ @validator.validate(@dummy)
363
+ end
364
+
365
+ it "sets a correct error message" do
366
+ expect(@dummy.errors[:avatar_content_type]).to include "should not be a PNG image"
367
+ end
368
+ end
369
+
370
+ context "with interpolation" do
371
+ before do
372
+ build_validator not: "image/png", message: "should not have content type %{types}"
373
+ allow(@dummy).to receive_messages(avatar_content_type: "image/png")
374
+ @validator.validate(@dummy)
375
+ end
376
+
377
+ it "sets a correct error message" do
378
+ expect(@dummy.errors[:avatar_content_type]).to include "should not have content type image/png"
379
+ end
380
+ end
381
+ end
382
+ end
383
+ end
384
+
385
+ context "using the helper" do
386
+ before do
387
+ Dummy.validates_attachment_content_type :avatar, content_type: "image/jpg"
388
+ end
389
+
390
+ it "adds the validator to the class" do
391
+ assert Dummy.validators_on(:avatar).any? { |validator| validator.kind == :attachment_content_type }
392
+ end
393
+ end
394
+
395
+ context "given options" do
396
+ it "raises argument error if no required argument was given" do
397
+ assert_raises(ArgumentError) do
398
+ build_validator message: "Some message"
399
+ end
400
+ end
401
+
402
+ it "does not raise argument error if :content_type was given" do
403
+ build_validator content_type: "image/jpg"
404
+ end
405
+
406
+ it "does not raise argument error if :not was given" do
407
+ build_validator not: "image/jpg"
408
+ end
409
+ end
410
+ end