cloudinary 1.11.1 → 1.18.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  4. data/.github/pull_request_template.md +24 -0
  5. data/.gitignore +6 -1
  6. data/.travis.yml +15 -5
  7. data/CHANGELOG.md +149 -0
  8. data/Rakefile +3 -45
  9. data/cloudinary.gemspec +20 -4
  10. data/lib/active_storage/blob_key.rb +20 -0
  11. data/lib/active_storage/service/cloudinary_service.rb +229 -0
  12. data/lib/cloudinary.rb +31 -22
  13. data/lib/cloudinary/api.rb +173 -5
  14. data/lib/cloudinary/auth_token.rb +6 -4
  15. data/lib/cloudinary/carrier_wave.rb +3 -1
  16. data/lib/cloudinary/carrier_wave/remote.rb +3 -2
  17. data/lib/cloudinary/carrier_wave/storage.rb +2 -1
  18. data/lib/cloudinary/cloudinary_controller.rb +2 -4
  19. data/lib/cloudinary/helper.rb +30 -3
  20. data/lib/cloudinary/railtie.rb +7 -3
  21. data/lib/cloudinary/uploader.rb +35 -6
  22. data/lib/cloudinary/utils.rb +112 -40
  23. data/lib/cloudinary/version.rb +1 -1
  24. data/lib/cloudinary/video_helper.rb +96 -22
  25. data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
  26. data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
  27. data/tools/allocate_test_cloud.sh +9 -0
  28. data/tools/get_test_cloud.sh +9 -0
  29. data/tools/update_version +29 -11
  30. data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +48 -14
  31. data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +24 -4
  32. data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +741 -561
  33. data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -1
  34. metadata +62 -67
  35. data/spec/access_control_spec.rb +0 -102
  36. data/spec/api_spec.rb +0 -567
  37. data/spec/archive_spec.rb +0 -129
  38. data/spec/auth_token_spec.rb +0 -77
  39. data/spec/cache_spec.rb +0 -109
  40. data/spec/cloudinary_helper_spec.rb +0 -325
  41. data/spec/cloudinary_spec.rb +0 -32
  42. data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
  43. data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
  44. data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
  45. data/spec/docx.docx +0 -0
  46. data/spec/favicon.ico +0 -0
  47. data/spec/image_spec.rb +0 -107
  48. data/spec/logo.png +0 -0
  49. data/spec/rake_spec.rb +0 -160
  50. data/spec/sample_asset_file.tsv +0 -4
  51. data/spec/search_spec.rb +0 -109
  52. data/spec/spec_helper.rb +0 -266
  53. data/spec/storage_spec.rb +0 -44
  54. data/spec/streaminig_profiles_api_spec.rb +0 -74
  55. data/spec/support/helpers/temp_file_helpers.rb +0 -22
  56. data/spec/support/shared_contexts/rake.rb +0 -19
  57. data/spec/uploader_spec.rb +0 -392
  58. data/spec/utils_methods_spec.rb +0 -54
  59. data/spec/utils_spec.rb +0 -970
  60. data/spec/video_tag_spec.rb +0 -253
  61. data/spec/video_url_spec.rb +0 -185
@@ -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!");}
@@ -1,3 +0,0 @@
1
- p#css {
2
- color: red;
3
- }
Binary file
Binary file
@@ -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
Binary file
@@ -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
@@ -1,4 +0,0 @@
1
- public_path public_id upload_time.to_i version width height
2
- stylesheets/foo.css css-foo 123 1 100 100
3
- javascripts/bar.js bar 123 1 100 100
4
- images/foo.jpg images-foo 123 1 100 100
@@ -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
@@ -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