cloudsight 0.0.5 → 0.0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +35 -0
- data/.rspec +1 -0
- data/.travis.yml +19 -0
- data/README.md +2 -2
- data/Rakefile +4 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/cloudsight.gemspec +14 -15
- data/lib/cloudsight.rb +12 -115
- data/lib/cloudsight/api.rb +32 -0
- data/lib/cloudsight/request.rb +47 -0
- data/lib/cloudsight/response.rb +30 -0
- data/lib/cloudsight/version.rb +3 -0
- data/spec/cloudsight/api_spec.rb +75 -0
- data/spec/cloudsight/request_spec.rb +123 -0
- data/spec/cloudsight/response_spec.rb +74 -0
- data/spec/cloudsight_spec.rb +24 -0
- data/spec/fixtures/completed_response.json +8 -0
- data/spec/fixtures/error_response.json +9 -0
- data/spec/fixtures/image_request.json +5 -0
- data/spec/fixtures/unexpected_response.json +6 -0
- data/spec/spec_helper.rb +55 -0
- metadata +104 -17
- data/Gemfile.lock +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9d0460a23e0f0707d9ddb9f2bb55498c620f850
|
4
|
+
data.tar.gz: 20c8412535ce925d41a25e69d1d5df650d4ac11b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4aaaf8b6c0a018ddd99b54e1b486c250a5f63240ed37d899797765fe5ba72f7396df4bd693c38bd45386c6c219789e8c0dc19341554f53a344089ad952f37b5c
|
7
|
+
data.tar.gz: 8a6dcc5478f4047437e5a045b702f8b320b72ebcb0ebef12dcbe06dac0a1c361409fb5ec6620b3928357a72dba22f8af33fa1d782696c09a27838e9b21806c56
|
data/.gitignore
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
Gemfile.lock
|
30
|
+
.ruby-version
|
31
|
+
.ruby-gemset
|
32
|
+
.rspec_status
|
33
|
+
|
34
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
35
|
+
.rvmrc
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -5,8 +5,8 @@ A simple CloudSight API Client
|
|
5
5
|
|
6
6
|
| Project | Gem Release |
|
7
7
|
|------------------------ | ----------------- |
|
8
|
-
| gem name |
|
9
|
-
| version | [![Gem Version](https://badge.fury.io/rb/
|
8
|
+
| gem name | cloudsight |
|
9
|
+
| version | [![Gem Version](https://badge.fury.io/rb/cloudsight.svg)](https://badge.fury.io/rb/cloudsight)
|
10
10
|
| continuous integration | [![Build Status](https://secure.travis-ci.org/cloudsight/cloudsight-ruby.png?branch=master)](https://travis-ci.org/cloudsight/cloudsight-ruby) |
|
11
11
|
|
12
12
|
Installation
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
data/cloudsight.gemspec
CHANGED
@@ -6,30 +6,29 @@ require 'cloudsight/version'
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = 'cloudsight'
|
8
8
|
s.version = Cloudsight::VERSION
|
9
|
-
s.date = '2015-11-05'
|
10
9
|
s.summary = "CloudSight API Client"
|
11
10
|
s.description = "A simple CloudSight API Client for Image Recognition"
|
12
|
-
s.authors = ['Brad Folkens']
|
13
|
-
s.email = '
|
11
|
+
s.authors = ['Brad Folkens', 'Jack McCallum', 'Chris Weilemann']
|
12
|
+
s.email = 'oss@cloudsight.ai'
|
14
13
|
s.homepage = 'http://github.com/cloudsight/cloudsight-ruby'
|
15
14
|
s.license = 'MIT'
|
16
15
|
s.platform = Gem::Platform::RUBY
|
17
16
|
|
18
|
-
s.files
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
'MIT-LICENSE',
|
23
|
-
'README.md',
|
24
|
-
'cloudsight.gemspec'
|
25
|
-
]
|
17
|
+
s.files = `git ls-files`.split($/)
|
18
|
+
s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
19
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
20
|
+
|
26
21
|
s.require_paths = [%q{lib}]
|
27
22
|
|
28
|
-
s.required_ruby_version = Gem::Requirement.new('>=
|
23
|
+
s.required_ruby_version = Gem::Requirement.new('>= 2.1')
|
29
24
|
|
30
|
-
s.add_dependency 'json'
|
31
|
-
s.add_dependency 'rest-client', '~>
|
25
|
+
s.add_dependency 'json', '~> 2.1'
|
26
|
+
s.add_dependency 'rest-client', '~> 2.0'
|
32
27
|
|
33
28
|
s.add_development_dependency 'bundler', '~> 1.6'
|
34
|
-
s.add_development_dependency 'rake'
|
29
|
+
s.add_development_dependency 'rake', '~> 12.0'
|
30
|
+
s.add_development_dependency 'rspec', '~> 3.6'
|
31
|
+
s.add_development_dependency 'pry', '~> 0.10'
|
32
|
+
s.add_development_dependency 'webmock', '~> 3.0'
|
33
|
+
s.add_development_dependency 'simple_oauth', '~> 0.3'
|
35
34
|
end
|
data/lib/cloudsight.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rest-client'
|
3
3
|
begin
|
4
4
|
require 'simple_oauth'
|
5
|
-
rescue LoadError
|
5
|
+
rescue LoadError
|
6
6
|
# Tolerate not having this unless it's actually configured
|
7
7
|
end
|
8
8
|
require 'json'
|
@@ -11,129 +11,26 @@ module Cloudsight
|
|
11
11
|
BASE_URL = 'https://api.cloudsight.ai'
|
12
12
|
|
13
13
|
class << self
|
14
|
+
FIELDS = %w(api_key oauth_options base_url)
|
15
|
+
attr_accessor(*FIELDS)
|
16
|
+
|
14
17
|
def oauth_options=(val)
|
15
|
-
raise RuntimeError.new(
|
18
|
+
raise RuntimeError.new(
|
19
|
+
"Could not load the simple_oauth gem. Install it with `gem install simple_oauth`."
|
20
|
+
) unless defined?(SimpleOAuth::Header)
|
16
21
|
|
17
22
|
val = val.inject({}) {|memo, (k, v)| memo[k.to_sym] = v; memo }
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def api_key=(val)
|
22
|
-
@@api_key = val
|
23
|
-
end
|
24
|
-
|
25
|
-
def api_key
|
26
|
-
@@api_key if defined?(@@api_key)
|
27
|
-
end
|
28
|
-
|
29
|
-
def oauth_options
|
30
|
-
@@oauth_options if defined?(@@oauth_options)
|
31
|
-
end
|
32
|
-
|
33
|
-
def base_url=(val)
|
34
|
-
@@base_url = val
|
23
|
+
@oauth_options = val
|
35
24
|
end
|
36
25
|
|
37
26
|
def base_url
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class Util
|
43
|
-
def self.post(url, params, headers = {})
|
44
|
-
headers['Authorization'] = authorization_header(:post, url, params)
|
45
|
-
RestClient.post(url, params, headers)
|
46
|
-
rescue RestClient::Exception => e
|
47
|
-
e.response
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.get(url, headers = {})
|
51
|
-
headers['Authorization'] = authorization_header(:get, url)
|
52
|
-
RestClient.get(url, headers)
|
53
|
-
rescue RestClient::Exception => e
|
54
|
-
e.response
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.authorization_header(http_method, url, params = {})
|
58
|
-
if Cloudsight.api_key
|
59
|
-
"CloudSight #{Cloudsight.api_key}"
|
60
|
-
else
|
61
|
-
# Exclude image file when generating OAuth header
|
62
|
-
filtered_payload = params.dup
|
63
|
-
filtered_payload.delete('image_request[image]')
|
64
|
-
|
65
|
-
oauth = SimpleOAuth::Header.new(http_method, url, filtered_payload, Cloudsight.oauth_options || {})
|
66
|
-
oauth.to_s
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
class Request
|
72
|
-
def self.send(options = {})
|
73
|
-
raise RuntimeError.new("Need to define either oauth_options or api_key") unless Cloudsight.api_key || Cloudsight.oauth_options
|
74
|
-
url = "#{Cloudsight::base_url}/image_requests"
|
75
|
-
|
76
|
-
params = {}
|
77
|
-
[:locale, :language, :latitude, :longitude, :altitude, :device_id, :ttl].each do |attr|
|
78
|
-
params["image_request[#{attr}]"] = options[attr] if options.has_key?(attr)
|
79
|
-
end
|
80
|
-
|
81
|
-
if options[:focus]
|
82
|
-
params['focus[x]'] = options[:focus][:x]
|
83
|
-
params['focus[y]'] = options[:focus][:y]
|
84
|
-
end
|
85
|
-
|
86
|
-
params['image_request[remote_image_url]'] = options[:url] if options.has_key?(:url)
|
87
|
-
params['image_request[image]'] = options[:file] if options.has_key?(:file)
|
88
|
-
|
89
|
-
response = Util.post(url, params)
|
90
|
-
data = JSON.parse(response.body)
|
91
|
-
raise ResponseException.new(data['error']) if data['error']
|
92
|
-
raise UnexpectedResponseException.new(response.body) unless data['token']
|
93
|
-
|
94
|
-
data
|
95
|
-
end
|
96
|
-
|
97
|
-
def self.repost(token, options = {})
|
98
|
-
url = "#{Cloudsight::base_url}/image_requests/#{token}/repost"
|
99
|
-
|
100
|
-
response = Util.post(url, options)
|
101
|
-
return true if response.code == 200 and response.body.to_s.strip.empty?
|
102
|
-
|
103
|
-
data = JSON.parse(response.body)
|
104
|
-
raise ResponseException.new(data['error']) if data['error']
|
105
|
-
raise UnexpectedResponseException.new(response.body) unless data['token']
|
106
|
-
|
107
|
-
data
|
27
|
+
@base_url ||= BASE_URL
|
108
28
|
end
|
109
29
|
end
|
110
30
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
response = Util.get(url)
|
116
|
-
data = JSON.parse(response.body)
|
117
|
-
raise ResponseException.new(data['error']) if data['error']
|
118
|
-
raise UnexpectedResponseException.new(response.body) unless data['status']
|
119
|
-
|
120
|
-
data
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.retrieve(token, options = {})
|
124
|
-
options = { poll_wait: 1 }.merge(options)
|
125
|
-
|
126
|
-
data = nil
|
127
|
-
loop do
|
128
|
-
sleep options[:poll_wait]
|
129
|
-
data = Cloudsight::Response.get(token, options)
|
130
|
-
yield data if block_given?
|
131
|
-
break if data['status'] != 'not completed' and data['status'] != 'in progress'
|
132
|
-
end
|
133
|
-
|
134
|
-
data
|
135
|
-
end
|
136
|
-
end
|
31
|
+
require 'cloudsight/api'
|
32
|
+
require 'cloudsight/request'
|
33
|
+
require 'cloudsight/response'
|
137
34
|
|
138
35
|
class ResponseException < Exception; end
|
139
36
|
class UnexpectedResponseException < Exception; end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Cloudsight
|
2
|
+
class Api
|
3
|
+
class << self
|
4
|
+
def post(url, params, headers = {})
|
5
|
+
headers['Authorization'] = authorization_header(:post, url, params)
|
6
|
+
RestClient.post(url, params, headers)
|
7
|
+
rescue RestClient::Exception => e
|
8
|
+
e.response
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(url, headers = {})
|
12
|
+
headers['Authorization'] = authorization_header(:get, url)
|
13
|
+
RestClient.get(url, headers)
|
14
|
+
rescue RestClient::Exception => e
|
15
|
+
e.response
|
16
|
+
end
|
17
|
+
|
18
|
+
def authorization_header(http_method, url, params = {})
|
19
|
+
if Cloudsight.api_key
|
20
|
+
"CloudSight #{Cloudsight.api_key}"
|
21
|
+
else
|
22
|
+
# Exclude image file when generating OAuth header
|
23
|
+
filtered_payload = params.dup
|
24
|
+
filtered_payload.delete('image_request[image]')
|
25
|
+
|
26
|
+
oauth = SimpleOAuth::Header.new(http_method, url, filtered_payload, Cloudsight.oauth_options || {})
|
27
|
+
oauth.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Cloudsight
|
2
|
+
class Request
|
3
|
+
class << self
|
4
|
+
def send(options = {})
|
5
|
+
raise RuntimeError.new("Need to define either oauth_options or api_key") unless Cloudsight.api_key || Cloudsight.oauth_options
|
6
|
+
url = "#{Cloudsight::base_url}/image_requests"
|
7
|
+
|
8
|
+
params = construct_params(options)
|
9
|
+
response = Api.post(url, params)
|
10
|
+
data = JSON.parse(response.body)
|
11
|
+
raise ResponseException.new(data['error']) if data['error']
|
12
|
+
raise UnexpectedResponseException.new(response.body) unless data['token']
|
13
|
+
|
14
|
+
data
|
15
|
+
end
|
16
|
+
|
17
|
+
def repost(token, options = {})
|
18
|
+
url = "#{Cloudsight::base_url}/image_requests/#{token}/repost"
|
19
|
+
|
20
|
+
response = Api.post(url, options)
|
21
|
+
return true if response.code == 200 and response.body.to_s.strip.empty?
|
22
|
+
|
23
|
+
data = JSON.parse(response.body)
|
24
|
+
raise ResponseException.new(data['error']) if data['error']
|
25
|
+
raise UnexpectedResponseException.new(response.body) unless data['token']
|
26
|
+
|
27
|
+
data
|
28
|
+
end
|
29
|
+
|
30
|
+
def construct_params(options)
|
31
|
+
params = {}
|
32
|
+
[:locale, :language, :latitude, :longitude, :altitude, :device_id, :ttl].each do |attr|
|
33
|
+
params["image_request[#{attr}]"] = options[attr] if options.has_key?(attr)
|
34
|
+
end
|
35
|
+
|
36
|
+
if options[:focus]
|
37
|
+
params['focus[x]'] = options[:focus][:x]
|
38
|
+
params['focus[y]'] = options[:focus][:y]
|
39
|
+
end
|
40
|
+
|
41
|
+
params['image_request[remote_image_url]'] = options[:url] if options.has_key?(:url)
|
42
|
+
params['image_request[image]'] = options[:file] if options.has_key?(:file)
|
43
|
+
params
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Cloudsight
|
2
|
+
class Response
|
3
|
+
class << self
|
4
|
+
def get(token, options = {})
|
5
|
+
url = "#{Cloudsight::base_url}/image_responses/#{token}"
|
6
|
+
|
7
|
+
response = Api.get(url)
|
8
|
+
data = JSON.parse(response.body)
|
9
|
+
raise ResponseException.new(data['error']) if data['error']
|
10
|
+
raise UnexpectedResponseException.new(response.body) unless data['status']
|
11
|
+
|
12
|
+
data
|
13
|
+
end
|
14
|
+
|
15
|
+
def retrieve(token, options = {})
|
16
|
+
options = { poll_wait: 1 }.merge(options)
|
17
|
+
|
18
|
+
data = nil
|
19
|
+
loop do
|
20
|
+
sleep options[:poll_wait]
|
21
|
+
data = Cloudsight::Response.get(token, options)
|
22
|
+
yield data if block_given?
|
23
|
+
break if data['status'] != 'not completed' and data['status'] != 'in progress'
|
24
|
+
end
|
25
|
+
|
26
|
+
data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'simple_oauth'
|
3
|
+
|
4
|
+
RSpec.describe Cloudsight::Api do
|
5
|
+
|
6
|
+
describe '#authorization_header' do
|
7
|
+
context 'with an api_key' do
|
8
|
+
it 'returns the proper header' do
|
9
|
+
Cloudsight.api_key = 'test_api_key'
|
10
|
+
header = described_class.authorization_header(:get, 'test')
|
11
|
+
expect(header).to eq 'CloudSight test_api_key'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with simple oauth' do
|
16
|
+
it 'returns the proper header' do
|
17
|
+
Cloudsight.oauth_options = {
|
18
|
+
consumer_key: 'test_consumer_key',
|
19
|
+
consumer_secret: 'test_consumer_secret'
|
20
|
+
}
|
21
|
+
|
22
|
+
header = described_class.authorization_header(:get, 'https://example.com', { image_request: {} })
|
23
|
+
expect(header).to match(/OAuth oauth_consumer_key=/)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#post' do
|
29
|
+
let(:url) { 'https://example.com' }
|
30
|
+
|
31
|
+
it 'should post with the correct params' do
|
32
|
+
allow(described_class).to receive(:authorization_header).and_return("CloudSight test_api_key")
|
33
|
+
|
34
|
+
expect(RestClient).to receive(:post).with(
|
35
|
+
url, {}, {"Authorization"=>"CloudSight test_api_key"}
|
36
|
+
)
|
37
|
+
|
38
|
+
described_class.post(url, {})
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should return the response if there is one' do
|
42
|
+
allow(described_class).to receive(:authorization_header).and_return("CloudSight test_api_key")
|
43
|
+
|
44
|
+
allow(RestClient).to receive(:post).with(
|
45
|
+
url, {}, {"Authorization"=>"CloudSight test_api_key"}
|
46
|
+
).and_raise(RestClient::Exception)
|
47
|
+
|
48
|
+
expect { described_class.post(url, {}) }.to_not raise_error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#get' do
|
53
|
+
let(:url) { 'https://example.com' }
|
54
|
+
|
55
|
+
it 'should post with the correct params' do
|
56
|
+
allow(described_class).to receive(:authorization_header).and_return("CloudSight test_api_key")
|
57
|
+
|
58
|
+
expect(RestClient).to receive(:get).with(
|
59
|
+
url, {"Authorization"=>"CloudSight test_api_key"}
|
60
|
+
)
|
61
|
+
|
62
|
+
described_class.get(url, {})
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should return the response if there is one' do
|
66
|
+
allow(described_class).to receive(:authorization_header).and_return("CloudSight test_api_key")
|
67
|
+
|
68
|
+
allow(RestClient).to receive(:get).with(
|
69
|
+
url, {"Authorization"=>"CloudSight test_api_key"}
|
70
|
+
).and_raise(RestClient::Exception)
|
71
|
+
|
72
|
+
expect { described_class.get(url, {}) }.to_not raise_error
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Cloudsight::Request do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Cloudsight.api_key = 'test_api_key'
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#construct_params' do
|
10
|
+
let(:params) do
|
11
|
+
{
|
12
|
+
locale: 'en',
|
13
|
+
language: 'en',
|
14
|
+
latitude: '5',
|
15
|
+
longitude: '5',
|
16
|
+
altitude: '5',
|
17
|
+
device_id: '5',
|
18
|
+
ttl: '5',
|
19
|
+
url: 'test_url',
|
20
|
+
file: 'test_file',
|
21
|
+
focus: {
|
22
|
+
x: '5',
|
23
|
+
y: '5'
|
24
|
+
}
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'correctly constructs the params' do
|
29
|
+
options = described_class.construct_params(params)
|
30
|
+
expect(options).to eq(
|
31
|
+
{
|
32
|
+
'image_request[locale]' => 'en',
|
33
|
+
'image_request[language]' => 'en',
|
34
|
+
'image_request[latitude]' => '5',
|
35
|
+
'image_request[longitude]' => '5',
|
36
|
+
'image_request[altitude]' => '5',
|
37
|
+
'image_request[device_id]' => '5',
|
38
|
+
'image_request[ttl]' => '5',
|
39
|
+
'image_request[remote_image_url]' => 'test_url',
|
40
|
+
'image_request[image]' => 'test_file',
|
41
|
+
'focus[x]' => '5',
|
42
|
+
'focus[y]' => '5'
|
43
|
+
}
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#send' do
|
49
|
+
let(:params) { { locale: 'en', url: 'test_url' } }
|
50
|
+
|
51
|
+
it 'returns the proper result' do
|
52
|
+
stub_post(
|
53
|
+
path: '/image_requests',
|
54
|
+
body: { "image_request"=>{ "locale"=>"en", "remote_image_url"=>"test_url" } },
|
55
|
+
response: fixture_file('image_request.json')
|
56
|
+
)
|
57
|
+
|
58
|
+
response = described_class.send(params)
|
59
|
+
|
60
|
+
expect(response["token"]).to eq "sample_token"
|
61
|
+
expect(response["url"]).to eq "https://example.com/image.jpg"
|
62
|
+
expect(response["status"]).to eq "not completed"
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'responds correctly to a response exception error' do
|
66
|
+
stub_post(
|
67
|
+
path: '/image_requests',
|
68
|
+
body: { "image_request"=>{ "locale"=>"en", "remote_image_url"=>"test_url" } },
|
69
|
+
response: fixture_file('error_response.json')
|
70
|
+
)
|
71
|
+
|
72
|
+
expect { described_class.send(params) }.to raise_error Cloudsight::ResponseException
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'responds correctly to an unexpected response' do
|
76
|
+
stub_post(
|
77
|
+
path: '/image_requests',
|
78
|
+
body: { "image_request"=>{ "locale"=>"en", "remote_image_url"=>"test_url" } },
|
79
|
+
response: fixture_file('unexpected_response.json')
|
80
|
+
)
|
81
|
+
|
82
|
+
expect { described_class.send(params) }.to raise_error Cloudsight::UnexpectedResponseException
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#repost' do
|
87
|
+
let(:params) { { image_request: { locale: 'en', remote_image_url: 'test_url' } } }
|
88
|
+
|
89
|
+
it 'returns the proper result' do
|
90
|
+
stub_post(
|
91
|
+
path: '/image_requests/sample_token/repost',
|
92
|
+
body: { "image_request"=>{ "locale"=>"en", "remote_image_url"=>"test_url" } },
|
93
|
+
response: fixture_file('image_request.json')
|
94
|
+
)
|
95
|
+
|
96
|
+
response = described_class.repost('sample_token', params)
|
97
|
+
|
98
|
+
expect(response["token"]).to eq "sample_token"
|
99
|
+
expect(response["url"]).to eq "https://example.com/image.jpg"
|
100
|
+
expect(response["status"]).to eq "not completed"
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'responds correctly to a response exception error' do
|
104
|
+
stub_post(
|
105
|
+
path: '/image_requests/sample_token/repost',
|
106
|
+
body: { "image_request"=>{ "locale"=>"en", "remote_image_url"=>"test_url" } },
|
107
|
+
response: fixture_file('error_response.json')
|
108
|
+
)
|
109
|
+
|
110
|
+
expect { described_class.repost('sample_token', params) }.to raise_error Cloudsight::ResponseException
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'responds correctly to an unexpected response' do
|
114
|
+
stub_post(
|
115
|
+
path: '/image_requests/sample_token/repost',
|
116
|
+
body: { "image_request"=>{ "locale"=>"en", "remote_image_url"=>"test_url" } },
|
117
|
+
response: fixture_file('unexpected_response.json')
|
118
|
+
)
|
119
|
+
|
120
|
+
expect { described_class.repost('sample_token', params) }.to raise_error Cloudsight::UnexpectedResponseException
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Cloudsight::Response do
|
4
|
+
before(:each) do
|
5
|
+
Cloudsight.api_key = 'test_api_key'
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#get' do
|
9
|
+
it 'returns the proper result' do
|
10
|
+
stub_get(
|
11
|
+
path: '/image_responses/sample_token',
|
12
|
+
response: fixture_file('completed_response.json')
|
13
|
+
)
|
14
|
+
|
15
|
+
response = described_class.get('sample_token')
|
16
|
+
|
17
|
+
expect(response["token"]).to eq "sample_token"
|
18
|
+
expect(response["url"]).to eq "http://www.example.com/your_headphones_image.jpg"
|
19
|
+
expect(response["status"]).to eq "completed"
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'responds correctly to a response exception error' do
|
23
|
+
stub_get(
|
24
|
+
path: '/image_responses/sample_token',
|
25
|
+
response: fixture_file('error_response.json')
|
26
|
+
)
|
27
|
+
|
28
|
+
expect { described_class.get('sample_token') }.to raise_error Cloudsight::ResponseException
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'responds correctly to an unexpected response' do
|
32
|
+
stub_get(
|
33
|
+
path: '/image_responses/sample_token',
|
34
|
+
response: fixture_file('unexpected_response.json')
|
35
|
+
)
|
36
|
+
|
37
|
+
expect { described_class.get('sample_token') }.to raise_error Cloudsight::UnexpectedResponseException
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#retrieve' do
|
42
|
+
it 'returns the proper result' do
|
43
|
+
stub_polling(3, 'image_request.json', 'completed_response.json', '/image_responses/sample_token')
|
44
|
+
|
45
|
+
response = described_class.retrieve('sample_token', poll_wait: 0.01)
|
46
|
+
|
47
|
+
expect(response["token"]).to eq "sample_token"
|
48
|
+
expect(response["url"]).to eq "http://www.example.com/your_headphones_image.jpg"
|
49
|
+
expect(response["status"]).to eq "completed"
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'responds correctly to a response exception error' do
|
53
|
+
stub_polling(3, 'image_request.json', 'error_response.json', '/image_responses/sample_token')
|
54
|
+
|
55
|
+
expect { described_class.retrieve('sample_token', poll_wait: 0.01) }.to raise_error Cloudsight::ResponseException
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'responds correctly to an unexpected response' do
|
59
|
+
stub_polling(3, 'image_request.json', 'unexpected_response.json', '/image_responses/sample_token')
|
60
|
+
|
61
|
+
expect { described_class.retrieve('sample_token', poll_wait: 0.01) }.to raise_error Cloudsight::UnexpectedResponseException
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def stub_polling(num_retries, file_1, file_2, path)
|
67
|
+
retries = 0
|
68
|
+
while retries < num_retries
|
69
|
+
stub_get(path: path, response: fixture_file(file_1))
|
70
|
+
retries += 1
|
71
|
+
end
|
72
|
+
|
73
|
+
stub_get(path: path, response: fixture_file(file_2))
|
74
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'simple_oauth'
|
3
|
+
|
4
|
+
RSpec.describe Cloudsight do
|
5
|
+
context 'initialization' do
|
6
|
+
it 'should assign the proper basic attributes' do
|
7
|
+
Cloudsight.api_key = 'test_api_key'
|
8
|
+
Cloudsight.base_url = 'test_base_url'
|
9
|
+
|
10
|
+
expect(Cloudsight.api_key) .to eq 'test_api_key'
|
11
|
+
expect(Cloudsight.base_url).to eq 'test_base_url'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should configure the oauth_options correctly' do
|
15
|
+
Cloudsight.oauth_options = {
|
16
|
+
consumer_key: 'test_consumer_key',
|
17
|
+
consumer_secret: 'test_consumer_secret'
|
18
|
+
}
|
19
|
+
|
20
|
+
expect(Cloudsight.oauth_options[:consumer_key]).to eq 'test_consumer_key'
|
21
|
+
expect(Cloudsight.oauth_options[:consumer_secret]).to eq 'test_consumer_secret'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'cloudsight'
|
3
|
+
require 'webmock/rspec'
|
4
|
+
require 'pry'
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
# Enable flags like --only-failures and --next-failure
|
8
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
9
|
+
|
10
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
11
|
+
config.disable_monkey_patching!
|
12
|
+
|
13
|
+
config.expect_with :rspec do |c|
|
14
|
+
c.syntax = :expect
|
15
|
+
end
|
16
|
+
|
17
|
+
config.after(:each) do
|
18
|
+
Cloudsight.api_key = nil
|
19
|
+
Cloudsight.oauth_options = {}
|
20
|
+
Cloudsight.base_url = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def stub_get(path:, response:, status: 200, message: nil)
|
26
|
+
stub_request(:get, Cloudsight::BASE_URL + path).to_return(
|
27
|
+
status: status,
|
28
|
+
body: response,
|
29
|
+
exception: message
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def stub_post(path:, body: {}, response: {}, status: 200, message: nil)
|
34
|
+
stub_request(:post, Cloudsight::BASE_URL + path).with(
|
35
|
+
body: hash_including(body)
|
36
|
+
).to_return(
|
37
|
+
status: status,
|
38
|
+
body: response,
|
39
|
+
exception: message
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def fixture_file(filename, options={})
|
44
|
+
return '' if filename == ''
|
45
|
+
file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
|
46
|
+
fixture = File.read(file_path)
|
47
|
+
|
48
|
+
case File.extname(file_path)
|
49
|
+
when '.json'
|
50
|
+
options[:parse] ? JSON.parse(fixture) : fixture
|
51
|
+
else
|
52
|
+
fixture
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
metadata
CHANGED
@@ -1,43 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudsight
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brad Folkens
|
8
|
+
- Jack McCallum
|
9
|
+
- Chris Weilemann
|
8
10
|
autorequire:
|
9
11
|
bindir: bin
|
10
12
|
cert_chain: []
|
11
|
-
date:
|
13
|
+
date: 2017-08-11 00:00:00.000000000 Z
|
12
14
|
dependencies:
|
13
15
|
- !ruby/object:Gem::Dependency
|
14
16
|
name: json
|
15
17
|
requirement: !ruby/object:Gem::Requirement
|
16
18
|
requirements:
|
17
|
-
- - "
|
19
|
+
- - "~>"
|
18
20
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
21
|
+
version: '2.1'
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
23
25
|
requirements:
|
24
|
-
- - "
|
26
|
+
- - "~>"
|
25
27
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
28
|
+
version: '2.1'
|
27
29
|
- !ruby/object:Gem::Dependency
|
28
30
|
name: rest-client
|
29
31
|
requirement: !ruby/object:Gem::Requirement
|
30
32
|
requirements:
|
31
33
|
- - "~>"
|
32
34
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
35
|
+
version: '2.0'
|
34
36
|
type: :runtime
|
35
37
|
prerelease: false
|
36
38
|
version_requirements: !ruby/object:Gem::Requirement
|
37
39
|
requirements:
|
38
40
|
- - "~>"
|
39
41
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
42
|
+
version: '2.0'
|
41
43
|
- !ruby/object:Gem::Dependency
|
42
44
|
name: bundler
|
43
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,28 +58,104 @@ dependencies:
|
|
56
58
|
name: rake
|
57
59
|
requirement: !ruby/object:Gem::Requirement
|
58
60
|
requirements:
|
59
|
-
- - "
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '12.0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '12.0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rspec
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - "~>"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.6'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - "~>"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '3.6'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: pry
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0.10'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - "~>"
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0.10'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: webmock
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - "~>"
|
60
104
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
105
|
+
version: '3.0'
|
62
106
|
type: :development
|
63
107
|
prerelease: false
|
64
108
|
version_requirements: !ruby/object:Gem::Requirement
|
65
109
|
requirements:
|
66
|
-
- - "
|
110
|
+
- - "~>"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '3.0'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: simple_oauth
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0.3'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - "~>"
|
67
125
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
126
|
+
version: '0.3'
|
69
127
|
description: A simple CloudSight API Client for Image Recognition
|
70
|
-
email:
|
71
|
-
executables:
|
128
|
+
email: oss@cloudsight.ai
|
129
|
+
executables:
|
130
|
+
- console
|
131
|
+
- setup
|
72
132
|
extensions: []
|
73
133
|
extra_rdoc_files: []
|
74
134
|
files:
|
135
|
+
- ".gitignore"
|
136
|
+
- ".rspec"
|
137
|
+
- ".travis.yml"
|
75
138
|
- Gemfile
|
76
|
-
- Gemfile.lock
|
77
139
|
- MIT-LICENSE
|
78
140
|
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- bin/console
|
143
|
+
- bin/setup
|
79
144
|
- cloudsight.gemspec
|
80
145
|
- lib/cloudsight.rb
|
146
|
+
- lib/cloudsight/api.rb
|
147
|
+
- lib/cloudsight/request.rb
|
148
|
+
- lib/cloudsight/response.rb
|
149
|
+
- lib/cloudsight/version.rb
|
150
|
+
- spec/cloudsight/api_spec.rb
|
151
|
+
- spec/cloudsight/request_spec.rb
|
152
|
+
- spec/cloudsight/response_spec.rb
|
153
|
+
- spec/cloudsight_spec.rb
|
154
|
+
- spec/fixtures/completed_response.json
|
155
|
+
- spec/fixtures/error_response.json
|
156
|
+
- spec/fixtures/image_request.json
|
157
|
+
- spec/fixtures/unexpected_response.json
|
158
|
+
- spec/spec_helper.rb
|
81
159
|
homepage: http://github.com/cloudsight/cloudsight-ruby
|
82
160
|
licenses:
|
83
161
|
- MIT
|
@@ -90,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
168
|
requirements:
|
91
169
|
- - ">="
|
92
170
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
171
|
+
version: '2.1'
|
94
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
173
|
requirements:
|
96
174
|
- - ">="
|
@@ -102,4 +180,13 @@ rubygems_version: 2.6.12
|
|
102
180
|
signing_key:
|
103
181
|
specification_version: 4
|
104
182
|
summary: CloudSight API Client
|
105
|
-
test_files:
|
183
|
+
test_files:
|
184
|
+
- spec/cloudsight/api_spec.rb
|
185
|
+
- spec/cloudsight/request_spec.rb
|
186
|
+
- spec/cloudsight/response_spec.rb
|
187
|
+
- spec/cloudsight_spec.rb
|
188
|
+
- spec/fixtures/completed_response.json
|
189
|
+
- spec/fixtures/error_response.json
|
190
|
+
- spec/fixtures/image_request.json
|
191
|
+
- spec/fixtures/unexpected_response.json
|
192
|
+
- spec/spec_helper.rb
|
data/Gemfile.lock
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
cloudsight (0.0.2)
|
5
|
-
json
|
6
|
-
rest-client (~> 1.6)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
domain_name (0.5.20170404)
|
12
|
-
unf (>= 0.0.5, < 1.0.0)
|
13
|
-
http-cookie (1.0.3)
|
14
|
-
domain_name (~> 0.5)
|
15
|
-
json (2.1.0)
|
16
|
-
mime-types (2.99.3)
|
17
|
-
netrc (0.11.0)
|
18
|
-
rake (12.0.0)
|
19
|
-
rest-client (1.8.0)
|
20
|
-
http-cookie (>= 1.0.2, < 2.0)
|
21
|
-
mime-types (>= 1.16, < 3.0)
|
22
|
-
netrc (~> 0.7)
|
23
|
-
unf (0.1.4)
|
24
|
-
unf_ext
|
25
|
-
unf_ext (0.0.7.4)
|
26
|
-
|
27
|
-
PLATFORMS
|
28
|
-
ruby
|
29
|
-
|
30
|
-
DEPENDENCIES
|
31
|
-
bundler (~> 1.6)
|
32
|
-
cloudsight!
|
33
|
-
rake
|
34
|
-
|
35
|
-
BUNDLED WITH
|
36
|
-
1.13.7
|