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,58 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::ContentTypeDetector do
4
+ it "returns a meaningful content type for open xml spreadsheets" do
5
+ file = File.new(fixture_file("empty.xlsx"))
6
+ assert_equal "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
7
+ Paperclip::ContentTypeDetector.new(file.path).detect
8
+ end
9
+
10
+ it 'returns a more specific content type based on the filename if it matches
11
+ multiple content types' do
12
+ file = File.new(fixture_file('sample.xlsm'))
13
+ assert_equal 'application/vnd.ms-excel.sheet.macroenabled.12',
14
+ Paperclip::ContentTypeDetector.new(file.path).detect
15
+ end
16
+
17
+ it "gives a sensible default when the name is empty" do
18
+ assert_equal "application/octet-stream", Paperclip::ContentTypeDetector.new("").detect
19
+ end
20
+
21
+ it "returns the empty content type when the file is empty" do
22
+ tempfile = Tempfile.new("empty")
23
+ assert_equal "inode/x-empty", Paperclip::ContentTypeDetector.new(tempfile.path).detect
24
+ tempfile.close
25
+ end
26
+
27
+ it "returns content type of file if it is an acceptable type" do
28
+ allow(MIME::Types).to receive(:type_for).and_return([
29
+ MIME::Type.new("content-type" => "application/mp4"),
30
+ MIME::Type.new("content-type" => "video/mp4"),
31
+ MIME::Type.new("content-type" => "audio/mp4"),
32
+ ])
33
+ allow_any_instance_of(Paperclip::ContentTypeDetector).to receive(:type_from_file_contents).and_return("video/mp4")
34
+ @filename = "my_file.mp4"
35
+ assert_equal "video/mp4", Paperclip::ContentTypeDetector.new(@filename).detect
36
+ end
37
+
38
+ it "finds the right type in the list via the file command" do
39
+ @filename = "#{Dir.tmpdir}/something.hahalolnotreal"
40
+ File.open(@filename, "w+") do |file|
41
+ file.puts "This is a text file."
42
+ file.rewind
43
+ assert_equal "text/plain", Paperclip::ContentTypeDetector.new(file.path).detect
44
+ end
45
+ FileUtils.rm @filename
46
+ end
47
+
48
+ it "returns a sensible default if something is wrong, like the file is gone" do
49
+ @filename = "/path/to/nothing"
50
+ assert_equal "application/octet-stream", Paperclip::ContentTypeDetector.new(@filename).detect
51
+ end
52
+
53
+ it "returns a sensible default when the file command is missing" do
54
+ allow(Paperclip).to receive(:run).and_raise(Terrapin::CommandLineError.new)
55
+ @filename = "/path/to/something"
56
+ assert_equal "application/octet-stream", Paperclip::ContentTypeDetector.new(@filename).detect
57
+ end
58
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::FileCommandContentTypeDetector do
4
+ it "returns a content type based on the content of the file" do
5
+ tempfile = Tempfile.new("something")
6
+ tempfile.write("This is a file.")
7
+ tempfile.rewind
8
+
9
+ assert_equal "text/plain", Paperclip::FileCommandContentTypeDetector.new(tempfile.path).detect
10
+
11
+ tempfile.close
12
+ end
13
+
14
+ it "returns a sensible default when the file command is missing" do
15
+ allow(Paperclip).to receive(:run).and_raise(Terrapin::CommandLineError.new)
16
+ @filename = "/path/to/something"
17
+ assert_equal "application/octet-stream",
18
+ Paperclip::FileCommandContentTypeDetector.new(@filename).detect
19
+ end
20
+
21
+ it "returns a sensible default on the odd chance that run returns nil" do
22
+ allow(Paperclip).to receive(:run).and_return(nil)
23
+ assert_equal "application/octet-stream",
24
+ Paperclip::FileCommandContentTypeDetector.new("windows").detect
25
+ end
26
+
27
+ context "#type_from_file_command" do
28
+ let(:detector) { Paperclip::FileCommandContentTypeDetector.new("html") }
29
+
30
+ it "does work with the output of old versions of file" do
31
+ allow(Paperclip).to receive(:run).and_return("text/html charset=us-ascii")
32
+ expect(detector.detect).to eq("text/html")
33
+ end
34
+
35
+ it "does work with the output of new versions of file" do
36
+ allow(Paperclip).to receive(:run).and_return("text/html; charset=us-ascii")
37
+ expect(detector.detect).to eq("text/html")
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::FilenameCleaner do
4
+ it "converts invalid characters to underscores" do
5
+ cleaner = Paperclip::FilenameCleaner.new(/[aeiou]/)
6
+ expect(cleaner.call("baseball")).to eq "b_s_b_ll"
7
+ end
8
+
9
+ it "does not convert anything if the character regex is nil" do
10
+ cleaner = Paperclip::FilenameCleaner.new(nil)
11
+ expect(cleaner.call("baseball")).to eq "baseball"
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::GeometryDetector do
4
+ it "identifies an image and extract its dimensions" do
5
+ allow_any_instance_of(Paperclip::GeometryParser).to receive(:make).and_return(:correct)
6
+ file = fixture_file("5k.png")
7
+ factory = Paperclip::GeometryDetector.new(file)
8
+
9
+ output = factory.make
10
+
11
+ expect(output).to eq :correct
12
+ end
13
+
14
+ it "identifies an image and extract its dimensions and orientation" do
15
+ allow_any_instance_of(Paperclip::GeometryParser).to receive(:make).and_return(:correct)
16
+ file = fixture_file("rotated.jpg")
17
+ factory = Paperclip::GeometryDetector.new(file)
18
+
19
+ output = factory.make
20
+
21
+ expect(output).to eq :correct
22
+ end
23
+
24
+ it "avoids reading EXIF orientation if so configured" do
25
+ begin
26
+ Paperclip.options[:use_exif_orientation] = false
27
+ allow_any_instance_of(Paperclip::GeometryParser).to receive(:make).and_return(:correct)
28
+ file = fixture_file("rotated.jpg")
29
+ factory = Paperclip::GeometryDetector.new(file)
30
+
31
+ output = factory.make
32
+
33
+ expect(output).to eq :correct
34
+ ensure
35
+ Paperclip.options[:use_exif_orientation] = true
36
+ end
37
+ end
38
+
39
+ it "raises an exception with a message when the file is not an image" do
40
+ file = fixture_file("text.txt")
41
+ factory = Paperclip::GeometryDetector.new(file)
42
+
43
+ expect do
44
+ factory.make
45
+ end.to raise_error(Paperclip::Errors::NotIdentifiedByImageMagickError, "Could not identify image size")
46
+ end
47
+ end
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::GeometryParser do
4
+ it "identifies an image and extract its dimensions with no orientation" do
5
+ allow(Paperclip::Geometry).to receive(:new).with(
6
+ height: "73",
7
+ width: "434",
8
+ modifier: nil,
9
+ orientation: nil
10
+ ).and_return(:correct)
11
+ factory = Paperclip::GeometryParser.new("434x73")
12
+
13
+ output = factory.make
14
+
15
+ assert_equal :correct, output
16
+ end
17
+
18
+ it "identifies an image and extract its dimensions with an empty orientation" do
19
+ allow(Paperclip::Geometry).to receive(:new).with(
20
+ height: "73",
21
+ width: "434",
22
+ modifier: nil,
23
+ orientation: ""
24
+ ).and_return(:correct)
25
+ factory = Paperclip::GeometryParser.new("434x73,")
26
+
27
+ output = factory.make
28
+
29
+ assert_equal :correct, output
30
+ end
31
+
32
+ it "identifies an image and extract its dimensions and orientation" do
33
+ allow(Paperclip::Geometry).to receive(:new).with(
34
+ height: "200",
35
+ width: "300",
36
+ modifier: nil,
37
+ orientation: "6"
38
+ ).and_return(:correct)
39
+ factory = Paperclip::GeometryParser.new("300x200,6")
40
+
41
+ output = factory.make
42
+
43
+ assert_equal :correct, output
44
+ end
45
+
46
+ it "identifies an image and extract its dimensions and modifier" do
47
+ allow(Paperclip::Geometry).to receive(:new).with(
48
+ height: "64",
49
+ width: "64",
50
+ modifier: "#",
51
+ orientation: nil
52
+ ).and_return(:correct)
53
+ factory = Paperclip::GeometryParser.new("64x64#")
54
+
55
+ output = factory.make
56
+
57
+ assert_equal :correct, output
58
+ end
59
+
60
+ it "identifies an image and extract its dimensions, orientation, and modifier" do
61
+ allow(Paperclip::Geometry).to receive(:new).with(
62
+ height: "50",
63
+ width: "100",
64
+ modifier: ">",
65
+ orientation: "7"
66
+ ).and_return(:correct)
67
+ factory = Paperclip::GeometryParser.new("100x50,7>")
68
+
69
+ output = factory.make
70
+
71
+ assert_equal :correct, output
72
+ end
73
+ end
@@ -0,0 +1,267 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::Geometry do
4
+ context "Paperclip::Geometry" do
5
+ it "correctly reports its given dimensions" do
6
+ assert @geo = Paperclip::Geometry.new(1024, 768)
7
+ assert_equal 1024, @geo.width
8
+ assert_equal 768, @geo.height
9
+ end
10
+
11
+ it "sets height to 0 if height dimension is missing" do
12
+ assert @geo = Paperclip::Geometry.new(1024)
13
+ assert_equal 1024, @geo.width
14
+ assert_equal 0, @geo.height
15
+ end
16
+
17
+ it "sets width to 0 if width dimension is missing" do
18
+ assert @geo = Paperclip::Geometry.new(nil, 768)
19
+ assert_equal 0, @geo.width
20
+ assert_equal 768, @geo.height
21
+ end
22
+
23
+ it "is generated from a WxH-formatted string" do
24
+ assert @geo = Paperclip::Geometry.parse("800x600")
25
+ assert_equal 800, @geo.width
26
+ assert_equal 600, @geo.height
27
+ end
28
+
29
+ it "is generated from a xH-formatted string" do
30
+ assert @geo = Paperclip::Geometry.parse("x600")
31
+ assert_equal 0, @geo.width
32
+ assert_equal 600, @geo.height
33
+ end
34
+
35
+ it "is generated from a Wx-formatted string" do
36
+ assert @geo = Paperclip::Geometry.parse("800x")
37
+ assert_equal 800, @geo.width
38
+ assert_equal 0, @geo.height
39
+ end
40
+
41
+ it "is generated from a W-formatted string" do
42
+ assert @geo = Paperclip::Geometry.parse("800")
43
+ assert_equal 800, @geo.width
44
+ assert_equal 0, @geo.height
45
+ end
46
+
47
+ it "ensures the modifier is nil if not present" do
48
+ assert @geo = Paperclip::Geometry.parse("123x456")
49
+ assert_nil @geo.modifier
50
+ end
51
+
52
+ it "recognizes an EXIF orientation and not rotate with auto_orient if not necessary" do
53
+ geo = Paperclip::Geometry.new(width: 1024, height: 768, orientation: 1)
54
+ assert geo
55
+ assert_equal 1024, geo.width
56
+ assert_equal 768, geo.height
57
+
58
+ geo.auto_orient
59
+
60
+ assert_equal 1024, geo.width
61
+ assert_equal 768, geo.height
62
+ end
63
+
64
+ it "recognizes an EXIF orientation and rotate with auto_orient if necessary" do
65
+ geo = Paperclip::Geometry.new(width: 1024, height: 768, orientation: 6)
66
+ assert geo
67
+ assert_equal 1024, geo.width
68
+ assert_equal 768, geo.height
69
+
70
+ geo.auto_orient
71
+
72
+ assert_equal 768, geo.width
73
+ assert_equal 1024, geo.height
74
+ end
75
+
76
+ it "treats x and X the same in geometries" do
77
+ @lower = Paperclip::Geometry.parse("123x456")
78
+ @upper = Paperclip::Geometry.parse("123X456")
79
+ assert_equal 123, @lower.width
80
+ assert_equal 123, @upper.width
81
+ assert_equal 456, @lower.height
82
+ assert_equal 456, @upper.height
83
+ end
84
+
85
+ [">", "<", "#", "@", "@>", ">@", "%", "^", "!", nil].each do |mod|
86
+ it "ensures the modifier #{description} is preserved" do
87
+ assert @geo = Paperclip::Geometry.parse("123x456#{mod}")
88
+ assert_equal mod, @geo.modifier
89
+ assert_equal "123x456#{mod}", @geo.to_s
90
+ end
91
+
92
+ it "ensures the modifier #{description} is preserved with no height" do
93
+ assert @geo = Paperclip::Geometry.parse("123x#{mod}")
94
+ assert_equal mod, @geo.modifier
95
+ assert_equal "123#{mod}", @geo.to_s
96
+ end
97
+ end
98
+
99
+ it "makes sure the modifier gets passed during transformation_to" do
100
+ assert @src = Paperclip::Geometry.parse("123x456")
101
+ assert @dst = Paperclip::Geometry.parse("123x456>")
102
+ assert_equal ["123x456>", nil], @src.transformation_to(@dst)
103
+ end
104
+
105
+ it "generates correct ImageMagick formatting string for W-formatted string" do
106
+ assert @geo = Paperclip::Geometry.parse("800")
107
+ assert_equal "800", @geo.to_s
108
+ end
109
+
110
+ it "generates correct ImageMagick formatting string for Wx-formatted string" do
111
+ assert @geo = Paperclip::Geometry.parse("800x")
112
+ assert_equal "800", @geo.to_s
113
+ end
114
+
115
+ it "generates correct ImageMagick formatting string for xH-formatted string" do
116
+ assert @geo = Paperclip::Geometry.parse("x600")
117
+ assert_equal "x600", @geo.to_s
118
+ end
119
+
120
+ it "generates correct ImageMagick formatting string for WxH-formatted string" do
121
+ assert @geo = Paperclip::Geometry.parse("800x600")
122
+ assert_equal "800x600", @geo.to_s
123
+ end
124
+
125
+ it "is generated from a file" do
126
+ file = fixture_file("5k.png")
127
+ file = File.new(file, "rb")
128
+ assert_nothing_raised { @geo = Paperclip::Geometry.from_file(file) }
129
+ assert_equal 66, @geo.height
130
+ assert_equal 434, @geo.width
131
+ end
132
+
133
+ it "is generated from a file path" do
134
+ file = fixture_file("5k.png")
135
+ assert_nothing_raised { @geo = Paperclip::Geometry.from_file(file) }
136
+ assert_equal 66, @geo.height
137
+ assert_equal 434, @geo.width
138
+ end
139
+
140
+ it "calculates an EXIF-rotated image dimensions from a path" do
141
+ file = fixture_file("rotated.jpg")
142
+ assert_nothing_raised { @geo = Paperclip::Geometry.from_file(file) }
143
+ @geo.auto_orient
144
+ assert_equal 300, @geo.height
145
+ assert_equal 200, @geo.width
146
+ end
147
+
148
+ it "does not generate from a bad file" do
149
+ file = "/home/This File Does Not Exist.omg"
150
+ expect do
151
+ @geo = Paperclip::Geometry.from_file(file)
152
+ end.to raise_error(Paperclip::Errors::NotIdentifiedByImageMagickError,
153
+ "Could not identify image size")
154
+ end
155
+
156
+ it "does not generate from a blank filename" do
157
+ file = ""
158
+ expect do
159
+ @geo = Paperclip::Geometry.from_file(file)
160
+ end.to raise_error(Paperclip::Errors::NotIdentifiedByImageMagickError,
161
+ "Cannot find the geometry of a file with a blank name")
162
+ end
163
+
164
+ it "does not generate from a nil file" do
165
+ file = nil
166
+ expect do
167
+ @geo = Paperclip::Geometry.from_file(file)
168
+ end.to raise_error(Paperclip::Errors::NotIdentifiedByImageMagickError,
169
+ "Cannot find the geometry of a file with a blank name")
170
+ end
171
+
172
+ it "does not generate from a file with no path" do
173
+ file = double("file", path: "")
174
+ allow(file).to receive(:respond_to?).with(:path).and_return(true)
175
+ expect do
176
+ @geo = Paperclip::Geometry.from_file(file)
177
+ end.to raise_error(Paperclip::Errors::NotIdentifiedByImageMagickError,
178
+ "Cannot find the geometry of a file with a blank name")
179
+ end
180
+
181
+ it "lets us know when a command isn't found versus a processing error" do
182
+ old_path = ENV["PATH"]
183
+ begin
184
+ ENV["PATH"] = ""
185
+ assert_raises(Paperclip::Errors::CommandNotFoundError) do
186
+ file = fixture_file("5k.png")
187
+ @geo = Paperclip::Geometry.from_file(file)
188
+ end
189
+ ensure
190
+ ENV["PATH"] = old_path
191
+ end
192
+ end
193
+
194
+ [["vertical", 900, 1440, true, false, false, 1440, 900, 0.625],
195
+ ["horizontal", 1024, 768, false, true, false, 1024, 768, 1.3333],
196
+ ["square", 100, 100, false, false, true, 100, 100, 1]].each do |args|
197
+ context "performing calculations on a #{args[0]} viewport" do
198
+ before do
199
+ @geo = Paperclip::Geometry.new(args[1], args[2])
200
+ end
201
+
202
+ it "is #{args[3] ? '' : 'not'} vertical" do
203
+ assert_equal args[3], @geo.vertical?
204
+ end
205
+
206
+ it "is #{args[4] ? '' : 'not'} horizontal" do
207
+ assert_equal args[4], @geo.horizontal?
208
+ end
209
+
210
+ it "is #{args[5] ? '' : 'not'} square" do
211
+ assert_equal args[5], @geo.square?
212
+ end
213
+
214
+ it "reports that #{args[6]} is the larger dimension" do
215
+ assert_equal args[6], @geo.larger
216
+ end
217
+
218
+ it "reports that #{args[7]} is the smaller dimension" do
219
+ assert_equal args[7], @geo.smaller
220
+ end
221
+
222
+ it "has an aspect ratio of #{args[8]}" do
223
+ expect(@geo.aspect).to be_within(0.0001).of(args[8])
224
+ end
225
+ end
226
+ end
227
+
228
+ [[[1000, 100], [64, 64], "x64", "64x64+288+0"],
229
+ [[100, 1000], [50, 950], "x950", "50x950+22+0"],
230
+ [[100, 1000], [50, 25], "50x", "50x25+0+237"]]. each do |args|
231
+ context "of #{args[0].inspect} and given a Geometry #{args[1].inspect} and sent transform_to" do
232
+ before do
233
+ @geo = Paperclip::Geometry.new(*args[0])
234
+ @dst = Paperclip::Geometry.new(*args[1])
235
+ @scale, @crop = @geo.transformation_to @dst, true
236
+ end
237
+
238
+ it "is able to return the correct scaling transformation geometry #{args[2]}" do
239
+ assert_equal args[2], @scale
240
+ end
241
+
242
+ it "is able to return the correct crop transformation geometry #{args[3]}" do
243
+ assert_equal args[3], @crop
244
+ end
245
+ end
246
+ end
247
+
248
+ [["256x256", { "150x150!" => [150, 150], "150x150#" => [150, 150], "150x150>" => [150, 150], "150x150<" => [256, 256], "150x150" => [150, 150] }],
249
+ ["256x256", { "512x512!" => [512, 512], "512x512#" => [512, 512], "512x512>" => [256, 256], "512x512<" => [512, 512], "512x512" => [512, 512] }],
250
+ ["600x400", { "512x512!" => [512, 512], "512x512#" => [512, 512], "512x512>" => [512, 341], "512x512<" => [600, 400], "512x512" => [512, 341] }]].each do |original_size, options|
251
+ options.each_pair do |size, dimensions|
252
+ context "#{original_size} resize_to #{size}" do
253
+ before do
254
+ @source = Paperclip::Geometry.parse original_size
255
+ @new_geometry = @source.resize_to size
256
+ end
257
+ it "has #{dimensions.first} width" do
258
+ assert_equal dimensions.first, @new_geometry.width
259
+ end
260
+ it "has #{dimensions.last} height" do
261
+ assert_equal dimensions.last, @new_geometry.height
262
+ end
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,63 @@
1
+ # require "spec_helper"
2
+
3
+ describe Paperclip::Glue do
4
+ describe "when ActiveRecord does not exist" do
5
+ before do
6
+ ActiveRecordSaved = ActiveRecord
7
+ Object.send :remove_const, "ActiveRecord"
8
+ end
9
+
10
+ after do
11
+ ActiveRecord = ActiveRecordSaved
12
+ Object.send :remove_const, "ActiveRecordSaved"
13
+ end
14
+
15
+ it "does not fail" do
16
+ NonActiveRecordModel = Class.new
17
+ NonActiveRecordModel.include Paperclip::Glue
18
+ Object.send :remove_const, "NonActiveRecordModel"
19
+ end
20
+ end
21
+
22
+ describe "when ActiveRecord does exist" do
23
+ before do
24
+ if Object.const_defined?("ActiveRecord")
25
+ @defined_active_record = false
26
+ else
27
+ ActiveRecord = :defined
28
+ @defined_active_record = true
29
+ end
30
+ end
31
+
32
+ after do
33
+ Object.send :remove_const, "ActiveRecord" if @defined_active_record
34
+ end
35
+
36
+ it "does not fail" do
37
+ NonActiveRecordModel = Class.new
38
+ NonActiveRecordModel.include Paperclip::Glue
39
+ Object.send :remove_const, "NonActiveRecordModel"
40
+ end
41
+ end
42
+
43
+ describe "when included" do
44
+ it "does not mutate I18n.load_path more than once" do
45
+ before_load_path = I18n.load_path
46
+ I18n.load_path = []
47
+
48
+ # expect twice because the load_path is reset after creating the classes
49
+ expect(I18n.config).to receive(:load_path=).and_call_original.twice
50
+
51
+ FirstModel = Class.new
52
+ FirstModel.include Paperclip::Glue
53
+
54
+ SecondModel = Class.new
55
+ SecondModel.include Paperclip::Glue
56
+
57
+ ThirdModel = Class.new
58
+ ThirdModel.include Paperclip::Glue
59
+
60
+ I18n.load_path = before_load_path
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,78 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::HasAttachedFile do
4
+ let(:a_class) { spy("Class") }
5
+
6
+ context "#define_on" do
7
+ it "defines a setter on the class object" do
8
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
9
+ expect(a_class).to have_received(:define_method).with("avatar=")
10
+ end
11
+
12
+ it "defines a getter on the class object" do
13
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
14
+ expect(a_class).to have_received(:define_method).with("avatar")
15
+ end
16
+
17
+ it "defines a query on the class object" do
18
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
19
+ expect(a_class).to have_received(:define_method).with("avatar?")
20
+ end
21
+
22
+ it "defines a method on the class to get all of its attachments" do
23
+ allow(a_class).to receive(:extend)
24
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
25
+ expect(a_class).to have_received(:extend).with(Paperclip::HasAttachedFile::ClassMethods)
26
+ end
27
+
28
+ it "flushes errors as part of validations" do
29
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
30
+ expect(a_class).to have_received(:validates_each).with("avatar")
31
+ end
32
+
33
+ it "registers the attachment with Paperclip::AttachmentRegistry" do
34
+ allow(Paperclip::AttachmentRegistry).to receive(:register)
35
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", size: 1)
36
+ expect(Paperclip::AttachmentRegistry).to have_received(:register).with(a_class, "avatar", size: 1)
37
+ end
38
+
39
+ it "defines an after_save callback" do
40
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
41
+ expect(a_class).to have_received("after_save")
42
+ end
43
+
44
+ it "defines a before_destroy callback" do
45
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
46
+ expect(a_class).to have_received("before_destroy")
47
+ end
48
+
49
+ it "defines an after_commit callback" do
50
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
51
+ expect(a_class).to have_received("after_commit")
52
+ end
53
+
54
+ context "when the class does not allow after_commit callbacks" do
55
+ it "defines an after_destroy callback" do
56
+ a_class = double("class", after_destroy: nil, validates_each: nil, define_method: nil, after_save: nil, before_destroy: nil, define_paperclip_callbacks: nil, validates_media_type_spoof_detection: nil)
57
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", {})
58
+ expect(a_class).to have_received("after_destroy")
59
+ end
60
+ end
61
+
62
+ it "defines the Paperclip-specific callbacks" do
63
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", validate_media_type: false)
64
+ expect(a_class).to_not have_received(:validates_media_type_spoof_detection)
65
+ expect(a_class).to have_received("define_paperclip_callbacks")
66
+ end
67
+
68
+ it "does not define a media_type check if told not to" do
69
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", validate_media_type: false)
70
+ expect(a_class).to_not have_received(:validates_media_type_spoof_detection)
71
+ end
72
+
73
+ it "does define a media_type check if told to" do
74
+ Paperclip::HasAttachedFile.define_on(a_class, "avatar", validate_media_type: true)
75
+ expect(a_class).to have_received(:validates_media_type_spoof_detection)
76
+ end
77
+ end
78
+ end