image_vise 0.1.6 → 0.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/.travis.yml +13 -0
  4. data/DEVELOPMENT.md +0 -11
  5. data/Gemfile +2 -20
  6. data/Rakefile +3 -26
  7. data/image_vise.gemspec +37 -132
  8. data/lib/image_vise/file_response.rb +2 -2
  9. data/lib/image_vise/image_request.rb +2 -0
  10. data/lib/image_vise/operators/background_fill.rb +18 -0
  11. data/lib/image_vise/operators/ellipse_stencil.rb +7 -5
  12. data/lib/image_vise/operators/force_jpg_out.rb +17 -0
  13. data/lib/image_vise/pipeline.rb +13 -3
  14. data/lib/image_vise/render_engine.rb +36 -64
  15. data/lib/image_vise/version.rb +3 -0
  16. data/lib/image_vise/writers/auto_writer.rb +23 -0
  17. data/lib/image_vise/writers/jpeg_writer.rb +9 -0
  18. data/lib/image_vise.rb +19 -19
  19. metadata +43 -135
  20. data/spec/image_vise/auto_orient_spec.rb +0 -10
  21. data/spec/image_vise/crop_spec.rb +0 -20
  22. data/spec/image_vise/ellipse_stencil_spec.rb +0 -19
  23. data/spec/image_vise/fetcher_file_spec.rb +0 -48
  24. data/spec/image_vise/fetcher_http_spec.rb +0 -44
  25. data/spec/image_vise/file_response_spec.rb +0 -45
  26. data/spec/image_vise/fit_crop_spec.rb +0 -20
  27. data/spec/image_vise/geom_spec.rb +0 -33
  28. data/spec/image_vise/image_request_spec.rb +0 -62
  29. data/spec/image_vise/pipeline_spec.rb +0 -72
  30. data/spec/image_vise/render_engine_spec.rb +0 -325
  31. data/spec/image_vise/sharpen_spec.rb +0 -17
  32. data/spec/image_vise/srgb_spec.rb +0 -28
  33. data/spec/image_vise/strip_metadata_spec.rb +0 -14
  34. data/spec/image_vise_spec.rb +0 -110
  35. data/spec/layers-with-blending.psd +0 -0
  36. data/spec/spec_helper.rb +0 -103
  37. data/spec/test_server.rb +0 -61
  38. data/spec/waterside_magic_hour.jpg +0 -0
  39. data/spec/waterside_magic_hour.psd +0 -0
  40. data/spec/waterside_magic_hour_adobergb.jpg +0 -0
  41. data/spec/waterside_magic_hour_gray.tif +0 -0
  42. data/spec/waterside_magic_hour_transp.png +0 -0
@@ -0,0 +1,23 @@
1
+ # Picks the most reasonable "default" output format for web resources. In practice, if the
2
+ # image contains transparency (an alpha channel) PNG will be chosen, and if not - JPEG will
3
+ # be chosen. Since ImageVise URLs do not contain a file extension we are free to pick
4
+ # the suitable format at render time
5
+ class ImageVise::AutoWriter
6
+ # The default file type for images with alpha
7
+ PNG_FILE_TYPE = MagicBytes::FileType.new('png','image/png').freeze
8
+
9
+ # Renders the file as a jpg if the custom output filetype operator is used
10
+ JPG_FILE_TYPE = MagicBytes::FileType.new('jpg','image/jpeg').freeze
11
+
12
+ def write_image!(magick_image, _, render_to_path)
13
+ # If processing the image has created an alpha channel, use PNG always.
14
+ # Otherwise, keep the original format for as far as the supported formats list goes.
15
+ render_file_type = if magick_image.alpha?
16
+ PNG_FILE_TYPE
17
+ else
18
+ JPG_FILE_TYPE
19
+ end
20
+ magick_image.format = render_file_type.ext
21
+ magick_image.write(render_to_path)
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ class ImageVise::JPGWriter < Ks.strict(:quality)
2
+ JPG_FILE_TYPE = MagicBytes::FileType.new('jpg','image/jpeg').freeze
3
+
4
+ def write_image!(magick_image, _, render_to_path)
5
+ q = self.quality # to avoid the changing "self" context
6
+ magick_image.format = JPG_FILE_TYPE.ext
7
+ magick_image.write(render_to_path) { self.quality = q }
8
+ end
9
+ end
data/lib/image_vise.rb CHANGED
@@ -8,37 +8,37 @@ require 'base64'
8
8
  require 'rack'
