vend 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +2 -1
- data/README.rdoc +38 -1
- data/Rakefile +1 -1
- data/lib/vend.rb +3 -0
- data/lib/vend/base.rb +2 -3
- data/lib/vend/http_client.rb +4 -2
- data/lib/vend/oauth2/auth_code.rb +48 -0
- data/lib/vend/oauth2/client.rb +31 -0
- data/lib/vend/resource_collection.rb +1 -1
- data/lib/vend/version.rb +1 -1
- data/spec/integration/product_spec.rb +0 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/support/matchers/have_attributes.rb +1 -1
- data/spec/support/shared_examples/integration.rb +15 -17
- data/spec/support/shared_examples/logger.rb +1 -1
- data/spec/vend/base_factory_spec.rb +1 -1
- data/spec/vend/base_spec.rb +127 -160
- data/spec/vend/client_spec.rb +4 -4
- data/spec/vend/http_client_spec.rb +3 -3
- data/spec/vend/oauth2/auth_code_spec.rb +47 -0
- data/spec/vend/oauth2/client_spec.rb +47 -0
- data/spec/vend/pagination_info_spec.rb +1 -1
- data/spec/vend/resource/register_sale_product_spec.rb +2 -2
- data/spec/vend/resource/register_sale_spec.rb +2 -2
- data/spec/vend/resource_collection_spec.rb +49 -45
- data/vend.gemspec +4 -1
- metadata +51 -35
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 36886eb6986fbeb8cea81493ff3f87cfc75d2e7c
|
4
|
+
data.tar.gz: d0bc6a8d32403071b1bcead22e49bd74771cb83b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: de2eeb7b4b76dd5d1fbbad65784fb63df20c1cd80314886e7cf9bbc5e69642c92340bbcd94c7ff9988d13f07481b9b38cabaac129094e81129bc8d414e352a44
|
7
|
+
data.tar.gz: e1539bfb0b731bb01b9ce40a38d888518b32db7dc66bc259fb223bc5b31048a07f388e52f6c22889641f4adb8e280a7c9e06645f6405e4c5cc01b9f461b885f3
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Vend API Gem
|
1
|
+
= Vend API Gem {<img src="https://travis-ci.org/trineo/vend-ruby.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/trineo/vend-ruby]
|
2
2
|
|
3
3
|
This gem provides access to Vend's REST API.
|
4
4
|
|
@@ -6,3 +6,40 @@ This gem provides access to Vend's REST API.
|
|
6
6
|
|
7
7
|
At the time of writing, this is located at
|
8
8
|
https://docs.google.com/document/pub?id=13JiV6771UcrkmawFRxzvVl3tf5PGSTBH56RYy0-5cps
|
9
|
+
|
10
|
+
== Using Vend API via Oauth 2.0
|
11
|
+
|
12
|
+
You will need to implement the following steps to connect your application to a Vend Retailer account.
|
13
|
+
|
14
|
+
=====1 Requesting authorisation url. User must be redirected to this url in order to receive authorisation code.
|
15
|
+
|
16
|
+
auth_code = Vend::Oauth2::AuthCode.new(STORE, CLIENT_ID, SECRET, REDIRECT_URI)
|
17
|
+
url = auth_code.authorize_url
|
18
|
+
|
19
|
+
Url will look like:
|
20
|
+
https://secure.vendhq.com/connect?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&state={state}
|
21
|
+
|
22
|
+
After successful authorisation, you will be redirected to:
|
23
|
+
{redirect_uri}?code={code}&domain_prefix={domain_prefix}&state={state}
|
24
|
+
|
25
|
+
|
26
|
+
=====2 Requesting access token.
|
27
|
+
|
28
|
+
auth_code = Vend::Oauth2::AuthCode.new(STORE, CLIENT_ID, SECRET, REDIRECT_URI)
|
29
|
+
token = auth_code.token_from_code(params[:code])
|
30
|
+
|
31
|
+
Where <b>token</b> is an instance of OAuth2::AccessToken http://www.rubydoc.info/gems/oauth2/1.0.0/OAuth2/AccessToken
|
32
|
+
|
33
|
+
=====3 Using the token to access the Vend API.
|
34
|
+
|
35
|
+
client = Vend::Oauth2::Client.new(STORE, AUTH_TOKEN)
|
36
|
+
client.Product.all.each do |product|
|
37
|
+
puts product.name
|
38
|
+
end
|
39
|
+
|
40
|
+
=====4 Refreshing the access token
|
41
|
+
|
42
|
+
auth_code = Vend::Oauth2::AuthCode.new(STORE, CLIENT_ID, SECRET, REDIRECT_URI)
|
43
|
+
token = auth_code.refresh_token(auth_token, refresh_token)
|
44
|
+
|
45
|
+
The response payload may include a refresh token, if so, you need to update your currently stored refresh token.
|
data/Rakefile
CHANGED
data/lib/vend.rb
CHANGED
data/lib/vend/base.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Vend
|
2
|
-
|
3
2
|
# This Base class provides the basic mapping between Vend::Resource subclasses
|
4
3
|
# and the HTTP endpoints in the Vend API.
|
5
4
|
#
|
@@ -90,9 +89,9 @@ module Vend
|
|
90
89
|
end
|
91
90
|
available_scopes << method_name
|
92
91
|
end
|
93
|
-
|
92
|
+
|
94
93
|
def self.findable_by(field, options = {})
|
95
|
-
|
94
|
+
|
96
95
|
(class << self ; self ; end).instance_eval do
|
97
96
|
define_method("find_by_#{field}") do |client, *args|
|
98
97
|
search(client, options[:as] || field, *args)
|
data/lib/vend/http_client.rb
CHANGED
@@ -10,13 +10,14 @@ module Vend
|
|
10
10
|
|
11
11
|
include Logable
|
12
12
|
|
13
|
-
attr_accessor :base_url, :verify_ssl, :username, :password
|
13
|
+
attr_accessor :base_url, :verify_ssl, :username, :password, :auth_token
|
14
14
|
alias :verify_ssl? :verify_ssl
|
15
15
|
|
16
16
|
def initialize(options = {})
|
17
17
|
@base_url = options[:base_url]
|
18
18
|
@username = options[:username]
|
19
19
|
@password = options[:password]
|
20
|
+
@auth_token = options[:auth_token]
|
20
21
|
@verify_ssl = if options.has_key?(:verify_ssl)
|
21
22
|
options[:verify_ssl]
|
22
23
|
else
|
@@ -74,7 +75,8 @@ module Vend
|
|
74
75
|
# FIXME extract method
|
75
76
|
method = ("Net::HTTP::" + options[:method].to_s.classify).constantize
|
76
77
|
request = method.new(url.path + url_params_for(options[:url_params]))
|
77
|
-
request.basic_auth username, password
|
78
|
+
request.basic_auth username, password if username && password
|
79
|
+
request['Authorization'] = "Bearer #{auth_token}" if auth_token
|
78
80
|
|
79
81
|
request.body = options[:body] if options[:body]
|
80
82
|
logger.debug url
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
|
3
|
+
module Vend
|
4
|
+
module Oauth2
|
5
|
+
|
6
|
+
class AuthCode
|
7
|
+
|
8
|
+
DEFAULT_OPTIONS = {}
|
9
|
+
AUTHORIZE_URL = '/connect'
|
10
|
+
TOKEN_URL = '/api/1.0/token'
|
11
|
+
|
12
|
+
attr_accessor :store, :client_id, :secret, :redirect_uri
|
13
|
+
|
14
|
+
def initialize(store, client_id, secret, redirect_uri, options = {})
|
15
|
+
@store = store
|
16
|
+
@client_id = client_id
|
17
|
+
@secret = secret
|
18
|
+
@redirect_uri = redirect_uri
|
19
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def authorize_url
|
23
|
+
get_oauth2_client.auth_code.authorize_url(:redirect_uri => redirect_uri)
|
24
|
+
end
|
25
|
+
|
26
|
+
def token_from_code(code)
|
27
|
+
client = get_oauth2_client(store)
|
28
|
+
client.auth_code.get_token(code, :redirect_uri => redirect_uri)
|
29
|
+
end
|
30
|
+
|
31
|
+
def refresh_token(auth_token, refresh_token)
|
32
|
+
access_token = OAuth2::AccessToken.new(get_oauth2_client(store), auth_token, {refresh_token: refresh_token})
|
33
|
+
access_token.refresh!
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def get_oauth2_client(domain_prefix = 'secure')
|
38
|
+
OAuth2::Client.new(client_id, secret, {
|
39
|
+
site: "https://#{domain_prefix}.vendhq.com",
|
40
|
+
authorize_url: AUTHORIZE_URL,
|
41
|
+
token_url: TOKEN_URL
|
42
|
+
})
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Vend
|
2
|
+
module Oauth2
|
3
|
+
|
4
|
+
class Client < Vend::Client
|
5
|
+
|
6
|
+
DEFAULT_OPTIONS = {}
|
7
|
+
|
8
|
+
include Logable
|
9
|
+
|
10
|
+
attr_accessor :store, :auth_token
|
11
|
+
|
12
|
+
def initialize(store, auth_token, options = {})
|
13
|
+
@store = store
|
14
|
+
@auth_token = auth_token
|
15
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def http_client
|
19
|
+
@http_client ||= Vend::HttpClient.new(http_client_options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def http_client_options
|
23
|
+
options.merge(
|
24
|
+
:auth_token => @auth_token, :base_url => base_url
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/lib/vend/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -2,13 +2,16 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'bundler/setup'
|
4
4
|
require 'webmock/rspec'
|
5
|
+
require 'rspec/its'
|
6
|
+
require 'pry'
|
5
7
|
Dir["./spec/support/**/*.rb"].each {|f| require f}
|
6
8
|
|
7
9
|
require 'cgi'
|
8
10
|
require 'vend'
|
9
11
|
|
10
12
|
RSpec.configure do |config|
|
11
|
-
|
13
|
+
config.mock_with(:rspec) { |c| c.syntax = [:should, :expect] }
|
14
|
+
config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }
|
12
15
|
end
|
13
16
|
|
14
17
|
def get_mock_response(file)
|
@@ -18,10 +18,9 @@ def build_receiver
|
|
18
18
|
end
|
19
19
|
|
20
20
|
shared_examples "a resource with a collection GET endpoint" do
|
21
|
-
|
22
|
-
let(:
|
23
|
-
let(:
|
24
|
-
let(:store) {"baz"}
|
21
|
+
let(:username) { "foo".freeze }
|
22
|
+
let(:password) { "bar".freeze }
|
23
|
+
let(:store) { "baz".freeze }
|
25
24
|
let(:append_to_url) { '' }
|
26
25
|
|
27
26
|
let(:client) do
|
@@ -33,23 +32,23 @@ shared_examples "a resource with a collection GET endpoint" do
|
|
33
32
|
username, password, store, class_basename.to_s.underscore.pluralize,
|
34
33
|
append_to_url
|
35
34
|
]
|
35
|
+
|
36
36
|
stub_request(:get, url).to_return(
|
37
37
|
:status => 200, :body => get_mock_from_path(:get)
|
38
38
|
)
|
39
39
|
|
40
40
|
collection = build_receiver.all
|
41
|
-
collection.count.
|
41
|
+
expect(collection.count).to eq(expected_collection_length)
|
42
42
|
|
43
43
|
first = collection.first
|
44
|
-
first.
|
44
|
+
expect(first).to have_attributes(expected_attributes)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
shared_examples "a resource with a singular GET endpoint" do
|
49
|
-
|
50
|
-
let(:
|
51
|
-
let(:
|
52
|
-
let(:store) {"baz"}
|
49
|
+
let(:username) { "foo".freeze }
|
50
|
+
let(:password) { "bar".freeze }
|
51
|
+
let(:store) { "baz".freeze }
|
53
52
|
|
54
53
|
let(:client) do
|
55
54
|
Vend::Client.new(store, username, password)
|
@@ -65,21 +64,20 @@ shared_examples "a resource with a singular GET endpoint" do
|
|
65
64
|
end
|
66
65
|
|
67
66
|
shared_examples "a resource with a DELETE endpoint" do
|
68
|
-
|
69
|
-
let(:
|
70
|
-
let(:
|
71
|
-
let(:store) {"baz"}
|
67
|
+
let(:username) { "foo".freeze }
|
68
|
+
let(:password) { "bar".freeze }
|
69
|
+
let(:store) { "baz".freeze }
|
72
70
|
|
73
71
|
let(:client) do
|
74
72
|
Vend::Client.new(store, username, password)
|
75
73
|
end
|
76
74
|
|
77
75
|
it "deletes the resource" do
|
76
|
+
|
78
77
|
stub_request(:delete, "https://#{username}:#{password}@#{store}.vendhq.com/api/#{class_basename.to_s.underscore.pluralize}/#{expected_attributes['id']}").
|
79
|
-
to_return(:
|
78
|
+
to_return(status: 200, body: {}.to_json)
|
80
79
|
|
81
80
|
objekt = build_receiver.build(expected_attributes)
|
82
|
-
objekt.delete.
|
81
|
+
expect(objekt.delete).to be_truthy
|
83
82
|
end
|
84
|
-
|
85
83
|
end
|
data/spec/vend/base_spec.rb
CHANGED
@@ -5,349 +5,316 @@ describe Vend::Base do
|
|
5
5
|
url_scope :bar
|
6
6
|
end
|
7
7
|
|
8
|
-
let(:client) {
|
9
|
-
let(:attribute_hash) { {:
|
10
|
-
let(:mock_response) {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
let(:client) { double(:client) }
|
9
|
+
let(:attribute_hash) { { key: 'value', 'id' => 1} }
|
10
|
+
let(:mock_response) {
|
11
|
+
{
|
12
|
+
'foos'=>[
|
13
|
+
{'id'=>'1','bar'=>'baz'},
|
14
|
+
{'id'=>'2','flar'=>'flum'}
|
15
|
+
]
|
16
|
+
}
|
17
17
|
}
|
18
18
|
|
19
19
|
subject { Vend::Resource::Foo.new(client, :attrs => attribute_hash) }
|
20
20
|
|
21
|
-
it
|
22
|
-
subject.
|
21
|
+
it 'creates an instance of Foo' do
|
22
|
+
expect(subject).to be_instance_of(Vend::Resource::Foo)
|
23
23
|
end
|
24
24
|
|
25
|
-
it
|
26
|
-
subject.client.
|
25
|
+
it 'assigns the client' do
|
26
|
+
expect(subject.client).to eq client
|
27
27
|
end
|
28
28
|
|
29
|
-
it
|
30
|
-
subject.attrs.
|
29
|
+
it 'assigns the attributes' do
|
30
|
+
expect(subject.attrs).to eq attribute_hash
|
31
31
|
end
|
32
32
|
|
33
33
|
describe '.build' do
|
34
|
-
it
|
35
|
-
Vend::Resource::Foo.build(client, :
|
36
|
-
be_instance_of(Vend::Resource::Foo)
|
34
|
+
it 'builds a Foo' do
|
35
|
+
expect(Vend::Resource::Foo.build(client, attrs: attribute_hash)).to be_instance_of(Vend::Resource::Foo)
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
39
|
describe '.initialize_singular' do
|
41
|
-
|
42
|
-
|
43
|
-
resource
|
44
|
-
resource.
|
45
|
-
resource.bar.should == "baz"
|
40
|
+
it 'initializes a singular resource from parsed JSON results' do
|
41
|
+
resource = Vend::Resource::Foo.initialize_singular(client, mock_response)
|
42
|
+
expect(resource).to be_a Vend::Resource::Foo
|
43
|
+
expect(resource.bar).to eq 'baz'
|
46
44
|
end
|
47
45
|
|
48
46
|
end
|
49
47
|
|
50
48
|
describe '.initialize_collection' do
|
51
|
-
|
52
49
|
subject { Vend::Resource::Foo }
|
53
50
|
|
54
|
-
let(:endpoint) {
|
55
|
-
let(:args) {
|
56
|
-
let(:resource_collection) {
|
51
|
+
let(:endpoint) { double('endpoint') }
|
52
|
+
let(:args) { double('args') }
|
53
|
+
let(:resource_collection) { double('resource_collection') }
|
57
54
|
|
58
55
|
before do
|
59
|
-
Vend::ResourceCollection.
|
56
|
+
expect(Vend::ResourceCollection).to receive(:new).with(
|
60
57
|
client, subject, endpoint, args
|
61
58
|
) { resource_collection }
|
62
59
|
end
|
63
60
|
|
64
|
-
it
|
65
|
-
|
66
|
-
client, endpoint, args
|
67
|
-
).
|
61
|
+
it 'creates a ResourceCollection instance' do
|
62
|
+
expect(
|
63
|
+
subject.initialize_collection(client, endpoint, args)
|
64
|
+
).to eq resource_collection
|
68
65
|
end
|
69
|
-
|
70
66
|
end
|
71
67
|
|
72
68
|
describe '.endpoint_name' do
|
73
|
-
|
74
|
-
|
75
|
-
Vend::Resource::Foo.endpoint_name.should == 'foo'
|
69
|
+
it 'returns the endpoint name' do
|
70
|
+
expect(Vend::Resource::Foo.endpoint_name).to eq 'foo'
|
76
71
|
end
|
77
|
-
|
78
72
|
end
|
79
73
|
|
80
74
|
describe '.collection_name' do
|
81
|
-
|
82
|
-
|
83
|
-
Vend::Resource::Foo.collection_name.should == 'foos'
|
75
|
+
it 'returns the collection name' do
|
76
|
+
expect(Vend::Resource::Foo.collection_name).to eq 'foos'
|
84
77
|
end
|
85
|
-
|
86
78
|
end
|
87
79
|
|
88
80
|
describe '.singular_name' do
|
89
|
-
|
90
|
-
|
91
|
-
Vend::Resource::Foo.singular_name(
|
92
|
-
Vend::Resource::Foo.singular_name(42).should == 'foos/42'
|
81
|
+
it 'returns the collection name plus the id' do
|
82
|
+
expect(Vend::Resource::Foo.singular_name('1')).to eq 'foos/1'
|
83
|
+
expect(Vend::Resource::Foo.singular_name(42)).to eq 'foos/42'
|
93
84
|
end
|
94
|
-
|
95
85
|
end
|
96
86
|
|
97
|
-
describe
|
98
|
-
|
99
|
-
|
100
|
-
let(:id) { 42 }
|
101
|
-
|
102
|
-
before do
|
103
|
-
subject.stub(:id => id)
|
104
|
-
described_class.stub(:singular_name).with(id) { singular_name }
|
87
|
+
describe '#singular_name' do
|
88
|
+
it :singular_name do
|
89
|
+
expect(subject.singular_name).to eq "foos/#{subject.id}"
|
105
90
|
end
|
106
|
-
|
107
|
-
its(:singular_name) { should == singular_name }
|
108
|
-
|
109
91
|
end
|
110
92
|
|
111
93
|
describe '.find' do
|
112
|
-
|
113
94
|
let(:id) { 1 }
|
114
|
-
let(:singular_name) {
|
95
|
+
let(:singular_name) { 'foos/1' }
|
115
96
|
|
116
97
|
before do
|
117
98
|
Vend::Resource::Foo.stub(:singular_name).with(id) { singular_name }
|
118
99
|
end
|
119
100
|
|
120
|
-
it
|
121
|
-
mock_response = {
|
122
|
-
client.
|
101
|
+
it 'finds a Foo by id' do
|
102
|
+
mock_response = { 'foos' => [{ 'id' => '1', 'bar' => 'baz' }]}
|
103
|
+
expect(client).to receive(:request).with(singular_name) { mock_response }
|
123
104
|
foo = Vend::Resource::Foo.find(client, id)
|
124
|
-
foo.
|
125
|
-
foo.bar.
|
105
|
+
expect(foo).to be_instance_of(Vend::Resource::Foo)
|
106
|
+
expect(foo.bar).to eq 'baz'
|
126
107
|
end
|
127
|
-
|
128
108
|
end
|
129
109
|
|
130
110
|
describe '.all' do
|
131
|
-
|
132
111
|
subject { Vend::Resource::Foo }
|
133
112
|
|
134
|
-
let(:collection_name) {
|
135
|
-
let(:resource_collection) {
|
113
|
+
let(:collection_name) { double('collection_name') }
|
114
|
+
let(:resource_collection) { double('resource_collection') }
|
136
115
|
|
137
116
|
before do
|
138
117
|
subject.stub(:collection_name => collection_name)
|
139
118
|
end
|
140
119
|
|
141
|
-
it
|
142
|
-
subject.
|
120
|
+
it 'calls initialize_collection with the collection_name' do
|
121
|
+
expect(subject).to receive(:initialize_collection).with(
|
143
122
|
client, collection_name
|
144
123
|
) { resource_collection }
|
145
|
-
subject.all(client).
|
124
|
+
expect(subject.all(client)).to eq resource_collection
|
146
125
|
end
|
147
|
-
|
148
126
|
end
|
149
127
|
|
150
128
|
describe '.url_scope' do
|
151
|
-
|
152
129
|
subject { Vend::Resource::Foo }
|
153
130
|
|
154
|
-
let(:collection_name) {
|
155
|
-
let(:resource_collection) {
|
156
|
-
let(:bar) {
|
131
|
+
let(:collection_name) { double('collection_name') }
|
132
|
+
let(:resource_collection) { double('resource_collection') }
|
133
|
+
let(:bar) { double('bar') }
|
157
134
|
|
158
135
|
before do
|
159
136
|
subject.stub(:collection_name => collection_name)
|
160
137
|
end
|
161
138
|
|
162
|
-
it
|
163
|
-
subject.
|
139
|
+
it 'calls initialize_collection with collection_name and :bar arg' do
|
140
|
+
expect(subject).to receive(:initialize_collection).with(
|
164
141
|
client, collection_name
|
165
142
|
) { resource_collection }
|
166
|
-
resource_collection.
|
143
|
+
expect(resource_collection).to receive(:scope).with(:bar, bar) {
|
167
144
|
resource_collection
|
168
145
|
}
|
169
|
-
subject.bar(client, bar).
|
146
|
+
expect(subject.bar(client, bar)).to eq resource_collection
|
170
147
|
end
|
171
|
-
|
172
148
|
end
|
173
149
|
|
174
|
-
describe
|
175
|
-
|
150
|
+
describe '.search' do
|
176
151
|
subject { Vend::Resource::Foo }
|
177
152
|
|
178
|
-
let(:collection_name) {
|
179
|
-
let(:resource_collection) {
|
180
|
-
let(:field) {
|
181
|
-
let(:query) {
|
153
|
+
let(:collection_name) { double('collection_name') }
|
154
|
+
let(:resource_collection) { double('resource_collection') }
|
155
|
+
let(:field) { 'field' }
|
156
|
+
let(:query) { 'query' }
|
182
157
|
|
183
158
|
before do
|
184
159
|
subject.stub(:collection_name => collection_name)
|
185
160
|
end
|
186
161
|
|
187
|
-
it
|
188
|
-
subject.
|
162
|
+
it 'calls initialize_collection with collection_name and :outlet_id arg' do
|
163
|
+
expect(subject).to receive(:initialize_collection).with(
|
189
164
|
client, collection_name, :url_params => { field.to_sym => query }
|
190
165
|
) { resource_collection }
|
191
|
-
subject.search(client, field, query).
|
166
|
+
expect(subject.search(client, field, query)).to eq resource_collection
|
192
167
|
end
|
193
|
-
|
194
168
|
end
|
195
169
|
|
196
|
-
describe
|
197
|
-
|
170
|
+
describe '.build_from_json' do
|
198
171
|
subject { Vend::Resource::Foo }
|
199
172
|
|
200
|
-
let(:json) { {
|
201
|
-
let(:attributes_one) {
|
202
|
-
let(:attributes_two) {
|
173
|
+
let(:json) { {'foos' => attributes_array} }
|
174
|
+
let(:attributes_one) { double('attributes_one') }
|
175
|
+
let(:attributes_two) { double('attributes_two') }
|
203
176
|
let(:attributes_array) { [attributes_one, attributes_two] }
|
204
|
-
let(:instance_one) {
|
205
|
-
let(:instance_two) {
|
177
|
+
let(:instance_one) { double('instance_one') }
|
178
|
+
let(:instance_two) { double('instance_two') }
|
206
179
|
|
207
180
|
specify do
|
208
181
|
subject.stub(:build).with(client, attributes_one) { instance_one }
|
209
182
|
subject.stub(:build).with(client, attributes_two) { instance_two }
|
210
|
-
subject.build_from_json(client, json).
|
183
|
+
expect(subject.build_from_json(client, json)).to eq [
|
211
184
|
instance_one, instance_two
|
212
185
|
]
|
213
186
|
end
|
214
|
-
|
215
187
|
end
|
216
188
|
|
217
|
-
describe
|
218
|
-
let(:attrs) { {
|
189
|
+
describe 'dynamic instance methods' do
|
190
|
+
let(:attrs) { { 'one' => 'foo', 'two' => 'bar', 'object_id' => 'fail' } }
|
219
191
|
subject { Vend::Resource::Foo.new(client, :attrs => attrs) }
|
220
192
|
|
221
|
-
it
|
222
|
-
subject.
|
223
|
-
subject.
|
224
|
-
subject.
|
225
|
-
|
226
|
-
subject.
|
227
|
-
subject.
|
228
|
-
subject.object_id.
|
229
|
-
subject.attrs['object_id'].should == "fail"
|
193
|
+
it 'responds to top level attributes' do
|
194
|
+
expect(subject).to respond_to(:one)
|
195
|
+
expect(subject).to respond_to(:two)
|
196
|
+
expect(subject).to respond_to(:object_id)
|
197
|
+
expect(subject.one).to eq 'foo'
|
198
|
+
expect(subject.two).to eq 'bar'
|
199
|
+
expect(subject.object_id).to_not eq 'fail'
|
200
|
+
expect(subject.attrs['object_id']).to eq 'fail'
|
230
201
|
end
|
231
202
|
end
|
232
203
|
|
233
|
-
describe
|
234
|
-
|
235
|
-
context "when id is present" do
|
204
|
+
describe 'delete!' do
|
205
|
+
context 'when id is present' do
|
236
206
|
subject { Vend::Resource::Foo.new(client, :attrs => {'id' => 1}) }
|
237
207
|
|
238
|
-
let(:singular_name) {
|
208
|
+
let(:singular_name) { double('singular_name')}
|
239
209
|
|
240
210
|
before do
|
241
211
|
subject.stub(:singular_name => singular_name)
|
242
212
|
end
|
243
213
|
|
244
|
-
it
|
245
|
-
client.
|
214
|
+
it 'deletes the object' do
|
215
|
+
expect(client).to receive(:request).with(singular_name, method: :delete)
|
246
216
|
subject.delete!
|
247
217
|
end
|
248
218
|
end
|
249
219
|
|
250
|
-
context
|
220
|
+
context 'when id is absent' do
|
251
221
|
subject { Vend::Resource::Foo.new(client, :attrs => {:foo => 'bar'}) }
|
252
222
|
|
253
|
-
it
|
254
|
-
client.
|
223
|
+
it 'raises Vend::Resource::IllegalAction' do
|
224
|
+
expect(client).to_not receive(:request)
|
255
225
|
expect {
|
256
226
|
subject.delete!
|
257
|
-
}.to raise_error(Vend::Resource::IllegalAction,
|
227
|
+
}.to raise_error(Vend::Resource::IllegalAction, 'Vend::Resource::Foo has no unique ID')
|
258
228
|
end
|
259
229
|
end
|
260
|
-
|
261
230
|
end
|
262
231
|
|
263
232
|
describe 'delete' do
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
objekt.delete.should be_false
|
233
|
+
it 'returns false when no id is present' do
|
234
|
+
subject = Vend::Resource::Foo.new(client, :attrs => {:foo => 'bar'})
|
235
|
+
expect(client).to_not receive(:request)
|
236
|
+
expect(subject.delete).to be_falsey
|
269
237
|
end
|
270
|
-
|
271
238
|
end
|
272
239
|
|
273
240
|
describe '.default_collection_request_args' do
|
274
241
|
subject { Vend::Resource::Foo }
|
275
|
-
|
242
|
+
it :default_collection_request_args do
|
243
|
+
expect(subject.default_collection_request_args).to eq({})
|
244
|
+
end
|
276
245
|
end
|
277
246
|
|
278
|
-
describe
|
279
|
-
|
247
|
+
describe '.paginates?' do
|
280
248
|
subject { Vend::Resource::Foo }
|
281
249
|
|
282
|
-
it
|
283
|
-
subject.paginates
|
250
|
+
it 'defaults to false' do
|
251
|
+
expect(subject.paginates?).to be_falsey
|
284
252
|
end
|
285
|
-
|
286
253
|
end
|
287
254
|
|
288
|
-
describe
|
255
|
+
describe '.available_scopes' do
|
289
256
|
subject { Vend::Resource::Foo }
|
290
|
-
|
257
|
+
it :available_scopes do
|
258
|
+
expect(subject.available_scopes).to eq [:bar]
|
259
|
+
end
|
291
260
|
end
|
292
261
|
|
293
|
-
describe
|
262
|
+
describe '.accepts_scope?' do
|
294
263
|
let(:scope_name) {:scope_name}
|
295
264
|
subject { Vend::Resource::Foo }
|
296
|
-
|
297
|
-
context
|
265
|
+
|
266
|
+
context 'when scope is accepted' do
|
298
267
|
before do
|
299
|
-
subject.stub(:
|
268
|
+
subject.stub(available_scopes: [scope_name])
|
300
269
|
end
|
301
270
|
specify do
|
302
|
-
subject.accepts_scope?(scope_name).
|
271
|
+
expect(subject.accepts_scope?(scope_name)).to be_truthy
|
303
272
|
end
|
304
273
|
end
|
305
274
|
|
306
|
-
context
|
275
|
+
context 'when scope is not accepted' do
|
307
276
|
before do
|
308
|
-
subject.stub(:
|
277
|
+
subject.stub(available_scopes: [])
|
309
278
|
end
|
310
279
|
specify do
|
311
|
-
subject.accepts_scope?(scope_name).
|
280
|
+
expect(subject.accepts_scope?(scope_name)).to be_falsey
|
312
281
|
end
|
313
282
|
end
|
314
283
|
end
|
315
284
|
|
316
|
-
describe
|
285
|
+
describe '.findable_by' do
|
317
286
|
subject { Vend::Resource::Foo }
|
318
287
|
|
319
|
-
let(:args) {
|
288
|
+
let(:args) { double('args') }
|
320
289
|
|
321
|
-
it
|
322
|
-
subject.
|
290
|
+
it 'creates a find_by_foo method on the class' do
|
291
|
+
expect(subject).to_not respond_to(:find_by_foo)
|
323
292
|
subject.findable_by(:foo)
|
324
|
-
subject.
|
293
|
+
expect(subject).to respond_to(:find_by_foo)
|
325
294
|
end
|
326
295
|
|
327
|
-
it
|
296
|
+
it 'proxies to search' do
|
328
297
|
subject.findable_by(:foo)
|
329
|
-
subject.
|
298
|
+
expect(subject).to receive(:search).with(client, :foo, args)
|
330
299
|
subject.find_by_foo(client, args)
|
331
300
|
end
|
332
301
|
|
333
|
-
it
|
334
|
-
subject.findable_by(:foo, :
|
335
|
-
subject.
|
302
|
+
it 'allows a different method name' do
|
303
|
+
subject.findable_by(:foo, as: :bar)
|
304
|
+
expect(subject).to receive(:search).with(client, :bar, args)
|
336
305
|
subject.find_by_foo(client, args)
|
337
306
|
end
|
338
|
-
|
339
307
|
end
|
340
308
|
|
341
|
-
describe
|
342
|
-
|
309
|
+
describe '.cast_attribute' do
|
343
310
|
subject { Vend::Resource::Foo }
|
344
311
|
|
345
312
|
let(:attrs) { {'floater' => '1.23'} }
|
346
313
|
|
347
|
-
it
|
314
|
+
it 'casts to float' do
|
348
315
|
subject.cast_attribute :floater, Float
|
349
|
-
foo = Vend::Resource::Foo.new(client, :
|
350
|
-
foo.floater.
|
316
|
+
foo = Vend::Resource::Foo.new(client, attrs: attrs)
|
317
|
+
expect(foo.floater).to eq 1.23
|
351
318
|
end
|
352
319
|
end
|
353
320
|
end
|