cloudinary 1.11.1 → 1.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- data/.github/pull_request_template.md +24 -0
- data/.gitignore +6 -1
- data/.travis.yml +15 -5
- data/CHANGELOG.md +149 -0
- data/Rakefile +3 -45
- data/cloudinary.gemspec +20 -4
- data/lib/active_storage/blob_key.rb +20 -0
- data/lib/active_storage/service/cloudinary_service.rb +229 -0
- data/lib/cloudinary.rb +31 -22
- data/lib/cloudinary/api.rb +173 -5
- data/lib/cloudinary/auth_token.rb +6 -4
- data/lib/cloudinary/carrier_wave.rb +3 -1
- data/lib/cloudinary/carrier_wave/remote.rb +3 -2
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/cloudinary_controller.rb +2 -4
- data/lib/cloudinary/helper.rb +30 -3
- data/lib/cloudinary/railtie.rb +7 -3
- data/lib/cloudinary/uploader.rb +35 -6
- data/lib/cloudinary/utils.rb +112 -40
- data/lib/cloudinary/version.rb +1 -1
- data/lib/cloudinary/video_helper.rb +96 -22
- data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
- data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
- data/tools/allocate_test_cloud.sh +9 -0
- data/tools/get_test_cloud.sh +9 -0
- data/tools/update_version +29 -11
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +48 -14
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +24 -4
- data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +741 -561
- data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -1
- metadata +62 -67
- data/spec/access_control_spec.rb +0 -102
- data/spec/api_spec.rb +0 -567
- data/spec/archive_spec.rb +0 -129
- data/spec/auth_token_spec.rb +0 -77
- data/spec/cache_spec.rb +0 -109
- data/spec/cloudinary_helper_spec.rb +0 -325
- data/spec/cloudinary_spec.rb +0 -32
- data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
- data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
- data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
- data/spec/docx.docx +0 -0
- data/spec/favicon.ico +0 -0
- data/spec/image_spec.rb +0 -107
- data/spec/logo.png +0 -0
- data/spec/rake_spec.rb +0 -160
- data/spec/sample_asset_file.tsv +0 -4
- data/spec/search_spec.rb +0 -109
- data/spec/spec_helper.rb +0 -266
- data/spec/storage_spec.rb +0 -44
- data/spec/streaminig_profiles_api_spec.rb +0 -74
- data/spec/support/helpers/temp_file_helpers.rb +0 -22
- data/spec/support/shared_contexts/rake.rb +0 -19
- data/spec/uploader_spec.rb +0 -392
- data/spec/utils_methods_spec.rb +0 -54
- data/spec/utils_spec.rb +0 -970
- data/spec/video_tag_spec.rb +0 -253
- data/spec/video_url_spec.rb +0 -185
data/spec/cloudinary_spec.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'cloudinary'
|
3
|
-
|
4
|
-
describe Cloudinary do
|
5
|
-
before :all do
|
6
|
-
@user_platform = Cloudinary.user_platform
|
7
|
-
end
|
8
|
-
after :all do
|
9
|
-
Cloudinary.user_platform = @user_platform
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should add a user platform to USER_AGENT' do
|
13
|
-
Cloudinary.user_platform = "Spec/1.0 (Test)"
|
14
|
-
expect(Cloudinary.USER_AGENT).to match( %r"Spec\/1.0 \(Test\) CloudinaryRuby/[\d.]+")
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
describe 'config' do
|
19
|
-
before do
|
20
|
-
@url_backup = ENV["CLOUDINARY_URL"]
|
21
|
-
end
|
22
|
-
after do
|
23
|
-
ENV["CLOUDINARY_URL"] = @url_backup
|
24
|
-
Cloudinary::config_from_url @url_backup
|
25
|
-
end
|
26
|
-
it "should allow nested values in CLOUDINARY_URL" do
|
27
|
-
ENV["CLOUDINARY_URL"] = "cloudinary://key:secret@test123?foo[bar]=value"
|
28
|
-
Cloudinary::config_from_url ENV["CLOUDINARY_URL"]
|
29
|
-
expect(Cloudinary::config.foo.bar).to eq 'value'
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
coffeescript = true
|
@@ -1 +0,0 @@
|
|
1
|
-
{ alert("I am javascript!");}
|
data/spec/docx.docx
DELETED
Binary file
|
data/spec/favicon.ico
DELETED
Binary file
|
data/spec/image_spec.rb
DELETED
@@ -1,107 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'cloudinary'
|
3
|
-
require 'action_view'
|
4
|
-
require 'cloudinary/helper'
|
5
|
-
|
6
|
-
COMMON_TRANS = {
|
7
|
-
effect: 'sepia',
|
8
|
-
cloud_name: DUMMY_CLOUD,
|
9
|
-
client_hints: false
|
10
|
-
}
|
11
|
-
COMMON_TRANSFORMATION_STR = 'e_sepia'
|
12
|
-
|
13
|
-
def expected_srcset(public_id, path, common_trans, breakpoints)
|
14
|
-
breakpoints.map {|width| "#{path}/#{common_trans}/c_scale,w_#{width}/#{public_id} #{width}w"}.join(', ')
|
15
|
-
end
|
16
|
-
|
17
|
-
describe 'Responsive breakpoints' do
|
18
|
-
|
19
|
-
|
20
|
-
before :all do
|
21
|
-
# Test the helper in the context it runs in in production
|
22
|
-
ActionView::Base.send :include, CloudinaryHelper
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
before :each do
|
27
|
-
Cloudinary.reset_config
|
28
|
-
end
|
29
|
-
|
30
|
-
let(:cloud_name) {COMMON_TRANS[:cloud_name]}
|
31
|
-
let(:root_path) {"http://res.cloudinary.com/#{cloud_name}"}
|
32
|
-
let(:upload_path) {"#{root_path}/image/upload"}
|
33
|
-
|
34
|
-
let(:options) {COMMON_TRANS}
|
35
|
-
# let(:helper) {helper_class.new}
|
36
|
-
let(:helper) {
|
37
|
-
ActionView::Base.new
|
38
|
-
}
|
39
|
-
let(:test_tag) {TestTag.new(helper.cl_image_tag('sample.jpg', options))}
|
40
|
-
describe 'srcset' do
|
41
|
-
it 'Should create srcset attribute with provided breakpoints' do
|
42
|
-
options[:srcset] = {:breakpoints => ResponsiveTest::BREAKPOINTS}
|
43
|
-
srcset = test_tag['srcset'].split(", ")
|
44
|
-
expect(srcset.length).to eq(4)
|
45
|
-
expected_tag = expected_srcset('sample.jpg', upload_path, COMMON_TRANSFORMATION_STR, ResponsiveTest::BREAKPOINTS)
|
46
|
-
expect(test_tag['srcset']).to match(expected_tag)
|
47
|
-
end
|
48
|
-
it "Support srcset attribute defined by min width max width and max images" do
|
49
|
-
options[:srcset] = {:min_width => ResponsiveTest::BREAKPOINTS.first,
|
50
|
-
:max_width => ResponsiveTest::BREAKPOINTS.last,
|
51
|
-
:max_images => ResponsiveTest::BREAKPOINTS.length}
|
52
|
-
|
53
|
-
expected_tag = expected_srcset('sample.jpg', upload_path, COMMON_TRANSFORMATION_STR, ResponsiveTest::BREAKPOINTS)
|
54
|
-
expect(test_tag['srcset']).to match(expected_tag)
|
55
|
-
end
|
56
|
-
it "should generate a single srcset image" do
|
57
|
-
options[:srcset] = {:min_width => ResponsiveTest::BREAKPOINTS.first,
|
58
|
-
:max_width => ResponsiveTest::BREAKPOINTS.last,
|
59
|
-
:max_images => 1}
|
60
|
-
|
61
|
-
expected_tag = expected_srcset('sample.jpg', upload_path, COMMON_TRANSFORMATION_STR, [ResponsiveTest::BREAKPOINTS.last])
|
62
|
-
expect(test_tag['srcset']).to match(expected_tag)
|
63
|
-
end
|
64
|
-
it "Should support custom transformation for srcset items" do
|
65
|
-
options[:srcset] = {
|
66
|
-
:breakpoints => ResponsiveTest::BREAKPOINTS,
|
67
|
-
:transformation => {:crop => 'crop', :width => 10, :height => 20}
|
68
|
-
}
|
69
|
-
|
70
|
-
expected_tag = expected_srcset('sample.jpg', upload_path, 'c_crop,h_20,w_10', ResponsiveTest::BREAKPOINTS)
|
71
|
-
expect(test_tag['srcset']).to match(expected_tag)
|
72
|
-
end
|
73
|
-
it "Should populate sizes attribute" do
|
74
|
-
options[:srcset] = {
|
75
|
-
:breakpoints => ResponsiveTest::BREAKPOINTS,
|
76
|
-
:sizes => true
|
77
|
-
}
|
78
|
-
expected_sizes_attr = '(max-width: 100px) 100px, (max-width: 200px) 200px, ' +
|
79
|
-
'(max-width: 300px) 300px, (max-width: 399px) 399px'
|
80
|
-
expect(test_tag['sizes']).to match(expected_sizes_attr)
|
81
|
-
end
|
82
|
-
it "Should support srcset string value" do
|
83
|
-
raw_src_set = "some srcset data as is"
|
84
|
-
options[:srcset] = raw_src_set
|
85
|
-
|
86
|
-
expect(test_tag['srcset']).to match(raw_src_set)
|
87
|
-
end
|
88
|
-
it "Should remove width and height attributes in case srcset is specified, but passed to transformation" do
|
89
|
-
options.merge!({
|
90
|
-
:srcset => {
|
91
|
-
:breakpoints => ResponsiveTest::BREAKPOINTS,
|
92
|
-
},
|
93
|
-
:width => 500,
|
94
|
-
:height => 500,
|
95
|
-
:crop => 'scale'
|
96
|
-
|
97
|
-
})
|
98
|
-
|
99
|
-
expected_tag = expected_srcset('sample.jpg', upload_path, 'c_scale,e_sepia,h_500,w_500', ResponsiveTest::BREAKPOINTS)
|
100
|
-
expect(test_tag['srcset']).to match(expected_tag)
|
101
|
-
expect(test_tag['width']).to be_nil
|
102
|
-
end
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
end
|
data/spec/logo.png
DELETED
Binary file
|
data/spec/rake_spec.rb
DELETED
@@ -1,160 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'cloudinary'
|
3
|
-
|
4
|
-
require 'tmpdir'
|
5
|
-
require 'pathname'
|
6
|
-
|
7
|
-
describe 'cloudinary:sync_static' do
|
8
|
-
include_context 'rake' # context needs to have the exact rake task as name
|
9
|
-
include Helpers::TempFileHelpers
|
10
|
-
|
11
|
-
before(:all) do
|
12
|
-
copy_root_to_temp('spec/data/sync_static/')
|
13
|
-
|
14
|
-
# Reuse some existing spec assets so as not to add weight to the project
|
15
|
-
copy_file_to_temp('spec/logo.png', 'app/assets/images/logo1.png')
|
16
|
-
copy_file_to_temp('spec/logo.png', 'app/assets/images/logo2.png')
|
17
|
-
copy_file_to_temp('samples/basic/lake.jpg', 'app/assets/images/lake1.jpg')
|
18
|
-
copy_file_to_temp('samples/basic/lake.jpg', 'public/images/lake2.jpg')
|
19
|
-
end
|
20
|
-
|
21
|
-
after(:all) do
|
22
|
-
clean_up_temp_files!
|
23
|
-
end
|
24
|
-
|
25
|
-
before (:each) do
|
26
|
-
allow(Cloudinary).to receive(:app_root).and_return(Pathname.new(temp_root))
|
27
|
-
Cloudinary::Static.send(:reset_static_file_config!)
|
28
|
-
end
|
29
|
-
|
30
|
-
after (:each) do
|
31
|
-
# destroy all uploaded assets
|
32
|
-
Cloudinary::Static.send(:build_metadata).each do |_, data|
|
33
|
-
Cloudinary::Uploader.destroy(data['public_id'], {:type => :asset})
|
34
|
-
end
|
35
|
-
# delete metadata_file_path
|
36
|
-
FileUtils.rm_f(Cloudinary::Static.send(:metadata_file_path))
|
37
|
-
FileUtils.rm_f(Cloudinary::Static.send(:metadata_trash_file_path))
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'should find correct file when running in default configuration' do
|
41
|
-
# with default settings, 4 images only will be uploaded
|
42
|
-
subject.invoke
|
43
|
-
expect(Cloudinary::Static.send(:build_metadata).size).to eq 4
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should respect deprecated static_image_dirs config setting' do
|
47
|
-
allow(Cloudinary.config).to receive(:static_image_dirs).and_return(['public/images'])
|
48
|
-
subject.invoke
|
49
|
-
expect(Cloudinary::Static.send(:build_metadata).size).to eq 1
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should allow to specify only dirs in images group, taking the file_mask from default' do
|
53
|
-
allow(Cloudinary.config).to receive(:static_files).and_return({
|
54
|
-
'images' => {
|
55
|
-
'dirs' => ['public/images']
|
56
|
-
}
|
57
|
-
})
|
58
|
-
subject.invoke
|
59
|
-
expect(Cloudinary::Static.send(:build_metadata).size).to eq 1
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'should allow to specify only file_mask in images group, taking the dirs from default' do
|
63
|
-
allow(Cloudinary.config).to receive(:static_files).and_return({
|
64
|
-
'images' => {
|
65
|
-
'file_mask' => 'png'
|
66
|
-
}
|
67
|
-
})
|
68
|
-
subject.invoke
|
69
|
-
expect(Cloudinary::Static.send(:build_metadata).size).to eq 2
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'should allow to specify regex expressions in file_mask' do
|
73
|
-
allow(Cloudinary.config).to receive(:static_files).and_return({
|
74
|
-
'images' => {
|
75
|
-
'file_mask' => 'p.?g|jp.?'
|
76
|
-
},
|
77
|
-
'javascripts' => {
|
78
|
-
'dirs' => ['app/assets/javascripts'],
|
79
|
-
'file_mask' => 'js'
|
80
|
-
},
|
81
|
-
'stylesheets' => {
|
82
|
-
'dirs' => ['app/assets/stylesheets'],
|
83
|
-
'file_mask' => 'css'
|
84
|
-
}
|
85
|
-
})
|
86
|
-
subject.invoke
|
87
|
-
expect(Cloudinary::Static.send(:build_metadata).size).to eq 6
|
88
|
-
end
|
89
|
-
|
90
|
-
context 'Cloudinary::Utils.cloudinary_url' do
|
91
|
-
def all_asset_forms_of(public_id)
|
92
|
-
[ "/#{public_id}", public_id.split('/').last]
|
93
|
-
end
|
94
|
-
|
95
|
-
RSpec::Matchers.define :be_asset_mapped_by_cloudinary_url_to do |expected|
|
96
|
-
match do |actual|
|
97
|
-
actual = [actual] unless actual.respond_to? :all?
|
98
|
-
actual.all? do |public_path|
|
99
|
-
@public_path = public_path
|
100
|
-
@actual = Cloudinary::Utils.cloudinary_url(public_path, :cloud_name => 'test', :type => 'asset')
|
101
|
-
@actual == expected
|
102
|
-
end
|
103
|
-
end
|
104
|
-
failure_message do |actual|
|
105
|
-
"URL for '#{@public_path}' should have been '#{expected}' but was '#{@actual}'.#{ differ.diff_as_string(@actual, expected)}"
|
106
|
-
end
|
107
|
-
failure_message_when_negated do |actual|
|
108
|
-
"URL for '#{@public_path}' should not have been '#{expected}'."
|
109
|
-
end
|
110
|
-
def differ
|
111
|
-
RSpec::Support::Differ.new(
|
112
|
-
:object_preparer => lambda { |object| RSpec::Matchers::Composable.surface_descriptions_in(object) },
|
113
|
-
:color => RSpec::Matchers.configuration.color?
|
114
|
-
)
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
|
-
before(:each) do
|
120
|
-
allow(Cloudinary.config).to receive(:static_files).and_return({
|
121
|
-
'images' => {
|
122
|
-
'dirs' => ['app/assets/images'],
|
123
|
-
'file_mask' => 'p.?g|jp.?'
|
124
|
-
},
|
125
|
-
'javascripts' => {
|
126
|
-
'dirs' => ['app/assets/javascripts'],
|
127
|
-
'file_mask' => 'js'
|
128
|
-
},
|
129
|
-
'stylesheets' => {
|
130
|
-
'dirs' => ['app/assets/stylesheets'],
|
131
|
-
'file_mask' => 'css'
|
132
|
-
}
|
133
|
-
})
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'should return Cloudinary asset urls for assets when Cloudinary.config.static_file_support is true' do
|
138
|
-
allow(Cloudinary.config).to receive(:static_file_support).and_return(true)
|
139
|
-
subject.invoke
|
140
|
-
|
141
|
-
expect(['logo1.png', '/images/logo1.png']).to be_asset_mapped_by_cloudinary_url_to('http://res.cloudinary.com/test/image/asset/logo1-7dc60722d4653261648038b579fdb89e.png')
|
142
|
-
expect('images/logo1.png').not_to be_asset_mapped_by_cloudinary_url_to('http://res.cloudinary.com/test/image/asset/logo1-7dc60722d4653261648038b579fdb89e.png')
|
143
|
-
expect('1.js').to be_asset_mapped_by_cloudinary_url_to('http://res.cloudinary.com/test/raw/asset/1-b01de57adb485efdde843154d030644e.js')
|
144
|
-
expect(['javascripts/1.js', '/javascripts/1.js']).not_to be_asset_mapped_by_cloudinary_url_to('http://res.cloudinary.com/test/raw/asset/1-b01de57adb485efdde843154d030644e.js')
|
145
|
-
expect('1.css').to be_asset_mapped_by_cloudinary_url_to('http://res.cloudinary.com/test/raw/asset/1-f24cc6123afd401ab86d8596cabc619f.css')
|
146
|
-
expect(['stylesheets/1.css', '/stylesheets/1.css']).not_to be_asset_mapped_by_cloudinary_url_to('http://res.cloudinary.com/test/raw/asset/1-f24cc6123afd401ab86d8596cabc619f.css')
|
147
|
-
|
148
|
-
# without :type => 'asset'
|
149
|
-
expect(Cloudinary::Utils.cloudinary_url('logo1.png')).not_to include('7dc60722d4653261648038b579fdb89e')
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'should return Cloudinary asset urls for assets when Cloudinary.config.static_image_support is true (backwards compatibility)' do
|
153
|
-
allow(Cloudinary.config).to receive(:static_image_support).and_return(true)
|
154
|
-
subject.invoke
|
155
|
-
|
156
|
-
expect(['logo1.png', '/images/logo1.png']).to be_asset_mapped_by_cloudinary_url_to('http://res.cloudinary.com/test/image/asset/logo1-7dc60722d4653261648038b579fdb89e.png')
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
end
|
data/spec/sample_asset_file.tsv
DELETED
data/spec/search_spec.rb
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'cloudinary'
|
3
|
-
|
4
|
-
describe Cloudinary::Search do
|
5
|
-
context 'unit' do
|
6
|
-
it 'should create empty json' do
|
7
|
-
query_hash = Cloudinary::Search.to_h
|
8
|
-
expect(query_hash).to eq({})
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'should always return same object in fluent interface' do
|
12
|
-
instance = Cloudinary::Search.new
|
13
|
-
%w(expression sort_by max_results next_cursor aggregate with_field).each do |method|
|
14
|
-
same_instance = instance.send(method, 'emptyarg')
|
15
|
-
expect(instance).to eq(same_instance)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should add expression to query' do
|
20
|
-
query = Cloudinary::Search.expression('format:jpg').to_h
|
21
|
-
expect(query).to eq(expression: 'format:jpg')
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'should add sort_by to query' do
|
25
|
-
query = Cloudinary::Search.sort_by('created_at', 'asc').sort_by('updated_at', 'desc').to_h
|
26
|
-
expect(query).to eq(sort_by: [{ 'created_at' => 'asc' }, { 'updated_at' => 'desc' }])
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should add max_results to query' do
|
30
|
-
query = Cloudinary::Search.max_results(10).to_h
|
31
|
-
expect(query).to eq(max_results: 10)
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'should add next_cursor to query' do
|
35
|
-
query = Cloudinary::Search.next_cursor('ASDFIUHASF9832HAFSOF').to_h
|
36
|
-
expect(query).to eq(next_cursor: 'ASDFIUHASF9832HAFSOF')
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should add aggregations arguments as array to query' do
|
40
|
-
query = Cloudinary::Search.aggregate('format').aggregate('size_category').to_h
|
41
|
-
expect(query).to eq(aggregate: %w(format size_category))
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'should add with_field to query' do
|
45
|
-
query = Cloudinary::Search.with_field('context').with_field('tags').to_h
|
46
|
-
expect(query).to eq(with_field: %w(context tags))
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context 'integration' do
|
51
|
-
SEARCH_TAG = TIMESTAMP_TAG + "_search"
|
52
|
-
include_context 'cleanup', SEARCH_TAG
|
53
|
-
prefix = "api_test_#{SUFFIX}"
|
54
|
-
test_id_1 = "#{prefix}_1"
|
55
|
-
test_id_2 = "#{prefix}_2"
|
56
|
-
test_id_3 = "#{prefix}_3"
|
57
|
-
before(:all) do
|
58
|
-
Cloudinary::Uploader.upload(TEST_IMG, public_id: test_id_1, tags: [TEST_TAG, TIMESTAMP_TAG, SEARCH_TAG], context: 'stage=in_review')
|
59
|
-
Cloudinary::Uploader.upload(TEST_IMG, public_id: test_id_2, tags: [TEST_TAG, TIMESTAMP_TAG, SEARCH_TAG], context: 'stage=new')
|
60
|
-
Cloudinary::Uploader.upload(TEST_IMG, public_id: test_id_3, tags: [TEST_TAG, TIMESTAMP_TAG, SEARCH_TAG], context: 'stage=validated')
|
61
|
-
sleep(3)
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should return all images tagged with #{SEARCH_TAG}" do
|
65
|
-
results = Cloudinary::Search.expression("tags:#{SEARCH_TAG}").execute
|
66
|
-
expect(results['resources'].count).to eq 3
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should return resource #{test_id_1}" do
|
70
|
-
results = Cloudinary::Search.expression("public_id:#{test_id_1}").execute
|
71
|
-
expect(results['resources'].count).to eq 1
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'should paginate resources limited by tag and ordered by ascending public_id' do
|
75
|
-
results = Cloudinary::Search.max_results(1).expression("tags:#{SEARCH_TAG}").sort_by('public_id', 'asc').execute
|
76
|
-
expect(results['resources'].count).to eq 1
|
77
|
-
expect(results['resources'][0]['public_id']).to eq test_id_1
|
78
|
-
expect(results['total_count']).to eq 3
|
79
|
-
|
80
|
-
results = Cloudinary::Search.max_results(1).expression("tags:#{SEARCH_TAG}").sort_by('public_id', 'asc').next_cursor(results['next_cursor']).execute
|
81
|
-
expect(results['resources'].count).to eq 1
|
82
|
-
expect(results['resources'][0]['public_id']).to eq test_id_2
|
83
|
-
expect(results['total_count']).to eq 3
|
84
|
-
|
85
|
-
results = Cloudinary::Search.max_results(1).expression("tags:#{SEARCH_TAG}").sort_by('public_id', 'asc').next_cursor(results['next_cursor']).execute
|
86
|
-
expect(results['resources'].count).to eq 1
|
87
|
-
expect(results['resources'][0]['public_id']).to eq test_id_3
|
88
|
-
expect(results['total_count']).to eq 3
|
89
|
-
expect(results['next_cursor']).to be_nil
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'should include context' do
|
93
|
-
results = Cloudinary::Search.expression("tags:#{SEARCH_TAG}").with_field('context').execute
|
94
|
-
expect(results['resources'].count).to eq 3
|
95
|
-
results['resources'].each do |res|
|
96
|
-
expect(res['context'].keys).to eq ['stage']
|
97
|
-
end
|
98
|
-
end
|
99
|
-
it 'should include context, tags and image_metadata' do
|
100
|
-
results = Cloudinary::Search.expression("tags:#{SEARCH_TAG}").with_field('context').with_field('tags').with_field('image_metadata').execute
|
101
|
-
expect(results['resources'].count).to eq 3
|
102
|
-
results['resources'].each do |res|
|
103
|
-
expect(res['context'].keys).to eq ['stage']
|
104
|
-
expect(res.key?('image_metadata')).to eq true
|
105
|
-
expect(res['tags'].count).to eq 3
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,266 +0,0 @@
|
|
1
|
-
require 'rspec'
|
2
|
-
require 'rexml/parsers/ultralightparser'
|
3
|
-
require 'nokogiri'
|
4
|
-
require 'rspec/version'
|
5
|
-
require 'rest_client'
|
6
|
-
require 'cloudinary'
|
7
|
-
|
8
|
-
Cloudinary.config.enhance_image_tag = true
|
9
|
-
|
10
|
-
DUMMY_CLOUD = "test123"
|
11
|
-
TEST_IMAGE_URL = "http://cloudinary.com/images/old_logo.png"
|
12
|
-
TEST_IMG = "spec/logo.png"
|
13
|
-
TEST_IMG_W = 241
|
14
|
-
TEST_IMG_H = 51
|
15
|
-
SUFFIX = ENV['TRAVIS_JOB_ID'] || rand(999999999).to_s
|
16
|
-
TEST_TAG = 'cloudinary_gem_test'
|
17
|
-
TIMESTAMP_TAG = "#{TEST_TAG}_#{SUFFIX}_#{RUBY_VERSION}_#{ defined? Rails::version ? Rails::version : 'no_rails'}"
|
18
|
-
|
19
|
-
# Auth token
|
20
|
-
KEY = "00112233FF99"
|
21
|
-
ALT_KEY = "CCBB2233FF00"
|
22
|
-
CACHE_KEY = "some_key" + SUFFIX
|
23
|
-
|
24
|
-
module ResponsiveTest
|
25
|
-
TRANSFORMATION = {:angle => 45, :crop => "scale"}
|
26
|
-
FORMAT = "png"
|
27
|
-
IMAGE_BP_VALUES = [206, 50]
|
28
|
-
BREAKPOINTS = [100, 200, 300, 399]
|
29
|
-
|
30
|
-
end
|
31
|
-
Dir[File.join(File.dirname(__FILE__), '/support/**/*.rb')].each {|f| require f}
|
32
|
-
|
33
|
-
module RSpec
|
34
|
-
def self.project_root
|
35
|
-
File.join(File.dirname(__FILE__), '..')
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
40
|
-
RSpec.configure do |config|
|
41
|
-
unless RSpec::Version::STRING.match( /^3/)
|
42
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
43
|
-
end
|
44
|
-
config.run_all_when_everything_filtered = true
|
45
|
-
config.filter_run_excluding :delete_all => true
|
46
|
-
end
|
47
|
-
|
48
|
-
RSpec.shared_context "cleanup" do |tag|
|
49
|
-
tag ||= TEST_TAG
|
50
|
-
after :all do
|
51
|
-
Cloudinary::Api.delete_resources_by_tag(tag) unless Cloudinary.config.keep_test_products
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
module Cloudinary
|
56
|
-
def self.reset_config
|
57
|
-
@@config = nil
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
CALLS_SERVER_WITH_PARAMETERS = "calls server with parameters"
|
64
|
-
RSpec.shared_examples CALLS_SERVER_WITH_PARAMETERS do |expected|
|
65
|
-
expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
|
66
|
-
end
|
67
|
-
|
68
|
-
# Create a regexp with the given +tag+ name.
|
69
|
-
def html_tag_matcher( tag)
|
70
|
-
/<#{tag}([\s]+([-[:word:]]+)[\s]*\=\s*\"([^\"]*)\")*\s*>.*<\s*\/#{tag}\s*>/
|
71
|
-
end
|
72
|
-
|
73
|
-
# Represents an HTML tag
|
74
|
-
class TestTag
|
75
|
-
attr_accessor :element
|
76
|
-
# Creates a new +TestTag+ from a given +element+ string
|
77
|
-
def initialize(element)
|
78
|
-
@html_string = element
|
79
|
-
@element = valid_tag(element) unless element.is_a? Array
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
def name
|
84
|
-
@element.name
|
85
|
-
end
|
86
|
-
|
87
|
-
def attributes
|
88
|
-
@element.attributes
|
89
|
-
end
|
90
|
-
|
91
|
-
def children
|
92
|
-
@element.children
|
93
|
-
end
|
94
|
-
# Parses a given +tag+ in string format
|
95
|
-
def valid_tag(tag)
|
96
|
-
parser = Nokogiri::HTML::Document.parse( tag)
|
97
|
-
# Parsed code will be strctured as either html>body>tag or html>head>tag
|
98
|
-
parser.children[1].children[0].children[0]
|
99
|
-
end
|
100
|
-
|
101
|
-
# Returns attribute named +symbol_or_string+
|
102
|
-
def [](symbol_or_string)
|
103
|
-
begin
|
104
|
-
attributes[symbol_or_string.to_s].value
|
105
|
-
rescue
|
106
|
-
nil
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def method_missing(symbol, *args)
|
111
|
-
if (m = /children_by_(\w+)/.match(symbol.to_s)) and !args.empty?
|
112
|
-
return unless children
|
113
|
-
children.select{ |c| c[m[1]] == args[0]}
|
114
|
-
else
|
115
|
-
super
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def ==(other)
|
120
|
-
case other
|
121
|
-
when String
|
122
|
-
@text == other
|
123
|
-
else
|
124
|
-
other.respond_to?( :text) &&
|
125
|
-
other.respond_to?( :name) &&
|
126
|
-
other.respond_to?( :attributes) &&
|
127
|
-
other.respond_to?( :children) &&
|
128
|
-
@text == other.text &&
|
129
|
-
@name == other.name &&
|
130
|
-
@attributes == other.attributes &&
|
131
|
-
@children == other.children
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
RSpec::Matchers.define :produce_url do |expected_url|
|
137
|
-
match do |params|
|
138
|
-
public_id, options = params
|
139
|
-
actual_options = options.clone
|
140
|
-
@url = Cloudinary::Utils.cloudinary_url(public_id, actual_options)
|
141
|
-
values_match? expected_url, @url
|
142
|
-
end
|
143
|
-
failure_message do |actual|
|
144
|
-
"expected #{actual} to\nproduce: #{expected_url}\nbut got: #{@url}"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
RSpec::Matchers.define :mutate_options_to do |expected_options|
|
149
|
-
match do |params|
|
150
|
-
public_id, options = params
|
151
|
-
options = options.clone
|
152
|
-
Cloudinary::Utils.cloudinary_url(public_id, options)
|
153
|
-
@actual = options
|
154
|
-
values_match? expected_options, @actual
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
RSpec::Matchers.define :empty_options do
|
159
|
-
match do |params|
|
160
|
-
public_id, options = params
|
161
|
-
options = options.clone
|
162
|
-
Cloudinary::Utils.cloudinary_url(public_id, options)
|
163
|
-
options.empty?
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
# Verify that the given URL can be served by Cloudinary by fetching the resource from the server
|
168
|
-
RSpec::Matchers.define :be_served_by_cloudinary do
|
169
|
-
match do |url|
|
170
|
-
if url.is_a? Array
|
171
|
-
url, options = url
|
172
|
-
url = Cloudinary::Utils.cloudinary_url(url, options.clone)
|
173
|
-
if Cloudinary.config.upload_prefix
|
174
|
-
res_prefix_uri = URI.parse(Cloudinary.config.upload_prefix)
|
175
|
-
res_prefix_uri.path = '/res'
|
176
|
-
url.gsub!(/https?:\/\/res.cloudinary.com/, res_prefix_uri.to_s)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
code = 0
|
180
|
-
@url = url
|
181
|
-
RestClient.get @url do |response, request, result|
|
182
|
-
@result = result
|
183
|
-
code = response.code
|
184
|
-
end
|
185
|
-
values_match? 200, code
|
186
|
-
end
|
187
|
-
|
188
|
-
failure_message do |actual|
|
189
|
-
if @result
|
190
|
-
"Couldn't serve #{actual}. #{@result["status"]}: #{@result["x-cld-error"]}"
|
191
|
-
else
|
192
|
-
"Couldn't serve #{actual}."
|
193
|
-
end
|
194
|
-
end
|
195
|
-
failure_message_when_negated do |actual|
|
196
|
-
if @result
|
197
|
-
"Expected #{@url} not to be served by cloudinary. #{@result["status"]}: #{@result["x-cld-error"]}"
|
198
|
-
else
|
199
|
-
"Expected #{@url} not to be served by cloudinary."
|
200
|
-
end
|
201
|
-
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def deep_fetch(hash, path)
|
206
|
-
Array(path).reduce(hash) { |h, key| h && h.fetch(key, nil) }
|
207
|
-
end
|
208
|
-
|
209
|
-
# Matches deep values in the actual Hash, disregarding other keys and values.
|
210
|
-
# @example
|
211
|
-
# expect( {:foo => { :bar => 'foobar'}}).to have_deep_hash_values_of( [:foo, :bar] => 'foobar')
|
212
|
-
# expect( foo_instance).to receive(:bar_method).with(deep_hash_values_of([:foo, :bar] => 'foobar'))
|
213
|
-
RSpec::Matchers.define :deep_hash_value do |expected|
|
214
|
-
match do |actual|
|
215
|
-
expected.all? do |path, value|
|
216
|
-
Cloudinary.values_match? value, deep_fetch(actual, path)
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
RSpec::Matchers.alias_matcher :have_deep_hash_values_of, :deep_hash_value
|
222
|
-
|
223
|
-
module Cloudinary
|
224
|
-
# @api private
|
225
|
-
def self.values_match?(expected, actual)
|
226
|
-
if Hash === actual
|
227
|
-
return hashes_match?(expected, actual) if Hash === expected
|
228
|
-
elsif Array === expected && Enumerable === actual && !(Struct === actual)
|
229
|
-
return arrays_match?(expected, actual.to_a)
|
230
|
-
elsif Regexp === expected
|
231
|
-
return expected.match actual.to_s
|
232
|
-
end
|
233
|
-
|
234
|
-
|
235
|
-
return true if actual == expected
|
236
|
-
|
237
|
-
begin
|
238
|
-
expected === actual
|
239
|
-
rescue ArgumentError
|
240
|
-
# Some objects, like 0-arg lambdas on 1.9+, raise
|
241
|
-
# ArgumentError for `expected === actual`.
|
242
|
-
false
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
# @private
|
247
|
-
def self.arrays_match?(expected_list, actual_list)
|
248
|
-
return false if expected_list.size != actual_list.size
|
249
|
-
|
250
|
-
expected_list.zip(actual_list).all? do |expected, actual|
|
251
|
-
values_match?(expected, actual)
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
# @private
|
256
|
-
def self.hashes_match?(expected_hash, actual_hash)
|
257
|
-
return false if expected_hash.size != actual_hash.size
|
258
|
-
|
259
|
-
expected_hash.all? do |expected_key, expected_value|
|
260
|
-
actual_value = actual_hash.fetch(expected_key) { return false }
|
261
|
-
values_match?(expected_value, actual_value)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
private_class_method :arrays_match?, :hashes_match?
|
266
|
-
end
|