cloudinary 1.9.1 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- 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 +7 -1
- data/.travis.yml +15 -8
- data/CHANGELOG.md +261 -0
- data/README.md +3 -0
- data/Rakefile +3 -45
- data/cloudinary.gemspec +27 -20
- data/lib/active_storage/blob_key.rb +20 -0
- data/lib/active_storage/service/cloudinary_service.rb +249 -0
- data/lib/cloudinary.rb +53 -63
- data/lib/cloudinary/account_api.rb +231 -0
- data/lib/cloudinary/account_config.rb +30 -0
- data/lib/cloudinary/api.rb +228 -71
- data/lib/cloudinary/auth_token.rb +10 -4
- data/lib/cloudinary/base_api.rb +79 -0
- data/lib/cloudinary/base_config.rb +70 -0
- data/lib/cloudinary/cache.rb +38 -0
- data/lib/cloudinary/cache/breakpoints_cache.rb +31 -0
- data/lib/cloudinary/cache/key_value_cache_adapter.rb +25 -0
- data/lib/cloudinary/cache/rails_cache_adapter.rb +34 -0
- data/lib/cloudinary/cache/storage/rails_cache_storage.rb +5 -0
- data/lib/cloudinary/carrier_wave.rb +4 -2
- data/lib/cloudinary/carrier_wave/remote.rb +3 -2
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/{controller.rb → cloudinary_controller.rb} +3 -5
- data/lib/cloudinary/config.rb +43 -0
- data/lib/cloudinary/helper.rb +77 -7
- data/lib/cloudinary/migrator.rb +3 -1
- data/lib/cloudinary/railtie.rb +7 -3
- data/lib/cloudinary/responsive.rb +111 -0
- data/lib/cloudinary/uploader.rb +67 -15
- data/lib/cloudinary/utils.rb +324 -54
- 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 +220 -0
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +51 -13
- 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 +92 -67
- data/spec/access_control_spec.rb +0 -99
- data/spec/api_spec.rb +0 -545
- data/spec/archive_spec.rb +0 -129
- data/spec/auth_token_spec.rb +0 -79
- data/spec/cloudinary_helper_spec.rb +0 -190
- 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/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 -245
- 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 -363
- data/spec/utils_methods_spec.rb +0 -54
- data/spec/utils_spec.rb +0 -906
- data/spec/video_tag_spec.rb +0 -251
- data/spec/video_url_spec.rb +0 -164
data/spec/favicon.ico
DELETED
Binary file
|
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,245 +0,0 @@
|
|
1
|
-
require 'rspec'
|
2
|
-
require 'rexml/parsers/ultralightparser'
|
3
|
-
require 'rspec/version'
|
4
|
-
require 'rest_client'
|
5
|
-
require 'cloudinary'
|
6
|
-
|
7
|
-
Cloudinary.config.enhance_image_tag = true
|
8
|
-
|
9
|
-
TEST_IMAGE_URL = "http://cloudinary.com/images/old_logo.png"
|
10
|
-
TEST_IMG = "spec/logo.png"
|
11
|
-
TEST_IMG_W = 241
|
12
|
-
TEST_IMG_H = 51
|
13
|
-
SUFFIX = ENV['TRAVIS_JOB_ID'] || rand(999999999).to_s
|
14
|
-
TEST_TAG = 'cloudinary_gem_test'
|
15
|
-
TIMESTAMP_TAG = "#{TEST_TAG}_#{SUFFIX}_#{RUBY_VERSION}_#{ defined? Rails::version ? Rails::version : 'no_rails'}"
|
16
|
-
|
17
|
-
# Auth token
|
18
|
-
KEY = "00112233FF99"
|
19
|
-
ALT_KEY = "CCBB2233FF00"
|
20
|
-
|
21
|
-
|
22
|
-
Dir[File.join(File.dirname(__FILE__), '/support/**/*.rb')].each {|f| require f}
|
23
|
-
|
24
|
-
module RSpec
|
25
|
-
def self.project_root
|
26
|
-
File.join(File.dirname(__FILE__), '..')
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
31
|
-
RSpec.configure do |config|
|
32
|
-
unless RSpec::Version::STRING.match( /^3/)
|
33
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
34
|
-
end
|
35
|
-
config.run_all_when_everything_filtered = true
|
36
|
-
config.filter_run_excluding :delete_all => true
|
37
|
-
end
|
38
|
-
|
39
|
-
RSpec.shared_context "cleanup" do |tag|
|
40
|
-
tag ||= TEST_TAG
|
41
|
-
after :all do
|
42
|
-
Cloudinary::Api.delete_resources_by_tag(tag) unless Cloudinary.config.keep_test_products
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
CALLS_SERVER_WITH_PARAMETERS = "calls server with parameters"
|
49
|
-
RSpec.shared_examples CALLS_SERVER_WITH_PARAMETERS do |expected|
|
50
|
-
expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
|
51
|
-
end
|
52
|
-
|
53
|
-
# Create a regexp with the given +tag+ name.
|
54
|
-
def html_tag_matcher( tag)
|
55
|
-
/<#{tag}([\s]+([-[:word:]]+)[\s]*\=\s*\"([^\"]*)\")*\s*>.*<\s*\/#{tag}\s*>/
|
56
|
-
end
|
57
|
-
|
58
|
-
# Represents an HTML tag
|
59
|
-
class TestTag
|
60
|
-
attr_accessor :name, :attributes, :children, :text, :html_string
|
61
|
-
# Creates a new +TestTag+ from a given +element+ string
|
62
|
-
def initialize(element)
|
63
|
-
@html_string = element
|
64
|
-
element = valid_tag(element) unless element.is_a? Array
|
65
|
-
case element[0]
|
66
|
-
when :start_element
|
67
|
-
@name = element[2]
|
68
|
-
@attributes = element[3]
|
69
|
-
@children = (Array(element[4..-1]) || []).map {|c | TestTag.new c}
|
70
|
-
when :text
|
71
|
-
@text = element[1]
|
72
|
-
@name = "text"
|
73
|
-
@attributes = []
|
74
|
-
@children = []
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
# Parses a given +tag+ in string format
|
80
|
-
def valid_tag(tag)
|
81
|
-
parser = REXML::Parsers::UltraLightParser.new( tag)
|
82
|
-
parser.parse[0]
|
83
|
-
end
|
84
|
-
|
85
|
-
# Returns attribute named +symbol_or_string+
|
86
|
-
def [](symbol_or_string)
|
87
|
-
attributes[symbol_or_string.to_s]
|
88
|
-
end
|
89
|
-
|
90
|
-
def method_missing(symbol, *args)
|
91
|
-
if (m = /children_by_(\w+)/.match(symbol.to_s)) and !args.empty?
|
92
|
-
@children.select{ |c| c[m[1]] == args[0]}
|
93
|
-
else
|
94
|
-
super
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def ==(other)
|
99
|
-
case other
|
100
|
-
when String
|
101
|
-
@text == other
|
102
|
-
else
|
103
|
-
other.respond_to?( :text) &&
|
104
|
-
other.respond_to?( :name) &&
|
105
|
-
other.respond_to?( :attributes) &&
|
106
|
-
other.respond_to?( :children) &&
|
107
|
-
@text == other.text &&
|
108
|
-
@name == other.name &&
|
109
|
-
@attributes == other.attributes &&
|
110
|
-
@children == other.children
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
RSpec::Matchers.define :produce_url do |expected_url|
|
116
|
-
match do |params|
|
117
|
-
public_id, options = params
|
118
|
-
actual_options = options.clone
|
119
|
-
@url = Cloudinary::Utils.cloudinary_url(public_id, actual_options)
|
120
|
-
values_match? expected_url, @url
|
121
|
-
end
|
122
|
-
failure_message do |actual|
|
123
|
-
"expected #{actual} to\nproduce: #{expected_url}\nbut got: #{@url}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
RSpec::Matchers.define :mutate_options_to do |expected_options|
|
128
|
-
match do |params|
|
129
|
-
public_id, options = params
|
130
|
-
options = options.clone
|
131
|
-
Cloudinary::Utils.cloudinary_url(public_id, options)
|
132
|
-
@actual = options
|
133
|
-
values_match? expected_options, @actual
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
RSpec::Matchers.define :empty_options do
|
138
|
-
match do |params|
|
139
|
-
public_id, options = params
|
140
|
-
options = options.clone
|
141
|
-
Cloudinary::Utils.cloudinary_url(public_id, options)
|
142
|
-
options.empty?
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
# Verify that the given URL can be served by Cloudinary by fetching the resource from the server
|
147
|
-
RSpec::Matchers.define :be_served_by_cloudinary do
|
148
|
-
match do |url|
|
149
|
-
if url.is_a? Array
|
150
|
-
url, options = url
|
151
|
-
url = Cloudinary::Utils.cloudinary_url(url, options.clone)
|
152
|
-
if Cloudinary.config.upload_prefix
|
153
|
-
res_prefix_uri = URI.parse(Cloudinary.config.upload_prefix)
|
154
|
-
res_prefix_uri.path = '/res'
|
155
|
-
url.gsub!(/https?:\/\/res.cloudinary.com/, res_prefix_uri.to_s)
|
156
|
-
end
|
157
|
-
end
|
158
|
-
code = 0
|
159
|
-
@url = url
|
160
|
-
RestClient.get @url do |response, request, result|
|
161
|
-
@result = result
|
162
|
-
code = response.code
|
163
|
-
end
|
164
|
-
values_match? 200, code
|
165
|
-
end
|
166
|
-
|
167
|
-
failure_message do |actual|
|
168
|
-
if @result
|
169
|
-
"Couldn't serve #{actual}. #{@result["status"]}: #{@result["x-cld-error"]}"
|
170
|
-
else
|
171
|
-
"Couldn't serve #{actual}."
|
172
|
-
end
|
173
|
-
end
|
174
|
-
failure_message_when_negated do |actual|
|
175
|
-
if @result
|
176
|
-
"Expected #{@url} not to be served by cloudinary. #{@result["status"]}: #{@result["x-cld-error"]}"
|
177
|
-
else
|
178
|
-
"Expected #{@url} not to be served by cloudinary."
|
179
|
-
end
|
180
|
-
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def deep_fetch(hash, path)
|
185
|
-
Array(path).reduce(hash) { |h, key| h && h.fetch(key, nil) }
|
186
|
-
end
|
187
|
-
|
188
|
-
# Matches deep values in the actual Hash, disregarding other keys and values.
|
189
|
-
# @example
|
190
|
-
# expect( {:foo => { :bar => 'foobar'}}).to have_deep_hash_values_of( [:foo, :bar] => 'foobar')
|
191
|
-
# expect( foo_instance).to receive(:bar_method).with(deep_hash_values_of([:foo, :bar] => 'foobar'))
|
192
|
-
RSpec::Matchers.define :deep_hash_value do |expected|
|
193
|
-
match do |actual|
|
194
|
-
expected.all? do |path, value|
|
195
|
-
Cloudinary.values_match? value, deep_fetch(actual, path)
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
RSpec::Matchers.alias_matcher :have_deep_hash_values_of, :deep_hash_value
|
201
|
-
|
202
|
-
module Cloudinary
|
203
|
-
# @api private
|
204
|
-
def self.values_match?(expected, actual)
|
205
|
-
if Hash === actual
|
206
|
-
return hashes_match?(expected, actual) if Hash === expected
|
207
|
-
elsif Array === expected && Enumerable === actual && !(Struct === actual)
|
208
|
-
return arrays_match?(expected, actual.to_a)
|
209
|
-
elsif Regexp === expected
|
210
|
-
return expected.match actual.to_s
|
211
|
-
end
|
212
|
-
|
213
|
-
|
214
|
-
return true if actual == expected
|
215
|
-
|
216
|
-
begin
|
217
|
-
expected === actual
|
218
|
-
rescue ArgumentError
|
219
|
-
# Some objects, like 0-arg lambdas on 1.9+, raise
|
220
|
-
# ArgumentError for `expected === actual`.
|
221
|
-
false
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
# @private
|
226
|
-
def self.arrays_match?(expected_list, actual_list)
|
227
|
-
return false if expected_list.size != actual_list.size
|
228
|
-
|
229
|
-
expected_list.zip(actual_list).all? do |expected, actual|
|
230
|
-
values_match?(expected, actual)
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
# @private
|
235
|
-
def self.hashes_match?(expected_hash, actual_hash)
|
236
|
-
return false if expected_hash.size != actual_hash.size
|
237
|
-
|
238
|
-
expected_hash.all? do |expected_key, expected_value|
|
239
|
-
actual_value = actual_hash.fetch(expected_key) { return false }
|
240
|
-
values_match?(expected_value, actual_value)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
private_class_method :arrays_match?, :hashes_match?
|
245
|
-
end
|