9
9
 
10
10
  class ImageVise
11
- VERSION = '0.1.6'
11
+ require_relative 'image_vise/version'
12
12
  S_MUTEX = Mutex.new
13
13
  private_constant :S_MUTEX
14
-
14
+
15
15
  @allowed_hosts = Set.new
16
16
  @keys = Set.new
17
17
  @operators = {}
18
18
  @allowed_glob_patterns = Set.new
19
19
  @fetchers = {}
20
-
20
+
21
21
  class << self
22
22
  # Resets all allowed hosts
23
23
  def reset_allowed_hosts!
24
24
  S_MUTEX.synchronize { @allowed_hosts.clear }
25
25
  end
26
-
26
+
27
27
  # Add an allowed host
28
28
  def add_allowed_host!(hostname)
29
29
  S_MUTEX.synchronize { @allowed_hosts << hostname }
30
30
  end
31
-
31
+
32
32
  # Returns both the allowed hosts added at runtime and the ones set in the constant
33
33
  def allowed_hosts
34
34
  S_MUTEX.synchronize { @allowed_hosts.to_a }
35
35
  end
36
-
36
+
37
37
  # Removes all set keys
38
38
  def reset_secret_keys!
39
39
  S_MUTEX.synchronize { @keys.clear }
40
40
  end
41
-
41
+
42
42
  def allow_filesystem_source!(glob_pattern)
43
43
  S_MUTEX.synchronize { @allowed_glob_patterns << glob_pattern }
44
44
  end
@@ -52,24 +52,24 @@ class ImageVise
52
52
  end
53
53
 
54
54
  # Adds a key against which the parameters are going to be verified.
55
- # Multiple applications may have their own different keys,
55
+ # Multiple applications may have their own different keys,
56
56
  # so we need to have multiple keys.
57
57
  def add_secret_key!(key)
58
58
  S_MUTEX.synchronize { @keys << key }
59
59
  self
60
60
  end
61
-
61
+
62
62
  # Returns the array of defined keys or raises an exception if no keys have been set yet
63
63
  def secret_keys
64
64
  keys = S_MUTEX.synchronize { @keys.any? && @keys.to_a }
65
65
  keys or raise "No keys set, add a key using `ImageVise.add_secret_key!(key)'"
66
66
  end
67
-
67
+
68
68
  # Generate a set of querystring params for a resized image. Yields a Pipeline object that
69
69
  # will receive method calls for adding image operations to a stack.
70
70
  #
71
71
  # ImageVise.image_params(src_url: image_url_on_s3, secret: '...') do |p|
72
- # p.center_fit width: 128, height: 128
72
+ # p.center_fit width: 128, height: 128
73
73
  # p.elliptic_stencil
74
74
  # end #=> {q: '...', sig: '...'}
75
75
  #
@@ -88,7 +88,7 @@ class ImageVise
88
88
  # will receive method calls for adding image operations to a stack.
89
89
  #
90
90
  # ImageVise.image_path(src_url: image_url_on_s3, secret: '...') do |p|
91
- # p.center_fit width: 128, height: 128
91
+ # p.center_fit width: 128, height: 128
92
92
  # p.elliptic_stencil
93
93
  # end #=> "/abcdef/xyz123"
94
94
  #
@@ -112,26 +112,26 @@ class ImageVise
112
112
  def operator_from(operator_name)
113
113
  @operators.fetch(operator_name.to_s)
114
114
  end
115
-
115
+
116
116
  def defined_operator_names
117
117
  @operators.keys
118
118
  end
119
-
119
+
120
120
  def register_fetcher(scheme, fetcher)
121
121
  S_MUTEX.synchronize { @fetchers[scheme.to_s] = fetcher }
122
122
  end
123
-
123
+
124
124
  def fetcher_for(scheme)
125
125
  S_MUTEX.synchronize { @fetchers[scheme.to_s] or raise "No fetcher registered for #{scheme}" }
126
126
  end
127
-
127
+
128
128
  def operator_name_for(operator)
129
129
  S_MUTEX.synchronize do
130
130
  @operators.key(operator.class) or raise "Operator #{operator.inspect} not registered using ImageVise.add_operator"
131
131
  end
132
132
  end
133
133
  end
134
-
134
+
135
135
  # Made available since the object that is used with `mount()` in Rails
136
136
  # has to, by itself, to respond to `call`.
137
137
  #
@@ -146,11 +146,11 @@ class ImageVise
146
146
  def self.call(rack_env)
