cloudinary 1.1.0 → 1.1.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/CHANGELOG.md +342 -142
- data/README.md +24 -7
- data/Rakefile +45 -19
- data/lib/cloudinary/carrier_wave/storage.rb +4 -1
- data/lib/cloudinary/helper.rb +2 -2
- data/lib/cloudinary/utils.rb +146 -30
- data/lib/cloudinary/version.rb +1 -1
- data/spec/spec_helper.rb +65 -6
- data/spec/utils_methods_spec.rb +3 -3
- data/spec/utils_spec.rb +437 -152
- data/spec/video_tag_spec.rb +1 -1
- data/spec/video_url_spec.rb +63 -22
- data/vendor/assets/html/cloudinary_cors.html +3 -7
- data/vendor/assets/javascripts/cloudinary/canvas-to-blob.min.js +1 -1
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +3482 -1001
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload-image.js +9 -3
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload-process.js +5 -2
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload-validate.js +6 -3
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +32 -15
- data/vendor/assets/javascripts/cloudinary/jquery.iframe-transport.js +5 -2
- data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +29 -15
- data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -0
- data/vendor/assets/javascripts/cloudinary/processing.js +1 -1
- metadata +4 -4
- data/vendor/assets/javascripts/cloudinary/load-image.min.js +0 -1
data/lib/cloudinary/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require 'rexml/parsers/ultralightparser'
|
3
3
|
require 'rspec/version'
|
4
|
+
require 'rest_client'
|
5
|
+
|
6
|
+
TEST_IMAGE_URL = "http://cloudinary.com/images/old_logo.png"
|
7
|
+
TEST_TAG = 'cloudinary_gem_test'
|
4
8
|
|
5
9
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
6
10
|
RSpec.configure do |config|
|
@@ -73,11 +77,66 @@ class TestTag
|
|
73
77
|
end
|
74
78
|
end
|
75
79
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
80
|
+
RSpec::Matchers.define :produce_url do |expected_url|
|
81
|
+
match do |params|
|
82
|
+
public_id, options = params
|
83
|
+
actual_options = options.clone
|
84
|
+
@url = Cloudinary::Utils.cloudinary_url(public_id, actual_options)
|
85
|
+
values_match? expected_url, @url
|
86
|
+
end
|
87
|
+
failure_message do |actual|
|
88
|
+
"expected #{actual} to\nproduce: #{expected_url}\nbut got: #{@url}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
RSpec::Matchers.define :mutate_options_to do |expected_options|
|
93
|
+
match do |params|
|
94
|
+
public_id, options = params
|
95
|
+
options = options.clone
|
96
|
+
Cloudinary::Utils.cloudinary_url(public_id, options)
|
97
|
+
@actual = options
|
98
|
+
values_match? expected_options, @actual
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
RSpec::Matchers.define :empty_options do
|
103
|
+
match do |params|
|
104
|
+
public_id, options = params
|
105
|
+
options = options.clone
|
106
|
+
Cloudinary::Utils.cloudinary_url(public_id, options)
|
107
|
+
options.empty?
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Verify that the given URL can be served by Cloudinary by fetching the resource from the server
|
112
|
+
RSpec::Matchers.define :be_served_by_cloudinary do
|
113
|
+
match do |url|
|
114
|
+
if url.is_a? Array
|
115
|
+
url = Cloudinary::Utils.cloudinary_url( url[0], url[1])
|
116
|
+
end
|
117
|
+
code = 0
|
118
|
+
@url = url
|
119
|
+
RestClient.get @url do |response, request, result|
|
120
|
+
@result = result
|
121
|
+
code = response.code
|
122
|
+
end
|
123
|
+
values_match? 200, code
|
124
|
+
end
|
125
|
+
|
126
|
+
failure_message do |actual|
|
127
|
+
if @result
|
128
|
+
"Couldn't serve #{actual}. #{@result["status"]}: #{@result["x-cld-error"]}"
|
129
|
+
else
|
130
|
+
"Couldn't serve #{actual}."
|
131
|
+
end
|
132
|
+
end
|
133
|
+
failure_message_when_negated do |actual|
|
134
|
+
if @result
|
135
|
+
"Expected #{@url} not to be served by cloudinary. #{@result["status"]}: #{@result["x-cld-error"]}"
|
136
|
+
else
|
137
|
+
"Expected #{@url} not to be served by cloudinary."
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
81
141
|
end
|
82
142
|
|
83
|
-
TEST_IMAGE_URL = "http://cloudinary.com/images/old_logo.png"
|
data/spec/utils_methods_spec.rb
CHANGED
@@ -7,12 +7,12 @@ include Cloudinary
|
|
7
7
|
describe Utils do
|
8
8
|
|
9
9
|
it 'should parse integer range values' do
|
10
|
-
expect(Utils.norm_range_value("200")).to eq( "200")
|
10
|
+
expect(Utils.instance_eval {norm_range_value("200")}).to eq( "200")
|
11
11
|
end
|
12
12
|
it "should parse float range values" do
|
13
|
-
expect(Utils.norm_range_value("200.0")).to eq("200.0"), "parse a float"
|
13
|
+
expect(Utils.instance_eval {norm_range_value("200.0")}).to eq("200.0"), "parse a float"
|
14
14
|
end
|
15
15
|
it "should parse a percent range value" do
|
16
|
-
expect(Utils.norm_range_value("20p")).to eq("20p")
|
16
|
+
expect(Utils.instance_eval {norm_range_value("20p")}).to eq("20p")
|
17
17
|
end
|
18
18
|
end
|
data/spec/utils_spec.rb
CHANGED
@@ -2,70 +2,94 @@ require 'spec_helper'
|
|
2
2
|
require 'cloudinary'
|
3
3
|
|
4
4
|
describe Cloudinary::Utils do
|
5
|
-
|
5
|
+
|
6
|
+
before :each do
|
6
7
|
Cloudinary.config do |config|
|
7
|
-
config.cloud_name = "
|
8
|
+
# config.cloud_name = "demo"
|
8
9
|
config.secure_distribution = nil
|
9
10
|
config.private_cdn = false
|
10
11
|
config.secure = false
|
11
12
|
config.cname = nil
|
12
13
|
config.cdn_subdomain = false
|
13
|
-
config.api_key = "1234"
|
14
|
-
config.api_secret = "b"
|
15
14
|
end
|
16
15
|
end
|
17
|
-
let(:
|
16
|
+
let(:cloud_name) {Cloudinary.config.cloud_name}
|
17
|
+
let(:root_path) { "http://res.cloudinary.com/#{cloud_name}" }
|
18
18
|
let(:upload_path) { "#{root_path}/image/upload" }
|
19
19
|
|
20
20
|
it "should use cloud_name from config" do
|
21
|
-
|
21
|
+
expect(["test", {}])
|
22
|
+
.to produce_url( "#{upload_path}/test")
|
23
|
+
.and empty_options
|
22
24
|
end
|
23
25
|
|
24
26
|
it "should allow overriding cloud_name in options" do
|
25
|
-
|
27
|
+
expect(["test", { :cloud_name => "test321" }])
|
28
|
+
.to produce_url("http://res.cloudinary.com/test321/image/upload/test")
|
29
|
+
.and empty_options
|
26
30
|
end
|
27
|
-
|
28
|
-
it "should use default secure distribution if secure=true" do
|
29
|
-
|
31
|
+
|
32
|
+
it "should use default secure distribution if secure=true" do
|
33
|
+
expect(["test",{:secure=>true}])
|
34
|
+
.to produce_url("https://res.cloudinary.com/#{cloud_name}/image/upload/test")
|
35
|
+
.and empty_options
|
30
36
|
end
|
31
37
|
|
32
|
-
it "should allow overriding secure distribution if secure=true" do
|
33
|
-
|
38
|
+
it "should allow overriding secure distribution if secure=true" do
|
39
|
+
expect(["test",{:secure=>true, :secure_distribution=>"something.else.com"}])
|
40
|
+
.to produce_url("https://something.else.com/#{cloud_name}/image/upload/test")
|
41
|
+
.and empty_options
|
34
42
|
end
|
35
43
|
|
36
44
|
it "should take secure distribution from config if secure=true" do
|
37
45
|
Cloudinary.config.secure_distribution = "config.secure.distribution.com"
|
38
|
-
|
46
|
+
expect(["test",{:secure=>true}])
|
47
|
+
.to produce_url("https://config.secure.distribution.com/#{cloud_name}/image/upload/test")
|
48
|
+
.and empty_options
|
39
49
|
end
|
40
50
|
|
41
51
|
it "should default to akamai if secure is given with private_cdn and no secure_distribution" do
|
42
|
-
|
52
|
+
expect(["test",{:secure=>true, :private_cdn=>true}])
|
53
|
+
.to produce_url("https://#{cloud_name}-res.cloudinary.com/image/upload/test")
|
54
|
+
.and empty_options
|
43
55
|
end
|
44
56
|
|
45
57
|
it "should not add cloud_name if secure private_cdn and secure non akamai secure_distribution" do
|
46
|
-
|
58
|
+
expect(["test",{:secure=>true, :private_cdn=>true, :secure_distribution=>"something.cloudfront.net"}])
|
59
|
+
.to produce_url("https://something.cloudfront.net/image/upload/test")
|
60
|
+
.and empty_options
|
47
61
|
end
|
48
62
|
|
49
63
|
it "should allow overriding private_cdn if private_cdn=true" do
|
50
|
-
|
64
|
+
expect(["test",{:private_cdn => true}])
|
65
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/image/upload/test")
|
66
|
+
.and empty_options
|
51
67
|
end
|
52
68
|
|
53
69
|
it "should allow overriding private_cdn if private_cdn=false" do
|
54
70
|
Cloudinary.config.private_cdn = true
|
55
|
-
|
71
|
+
expect(["test",{ :private_cdn => false }])
|
72
|
+
.to produce_url("#{upload_path}/test")
|
73
|
+
.and empty_options
|
56
74
|
end
|
57
75
|
|
58
76
|
it "should allow overriding cname if cname=example.com" do
|
59
|
-
|
77
|
+
expect(["test",{:cname => "example.com"}])
|
78
|
+
.to produce_url("http://example.com/#{cloud_name}/image/upload/test")
|
79
|
+
.and empty_options
|
60
80
|
end
|
61
81
|
|
62
82
|
it "should allow overriding cname if cname=false" do
|
63
83
|
Cloudinary.config.cname = "example.com"
|
64
|
-
|
84
|
+
expect(["test",{ :cname => false }])
|
85
|
+
.to produce_url("#{upload_path}/test")
|
86
|
+
.and empty_options
|
65
87
|
end
|
66
88
|
|
67
89
|
it "should use format from options" do
|
68
|
-
|
90
|
+
expect(["test",{ :format => :jpg }])
|
91
|
+
.to produce_url("#{upload_path}/test.jpg")
|
92
|
+
.and empty_options
|
69
93
|
end
|
70
94
|
|
71
95
|
it "should disallow url_suffix in shared distribution" do
|
@@ -81,42 +105,64 @@ describe Cloudinary::Utils do
|
|
81
105
|
expect{Cloudinary::Utils.cloudinary_url("test", {:url_suffix=>"hello.world", :private_cdn=>true})}.to raise_error(CloudinaryException)
|
82
106
|
end
|
83
107
|
|
84
|
-
it "should support url_suffix for private_cdn" do
|
85
|
-
|
86
|
-
|
108
|
+
it "should support url_suffix for private_cdn" do
|
109
|
+
expect(["test",{:url_suffix=>"hello", :private_cdn=>true}])
|
110
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/images/test/hello")
|
111
|
+
.and empty_options
|
112
|
+
expect(["test",{:url_suffix=>"hello", :angle=>0, :private_cdn=>true}])
|
113
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/images/a_0/test/hello")
|
114
|
+
.and empty_options
|
87
115
|
end
|
88
116
|
|
89
117
|
it "should put format after url_suffix" do
|
90
|
-
|
118
|
+
expect(["test",{:url_suffix=>"hello", :private_cdn=>true, :format=>"jpg"}])
|
119
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/images/test/hello.jpg")
|
120
|
+
.and empty_options
|
91
121
|
end
|
92
122
|
|
93
123
|
it "should not sign the url_suffix" do
|
94
124
|
expected_signture = Cloudinary::Utils.cloudinary_url("test", :format=>"jpg", :sign_url=>true).match(/s--[0-9A-Za-z_-]{8}--/).to_s
|
95
|
-
|
125
|
+
expect(["test",{:url_suffix=>"hello", :private_cdn=>true, :format=>"jpg", :sign_url=>true}])
|
126
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/images/#{expected_signture}/test/hello.jpg")
|
127
|
+
.and empty_options
|
96
128
|
|
97
129
|
expected_signture = Cloudinary::Utils.cloudinary_url("test", :format=>"jpg", :angle=>0, :sign_url=>true).match(/s--[0-9A-Za-z_-]{8}--/).to_s
|
98
|
-
|
130
|
+
expect(["test",{:url_suffix=>"hello", :private_cdn=>true, :format=>"jpg", :angle=>0, :sign_url=>true}])
|
131
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/images/#{expected_signture}/a_0/test/hello.jpg")
|
132
|
+
.and empty_options
|
99
133
|
end
|
100
134
|
|
101
|
-
it "should support url_suffix for raw uploads" do
|
102
|
-
|
135
|
+
it "should support url_suffix for raw uploads" do
|
136
|
+
expect(["test",{:url_suffix=>"hello", :private_cdn=>true, :resource_type=>:raw}])
|
137
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/files/test/hello")
|
138
|
+
.and empty_options
|
103
139
|
end
|
104
140
|
|
105
141
|
describe 'root_path support' do
|
106
142
|
|
107
143
|
it "should allow use_root_path in shared distribution" do
|
108
144
|
# expect{Cloudinary::Utils.cloudinary_url("test", {:use_root_path=>true})}.to raise_error(CloudinaryException)
|
109
|
-
|
110
|
-
|
145
|
+
expect(["test",{ :use_root_path => true, :private_cdn => false }])
|
146
|
+
.to produce_url("#{root_path}/test")
|
147
|
+
.and empty_options
|
148
|
+
expect(["test",{ :use_root_path => true, :private_cdn => false, :angle => 0 }])
|
149
|
+
.to produce_url("#{root_path}/a_0/test")
|
150
|
+
.and empty_options
|
111
151
|
end
|
112
152
|
|
113
153
|
it "should support use_root_path for private_cdn" do
|
114
|
-
|
115
|
-
|
154
|
+
expect(["test",{:use_root_path=>true, :private_cdn=>true}])
|
155
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/test")
|
156
|
+
.and empty_options
|
157
|
+
expect(["test",{:use_root_path=>true, :private_cdn=>true, :angle=>0}])
|
158
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/a_0/test")
|
159
|
+
.and empty_options
|
116
160
|
end
|
117
161
|
|
118
162
|
it "should support use_root_path together with url_suffix for private_cdn" do
|
119
|
-
|
163
|
+
expect(["test",{:use_root_path=>true, :url_suffix=>"hello", :private_cdn=>true}])
|
164
|
+
.to produce_url("http://#{cloud_name}-res.cloudinary.com/test/hello")
|
165
|
+
.and empty_options
|
120
166
|
end
|
121
167
|
|
122
168
|
it "should disallow use_root_path if not image/upload" do
|
@@ -125,174 +171,395 @@ describe Cloudinary::Utils do
|
|
125
171
|
end
|
126
172
|
|
127
173
|
end
|
174
|
+
describe ":width, :height" do
|
175
|
+
it "should use width and height from options only if crop is given" do
|
176
|
+
expect(["test",{ :width => 100, :height => 100 }])
|
177
|
+
.to produce_url("#{upload_path}/test")
|
178
|
+
.and mutate_options_to({ :width => 100, :height => 100 })
|
179
|
+
expect(["test",{ :width => 100, :height => 100, :crop => :crop }])
|
180
|
+
.to produce_url("#{upload_path}/c_crop,h_100,w_100/test")
|
181
|
+
.and mutate_options_to({ :width => 100, :height => 100 })
|
182
|
+
end
|
128
183
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
184
|
+
it "should not pass width and height to html in case of fit, lfill or limit crop" do
|
185
|
+
expect(["test",{ :width => 100, :height => 100, :crop => :limit }])
|
186
|
+
.to produce_url("#{upload_path}/c_limit,h_100,w_100/test")
|
187
|
+
.and empty_options
|
188
|
+
expect(["test",{ :width => 100, :height => 100, :crop => :lfill }])
|
189
|
+
.to produce_url("#{upload_path}/c_lfill,h_100,w_100/test")
|
190
|
+
.and empty_options
|
191
|
+
expect(["test",{ :width => 100, :height => 100, :crop => :fit }])
|
192
|
+
.to produce_url("#{upload_path}/c_fit,h_100,w_100/test")
|
193
|
+
.and empty_options
|
194
|
+
end
|
133
195
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
196
|
+
it "should not pass width and height to html in case angle was used" do
|
197
|
+
expect(["test",{ :width => 100, :height => 100, :crop => :scale, :angle => :auto }])
|
198
|
+
.to produce_url("#{upload_path}/a_auto,c_scale,h_100,w_100/test")
|
199
|
+
.and empty_options
|
200
|
+
end
|
201
|
+
it "should support size" do
|
202
|
+
expect(["test",{ :size => "10x10", :crop => :crop }])
|
203
|
+
.to produce_url("#{upload_path}/c_crop,h_10,w_10/test")
|
204
|
+
.and mutate_options_to({ :width => "10", :height => "10" })
|
205
|
+
end
|
138
206
|
end
|
139
207
|
|
140
|
-
it "should not pass width and height to html in case angle was used" do
|
141
|
-
test_cloudinary_url("test", { :width => 100, :height => 100, :crop => :scale, :angle => :auto }, "#{upload_path}/a_auto,c_scale,h_100,w_100/test", {})
|
142
|
-
end
|
143
|
-
|
144
208
|
it "should use x, y, radius, prefix, gravity and quality from options" do
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
it "should support named tranformation" do
|
149
|
-
test_cloudinary_url("test", { :transformation => "blip" }, "#{upload_path}/t_blip/test", {})
|
209
|
+
expect(["test",{ :x => 1, :y => 2, :radius => 3, :gravity => :center, :quality => 0.4, :prefix => "a" }])
|
210
|
+
.to produce_url("#{upload_path}/g_center,p_a,q_0.4,r_3,x_1,y_2/test")
|
211
|
+
.and empty_options
|
150
212
|
end
|
151
213
|
|
152
|
-
|
153
|
-
|
154
|
-
|
214
|
+
describe ":transformation" do
|
215
|
+
it "should support named tranformation" do
|
216
|
+
expect(["test",{ :transformation => "blip" }])
|
217
|
+
.to produce_url("#{upload_path}/t_blip/test")
|
218
|
+
.and empty_options
|
219
|
+
end
|
155
220
|
|
156
|
-
|
157
|
-
|
158
|
-
|
221
|
+
it "should support array of named tranformations" do
|
222
|
+
expect(["test",{ :transformation => ["blip", "blop"] }])
|
223
|
+
.to produce_url("#{upload_path}/t_blip.blop/test")
|
224
|
+
.and empty_options
|
225
|
+
end
|
159
226
|
|
160
|
-
|
161
|
-
|
162
|
-
|
227
|
+
it "should support base tranformation" do
|
228
|
+
expect(["test",{ :transformation => { :x => 100, :y => 100, :crop => :fill }, :crop => :crop, :width => 100 }])
|
229
|
+
.to produce_url("#{upload_path}/c_fill,x_100,y_100/c_crop,w_100/test")
|
230
|
+
.and mutate_options_to({ :width => 100 })
|
231
|
+
end
|
163
232
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
233
|
+
it "should support array of base tranformations" do
|
234
|
+
expect(["test",{ :transformation => [{ :x => 100, :y => 100, :width => 200, :crop => :fill }, { :radius => 10 }], :crop => :crop, :width => 100 }])
|
235
|
+
.to produce_url("#{upload_path}/c_fill,w_200,x_100,y_100/r_10/c_crop,w_100/test")
|
236
|
+
.and mutate_options_to({ :width => 100 })
|
237
|
+
end
|
168
238
|
|
169
|
-
|
170
|
-
|
171
|
-
|
239
|
+
it "should support array of tranformations" do
|
240
|
+
result = Cloudinary::Utils.generate_transformation_string([{:x=>100, :y=>100, :width=>200, :crop=>:fill}, {:radius=>10}])
|
241
|
+
expect(result).to eq("c_fill,w_200,x_100,y_100/r_10")
|
242
|
+
end
|
172
243
|
|
173
|
-
|
174
|
-
|
244
|
+
it "should not include empty tranformations" do
|
245
|
+
expect(["test", { :transformation => [{}, { :x => 100, :y => 100, :crop => :fill },{}] }])
|
246
|
+
.to produce_url("#{upload_path}/c_fill,x_100,y_100/test")
|
247
|
+
.and empty_options
|
248
|
+
end
|
175
249
|
end
|
176
250
|
|
251
|
+
|
177
252
|
it "should use type from options" do
|
178
|
-
|
253
|
+
expect(["test", { :type => :facebook }])
|
254
|
+
.to produce_url("#{root_path}/image/facebook/test")
|
255
|
+
.and empty_options
|
179
256
|
end
|
180
257
|
|
181
258
|
it "should use resource_type from options" do
|
182
|
-
|
259
|
+
expect(["test", { :resource_type => :raw }])
|
260
|
+
.to produce_url("#{root_path}/raw/upload/test")
|
261
|
+
.and empty_options
|
183
262
|
end
|
184
263
|
|
185
264
|
it "should ignore http links only if type is not given or is asset" do
|
186
|
-
|
187
|
-
|
188
|
-
|
265
|
+
expect(["http://test", { :type => nil }])
|
266
|
+
.to produce_url("http://test")
|
267
|
+
.and empty_options
|
268
|
+
expect(["http://test", { :type => :asset }])
|
269
|
+
.to produce_url("http://test")
|
270
|
+
.and empty_options
|
271
|
+
expect(["http://test", { :type => :fetch }])
|
272
|
+
.to produce_url("#{root_path}/image/fetch/http://test")
|
273
|
+
.and empty_options
|
189
274
|
end
|
190
275
|
|
191
276
|
it "should use allow absolute links to /images" do
|
192
|
-
|
193
|
-
|
277
|
+
expect(["/images/test", {}])
|
278
|
+
.to produce_url("#{upload_path}/test")
|
279
|
+
.and empty_options
|
280
|
+
end
|
194
281
|
|
195
282
|
it "should use ignore absolute links not to /images" do
|
196
|
-
|
197
|
-
|
283
|
+
expect(["/js/test", {}])
|
284
|
+
.to produce_url("/js/test")
|
285
|
+
.and empty_options
|
286
|
+
end
|
198
287
|
|
199
288
|
it "should escape fetch urls" do
|
200
|
-
|
201
|
-
|
289
|
+
expect(["http://blah.com/hello?a=b", { :type => :fetch }])
|
290
|
+
.to produce_url("#{root_path}/image/fetch/http://blah.com/hello%3Fa%3Db")
|
291
|
+
.and empty_options
|
292
|
+
end
|
202
293
|
|
203
294
|
it "should should escape http urls" do
|
204
|
-
|
205
|
-
|
295
|
+
expect(["http://www.youtube.com/watch?v=d9NF2edxy-M", { :type => :youtube }])
|
296
|
+
.to produce_url("#{root_path}/image/youtube/http://www.youtube.com/watch%3Fv%3Dd9NF2edxy-M")
|
297
|
+
.and empty_options
|
298
|
+
end
|
206
299
|
|
207
300
|
it "should support background" do
|
208
|
-
|
209
|
-
|
301
|
+
expect(["test", { :background => "red" }])
|
302
|
+
.to produce_url("#{upload_path}/b_red/test")
|
303
|
+
.and empty_options
|
304
|
+
expect(["test", { :background => "#112233" }])
|
305
|
+
.to produce_url("#{upload_path}/b_rgb:112233/test")
|
306
|
+
.and empty_options
|
210
307
|
end
|
211
|
-
|
308
|
+
|
212
309
|
it "should support default_image" do
|
213
|
-
|
310
|
+
expect(["test", { :default_image => "default" }])
|
311
|
+
.to produce_url("#{upload_path}/d_default/test")
|
312
|
+
.and empty_options
|
214
313
|
end
|
215
314
|
|
216
315
|
it "should support angle" do
|
217
|
-
|
218
|
-
|
316
|
+
expect(["test", { :angle => "55" }])
|
317
|
+
.to produce_url("#{upload_path}/a_55/test")
|
318
|
+
.and empty_options
|
319
|
+
expect(["test", { :angle => ["auto", "55"] }])
|
320
|
+
.to produce_url("#{upload_path}/a_auto.55/test")
|
321
|
+
.and empty_options
|
219
322
|
end
|
220
|
-
|
323
|
+
|
221
324
|
it "should support format for fetch urls" do
|
222
|
-
|
325
|
+
expect(["http://cloudinary.com/images/logo.png", { :format => "jpg", :type => :fetch }])
|
326
|
+
.to produce_url("#{root_path}/image/fetch/f_jpg/http://cloudinary.com/images/logo.png")
|
327
|
+
.and empty_options
|
223
328
|
end
|
224
|
-
|
329
|
+
|
225
330
|
it "should support effect" do
|
226
|
-
|
331
|
+
expect(["test", { :effect => "sepia" }])
|
332
|
+
.to produce_url("#{upload_path}/e_sepia/test")
|
333
|
+
.and empty_options
|
227
334
|
end
|
228
335
|
|
229
336
|
it "should support effect with hash param" do
|
230
|
-
|
337
|
+
expect(["test", { :effect => { "sepia" => 10 } }])
|
338
|
+
.to produce_url("#{upload_path}/e_sepia:10/test")
|
339
|
+
.and empty_options
|
231
340
|
end
|
232
341
|
|
233
342
|
it "should support effect with array param" do
|
234
|
-
|
343
|
+
expect(["test", { :effect => ["sepia", 10] }])
|
344
|
+
.to produce_url("#{upload_path}/e_sepia:10/test")
|
345
|
+
.and empty_options
|
235
346
|
end
|
236
347
|
|
237
|
-
|
238
|
-
|
239
|
-
|
348
|
+
shared_examples "a signed url" do |specific_options = {}, specific_transformation = ""|
|
349
|
+
let(:expected_transformation) do
|
350
|
+
(specific_transformation.blank? || specific_transformation.match(/\/$/)) ? specific_transformation : "#{specific_transformation}/"
|
240
351
|
end
|
241
|
-
|
242
|
-
|
243
|
-
|
352
|
+
let! (:authenticated_image) do
|
353
|
+
Cloudinary::Uploader.upload "http://res.cloudinary.com/demo/image/upload/sample.jpg",
|
354
|
+
:type => 'authenticated',
|
355
|
+
:tags => TEST_TAG
|
356
|
+
end
|
357
|
+
let(:options) {{ :version => authenticated_image['version'], :sign_url => true, :type => :authenticated }.merge(specific_options)}
|
358
|
+
let(:authenticated_path) { "#{root_path}/image/authenticated" }
|
359
|
+
|
360
|
+
it "should not serve resource with the wrong signature" do
|
361
|
+
expect(authenticated_image["url"].sub(/(?:s--)([\w-]+)(?:--)/) {|s| s.succ})
|
362
|
+
.not_to be_served_by_cloudinary
|
363
|
+
end
|
364
|
+
|
365
|
+
it "should correctly sign URL with version" do
|
366
|
+
expect(["#{authenticated_image['public_id']}.jpg", options])
|
367
|
+
.to produce_url(%r"#{authenticated_path}/s--[\w-]+--/#{expected_transformation}v#{authenticated_image['version']}/#{authenticated_image['public_id']}.jpg")
|
368
|
+
.and empty_options
|
369
|
+
.and be_served_by_cloudinary
|
370
|
+
end
|
371
|
+
it "should correctly sign URL with transformation and version" do
|
372
|
+
options[:transformation] = { :crop => "crop", :width => 10, :height => 20 }
|
373
|
+
expect(["#{authenticated_image['public_id']}.jpg", options])
|
374
|
+
.to produce_url(%r"#{authenticated_path}/s--[\w-]+--/c_crop,h_20,w_10/#{expected_transformation}v#{authenticated_image['version']}/#{authenticated_image['public_id']}.jpg")
|
375
|
+
.and empty_options
|
376
|
+
.and be_served_by_cloudinary
|
377
|
+
end
|
378
|
+
it "should correctly sign URL with transformation" do
|
379
|
+
options[:transformation] = { :crop => "crop", :width => 10, :height => 20 }
|
380
|
+
expect(["#{authenticated_image['public_id']}.jpg", options])
|
381
|
+
.to produce_url(%r"#{authenticated_path}/s--[\w-]+--/c_crop,h_20,w_10/#{expected_transformation}v#{authenticated_image['version']}/#{authenticated_image['public_id']}.jpg")
|
382
|
+
.and empty_options
|
383
|
+
.and be_served_by_cloudinary
|
384
|
+
end
|
385
|
+
it "should correctly sign fetch URL" do
|
386
|
+
options[:type] = :fetch
|
387
|
+
expect(["http://res.cloudinary.com/demo/sample.png", options])
|
388
|
+
.to produce_url(%r"^#{root_path}/image/fetch/s--[\w-]+--/#{expected_transformation}v#{authenticated_image['version']}/http://res.cloudinary.com/demo/sample.png$")
|
389
|
+
.and empty_options
|
390
|
+
.and be_served_by_cloudinary
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
|
395
|
+
{ 'overlay' => :l, :underlay => :u }.each do |param, letter|
|
396
|
+
describe param do
|
397
|
+
let(:root_path) { "http://res.cloudinary.com/#{cloud_name}" }
|
398
|
+
# [name, options, result]
|
399
|
+
let(:layers_options) { [
|
400
|
+
["string", "text:hello", "text:hello"],
|
401
|
+
["public_id", { "public_id" => "logo" }, "logo"],
|
402
|
+
["public_id with folder", { "public_id" => "folder/logo" }, "folder:logo"],
|
403
|
+
["private", { "public_id" => "logo", "type" => "private" }, "private:logo"],
|
404
|
+
["format", { "public_id" => "logo", "format" => "png" }, "logo.png"],
|
405
|
+
["video", { "resource_type" => "video", "public_id" => "cat" }, "video:cat"],
|
406
|
+
] }
|
407
|
+
it "should support #{param}" do
|
408
|
+
layers_options.each do |name, options, result|
|
409
|
+
expect(["test", { param => options }]).to produce_url("#{upload_path}/#{letter}_#{result}/test").and empty_options
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
it "should not pass width/height to html for #{param}" do
|
414
|
+
expect(["test", { param => "text:hello", :height => 100, :width => 100 }])
|
415
|
+
.to produce_url("#{upload_path}/h_100,#{letter}_text:hello,w_100/test")
|
416
|
+
.and empty_options
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
|
422
|
+
describe "text" do
|
423
|
+
|
424
|
+
text_layer = "Hello World, /Nice to meet you?"
|
425
|
+
text_encoded = "Hello%20World%252C%20%252FNice%20to%20meet%20you%3F"
|
426
|
+
before :all do
|
427
|
+
Cloudinary::Uploader.text(text_layer, {
|
428
|
+
:public_id => "test_text",
|
429
|
+
:overwrite => true,
|
430
|
+
:font_family => "Arial",
|
431
|
+
:font_size => "18",
|
432
|
+
:tags => TEST_TAG
|
433
|
+
})
|
434
|
+
srt = Tempfile.new('test_subtitles.srt')
|
435
|
+
srt.write <<-END
|
436
|
+
1
|
437
|
+
00:00:10,500 --> 00:00:13,000
|
438
|
+
Hello World, Nice to meet you?
|
439
|
+
|
440
|
+
END
|
441
|
+
srt.rewind
|
442
|
+
Cloudinary::Uploader.upload srt, :public_id => 'subtitles.srt', :resource_type => 'raw', :overwrite => true, :tags => TEST_TAG
|
443
|
+
srt.unlink
|
444
|
+
end
|
445
|
+
|
446
|
+
# after :all do
|
447
|
+
# Cloudinary::Api.delete_resources_by_tag TEST_TAG
|
448
|
+
# end
|
449
|
+
|
450
|
+
{ 'overlay' => 'l', 'underlay' => 'u' }.each do |param, short|
|
451
|
+
describe param do
|
452
|
+
let(:root_path) { "http://res.cloudinary.com/#{cloud_name}" }
|
453
|
+
# [name, options, result]
|
454
|
+
layers_options= [
|
455
|
+
["string", "text:test_text:hello", "text:test_text:hello"],
|
456
|
+
["explicit layer parameter", "text:test_text:#{text_encoded}", "text:test_text:#{text_encoded}" ],
|
457
|
+
["text parameter", { :public_id => "test_text", :text => text_layer }, "text:test_text:#{text_encoded}" ],
|
458
|
+
["text with font family and size parameters", { :text => text_layer, :font_family => "Arial", :font_size => "18" }, "text:Arial_18:#{text_encoded}"],
|
459
|
+
["text with text style parameter", { :text => text_layer, :font_family => "Arial", :font_size => "18", :font_weight => "bold", :font_style => "italic", :letter_spacing => 4 }, "text:Arial_18_bold_italic_letter_spacing_4:#{text_encoded}"],
|
460
|
+
["subtitles", { :resource_type => "subtitles", :public_id => "subtitles.srt" }, "subtitles:subtitles.srt"],
|
461
|
+
["subtitles with font family and size", { :resource_type => "subtitles", :public_id => "subtitles.srt", :font_family => "Arial", :font_size => "40" }, "subtitles:Arial_40:subtitles.srt"]
|
462
|
+
]
|
463
|
+
layers_options.each do |name, options, result|
|
464
|
+
it "should support #{name}" do
|
465
|
+
expect(["sample", { param => options }]).to produce_url("#{upload_path}/#{short}_#{result}/sample").and empty_options
|
466
|
+
expect("#{upload_path}/#{short}_#{result}/sample").to be_served_by_cloudinary
|
467
|
+
end
|
468
|
+
unless options.is_a? String
|
469
|
+
op = Hash.new
|
470
|
+
op[param] = options
|
471
|
+
it_behaves_like "a signed url", op, "#{short}_#{result}"
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
it "should not pass width/height to html for #{param}" do
|
476
|
+
expect(["test", { param => "text:test_text", :height => 100, :width => 100 }])
|
477
|
+
.to produce_url("#{upload_path}/h_100,#{short}_text:test_text,w_100/test")
|
478
|
+
.and empty_options
|
479
|
+
|
480
|
+
end
|
481
|
+
end
|
244
482
|
end
|
245
483
|
end
|
246
484
|
|
247
485
|
|
248
|
-
it "should use ssl_detected if secure is not given as parameter and not set to true in configuration" do
|
249
|
-
test_cloudinary_url("test", {:ssl_detected=>true}, "https://res.cloudinary.com/test123/image/upload/test", {})
|
250
|
-
end
|
251
486
|
|
252
|
-
it "should use
|
487
|
+
it "should use ssl_detected if secure is not given as parameter and not set to true in configuration" do
|
488
|
+
expect(["test",{:ssl_detected=>true}])
|
489
|
+
.to produce_url("https://res.cloudinary.com/#{cloud_name}/image/upload/test")
|
490
|
+
.and empty_options
|
491
|
+
end
|
492
|
+
|
493
|
+
it "should use secure if given over ssl_detected and configuration" do
|
253
494
|
Cloudinary.config.secure = true
|
254
|
-
|
255
|
-
|
495
|
+
expect(["test",{ :ssl_detected => true, :secure => false }])
|
496
|
+
.to produce_url("#{upload_path}/test")
|
497
|
+
.and empty_options
|
498
|
+
end
|
256
499
|
|
257
|
-
it "should use secure: true from configuration over ssl_detected" do
|
500
|
+
it "should use secure: true from configuration over ssl_detected" do
|
258
501
|
Cloudinary.config.secure = true
|
259
|
-
|
260
|
-
|
502
|
+
expect(["test",{:ssl_detected=>false}])
|
503
|
+
.to produce_url("https://res.cloudinary.com/#{cloud_name}/image/upload/test")
|
504
|
+
.and empty_options
|
505
|
+
end
|
261
506
|
|
262
507
|
it "should support extenal cname" do
|
263
|
-
|
508
|
+
expect(["test",{:cname=>"hello.com"}])
|
509
|
+
.to produce_url("http://hello.com/#{cloud_name}/image/upload/test")
|
510
|
+
.and empty_options
|
264
511
|
end
|
265
512
|
|
266
513
|
it "should support extenal cname with cdn_subdomain on" do
|
267
|
-
|
514
|
+
expect(["test",{:cname=>"hello.com", :cdn_subdomain=>true}])
|
515
|
+
.to produce_url("http://a2.hello.com/#{cloud_name}/image/upload/test")
|
516
|
+
.and empty_options
|
268
517
|
end
|
269
|
-
|
518
|
+
|
270
519
|
it "should support cdn_subdomain with secure on if using shared_domain" do
|
271
|
-
|
520
|
+
expect(["test",{:secure=>true, :cdn_subdomain=>true}])
|
521
|
+
.to produce_url("https://res-2.cloudinary.com/#{cloud_name}/image/upload/test")
|
522
|
+
.and empty_options
|
272
523
|
end
|
273
524
|
|
274
525
|
it "should support secure_cdn_subdomain false override with secure" do
|
275
|
-
|
526
|
+
expect(["test",{:secure=>true, :cdn_subdomain=>true, :secure_cdn_subdomain=>false}])
|
527
|
+
.to produce_url("https://res.cloudinary.com/#{cloud_name}/image/upload/test")
|
528
|
+
.and empty_options
|
276
529
|
end
|
277
530
|
|
278
531
|
it "should support secure_cdn_subdomain true override with secure" do
|
279
|
-
|
532
|
+
expect(["test",{:secure=>true, :cdn_subdomain=>true, :secure_cdn_subdomain=>true, :private_cdn=>true}])
|
533
|
+
.to produce_url("https://#{cloud_name}-res-2.cloudinary.com/image/upload/test")
|
534
|
+
.and empty_options
|
280
535
|
end
|
281
536
|
|
282
537
|
it "should support string param" do
|
283
|
-
|
538
|
+
expect(["test",{ "effect" => { "sepia" => 10 } }])
|
539
|
+
.to produce_url("#{upload_path}/e_sepia:10/test")
|
540
|
+
.and empty_options
|
284
541
|
end
|
285
|
-
|
542
|
+
|
286
543
|
it "should support border" do
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
544
|
+
expect(["test",{ "border" => { :width => 5 } }])
|
545
|
+
.to produce_url("#{upload_path}/bo_5px_solid_black/test")
|
546
|
+
.and empty_options
|
547
|
+
expect(["test",{ "border" => { :width => 5, :color => "#ffaabbdd" } }])
|
548
|
+
.to produce_url("#{upload_path}/bo_5px_solid_rgb:ffaabbdd/test")
|
549
|
+
.and empty_options
|
550
|
+
expect(["test",{ "border" => "1px_solid_blue" }])
|
551
|
+
.to produce_url("#{upload_path}/bo_1px_solid_blue/test")
|
552
|
+
.and empty_options
|
553
|
+
expect(["test", { "border" => "2" }]).to produce_url("#{upload_path}/test").and mutate_options_to({ :border => "2" })
|
291
554
|
end
|
292
|
-
|
555
|
+
|
293
556
|
it "should support flags" do
|
294
|
-
|
295
|
-
|
557
|
+
expect(["test",{ "flags" => "abc" }])
|
558
|
+
.to produce_url("#{upload_path}/fl_abc/test")
|
559
|
+
.and empty_options
|
560
|
+
expect(["test",{ "flags" => ["abc", "def"] }])
|
561
|
+
.to produce_url("#{upload_path}/fl_abc.def/test")
|
562
|
+
.and empty_options
|
296
563
|
end
|
297
564
|
|
298
565
|
it "build_upload_params should not destroy options" do
|
@@ -302,36 +569,49 @@ describe Cloudinary::Utils do
|
|
302
569
|
end
|
303
570
|
|
304
571
|
it "build_upload_params canonize booleans" do
|
305
|
-
options = {:backup=>true, :use_filename=>false, :colors
|
306
|
-
:image_metadata=>:false, :invalidate=>1
|
572
|
+
options = {:backup=>true, :use_filename=>false, :colors=>:true,
|
573
|
+
:image_metadata=>:false, :invalidate=>1}
|
307
574
|
params = Cloudinary::Uploader.build_upload_params(options)
|
308
575
|
expect(Cloudinary::Api.only(params, *options.keys)).to eq(
|
309
|
-
:backup=>1, :use_filename=>0, :colors=>1,
|
310
|
-
:image_metadata=>0, :invalidate=>1
|
576
|
+
:backup=>1, :use_filename=>0, :colors=>1,
|
577
|
+
:image_metadata=>0, :invalidate=>1
|
578
|
+
)
|
579
|
+
options = {:colors=>"true", :exif=>"false", :eager_async=>"1"}
|
580
|
+
params = Cloudinary::Uploader.build_upload_params(options)
|
581
|
+
expect(Cloudinary::Api.only(params, *options.keys)).to eq(
|
582
|
+
:exif=>0, :colors=>1, :eager_async=>1
|
311
583
|
)
|
312
584
|
expect(Cloudinary::Uploader.build_upload_params(:backup=>nil)[:backup]).to be_nil
|
313
585
|
expect(Cloudinary::Uploader.build_upload_params({})[:backup]).to be_nil
|
314
586
|
end
|
315
|
-
|
587
|
+
|
316
588
|
it "should add version if public_id contains /" do
|
317
|
-
|
318
|
-
|
589
|
+
expect(["folder/test", {}])
|
590
|
+
.to produce_url( "#{upload_path}/v1/folder/test")
|
591
|
+
.and empty_options
|
592
|
+
expect(["folder/test",{ :version => 123 }])
|
593
|
+
.to produce_url("#{upload_path}/v123/folder/test")
|
594
|
+
.and empty_options
|
319
595
|
end
|
320
596
|
|
321
597
|
it "should not add version if public_id contains version already" do
|
322
|
-
|
598
|
+
expect(["v1234/test", {}])
|
599
|
+
.to produce_url( "#{upload_path}/v1234/test")
|
600
|
+
.and empty_options
|
323
601
|
end
|
324
602
|
|
325
603
|
it "should allow to shorted image/upload urls" do
|
326
|
-
|
604
|
+
expect(["test",{ :shorten => true }])
|
605
|
+
.to produce_url("#{root_path}/iu/test")
|
606
|
+
.and empty_options
|
327
607
|
end
|
328
|
-
|
608
|
+
|
329
609
|
it "should allow to use folders in PreloadedFile" do
|
330
610
|
signature = Cloudinary::Utils.api_sign_request({:public_id=>"folder/file", :version=>"1234"}, Cloudinary.config.api_secret)
|
331
611
|
preloaded = Cloudinary::PreloadedFile.new("image/upload/v1234/folder/file.jpg#" + signature)
|
332
612
|
expect(preloaded).to be_valid
|
333
613
|
end
|
334
|
-
|
614
|
+
|
335
615
|
it "should escape public_ids" do
|
336
616
|
[
|
337
617
|
["a b", "a%20b"],
|
@@ -343,33 +623,38 @@ describe Cloudinary::Utils do
|
|
343
623
|
].each do
|
344
624
|
|source, target|
|
345
625
|
expect(Cloudinary::Utils.cloudinary_url(source)).to eq("#{upload_path}/#{target}")
|
346
|
-
end
|
626
|
+
end
|
347
627
|
end
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
test_cloudinary_url("image.jpg", { :transformation => { :crop => "crop", :width => 10, :height => 20 }, :sign_url => true }, "#{upload_path}/s--Ai4Znfl3--/c_crop,h_20,w_10/image.jpg", {})
|
353
|
-
test_cloudinary_url("image.jpg", { :transformation => { :crop => "crop", :width => 10, :height => 20 }, :type => :authenticated, :sign_url => true }, "#{root_path}/image/authenticated/s--Ai4Znfl3--/c_crop,h_20,w_10/image.jpg", {})
|
354
|
-
test_cloudinary_url("http://google.com/path/to/image.png", { :type => "fetch", :version => 1234, :sign_url => true }, "#{root_path}/image/fetch/s--hH_YcbiS--/v1234/http://google.com/path/to/image.png", {})
|
628
|
+
|
629
|
+
|
630
|
+
describe ":sign_url" do
|
631
|
+
it_behaves_like "a signed url"
|
355
632
|
end
|
356
633
|
|
357
|
-
|
358
|
-
|
359
|
-
test_cloudinary_url("image.jpg", { :version => 1234, :sign_url => true, :sign_version => true }, "#{upload_path}/s--ZlgFLQcO--/v1234/image.jpg", {})
|
360
|
-
test_cloudinary_url("image.jpg", { :transformation => { :crop => "crop", :width => 10, :height => 20 }, :sign_url => true, :sign_version => true }, "#{upload_path}/s--Ai4Znfl3--/c_crop,h_20,w_10/image.jpg", {})
|
361
|
-
test_cloudinary_url("http://google.com/path/to/image.png", { :type => "fetch", :version => 1234, :sign_url => true, :sign_version => true }, "#{root_path}/image/fetch/s--_GAUclyB--/v1234/http://google.com/path/to/image.png", {})
|
634
|
+
describe ":sign_version (deprecated)" do
|
635
|
+
it_behaves_like "a signed url", :sign_version => true
|
362
636
|
end
|
363
|
-
|
637
|
+
|
364
638
|
it "should correctly sign_request" do
|
365
|
-
params = Cloudinary::Utils.sign_request({
|
366
|
-
|
639
|
+
params = Cloudinary::Utils.sign_request({
|
640
|
+
:cloud_name => "demo",
|
641
|
+
:api_key => "1234",
|
642
|
+
:api_secret => "b",
|
643
|
+
:public_id=>"folder/file",
|
644
|
+
:version=>"1234"})
|
645
|
+
expect(params).to include(
|
646
|
+
:signature=>"bc812f98b6c86c7a4e7779324f554d7c010d3510"
|
647
|
+
)
|
367
648
|
end
|
368
649
|
|
369
650
|
it "should support responsive width" do
|
370
|
-
|
651
|
+
expect(["test",{ :width => 100, :height => 100, :crop => :crop, :responsive_width => true }])
|
652
|
+
.to produce_url("#{upload_path}/c_crop,h_100,w_100/c_limit,w_auto/test")
|
653
|
+
.and mutate_options_to({ :responsive => true })
|
371
654
|
Cloudinary.config.responsive_width_transformation = {:width => :auto, :crop => :pad}
|
372
|
-
|
655
|
+
expect(["test", { :width => 100, :height => 100, :crop => :crop, :responsive_width => true }])
|
656
|
+
.to produce_url( "#{upload_path}/c_crop,h_100,w_100/c_pad,w_auto/test")
|
657
|
+
.and mutate_options_to( { :responsive => true })
|
373
658
|
end
|
374
659
|
|
375
660
|
it "should correctly encode double arrays" do
|