vend 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|