147
147
  ImageVise::RenderEngine.new.call(rack_env)
148
148
  end
149
-
149
+
150
150
  def call(rack_env)
151
151
  ImageVise::RenderEngine.new.call(rack_env)
152
152
  end
153
-
153
+
154
154
  # Used as a shorthand to force-destroy Magick images in ensure() blocks. Since
155
155
  # ensure blocks sometimes deal with variables in inconsistent states (variable
156
156
  # in scope but not yet set to an image) we take the possibility of nils into account.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: image_vise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-07 00:00:00.000000000 Z
11
+ date: 2017-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: patron
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.15'
41
- - !ruby/object:Gem::Dependency
42
- name: exceptional_fork
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.2'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.2'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: ks
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -70,88 +56,60 @@ dependencies:
70
56
  name: magic_bytes
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
- - - ">="
59
+ - - "~>"
74
60
  - !ruby/object:Gem::Version
75
- version: '0'
61
+ version: '1'
76
62
  type: :runtime
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: bundler
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: yard
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
66
+ - - "~>"
109
67
  - !ruby/object:Gem::Version
110
- version: '0'
68
+ version: '1'
111
69
  - !ruby/object:Gem::Dependency
112
- name: simplecov
70
+ name: rack
113
71
  requirement: !ruby/object:Gem::Requirement
114
72
  requirements:
115
- - - ">="
73
+ - - "~>"
116
74
  - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
75
+ version: '1'
76
+ type: :runtime
119
77
  prerelease: false
120
78
  version_requirements: !ruby/object:Gem::Requirement
121
79
  requirements:
122
- - - ">="
80
+ - - "~>"
123
81
  - !ruby/object:Gem::Version
124
- version: '0'
82
+ version: '1'
125
83
  - !ruby/object:Gem::Dependency
126
- name: rack-cache
84
+ name: bundler
127
85
  requirement: !ruby/object:Gem::Requirement
128
86
  requirements:
129
- - - ">="
87
+ - - "~>"
130
88
  - !ruby/object:Gem::Version
131
- version: '0'
89
+ version: '1.7'
132
90
  type: :development
133
91
  prerelease: false
134
92
  version_requirements: !ruby/object:Gem::Requirement
135
93
  requirements:
136
- - - ">="
94
+ - - "~>"
137
95
  - !ruby/object:Gem::Version
138
- version: '0'
96
+ version: '1.7'
139
97
  - !ruby/object:Gem::Dependency
140
- name: strenv
98
+ name: rake
141
99
  requirement: !ruby/object:Gem::Requirement
142
100
  requirements:
143
- - - ">="
101
+ - - "~>"
144
102
  - !ruby/object:Gem::Version
145
- version: '0'
103
+ version: '10.0'
146
104
  type: :development
147
105
  prerelease: false
148
106
  version_requirements: !ruby/object:Gem::Requirement
149
107
  requirements:
150
- - - ">="
108
+ - - "~>"
151
109
  - !ruby/object:Gem::Version
152
- version: '0'
110
+ version: '10.0'
153
111
  - !ruby/object:Gem::Dependency
154
- name: addressable
112
+ name: rack-test
155
113
  requirement: !ruby/object:Gem::Requirement
156
114
  requirements:
157
115
  - - ">="
@@ -165,21 +123,21 @@ dependencies:
165
123
  - !ruby/object:Gem::Version
166
124
  version: '0'
167
125
  - !ruby/object:Gem::Dependency
168
- name: rack
126
+ name: rspec
169
127
  requirement: !ruby/object:Gem::Requirement
170
128
  requirements:
171
129
  - - "~>"
172
130
  - !ruby/object:Gem::Version
173
- version: '1'
131
+ version: '3.0'
174
132
  type: :development
175
133
  prerelease: false
176
134
  version_requirements: !ruby/object:Gem::Requirement
177
135
  requirements:
178
136
  - - "~>"
179
137
  - !ruby/object:Gem::Version
180
- version: '1'
138
+ version: '3.0'
181
139
  - !ruby/object:Gem::Dependency
182
- name: rack-test
140
+ name: addressable
183
141
  requirement: !ruby/object:Gem::Requirement
184
142
  requirements:
185
143
  - - ">="
@@ -193,7 +151,7 @@ dependencies:
193
151
  - !ruby/object:Gem::Version
194
152
  version: '0'
195
153
  - !ruby/object:Gem::Dependency
