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,64 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::StringioAdapter do
4
+ context "a new instance" do
5
+ before do
6
+ @contents = "abc123"
7
+ @stringio = StringIO.new(@contents)
8
+ @subject = Paperclip.io_adapters.for(@stringio, hash_digest: Digest::MD5)
9
+ end
10
+
11
+ it "returns a file name" do
12
+ assert_equal "data", @subject.original_filename
13
+ end
14
+
15
+ it "returns a content type" do
16
+ assert_equal "text/plain", @subject.content_type
17
+ end
18
+
19
+ it "returns the size of the data" do
20
+ assert_equal 6, @subject.size
21
+ end
22
+
23
+ it "returns the length of the data" do
24
+ assert_equal 6, @subject.length
25
+ end
26
+
27
+ it "generates an MD5 hash of the contents" do
28
+ assert_equal Digest::MD5.hexdigest(@contents), @subject.fingerprint
29
+ end
30
+
31
+ it "generates correct fingerprint after read" do
32
+ fingerprint = Digest::MD5.hexdigest(@subject.read)
33
+ assert_equal fingerprint, @subject.fingerprint
34
+ end
35
+
36
+ it "generates same fingerprint" do
37
+ assert_equal @subject.fingerprint, @subject.fingerprint
38
+ end
39
+
40
+ it "returns the data contained in the StringIO" do
41
+ assert_equal "abc123", @subject.read
42
+ end
43
+
44
+ it "accepts a content_type" do
45
+ @subject.content_type = "image/png"
46
+ assert_equal "image/png", @subject.content_type
47
+ end
48
+
49
+ it "accepts an original_filename" do
50
+ @subject.original_filename = "image.png"
51
+ assert_equal "image.png", @subject.original_filename
52
+ end
53
+
54
+ it "does not generate filenames that include restricted characters" do
55
+ @subject.original_filename = "image:restricted.png"
56
+ assert_equal "image_restricted.png", @subject.original_filename
57
+ end
58
+
59
+ it "does not generate paths that include restricted characters" do
60
+ @subject.original_filename = "image:restricted.png"
61
+ expect(@subject.path).to_not match(/:/)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,146 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::UploadedFileAdapter do
4
+ context "a new instance" do
5
+ context "with UploadedFile responding to #tempfile" do
6
+ before do
7
+ Paperclip::UploadedFileAdapter.content_type_detector = nil
8
+
9
+ class UploadedFile < OpenStruct; end
10
+ tempfile = File.new(fixture_file("5k.png"))
11
+ tempfile.binmode
12
+
13
+ @file = UploadedFile.new(
14
+ original_filename: "5k.png",
15
+ content_type: "image/x-png-by-browser\r",
16
+ head: "",
17
+ tempfile: tempfile,
18
+ path: tempfile.path
19
+ )
20
+ @subject = Paperclip.io_adapters.for(@file, hash_digest: Digest::MD5)
21
+ end
22
+
23
+ it "gets the right filename" do
24
+ assert_equal "5k.png", @subject.original_filename
25
+ end
26
+
27
+ it "forces binmode on tempfile" do
28
+ assert @subject.instance_variable_get("@tempfile").binmode?
29
+ end
30
+
31
+ it "gets the content type" do
32
+ assert_equal "image/png", @subject.content_type
33
+ end
34
+
35
+ it "gets the file's size" do
36
+ assert_equal 4456, @subject.size
37
+ end
38
+
39
+ it "returns false for a call to nil?" do
40
+ assert !@subject.nil?
41
+ end
42
+
43
+ it "generates a MD5 hash of the contents" do
44
+ expected = Digest::MD5.file(@file.tempfile.path).to_s
45
+ assert_equal expected, @subject.fingerprint
46
+ end
47
+
48
+ it "reads the contents of the file" do
49
+ expected = @file.tempfile.read
50
+ assert !expected.empty?
51
+ assert_equal expected, @subject.read
52
+ end
53
+ end
54
+
55
+ context "with UploadedFile that has restricted characters" do
56
+ before do
57
+ Paperclip::UploadedFileAdapter.content_type_detector = nil
58
+
59
+ class UploadedFile < OpenStruct; end
60
+ @file = UploadedFile.new(
61
+ original_filename: "image:restricted.gif",
62
+ content_type: "image/x-png-by-browser",
63
+ head: "",
64
+ path: fixture_file("5k.png")
65
+ )
66
+ @subject = Paperclip.io_adapters.for(@file, hash_digest: Digest::MD5)
67
+ end
68
+
69
+ it "does not generate paths that include restricted characters" do
70
+ expect(@subject.path).to_not match(/:/)
71
+ end
72
+
73
+ it "does not generate filenames that include restricted characters" do
74
+ assert_equal "image_restricted.gif", @subject.original_filename
75
+ end
76
+ end
77
+
78
+ context "with UploadFile responding to #path" do
79
+ before do
80
+ Paperclip::UploadedFileAdapter.content_type_detector = nil
81
+
82
+ class UploadedFile < OpenStruct; end
83
+ @file = UploadedFile.new(
84
+ original_filename: "5k.png",
85
+ content_type: "image/x-png-by-browser",
86
+ head: "",
87
+ path: fixture_file("5k.png")
88
+ )
89
+ @subject = Paperclip.io_adapters.for(@file, hash_digest: Digest::MD5)
90
+ end
91
+
92
+ it "gets the right filename" do
93
+ assert_equal "5k.png", @subject.original_filename
94
+ end
95
+
96
+ it "forces binmode on tempfile" do
97
+ assert @subject.instance_variable_get("@tempfile").binmode?
98
+ end
99
+
100
+ it "gets the content type" do
101
+ assert_equal "image/png", @subject.content_type
102
+ end
103
+
104
+ it "gets the file's size" do
105
+ assert_equal 4456, @subject.size
106
+ end
107
+
108
+ it "returns false for a call to nil?" do
109
+ assert !@subject.nil?
110
+ end
111
+
112
+ it "generates a MD5 hash of the contents" do
113
+ expected = Digest::MD5.file(@file.path).to_s
114
+ assert_equal expected, @subject.fingerprint
115
+ end
116
+
117
+ it "reads the contents of the file" do
118
+ expected_file = File.new(@file.path)
119
+ expected_file.binmode
120
+ expected = expected_file.read
121
+ assert !expected.empty?
122
+ assert_equal expected, @subject.read
123
+ end
124
+
125
+ context "don't trust client-given MIME type" do
126
+ before do
127
+ Paperclip::UploadedFileAdapter.content_type_detector =
128
+ Paperclip::FileCommandContentTypeDetector
129
+
130
+ class UploadedFile < OpenStruct; end
131
+ @file = UploadedFile.new(
132
+ original_filename: "5k.png",
133
+ content_type: "image/x-png-by-browser",
134
+ head: "",
135
+ path: fixture_file("5k.png")
136
+ )
137
+ @subject = Paperclip.io_adapters.for(@file)
138
+ end
139
+
140
+ it "gets the content type" do
141
+ assert_equal "image/png", @subject.content_type
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,221 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::UriAdapter do
4
+ let(:content_type) { "image/png" }
5
+ let(:meta) { {} }
6
+
7
+ before do
8
+ @open_return = StringIO.new("xxx")
9
+ allow(@open_return).to receive(:content_type).and_return(content_type)
10
+ allow(@open_return).to receive(:meta).and_return(meta)
11
+ Paperclip::UriAdapter.register
12
+ end
13
+
14
+ after do
15
+ Paperclip.io_adapters.unregister(described_class)
16
+ end
17
+
18
+ context "a new instance" do
19
+ let(:meta) { { "content-type" => "image/png" } }
20
+
21
+ before do
22
+ allow_any_instance_of(Paperclip::UriAdapter).
23
+ to receive(:download_content).and_return(@open_return)
24
+
25
+ @uri = URI.parse("http://thoughtbot.com/images/thoughtbot-logo.png")
26
+ @subject = Paperclip.io_adapters.for(@uri, hash_digest: Digest::MD5)
27
+ end
28
+
29
+ it "returns a file name" do
30
+ assert_equal "thoughtbot-logo.png", @subject.original_filename
31
+ end
32
+
33
+ it "closes open handle after reading" do
34
+ assert_equal true, @open_return.closed?
35
+ end
36
+
37
+ it "returns a content type" do
38
+ assert_equal "image/png", @subject.content_type
39
+ end
40
+
41
+ it "returns the size of the data" do
42
+ assert_equal @open_return.size, @subject.size
43
+ end
44
+
45
+ it "generates an MD5 hash of the contents" do
46
+ assert_equal Digest::MD5.hexdigest("xxx"), @subject.fingerprint
47
+ end
48
+
49
+ it "generates correct fingerprint after read" do
50
+ fingerprint = Digest::MD5.hexdigest(@subject.read)
51
+ assert_equal fingerprint, @subject.fingerprint
52
+ end
53
+
54
+ it "generates same fingerprint" do
55
+ assert_equal @subject.fingerprint, @subject.fingerprint
56
+ end
57
+
58
+ it "returns the data contained in the StringIO" do
59
+ assert_equal "xxx", @subject.read
60
+ end
61
+
62
+ it "accepts a content_type" do
63
+ @subject.content_type = "image/png"
64
+ assert_equal "image/png", @subject.content_type
65
+ end
66
+
67
+ it "accepts an original_filename" do
68
+ @subject.original_filename = "image.png"
69
+ assert_equal "image.png", @subject.original_filename
70
+ end
71
+ end
72
+
73
+ context "a directory index url" do
74
+ let(:content_type) { "text/html" }
75
+ let(:meta) { { "content-type" => "text/html" } }
76
+
77
+ before do
78
+ allow_any_instance_of(Paperclip::UriAdapter).
79
+ to receive(:download_content).and_return(@open_return)
80
+
81
+ @uri = URI.parse("http://thoughtbot.com")
82
+ @subject = Paperclip.io_adapters.for(@uri)
83
+ end
84
+
85
+ it "returns a file name" do
86
+ assert_equal "index.html", @subject.original_filename
87
+ end
88
+
89
+ it "returns a content type" do
90
+ assert_equal "text/html", @subject.content_type
91
+ end
92
+ end
93
+
94
+ context "a url with query params" do
95
+ before do
96
+ allow_any_instance_of(Paperclip::UriAdapter).
97
+ to receive(:download_content).and_return(@open_return)
98
+
99
+ @uri = URI.parse("https://github.com/thoughtbot/paperclip?file=test")
100
+ @subject = Paperclip.io_adapters.for(@uri)
101
+ end
102
+
103
+ it "returns a file name" do
104
+ assert_equal "paperclip", @subject.original_filename
105
+ end
106
+ end
107
+
108
+ context "a url with content disposition headers" do
109
+ let(:file_name) { "test_document.pdf" }
110
+ let(:filename_from_path) { "paperclip" }
111
+
112
+ before do
113
+ allow_any_instance_of(Paperclip::UriAdapter).
114
+ to receive(:download_content).and_return(@open_return)
115
+
116
+ @uri = URI.parse(
117
+ "https://github.com/thoughtbot/#{filename_from_path}?file=test"
118
+ )
119
+ end
120
+
121
+ it "returns file name from path" do
122
+ meta["content-disposition"] = "inline;"
123
+
124
+ @subject = Paperclip.io_adapters.for(@uri)
125
+
126
+ assert_equal filename_from_path, @subject.original_filename
127
+ end
128
+
129
+ it "returns a file name enclosed in double quotes" do
130
+ file_name = "john's test document.pdf"
131
+ meta["content-disposition"] = "attachment; filename=\"#{file_name}\";"
132
+
133
+ @subject = Paperclip.io_adapters.for(@uri)
134
+
135
+ assert_equal file_name, @subject.original_filename
136
+ end
137
+
138
+ it "returns a file name not enclosed in double quotes" do
139
+ meta["content-disposition"] = "ATTACHMENT; FILENAME=#{file_name};"
140
+
141
+ @subject = Paperclip.io_adapters.for(@uri)
142
+
143
+ assert_equal file_name, @subject.original_filename
144
+ end
145
+
146
+ it "does not crash when an empty filename is given" do
147
+ meta["content-disposition"] = "ATTACHMENT; FILENAME=\"\";"
148
+
149
+ @subject = Paperclip.io_adapters.for(@uri)
150
+
151
+ assert_equal "", @subject.original_filename
152
+ end
153
+
154
+ it "returns a file name ignoring RFC 5987 encoding" do
155
+ meta["content-disposition"] =
156
+ "attachment; filename=#{file_name}; filename* = utf-8''%e2%82%ac%20rates"
157
+
158
+ @subject = Paperclip.io_adapters.for(@uri)
159
+
160
+ assert_equal file_name, @subject.original_filename
161
+ end
162
+
163
+ context "when file name has consecutive periods" do
164
+ let(:file_name) { "test_document..pdf" }
165
+
166
+ it "returns a file name" do
167
+ @uri = URI.parse(
168
+ "https://github.com/thoughtbot/#{file_name}?file=test"
169
+ )
170
+ @subject = Paperclip.io_adapters.for(@uri)
171
+ assert_equal file_name, @subject.original_filename
172
+ end
173
+ end
174
+ end
175
+
176
+ context "a url with restricted characters in the filename" do
177
+ before do
178
+ allow_any_instance_of(Paperclip::UriAdapter).
179
+ to receive(:download_content).and_return(@open_return)
180
+
181
+ @uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
182
+ @subject = Paperclip.io_adapters.for(@uri)
183
+ end
184
+
185
+ it "does not generate filenames that include restricted characters" do
186
+ assert_equal "paper_clip.jpg", @subject.original_filename
187
+ end
188
+
189
+ it "does not generate paths that include restricted characters" do
190
+ expect(@subject.path).to_not match(/:/)
191
+ end
192
+ end
193
+
194
+ describe "#download_content" do
195
+ before do
196
+ allow_any_instance_of(Paperclip::UriAdapter).to receive(:open).and_return(@open_return)
197
+ @uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
198
+ @subject = Paperclip.io_adapters.for(@uri)
199
+ end
200
+
201
+ after do
202
+ @subject.send(:download_content)
203
+ end
204
+
205
+ context "with default read_timeout" do
206
+ it "calls open without options" do
207
+ expect(@subject).to receive(:open).with(@uri, {}).at_least(1).times
208
+ end
209
+ end
210
+
211
+ context "with custom read_timeout" do
212
+ before do
213
+ Paperclip.options[:read_timeout] = 120
214
+ end
215
+
216
+ it "calls open with read_timeout option" do
217
+ expect(@subject).to receive(:open).with(@uri, read_timeout: 120).at_least(1).times
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+ require "paperclip/matchers"
3
+
4
+ describe Paperclip::Shoulda::Matchers::HaveAttachedFileMatcher do
5
+ extend Paperclip::Shoulda::Matchers
6
+
7
+ it "rejects the dummy class if it has no attachment" do
8
+ reset_table "dummies"
9
+ reset_class "Dummy"
10
+ matcher = self.class.have_attached_file(:avatar)
11
+ expect(matcher).to_not accept(Dummy)
12
+ end
13
+
14
+ it "accepts the dummy class if it has an attachment" do
15
+ rebuild_model
16
+ matcher = self.class.have_attached_file(:avatar)
17
+ expect(matcher).to accept(Dummy)
18
+ end
19
+ end