resizing 1.2.1 → 1.3.1
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.
- checksums.yaml +4 -4
- data/.devcontainer/Dockerfile +73 -0
- data/.devcontainer/compose.yaml +58 -0
- data/.devcontainer/devcontainer-lock.json +9 -0
- data/.devcontainer/devcontainer.json +32 -0
- data/.devcontainer/post-create.sh +41 -0
- data/.github/copilot-instructions.md +1 -0
- data/.github/labeler.yml +28 -0
- data/.github/release.yml +35 -0
- data/.github/workflows/labeler.yml +20 -0
- data/.github/workflows/lint.yml +37 -0
- data/.github/workflows/test.yml +16 -9
- data/.gitignore +6 -0
- data/AGENTS.md +1 -0
- data/CHANGELOG.md +3 -0
- data/CLAUDE.md +68 -0
- data/Gemfile +9 -3
- data/README.md +114 -2
- data/Rakefile +5 -7
- data/bin/setup +3 -0
- data/git-hooks/pre-push +6 -0
- data/git-hooks/pre-push-ruby.sh +48 -0
- data/lib/resizing/carrier_wave/callback_file.rb +88 -0
- data/lib/resizing/carrier_wave/storage/file.rb +120 -47
- data/lib/resizing/carrier_wave/storage/remote.rb +7 -3
- data/lib/resizing/carrier_wave.rb +51 -7
- data/lib/resizing/client.rb +0 -1
- data/lib/resizing/configurable.rb +1 -1
- data/lib/resizing/configuration.rb +40 -10
- data/lib/resizing/mock_client.rb +23 -7
- data/lib/resizing/public_id.rb +3 -2
- data/lib/resizing/version.rb +1 -1
- data/lib/resizing.rb +0 -1
- data/resizing.gemspec +3 -3
- data/test/resizing/carrier_wave/storage/file_test.rb +455 -9
- data/test/resizing/carrier_wave/storage/remote_test.rb +91 -9
- data/test/resizing/carrier_wave_cache_callbacks_test.rb +224 -0
- data/test/resizing/carrier_wave_callback_file_test.rb +77 -0
- data/test/resizing/carrier_wave_test.rb +477 -23
- data/test/resizing/carrier_wave_uploader_test.rb +211 -0
- data/test/resizing/client_test.rb +324 -25
- data/test/resizing/configuration_test.rb +235 -10
- data/test/resizing/http_clientable_test.rb +27 -0
- data/test/resizing/mock_client_test.rb +111 -1
- data/test/resizing/public_id_test.rb +96 -0
- data/test/resizing_module_test.rb +110 -0
- data/test/resizing_test.rb +8 -0
- data/test/test_helper.rb +358 -11
- data/test/vcr/carrier_wave_test/update_image.yml +63 -0
- metadata +35 -10
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
module Resizing
|
|
6
|
+
# Resizing::CarrierWave を include したアップローダ単体の挙動をテストする
|
|
7
|
+
# (モデルの保存・削除を伴う結合テストは carrier_wave_test.rb を参照)
|
|
8
|
+
class CarrierWaveUploaderTest < Minitest::Test
|
|
9
|
+
include VCRRequestAssertions
|
|
10
|
+
include ResizingTestConfiguration
|
|
11
|
+
|
|
12
|
+
IDENTIFIER = ResizingTestConfiguration::UPLOADED_IDENTIFIER
|
|
13
|
+
|
|
14
|
+
class TransformationUploader < ::CarrierWave::Uploader::Base
|
|
15
|
+
include Resizing::CarrierWave
|
|
16
|
+
|
|
17
|
+
process resize_to_fit: [100, 200]
|
|
18
|
+
process transformation: { quality: 80, fetch_format: 'webp' }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class FormatOverridesFetchFormatUploader < ::CarrierWave::Uploader::Base
|
|
22
|
+
include Resizing::CarrierWave
|
|
23
|
+
|
|
24
|
+
process transformation: { fetch_format: 'webp', format: 'png' }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class UnsupportedProcessorUploader < ::CarrierWave::Uploader::Base
|
|
28
|
+
include Resizing::CarrierWave
|
|
29
|
+
|
|
30
|
+
process convert: 'png'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class NoProcessorUploader < ::CarrierWave::Uploader::Base
|
|
34
|
+
include Resizing::CarrierWave
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def setup
|
|
38
|
+
configure_resizing
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def teardown
|
|
42
|
+
# NOP
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def model_with_image(model_class = TestModel, identifier = IDENTIFIER)
|
|
46
|
+
model = model_class.new
|
|
47
|
+
model.send(:write_attribute, :resizing_picture, identifier)
|
|
48
|
+
model
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# ============================================================
|
|
52
|
+
# include 時の設定
|
|
53
|
+
# ============================================================
|
|
54
|
+
|
|
55
|
+
def test_including_module_sets_remote_storage
|
|
56
|
+
assert_equal Resizing::CarrierWave::Storage::Remote, NoProcessorUploader.storage
|
|
57
|
+
assert_instance_of Resizing::CarrierWave::Storage::Remote, NoProcessorUploader.new.send(:storage)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_railtie_is_defined
|
|
61
|
+
assert Resizing::CarrierWave::Railtie < ::Rails::Railtie
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# ============================================================
|
|
65
|
+
# transform_string
|
|
66
|
+
# ============================================================
|
|
67
|
+
|
|
68
|
+
def test_transform_string_for_resize_to_limit_without_height
|
|
69
|
+
assert_equal 'c_limit,w_1000', ResizingUploader.new.transform_string
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_transform_string_for_version_with_resize_to_fill
|
|
73
|
+
assert_equal 'c_fill,w_40,h_40', TestModel.new.resizing_picture.versions[:small].transform_string
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_transform_string_joins_multiple_processors_with_slash
|
|
77
|
+
assert_equal 'c_fit,w_100,h_200/q_80,f_webp', TransformationUploader.new.transform_string
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_transform_string_format_takes_precedence_over_fetch_format
|
|
81
|
+
assert_equal 'f_png', FormatOverridesFetchFormatUploader.new.transform_string
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def test_transform_string_is_empty_without_processors
|
|
85
|
+
assert_equal '', NoProcessorUploader.new.transform_string
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_transform_string_raises_for_unsupported_processor
|
|
89
|
+
error = assert_raises(NotImplementedError) { UnsupportedProcessorUploader.new.transform_string }
|
|
90
|
+
assert_includes error.message, 'convert'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# ============================================================
|
|
94
|
+
# url
|
|
95
|
+
# ============================================================
|
|
96
|
+
|
|
97
|
+
def test_url_is_built_from_configured_image_host_and_column_value
|
|
98
|
+
model = model_with_image
|
|
99
|
+
|
|
100
|
+
assert_equal "http://192.168.56.101:5000#{IDENTIFIER}/", model.resizing_picture.url
|
|
101
|
+
|
|
102
|
+
# image_host を差し替えると URL も追従する (保存済みカラム値にはホストを含まない)
|
|
103
|
+
configure_resizing(image_host: 'https://cdn.example.com')
|
|
104
|
+
assert_equal "https://cdn.example.com#{IDENTIFIER}/", model.resizing_picture.url
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def test_url_with_version_appends_transform_string
|
|
108
|
+
model = model_with_image
|
|
109
|
+
|
|
110
|
+
assert_equal "http://192.168.56.101:5000#{IDENTIFIER}/c_fill,w_40,h_40", model.resizing_picture.url(:small)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def test_url_accepts_string_version_name
|
|
114
|
+
model = model_with_image
|
|
115
|
+
|
|
116
|
+
assert_equal model.resizing_picture.url(:small), model.resizing_picture.url('small')
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_url_raises_for_unknown_version
|
|
120
|
+
model = model_with_image
|
|
121
|
+
|
|
122
|
+
error = assert_raises(RuntimeError) { model.resizing_picture.url(:nope) }
|
|
123
|
+
assert_includes error.message, 'nope'
|
|
124
|
+
assert_includes error.message, 'small'
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def test_url_returns_default_url_when_column_is_blank
|
|
128
|
+
assert_nil TestModel.new.resizing_picture.url
|
|
129
|
+
assert_equal 'http://example.com/test.jpg', TestModelWithDefaultURL.new.resizing_picture.url
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def test_url_ignores_version_when_column_is_blank
|
|
133
|
+
# カラムが空なら version 指定があっても default_url を返す
|
|
134
|
+
assert_nil TestModel.new.resizing_picture.url(:small)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def test_model_url_helper_delegates_to_uploader_url
|
|
138
|
+
model = model_with_image
|
|
139
|
+
|
|
140
|
+
assert_equal model.resizing_picture.url, model.resizing_picture_url
|
|
141
|
+
assert_equal model.resizing_picture.url(:small), model.resizing_picture_url(:small)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# ============================================================
|
|
145
|
+
# identifier / filename / file
|
|
146
|
+
# ============================================================
|
|
147
|
+
|
|
148
|
+
def test_filename_and_identifier_return_column_value
|
|
149
|
+
model = model_with_image
|
|
150
|
+
|
|
151
|
+
assert_equal IDENTIFIER, model.resizing_picture.filename
|
|
152
|
+
assert_equal IDENTIFIER, model.resizing_picture.identifier
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def test_file_reflects_column_value
|
|
156
|
+
model = model_with_image
|
|
157
|
+
file = model.resizing_picture.file
|
|
158
|
+
|
|
159
|
+
assert_instance_of Resizing::CarrierWave::Storage::File, file
|
|
160
|
+
assert_equal IDENTIFIER, file.public_id.to_s
|
|
161
|
+
assert_equal IDENTIFIER, file.path
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_uploader_is_present_when_column_has_value
|
|
165
|
+
model = model_with_image
|
|
166
|
+
|
|
167
|
+
assert model.resizing_picture.present?
|
|
168
|
+
refute model.resizing_picture.blank?
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# ============================================================
|
|
172
|
+
# cache! / store_versions! / remove_versions! / rename
|
|
173
|
+
# ============================================================
|
|
174
|
+
|
|
175
|
+
def test_cache_with_nil_does_nothing
|
|
176
|
+
uploader = TestModel.new.resizing_picture
|
|
177
|
+
|
|
178
|
+
assert_vcr_no_requests 'carrier_wave_test/save' do
|
|
179
|
+
assert_nil uploader.cache!(nil)
|
|
180
|
+
end
|
|
181
|
+
assert_nil uploader.file
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def test_store_versions_and_remove_versions_are_noop
|
|
185
|
+
uploader = TestModel.new.resizing_picture
|
|
186
|
+
|
|
187
|
+
assert_nil uploader.store_versions!
|
|
188
|
+
assert_nil uploader.remove_versions!
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def test_rename_raises_not_implemented_error
|
|
192
|
+
assert_raises(NotImplementedError) { TestModel.new.resizing_picture.rename }
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# ============================================================
|
|
196
|
+
# format
|
|
197
|
+
# ============================================================
|
|
198
|
+
|
|
199
|
+
def test_format_related_methods_default_to_nil
|
|
200
|
+
uploader = TestModel.new.resizing_picture
|
|
201
|
+
|
|
202
|
+
assert_nil uploader.requested_format
|
|
203
|
+
assert_nil uploader.default_format
|
|
204
|
+
assert_nil uploader.format
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def test_format_uses_overridden_default_format
|
|
208
|
+
assert_equal 'jpg', TestJPGModel.new.resizing_picture.format
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
@@ -4,23 +4,14 @@ require 'test_helper'
|
|
|
4
4
|
|
|
5
5
|
module Resizing
|
|
6
6
|
class ClientTest < Minitest::Test
|
|
7
|
-
|
|
8
|
-
@configuration_template = {
|
|
9
|
-
image_host: 'http://192.168.56.101:5000',
|
|
10
|
-
video_host: 'http://192.168.56.101:5000',
|
|
11
|
-
project_id: 'e06e710d-f026-4dcf-b2c0-eab0de8bb83f',
|
|
12
|
-
secret_token: 'ewbym2r1pk49x1d2lxdbiiavnqp25j2kh00hsg3koy0ppm620x5mhlmgl3rq5ci8',
|
|
13
|
-
open_timeout: 10,
|
|
14
|
-
response_timeout: 20
|
|
15
|
-
}
|
|
16
|
-
end
|
|
7
|
+
include ResizingTestConfiguration
|
|
17
8
|
|
|
18
9
|
def teardown
|
|
19
10
|
# NOP
|
|
20
11
|
end
|
|
21
12
|
|
|
22
13
|
def test_is_initialized
|
|
23
|
-
Resizing.configure =
|
|
14
|
+
Resizing.configure = configuration_template
|
|
24
15
|
|
|
25
16
|
client = Resizing::Client.new
|
|
26
17
|
assert(!client.config.nil?)
|
|
@@ -28,14 +19,14 @@ module Resizing
|
|
|
28
19
|
end
|
|
29
20
|
|
|
30
21
|
def test_is_initialized_with_configuration
|
|
31
|
-
config = Resizing::Configuration.new(
|
|
22
|
+
config = Resizing::Configuration.new(configuration_template)
|
|
32
23
|
client = Resizing::Client.new(config)
|
|
33
24
|
assert(!client.config.nil?)
|
|
34
25
|
assert_equal(client.config, config)
|
|
35
26
|
end
|
|
36
27
|
|
|
37
28
|
def test_is_postable_with_filename
|
|
38
|
-
Resizing.configure =
|
|
29
|
+
Resizing.configure = configuration_template
|
|
39
30
|
|
|
40
31
|
client = Resizing::Client.new
|
|
41
32
|
VCR.use_cassette 'client/post', record: :once do
|
|
@@ -53,7 +44,7 @@ module Resizing
|
|
|
53
44
|
end
|
|
54
45
|
|
|
55
46
|
def test_is_unpostable_with_filename
|
|
56
|
-
Resizing.configure =
|
|
47
|
+
Resizing.configure = configuration_template
|
|
57
48
|
|
|
58
49
|
client = Resizing::Client.new
|
|
59
50
|
VCR.use_cassette 'client/post', record: :once do
|
|
@@ -64,7 +55,7 @@ module Resizing
|
|
|
64
55
|
end
|
|
65
56
|
|
|
66
57
|
def test_is_postable_with_file
|
|
67
|
-
Resizing.configure =
|
|
58
|
+
Resizing.configure = configuration_template
|
|
68
59
|
|
|
69
60
|
client = Resizing::Client.new
|
|
70
61
|
VCR.use_cassette 'client/post', record: :once do
|
|
@@ -83,7 +74,7 @@ module Resizing
|
|
|
83
74
|
end
|
|
84
75
|
|
|
85
76
|
def test_is_timeout_with_post_method
|
|
86
|
-
Resizing.configure =
|
|
77
|
+
Resizing.configure = configuration_template.merge(project_id: 'timeout_project_id')
|
|
87
78
|
|
|
88
79
|
client = Resizing::Client.new
|
|
89
80
|
f = File.open('test/data/images/sample1.jpg', 'r')
|
|
@@ -93,7 +84,7 @@ module Resizing
|
|
|
93
84
|
end
|
|
94
85
|
|
|
95
86
|
def test_is_putable_file
|
|
96
|
-
Resizing.configure =
|
|
87
|
+
Resizing.configure = configuration_template
|
|
97
88
|
|
|
98
89
|
client = Resizing::Client.new
|
|
99
90
|
VCR.use_cassette 'client/put', record: :once do
|
|
@@ -115,7 +106,7 @@ module Resizing
|
|
|
115
106
|
end
|
|
116
107
|
|
|
117
108
|
def test_is_timeout_with_put_method
|
|
118
|
-
Resizing.configure =
|
|
109
|
+
Resizing.configure = configuration_template.merge(project_id: 'timeout_project_id')
|
|
119
110
|
|
|
120
111
|
client = Resizing::Client.new
|
|
121
112
|
name = 'AWEaewfAreaweFAFASfwe'
|
|
@@ -127,7 +118,7 @@ module Resizing
|
|
|
127
118
|
end
|
|
128
119
|
|
|
129
120
|
def test_raise_error
|
|
130
|
-
Resizing.configure =
|
|
121
|
+
Resizing.configure = configuration_template
|
|
131
122
|
|
|
132
123
|
client = Resizing::Client.new
|
|
133
124
|
VCR.use_cassette 'client/error', record: :once do
|
|
@@ -139,7 +130,7 @@ module Resizing
|
|
|
139
130
|
end
|
|
140
131
|
|
|
141
132
|
def test_handleable_response_body_from_resizing
|
|
142
|
-
Resizing.configure =
|
|
133
|
+
Resizing.configure = configuration_template
|
|
143
134
|
|
|
144
135
|
client = Resizing::Client.new
|
|
145
136
|
VCR.use_cassette 'client/error', record: :once do
|
|
@@ -159,7 +150,7 @@ module Resizing
|
|
|
159
150
|
def test_get_the_metadata
|
|
160
151
|
# TODO
|
|
161
152
|
|
|
162
|
-
Resizing.configure =
|
|
153
|
+
Resizing.configure = configuration_template
|
|
163
154
|
|
|
164
155
|
client = Resizing::Client.new
|
|
165
156
|
VCR.use_cassette 'client/metadata', record: :once do
|
|
@@ -202,7 +193,7 @@ module Resizing
|
|
|
202
193
|
end
|
|
203
194
|
|
|
204
195
|
def test_get_raises_not_implemented_error
|
|
205
|
-
Resizing.configure =
|
|
196
|
+
Resizing.configure = configuration_template
|
|
206
197
|
client = Resizing::Client.new
|
|
207
198
|
|
|
208
199
|
assert_raises NotImplementedError do
|
|
@@ -211,7 +202,7 @@ module Resizing
|
|
|
211
202
|
end
|
|
212
203
|
|
|
213
204
|
def test_post_raises_error_without_content_type
|
|
214
|
-
Resizing.configure =
|
|
205
|
+
Resizing.configure = configuration_template
|
|
215
206
|
client = Resizing::Client.new
|
|
216
207
|
|
|
217
208
|
assert_raises ArgumentError do
|
|
@@ -220,7 +211,7 @@ module Resizing
|
|
|
220
211
|
end
|
|
221
212
|
|
|
222
213
|
def test_post_raises_error_with_invalid_io
|
|
223
|
-
Resizing.configure =
|
|
214
|
+
Resizing.configure = configuration_template
|
|
224
215
|
client = Resizing::Client.new
|
|
225
216
|
|
|
226
217
|
assert_raises ArgumentError do
|
|
@@ -229,12 +220,320 @@ module Resizing
|
|
|
229
220
|
end
|
|
230
221
|
|
|
231
222
|
def test_put_raises_error_without_content_type
|
|
232
|
-
Resizing.configure =
|
|
223
|
+
Resizing.configure = configuration_template
|
|
233
224
|
client = Resizing::Client.new
|
|
234
225
|
|
|
235
226
|
assert_raises ArgumentError do
|
|
236
227
|
client.put('image_id', 'test/data/images/sample1.jpg', {})
|
|
237
228
|
end
|
|
238
229
|
end
|
|
230
|
+
|
|
231
|
+
# ============================================================
|
|
232
|
+
# 偽 HTTP クライアントを使ったリクエスト内容・レスポンス処理のテスト
|
|
233
|
+
# VCR カセットでは表現しづらい (URL, ヘッダ, multipart パラメータ, 異常系ステータス) を検証する
|
|
234
|
+
# ============================================================
|
|
235
|
+
|
|
236
|
+
# Faraday::Connection の代わりに使う偽クライアント
|
|
237
|
+
# 発行されたリクエスト (メソッド, URL, パラメータ, ヘッダ) を記録し、あらかじめ設定したレスポンスを返す
|
|
238
|
+
class FakeHttpClient
|
|
239
|
+
FakeRequest = Struct.new(:headers)
|
|
240
|
+
FakeResponse = Struct.new(:status, :body)
|
|
241
|
+
|
|
242
|
+
attr_reader :requests
|
|
243
|
+
|
|
244
|
+
def initialize(status: 200, body: '{}', respond_with_nil: false)
|
|
245
|
+
@response = respond_with_nil ? nil : FakeResponse.new(status, body)
|
|
246
|
+
@requests = []
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
%i[post put delete get].each do |verb|
|
|
250
|
+
define_method(verb) do |url, params = nil, &block|
|
|
251
|
+
request = FakeRequest.new({})
|
|
252
|
+
block&.call(request)
|
|
253
|
+
@requests << { method: verb, url: url, params: params, headers: request.headers }
|
|
254
|
+
@response
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def last_request
|
|
259
|
+
@requests.last
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def client_with_fake_http(**fake_options)
|
|
264
|
+
Resizing.configure = configuration_template
|
|
265
|
+
client = Resizing::Client.new
|
|
266
|
+
fake = FakeHttpClient.new(**fake_options)
|
|
267
|
+
client.instance_variable_set(:@http_client, fake)
|
|
268
|
+
[client, fake]
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def base_url
|
|
272
|
+
"#{configuration_template[:image_host]}/projects/#{configuration_template[:project_id]}/upload/images"
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def sample_path
|
|
276
|
+
'test/data/images/sample1.jpg'
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def not_found_body(image_id)
|
|
280
|
+
%({"error":"ActiveRecord::RecordNotFound","message":"Upload::Image##{image_id} not found(no record)"})
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def forbidden_body
|
|
284
|
+
'{"error":"AuthenticatableSecretToken::SecretTokenError","message":"invalid token is found"}'
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def test_post_sends_multipart_image_to_upload_url_with_auth_header
|
|
288
|
+
client, fake = client_with_fake_http(body: '{"id":"posted"}')
|
|
289
|
+
|
|
290
|
+
Timecop.freeze do
|
|
291
|
+
result = client.post(sample_path, content_type: 'image/jpeg')
|
|
292
|
+
|
|
293
|
+
request = fake.last_request
|
|
294
|
+
assert_equal :post, request[:method]
|
|
295
|
+
assert_equal "#{base_url}/", request[:url]
|
|
296
|
+
assert_equal client.config.generate_auth_header, request[:headers]['X-ResizingToken']
|
|
297
|
+
|
|
298
|
+
part = request[:params][:image]
|
|
299
|
+
assert_instance_of Faraday::Multipart::FilePart, part
|
|
300
|
+
assert_equal 'image/jpeg', part.content_type
|
|
301
|
+
assert_equal 'sample1.jpg', part.original_filename
|
|
302
|
+
|
|
303
|
+
assert_equal({ 'id' => 'posted' }, result)
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def test_post_uses_filename_option_over_path_basename
|
|
308
|
+
client, fake = client_with_fake_http
|
|
309
|
+
|
|
310
|
+
client.post(sample_path, content_type: 'image/jpeg', filename: 'renamed.jpg')
|
|
311
|
+
|
|
312
|
+
assert_equal 'renamed.jpg', fake.last_request[:params][:image].original_filename
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def test_post_accepts_io_like_object
|
|
316
|
+
client, fake = client_with_fake_http
|
|
317
|
+
io = StringIO.new(File.binread(sample_path))
|
|
318
|
+
|
|
319
|
+
client.post(io, content_type: 'image/png', filename: 'from_io.png')
|
|
320
|
+
|
|
321
|
+
part = fake.last_request[:params][:image]
|
|
322
|
+
assert_same io, part.io
|
|
323
|
+
assert_equal 'image/png', part.content_type
|
|
324
|
+
assert_equal 'from_io.png', part.original_filename
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def test_post_accepts_created_status
|
|
328
|
+
client, = client_with_fake_http(status: 201, body: '{"id":"created"}')
|
|
329
|
+
|
|
330
|
+
assert_equal({ 'id' => 'created' }, client.post(sample_path, content_type: 'image/jpeg'))
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def test_post_raises_api_error_with_server_message_on_error_status
|
|
334
|
+
client, = client_with_fake_http(status: 403, body: forbidden_body)
|
|
335
|
+
|
|
336
|
+
error = assert_raises(Resizing::APIError) { client.post(sample_path, content_type: 'image/jpeg') }
|
|
337
|
+
|
|
338
|
+
assert_equal 'invalid token is found', error.message
|
|
339
|
+
assert_equal JSON.parse(forbidden_body), error.decoded_body
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def test_post_raises_api_error_on_not_found
|
|
343
|
+
client, = client_with_fake_http(status: 404, body: not_found_body('x'))
|
|
344
|
+
|
|
345
|
+
assert_raises(Resizing::APIError) { client.post(sample_path, content_type: 'image/jpeg') }
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def test_post_raises_api_error_with_status_code_when_body_is_not_json
|
|
349
|
+
client, = client_with_fake_http(status: 502, body: '<html>Bad Gateway</html>')
|
|
350
|
+
|
|
351
|
+
error = assert_raises(Resizing::APIError) { client.post(sample_path, content_type: 'image/jpeg') }
|
|
352
|
+
|
|
353
|
+
assert_equal 'invalid http status code 502', error.message
|
|
354
|
+
assert_equal({}, error.decoded_body)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def test_post_raises_api_error_when_response_is_nil
|
|
358
|
+
client, = client_with_fake_http(respond_with_nil: true)
|
|
359
|
+
|
|
360
|
+
error = assert_raises(Resizing::APIError) { client.post(sample_path, content_type: 'image/jpeg') }
|
|
361
|
+
assert_equal 'No response is returned', error.message
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def test_put_sends_multipart_image_to_image_url_with_auth_header
|
|
365
|
+
client, fake = client_with_fake_http(body: '{"id":"img-1"}')
|
|
366
|
+
|
|
367
|
+
result = client.put('img-1', sample_path, content_type: 'image/jpeg')
|
|
368
|
+
|
|
369
|
+
request = fake.last_request
|
|
370
|
+
assert_equal :put, request[:method]
|
|
371
|
+
assert_equal "#{base_url}/img-1", request[:url]
|
|
372
|
+
assert_match(/\Av1,\d+,[0-9a-f]{64}\z/, request[:headers]['X-ResizingToken'])
|
|
373
|
+
part = request[:params][:image]
|
|
374
|
+
assert_instance_of Faraday::Multipart::FilePart, part
|
|
375
|
+
assert_equal 'image/jpeg', part.content_type
|
|
376
|
+
assert_equal 'sample1.jpg', part.original_filename
|
|
377
|
+
assert_equal({ 'id' => 'img-1' }, result)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def test_put_raises_api_error_on_error_status
|
|
381
|
+
client, = client_with_fake_http(status: 403, body: forbidden_body)
|
|
382
|
+
|
|
383
|
+
error = assert_raises(Resizing::APIError) { client.put('img-1', sample_path, content_type: 'image/jpeg') }
|
|
384
|
+
assert_equal 'invalid token is found', error.message
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def test_put_raises_error_with_invalid_io
|
|
388
|
+
Resizing.configure = configuration_template
|
|
389
|
+
client = Resizing::Client.new
|
|
390
|
+
|
|
391
|
+
assert_raises ArgumentError do
|
|
392
|
+
client.put('image_id', 12_345, content_type: 'image/jpeg')
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def test_delete_sends_delete_request_to_image_url_with_auth_header
|
|
397
|
+
client, fake = client_with_fake_http(body: '{"id":"img-1"}')
|
|
398
|
+
|
|
399
|
+
result = client.delete('img-1')
|
|
400
|
+
|
|
401
|
+
request = fake.last_request
|
|
402
|
+
assert_equal :delete, request[:method]
|
|
403
|
+
assert_equal "#{base_url}/img-1", request[:url]
|
|
404
|
+
assert_match(/\Av1,\d+,[0-9a-f]{64}\z/, request[:headers]['X-ResizingToken'])
|
|
405
|
+
assert_equal({ 'id' => 'img-1' }, result)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def test_delete_returns_error_body_without_raising_on_not_found
|
|
409
|
+
client, = client_with_fake_http(status: 404, body: not_found_body('img-1'))
|
|
410
|
+
|
|
411
|
+
result = client.delete('img-1')
|
|
412
|
+
|
|
413
|
+
assert_equal 'ActiveRecord::RecordNotFound', result['error']
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def test_delete_raises_api_error_on_other_error_status
|
|
417
|
+
client, = client_with_fake_http(status: 403, body: forbidden_body)
|
|
418
|
+
|
|
419
|
+
error = assert_raises(Resizing::APIError) { client.delete('img-1') }
|
|
420
|
+
assert_equal 'invalid token is found', error.message
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def test_delete_raises_api_error_when_response_is_nil
|
|
424
|
+
client, = client_with_fake_http(respond_with_nil: true)
|
|
425
|
+
|
|
426
|
+
assert_raises(Resizing::APIError) { client.delete('img-1') }
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def test_metadata_sends_get_request_to_metadata_url_with_auth_header
|
|
430
|
+
client, fake = client_with_fake_http(body: '{"id":"img-1","width":100}')
|
|
431
|
+
|
|
432
|
+
result = client.metadata('img-1')
|
|
433
|
+
|
|
434
|
+
request = fake.last_request
|
|
435
|
+
assert_equal :get, request[:method]
|
|
436
|
+
assert_equal "#{base_url}/img-1/metadata", request[:url]
|
|
437
|
+
assert_match(/\Av1,\d+,[0-9a-f]{64}\z/, request[:headers]['X-ResizingToken'])
|
|
438
|
+
assert_equal({ 'id' => 'img-1', 'width' => 100 }, result)
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def test_metadata_returns_error_body_without_raising_on_not_found_by_default
|
|
442
|
+
client, = client_with_fake_http(status: 404, body: not_found_body('img-1'))
|
|
443
|
+
|
|
444
|
+
result = client.metadata('img-1')
|
|
445
|
+
|
|
446
|
+
assert_equal 'ActiveRecord::RecordNotFound', result['error']
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def test_metadata_raises_api_error_on_not_found_when_requested
|
|
450
|
+
client, = client_with_fake_http(status: 404, body: not_found_body('img-1'))
|
|
451
|
+
|
|
452
|
+
error = assert_raises(Resizing::APIError) { client.metadata('img-1', when_not_found: :raise) }
|
|
453
|
+
|
|
454
|
+
assert_equal 'Upload::Image#img-1 not found(no record)', error.message
|
|
455
|
+
assert_equal 'ActiveRecord::RecordNotFound', error.decoded_body['error']
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
def test_metadata_raises_api_error_on_other_error_status
|
|
459
|
+
client, = client_with_fake_http(status: 500, body: 'Internal Server Error')
|
|
460
|
+
|
|
461
|
+
error = assert_raises(Resizing::APIError) { client.metadata('img-1') }
|
|
462
|
+
assert_equal 'invalid http status code 500', error.message
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def test_metadata_raises_api_error_when_response_is_nil
|
|
466
|
+
client, = client_with_fake_http(respond_with_nil: true)
|
|
467
|
+
|
|
468
|
+
assert_raises(Resizing::APIError) { client.metadata('img-1') }
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
# ============================================================
|
|
472
|
+
# VCR カセットを使った delete / timeout のテスト
|
|
473
|
+
# ============================================================
|
|
474
|
+
|
|
475
|
+
def test_is_deletable
|
|
476
|
+
# client/delete.yml は別プロジェクト ID で記録されている
|
|
477
|
+
Resizing.configure = configuration_template.merge(project_id: '098a2a0d-c387-4135-a071-1254d6d7e70a')
|
|
478
|
+
client = Resizing::Client.new
|
|
479
|
+
image_id = '28c49144-c00d-4cb5-8619-98ce95977b9c'
|
|
480
|
+
|
|
481
|
+
VCR.use_cassette 'client/delete', record: :none do
|
|
482
|
+
r = client.delete(image_id)
|
|
483
|
+
|
|
484
|
+
assert_equal image_id, r['id']
|
|
485
|
+
assert_equal '098a2a0d-c387-4135-a071-1254d6d7e70a', r['project_id']
|
|
486
|
+
assert_equal(
|
|
487
|
+
"/projects/098a2a0d-c387-4135-a071-1254d6d7e70a/upload/images/#{image_id}/v1Id850__tqNsnoGWWUibtIBZ5NgjV45M",
|
|
488
|
+
r['public_id']
|
|
489
|
+
)
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def test_is_timeout_with_delete_method
|
|
494
|
+
Resizing.configure = configuration_template.merge(project_id: 'timeout_project_id')
|
|
495
|
+
client = Resizing::Client.new
|
|
496
|
+
|
|
497
|
+
assert_raises Resizing::APIError do
|
|
498
|
+
client.delete('some_image_id')
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
def test_is_timeout_with_metadata_method
|
|
503
|
+
Resizing.configure = configuration_template.merge(project_id: 'timeout_project_id')
|
|
504
|
+
client = Resizing::Client.new
|
|
505
|
+
|
|
506
|
+
assert_raises Resizing::APIError do
|
|
507
|
+
client.metadata('some_image_id')
|
|
508
|
+
end
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
# ============================================================
|
|
512
|
+
# 設定の受け渡し
|
|
513
|
+
# ============================================================
|
|
514
|
+
|
|
515
|
+
def test_is_initialized_with_hash
|
|
516
|
+
client = Resizing::Client.new(configuration_template)
|
|
517
|
+
|
|
518
|
+
assert_equal Resizing::Configuration.new(configuration_template), client.config
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def test_each_client_instance_keeps_its_own_configuration
|
|
522
|
+
Resizing.configure = configuration_template
|
|
523
|
+
other = Resizing::Client.new(configuration_template.merge(project_id: 'other-project'))
|
|
524
|
+
|
|
525
|
+
assert_equal 'other-project', other.config.project_id
|
|
526
|
+
assert_equal configuration_template[:project_id], Resizing::Client.new.config.project_id
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def test_client_uses_configuration_at_instantiation
|
|
530
|
+
Resizing.configure = configuration_template
|
|
531
|
+
client = Resizing::Client.new
|
|
532
|
+
|
|
533
|
+
# インスタンス生成後にグローバル設定を差し替えても既存クライアントには影響しない
|
|
534
|
+
Resizing.configure = configuration_template.merge(project_id: 'replaced-project')
|
|
535
|
+
|
|
536
|
+
assert_equal configuration_template[:project_id], client.config.project_id
|
|
537
|
+
end
|
|
239
538
|
end
|
|
240
539
|
end
|