196
- name: foreman
154
+ name: strenv
197
155
  requirement: !ruby/object:Gem::Requirement
198
156
  requirements:
199
157
  - - ">="
@@ -207,41 +165,7 @@ dependencies:
207
165
  - !ruby/object:Gem::Version
208
166
  version: '0'
209
167
  - !ruby/object:Gem::Dependency
210
- name: rspec
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - "<"
214
- - !ruby/object:Gem::Version
215
- version: '3.3'
216
- - - "~>"
217
- - !ruby/object:Gem::Version
218
- version: '3.2'
219
- type: :development
220
- prerelease: false
221
- version_requirements: !ruby/object:Gem::Requirement
222
- requirements:
223
- - - "<"
224
- - !ruby/object:Gem::Version
225
- version: '3.3'
226
- - - "~>"
227
- - !ruby/object:Gem::Version
228
- version: '3.2'
229
- - !ruby/object:Gem::Dependency
230
- name: rake
231
- requirement: !ruby/object:Gem::Requirement
232
- requirements:
233
- - - "~>"
234
- - !ruby/object:Gem::Version
235
- version: '10'
236
- type: :development
237
- prerelease: false
238
- version_requirements: !ruby/object:Gem::Requirement
239
- requirements:
240
- - - "~>"
241
- - !ruby/object:Gem::Version
242
- version: '10'
243
- - !ruby/object:Gem::Dependency
244
- name: jeweler
168
+ name: simplecov
245
169
  requirement: !ruby/object:Gem::Requirement
246
170
  requirements:
247
171
  - - ">="
@@ -255,13 +179,14 @@ dependencies:
255
179
  - !ruby/object:Gem::Version
256
180
  version: '0'
257
181
  description: Image processing via URLs
258
- email: me@julik.nl
182
+ email:
183
+ - me@julik.nl
259
184
  executables: []
260
185
  extensions: []
261
- extra_rdoc_files:
262
- - LICENSE.txt
263
- - README.md
186
+ extra_rdoc_files: []
264
187
  files:
188
+ - ".gitignore"
189
+ - ".travis.yml"
265
190
  - DEVELOPMENT.md
266
191
  - Gemfile
267
192
  - LICENSE.txt
@@ -279,9 +204,11 @@ files:
279
204
  - lib/image_vise/file_response.rb
280
205
  - lib/image_vise/image_request.rb
281
206
  - lib/image_vise/operators/auto_orient.rb
207
+ - lib/image_vise/operators/background_fill.rb
282
208
  - lib/image_vise/operators/crop.rb
283
209
  - lib/image_vise/operators/ellipse_stencil.rb
284
210
  - lib/image_vise/operators/fit_crop.rb
211
+ - lib/image_vise/operators/force_jpg_out.rb
285
212
  - lib/image_vise/operators/geom.rb
286
213
  - lib/image_vise/operators/sRGB_v4_ICC_preference_displayclass.icc
287
214
  - lib/image_vise/operators/sharpen.rb
@@ -289,33 +216,14 @@ files:
289
216
  - lib/image_vise/operators/strip_metadata.rb
290
217
  - lib/image_vise/pipeline.rb
291
218
  - lib/image_vise/render_engine.rb
292
- - spec/image_vise/auto_orient_spec.rb
293
- - spec/image_vise/crop_spec.rb
294
- - spec/image_vise/ellipse_stencil_spec.rb
295
- - spec/image_vise/fetcher_file_spec.rb
296
- - spec/image_vise/fetcher_http_spec.rb
297
- - spec/image_vise/file_response_spec.rb
298
- - spec/image_vise/fit_crop_spec.rb
299
- - spec/image_vise/geom_spec.rb
300
- - spec/image_vise/image_request_spec.rb
301
- - spec/image_vise/pipeline_spec.rb
302
- - spec/image_vise/render_engine_spec.rb
303
- - spec/image_vise/sharpen_spec.rb
304
- - spec/image_vise/srgb_spec.rb
305
- - spec/image_vise/strip_metadata_spec.rb
306
- - spec/image_vise_spec.rb
307
- - spec/layers-with-blending.psd
308
- - spec/spec_helper.rb
309
- - spec/test_server.rb
310
- - spec/waterside_magic_hour.jpg
311
- - spec/waterside_magic_hour.psd
312
- - spec/waterside_magic_hour_adobergb.jpg
313
- - spec/waterside_magic_hour_gray.tif
314
- - spec/waterside_magic_hour_transp.png
219
+ - lib/image_vise/version.rb
220
+ - lib/image_vise/writers/auto_writer.rb
221
+ - lib/image_vise/writers/jpeg_writer.rb
315
222
  homepage: https://github.com/WeTransfer/image_vise
