cloudinary 1.9.1 → 1.20.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|