316
223
  licenses:
317
224
  - MIT
318
- metadata: {}
225
+ metadata:
226
+ allowed_push_host: https://rubygems.org
319
227
  post_install_message:
320
228
  rdoc_options: []
321
229
  require_paths:
@@ -332,7 +240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
332
240
  version: '0'
333
241
  requirements: []
334
242
  rubyforge_project:
335
- rubygems_version: 2.4.5.1
243
+ rubygems_version: 2.5.2
336
244
  signing_key:
337
245
  specification_version: 4
338
246
  summary: Runtime thumbnailing proxy
@@ -1,10 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ImageVise::AutoOrient do
4
- it 'applies auto orient to the image' do
5
- image = Magick::Image.read(test_image_path)[0]
6
- orient = described_class.new
7
- expect(image).to receive(:auto_orient!).and_call_original
8
- orient.apply!(image)
9
- end
10
- end
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ImageVise::Crop do
4
- it 'refuses invalid parameters' do
5
- expect { described_class.new(width: 0, height: -1, gravity: '') }.to raise_error(ArgumentError)
6
- end
7
-
8
- it 'applies the crop with different gravities' do
9
- %w( s sw se n ne nw c).each do |gravity|
10
- image = Magick::Image.read(test_image_path)[0]
11
- crop = described_class.new(width: 120, height: 220, gravity: gravity)
12
-
13
- crop.apply!(image)
14
-
15
- expect(image.columns).to eq(120)
16
- expect(image.rows).to eq(220)
17
- examine_image(image, "gravity-%s-" % gravity)
18
- end
19
- end
20
- end
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ImageVise::EllipseStencil do
4
- it 'applies the circle stencil' do
5
- image = Magick::Image.read(test_image_path)[0]
6
- stencil = described_class.new
7
- stencil.apply!(image)
8
- examine_image(image, "circle-stencil")
9
- end
10
-
11
- it 'applies the circle stencil to a png with transparency' do
12
- png_transparent_path = File.expand_path(__dir__ + '/../waterside_magic_hour_transp.png')
13
- image = Magick::Image.read(png_transparent_path)[0]
14
- stencil = described_class.new
15
- stencil.apply!(image)
16
- examine_image(image, "circle-stencil-transparent-bg")
17
- end
18
-
19
- end
@@ -1,48 +0,0 @@
1
- require_relative '../spec_helper'
2
-
3
- describe ImageVise::FetcherFile do
4
- it 'is a class (can be inherited from)' do
5
- expect(ImageVise::FetcherFile).to be_kind_of(Class)
6
- end
7
-
8
- it 'is registered as a fetcher for file://' do
9
- expect(ImageVise.fetcher_for('file')).to eq(ImageVise::FetcherFile)
10
- end
11
-
12
- it 'returns a Tempfile containing this test suite' do
13
- path = File.expand_path(__FILE__)
14
- ruby_files_in_this_directory = __dir__ + '/*.rb'
15
- ImageVise.allow_filesystem_source! ruby_files_in_this_directory
16
-
17
- uri = URI('file://' + URI.encode(path))
18
- fetched = ImageVise::FetcherFile.fetch_uri_to_tempfile(uri)
19
-
20
- expect(fetched).to be_kind_of(Tempfile)
21
- expect(fetched.size).to eq(File.size(__FILE__))
22
- expect(fetched.pos).to be_zero
23
- end
24
-
25
- it 'raises a meaningful exception if no file sources are permitted' do
26
- path = File.expand_path(__FILE__)
27
-
28
- ImageVise.deny_filesystem_sources!
29
-
30
- uri = URI('file://' + URI.encode(path))
31
- expect {
32
- ImageVise::FetcherFile.fetch_uri_to_tempfile(uri)
33
- }.to raise_error(ImageVise::FetcherFile::AccessError)
34
- end
35
-
36
- it 'raises a meaningful exception if this file is not permitted as source' do
37
- path = File.expand_path(__FILE__)
38
-
39
- text_files_in_this_directory = __dir__ + '/*.txt'
40
- ImageVise.deny_filesystem_sources!
41
- ImageVise.allow_filesystem_source! text_files_in_this_directory
42
-
43
- uri = URI('file://' + URI.encode(path))
44
- expect {
45
- ImageVise::FetcherFile.fetch_uri_to_tempfile(uri)
46
- }.to raise_error(ImageVise::FetcherFile::AccessError)
47
- end
48
- end
@@ -1,44 +0,0 @@
1
- require_relative '../spec_helper'
2
-
3
- describe ImageVise::FetcherHTTP do
4
- it 'is a class (can be inherited from)' do
5
- expect(ImageVise::FetcherHTTP).to be_kind_of(Class)
6
- end
7
-
8
- it 'is registered as a fetcher for http:// and https://' do
9
- expect(ImageVise.fetcher_for('http')).to eq(ImageVise::FetcherHTTP)
10
- expect(ImageVise.fetcher_for('https')).to eq(ImageVise::FetcherHTTP)
11
- end
12
-
13
- it 'raises an AccessError if the host of the URL is not on the whitelist' do
14
- uri = URI('https://wrong-origin.com/image.psd')
15
- expect {
16
- ImageVise::FetcherHTTP.fetch_uri_to_tempfile(uri)
17
- }.to raise_error(ImageVise::FetcherHTTP::AccessError, /is not permitted as source/)
18
- end
19
-
20
- it 'raises an UpstreamError if the upstream fetch returns an error-ish status code' do
21
- uri = URI('http://localhost:9001/forbidden')
22
- ImageVise.add_allowed_host! 'localhost'
23
-
24
- expect {
25
- ImageVise::FetcherHTTP.fetch_uri_to_tempfile(uri)
26
- }.to raise_error {|e|
27
- expect(e).to be_kind_of(ImageVise::FetcherHTTP::UpstreamError)
28
- expect(e.message).to include(uri.to_s)
29
- expect(e.message).to include('403')
30
- expect(e.http_status).to eq(403)
31
- }
32
- end
33
-
34
- it 'fetches the image into a Tempfile' do
35
- uri = URI(public_url_psd)
36
- ImageVise.add_allowed_host! 'localhost'
37
-
38
- result = ImageVise::FetcherHTTP.fetch_uri_to_tempfile(uri)
39
-
40
- expect(result).to be_kind_of(Tempfile)
41
- expect(result.size).to be_nonzero
42
- expect(result.pos).to be_zero
43
- end
44
- end
@@ -1,45 +0,0 @@
1
- require_relative '../spec_helper'
2
-
3
- describe ImageVise::FileResponse do
4
- it 'reads the file in binary mode, closes and unlinks the tempfile when close() is called' do
5
- random_data = SecureRandom.random_bytes(1024 * 2048)
6
- f = Tempfile.new("experiment")
7
- f.binmode
8
- f << random_data
9
-
10
- response = described_class.new(f)
11
- readback = ''.encode(Encoding::BINARY)
12
- response.each do | chunk |
13
- expect(chunk.encoding).to eq(Encoding::BINARY)
14
- readback << chunk
15
- end
16
-
17
- response.close
18
-
19
- expect(readback).to eq(random_data)
20
- expect(f).to be_closed
21
- expect(f.path).to be_nil
22
- end
23
-
24
- it 'only asks for the path of the tempfile and uses a separate file descriptor' do
25
- f = Tempfile.new("experiment")
26
- f.binmode
27
- f << SecureRandom.random_bytes(2048)
28
- f.flush
29
-
30
- # Use a double so that all the methods except the ones we mock raise an assertion
31
- double = double(path: f.path)
32
- expect(double).to receive(:flush)
33
-
34
- read_from_response = ''.encode(Encoding::BINARY)
35
- response = described_class.new(double)
36
- response.each{|b| read_from_response << b }
37
-
38
- f.rewind
39
-
40
- expect(f.read).to eq(read_from_response)
41
-
42
- f.close
43
- f.unlink
44
- end
45
- end
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ImageVise::FitCrop do
4
- it 'refuses invalid arguments' do
5
- expect { described_class.new(width: 0, height: -1, gravity: '') }.to raise_error(ArgumentError)
6
- end
7
-
8
- it 'applies the crop with different gravities' do
9
- %w( s sw se n ne nw c).each do |gravity|
10
- image = Magick::Image.read(test_image_path)[0]
11
- crop = described_class.new(width: 120, height: 220, gravity: gravity)
12
-
13
- crop.apply!(image)
14
-
15
- expect(image.columns).to eq(120)
16
- expect(image.rows).to eq(220)
17
- examine_image(image, "gravity-%s-" % gravity)
18
- end
19
- end
20
- end