sage_one 0.0.1

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 (50) hide show
  1. data/.gitignore +14 -0
  2. data/.travis.yml +11 -0
  3. data/.yardopts +4 -0
  4. data/Gemfile +8 -0
  5. data/LICENSE +19 -0
  6. data/README.md +141 -0
  7. data/Rakefile +4 -0
  8. data/bin/autospec +16 -0
  9. data/bin/htmldiff +16 -0
  10. data/bin/ldiff +16 -0
  11. data/bin/rake +16 -0
  12. data/bin/rspec +16 -0
  13. data/bin/yard +16 -0
  14. data/bin/yardoc +16 -0
  15. data/bin/yri +16 -0
  16. data/lib/faraday/request/oauth2.rb +25 -0
  17. data/lib/faraday/response/convert_sdata_to_headers.rb +70 -0
  18. data/lib/faraday/response/raise_sage_one_exception.rb +42 -0
  19. data/lib/sage_one/client/contacts.rb +14 -0
  20. data/lib/sage_one/client/sales_invoices.rb +77 -0
  21. data/lib/sage_one/client.rb +33 -0
  22. data/lib/sage_one/configuration.rb +81 -0
  23. data/lib/sage_one/connection.rb +44 -0
  24. data/lib/sage_one/error.rb +39 -0
  25. data/lib/sage_one/oauth.rb +49 -0
  26. data/lib/sage_one/request.rb +72 -0
  27. data/lib/sage_one/version.rb +3 -0
  28. data/lib/sage_one.rb +31 -0
  29. data/sage_one.gemspec +32 -0
  30. data/spec/faraday/request/oauth2_spec.rb +44 -0
  31. data/spec/faraday/response/convert_sdata_to_headers_spec.rb +113 -0
  32. data/spec/faraday/response/raise_sage_one_exception_spec.rb +45 -0
  33. data/spec/fixtures/contact.json +28 -0
  34. data/spec/fixtures/invalid_sales_invoice.json +28 -0
  35. data/spec/fixtures/oauth/invalid_client.json +1 -0
  36. data/spec/fixtures/oauth/invalid_grant.json +1 -0
  37. data/spec/fixtures/oauth/oauth_token.json +4 -0
  38. data/spec/fixtures/sales_invoice.json +43 -0
  39. data/spec/fixtures/sales_invoices.json +90 -0
  40. data/spec/sage_one/client/contacts_spec.rb +19 -0
  41. data/spec/sage_one/client/sales_invoices_spec.rb +53 -0
  42. data/spec/sage_one/client_spec.rb +41 -0
  43. data/spec/sage_one/configuration_spec.rb +88 -0
  44. data/spec/sage_one/connection_spec.rb +36 -0
  45. data/spec/sage_one/oauth_spec.rb +44 -0
  46. data/spec/sage_one/request_spec.rb +113 -0
  47. data/spec/sage_one/version_spec.rb +7 -0
  48. data/spec/sage_one_spec.rb +38 -0
  49. data/spec/spec_helper.rb +76 -0
  50. metadata +301 -0
@@ -0,0 +1,90 @@
1
+ { "$totalResults":2,
2
+ "$startIndex":0,
3
+ "$itemsPerPage":20,
4
+
5
+ "$resources":[
6
+ { "id":954380,
7
+ "invoice_number":"SI-4",
8
+ "status":{"id":1, "$key":1},
9
+ "due_date":"19/04/2013",
10
+ "date":"20/03/2013",
11
+ "void_reason":null,
12
+ "outstanding_amount":"17.0",
13
+ "total_net_amount":"14.17",
14
+ "total_tax_amount":"2.83",
15
+ "tax_scheme_period_id":30394,
16
+ "carriage":"0.0",
17
+ "carriage_tax_code":{"id":1, "$key":1},
18
+ "carriage_tax_rate_percentage":"20.0",
19
+ "contact":{"id":568085, "$key":568085},
20
+ "contact_name":"Luke corp (Luke Brown)",
21
+ "main_address":"Killer Bees",
22
+ "delivery_address":"",
23
+ "delivery_address_same_as_main":false,
24
+ "reference":"",
25
+ "notes":"future date. did email it.",
26
+ "terms_and_conditions":"",
27
+ "lock_version":0,
28
+ "line_items":[{
29
+ "id":1570294,
30
+ "description":"Some fish - herring",
31
+ "quantity":"1.0",
32
+ "unit_price":"17.0",
33
+ "net_amount":"14.17",
34
+ "tax_amount":"2.83",
35
+ "tax_code":{"id":1, "$key":1},
36
+ "tax_rate_percentage":"20.0",
37
+ "unit_price_includes_tax":true,
38
+ "ledger_account":{"id":1898509,
39
+ "$key":1898509},
40
+ "product_code":"HERRING",
41
+ "product":{"id":68656, "$key":68656},
42
+ "service":{"$key":null},
43
+ "lock_version":0,
44
+ "$key":1570294
45
+ }
46
+ ],
47
+ "$key":954380},
48
+ {"id":954368,
49
+ "invoice_number":"SI-3",
50
+ "status":{"id":1, "$key":1},
51
+ "due_date":"07/12/2012",
52
+ "date":"07/11/2012",
53
+ "void_reason":null,
54
+ "outstanding_amount":"19.4",
55
+ "total_net_amount":"16.17",
56
+ "total_tax_amount":"3.23",
57
+ "tax_scheme_period_id":30394,
58
+ "carriage":"2.0",
59
+ "carriage_tax_code":{"id":1, "$key":1},
60
+ "carriage_tax_rate_percentage":"20.0",
61
+ "contact":{"id":568085, "$key":568085},
62
+ "contact_name":"Luke corp (Luke Brown)",
63
+ "main_address":"here man.",
64
+ "delivery_address":"",
65
+ "delivery_address_same_as_main":false,
66
+ "reference":"",
67
+ "notes":"this one neither emailed nor printed.",
68
+ "terms_and_conditions":"",
69
+ "lock_version":0,
70
+ "line_items":[{
71
+ "id":1570277,
72
+ "description":"Some fish - herring",
73
+ "quantity":"1.0",
74
+ "unit_price":"17.0",
75
+ "net_amount":"14.17",
76
+ "tax_amount":"2.83",
77
+ "tax_code":{"id":1, "$key":1},
78
+ "tax_rate_percentage":"20.0",
79
+ "unit_price_includes_tax":true,
80
+ "ledger_account":{"id":1898509, "$key":1898509},
81
+ "product_code":"HERRING",
82
+ "product":{"id":68656, "$key":68656},
83
+ "service":{"$key":null},
84
+ "lock_version":0,
85
+ "$key":1570277
86
+ }
87
+ ],
88
+ "$key":954368}
89
+ ]
90
+ }
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne::Client::Contacts do
4
+
5
+ let(:client) { SageOne.new }
6
+
7
+ describe '.contact' do
8
+ context 'when the contact exists' do
9
+ it 'returns a Hashie::Mash of the contact' do
10
+ stub_get('contacts/1').to_return(body: fixture('contact.json'))
11
+ contact = client.contact(1)
12
+ expect(contact).to be_a(Hashie::Mash)
13
+ expect(contact.name).to eq('Luke Brown')
14
+ expect(contact.email).to eq('luke.brown@example.com')
15
+ end
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne::Client::SalesInvoices do
4
+
5
+ let(:client) { SageOne.new }
6
+
7
+ describe 'sales_invoices' do
8
+ it 'returns an array of Hashie::Mashes, representing the available invoices' do
9
+ stub_get('sales_invoices').to_return(body: fixture('sales_invoices.json'))
10
+ inv = client.sales_invoices.first
11
+ expect(inv.outstanding_amount).to eq '17.0'
12
+ expect(inv.outstanding_amount).to eq '17.0'
13
+ expect(inv.notes).to eq 'future date. did email it.'
14
+ end
15
+ end
16
+
17
+ describe 'create_sales_invoice' do
18
+ it 'posts to the correct endpoint and returns the new invoice' do
19
+ stub_post('sales_invoices').to_return(body: fixture('sales_invoice.json'))
20
+ invoice = client.create_sales_invoice(foo: 'bar')
21
+ a_post('sales_invoices').with(body: { sales_invoice: { foo: 'bar' } }).should have_been_made.once
22
+ expect(invoice.invoice_number).to eq 'SI-4'
23
+ end
24
+ end
25
+
26
+ describe 'sales_invoice' do
27
+ it 'gets the requested sales invoice' do
28
+ stub_get('sales_invoices/333').to_return(body: fixture('sales_invoice.json'))
29
+ invoice = client.sales_invoice(333)
30
+ a_get('sales_invoices/333').should have_been_made.once
31
+ expect(invoice.invoice_number).to eq 'SI-4'
32
+ end
33
+ end
34
+
35
+ describe 'update_sales_invoice' do
36
+ it "makes a put and returns the new invoice" do
37
+ stub_put('sales_invoices/333').to_return(body: fixture('sales_invoice.json'))
38
+ invoice = client.update_sales_invoice(333, foo: 'bar')
39
+ a_put('sales_invoices/333').with(body: { sales_invoice: { foo: 'bar' } }).should have_been_made.once
40
+ expect(invoice.invoice_number).to eq 'SI-4'
41
+ end
42
+ end
43
+
44
+ describe 'delete_sales_invoice!' do
45
+ it "makes a delete and returns the deleted invoice" do
46
+ stub_delete('sales_invoices/444').to_return(body: fixture('sales_invoice.json'))
47
+ invoice = client.delete_sales_invoice!(444)
48
+ a_delete('sales_invoices/444').should have_been_made.once
49
+ expect(invoice.invoice_number).to eq 'SI-4'
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne::Client do
4
+
5
+ it 'creates accessors for all the keys in the SageOne::Configuration::VALID_OPTIONS_KEYS constant' do
6
+ client = SageOne::Client.new
7
+ SageOne::Configuration::VALID_OPTIONS_KEYS.each_with_index do |method, i|
8
+ value = "Setting attribute #{i}"
9
+ client.send("#{method}=", value)
10
+ expect(client.send(method)).to eq(value)
11
+ end
12
+ end
13
+
14
+ describe 'initialize' do
15
+ it 'copies the SageOne.options to the new client' do
16
+ client = SageOne::Client.new
17
+ SageOne::Configuration::VALID_OPTIONS_KEYS.each do |method|
18
+ expect(client.send(method)).to eq(SageOne.options[method])
19
+ end
20
+ end
21
+ it 'allows you to override any config options' do
22
+ better_options = {
23
+ adapter: 'BestAdaptor',
24
+ faraday_config_block: 'blocky block',
25
+ api_endpoint: 'https://www.example.com/',
26
+ proxy: 'proxy.example.com',
27
+ access_token: 'let_me_in',
28
+ client_id: 'client123',
29
+ client_secret: 'secret',
30
+ user_agent: 'Gem Awesome',
31
+ request_host: 'example.com',
32
+ auto_traversal: true,
33
+ raw_response: true
34
+ }
35
+ client = SageOne::Client.new(better_options)
36
+ SageOne::Configuration::VALID_OPTIONS_KEYS.each do |method|
37
+ expect(client.send(method)).to eq(better_options[method])
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne::Configuration do
4
+
5
+ subject do
6
+ module TestConfigModule
7
+ extend SageOne::Configuration
8
+ end
9
+ end
10
+
11
+ it 'has some default constants setup' do
12
+ expect(SageOne::Configuration::DEFAULT_ADAPTER).to eq(Faraday.default_adapter)
13
+ expect(SageOne::Configuration::DEFAULT_API_ENDPOINT).to eq('https://app.sageone.com/api/v1/')
14
+ expect(SageOne::Configuration::DEFAULT_USER_AGENT).to eq("SageOne Ruby Gem #{SageOne::VERSION}")
15
+ expect(SageOne::Configuration::DEFAULT_AUTO_TRAVERSAL).to be_false
16
+ expect(SageOne::Configuration::DEFAULT_RAW_RESPONSE).to be_false
17
+ expect(SageOne::Configuration::VALID_OPTIONS_KEYS).to be_a(Array)
18
+ end
19
+
20
+ describe 'attr_accessors' do
21
+ it 'creates accessors for all the keys in the VALID_OPTIONS_KEYS constant' do
22
+ SageOne::Configuration::VALID_OPTIONS_KEYS.reject { |k| [:api_endpoint].include?(k) }.each_with_index do |method, i|
23
+ value = "Setting attribute #{i}"
24
+ subject.send("#{method}=", value)
25
+ expect(subject.send(method)).to eq(value)
26
+ end
27
+ end
28
+ it 'uses an overridden method for setting the api_endpoint which ensures a trailing forward slash is present' do
29
+ subject.api_endpoint = 'http://www.example.com'
30
+ expect(subject.api_endpoint).to eq('http://www.example.com/')
31
+ end
32
+ end
33
+
34
+ describe "faraday_config" do
35
+ it 'assigns the given block to faraday_config_block' do
36
+ p = lambda { 'hi' }
37
+ subject.faraday_config(&p)
38
+ expect(subject.faraday_config_block.call).to eq('hi')
39
+ end
40
+ end
41
+
42
+ describe 'configure' do
43
+ it 'yields the given block passing in self - allowing you to config attributes' do
44
+ value = "my new client id"
45
+
46
+ subject.configure do |config|
47
+ config.client_id = value
48
+ end
49
+
50
+ expect(subject.client_id).to eq(value)
51
+ end
52
+ end
53
+
54
+ describe 'options' do
55
+ it 'returns a new hash of all the config options' do
56
+ expect(subject.options).to be_a(Hash)
57
+ expect(subject.options.keys).to eq(SageOne::Configuration::VALID_OPTIONS_KEYS)
58
+ expect(subject.options[:adapter]).to eq(SageOne::Configuration::DEFAULT_ADAPTER)
59
+ end
60
+ end
61
+
62
+ describe 'extended' do
63
+ it 'calls reset on module extending it' do
64
+ module NewMod; end
65
+ NewMod.should_receive(:reset).once
66
+ NewMod.extend(SageOne::Configuration)
67
+ end
68
+ end
69
+
70
+ describe 'reset' do
71
+ it 'resets all the config options to the default values' do
72
+ # Change them first
73
+ SageOne::Configuration::VALID_OPTIONS_KEYS.each { |method| subject.send("#{method}=", 'something') }
74
+ subject.reset
75
+ expect(subject.adapter).to eq(SageOne::Configuration::DEFAULT_ADAPTER)
76
+ expect(subject.api_endpoint).to eq(SageOne::Configuration::DEFAULT_API_ENDPOINT)
77
+ expect(subject.proxy).to be_nil
78
+ expect(subject.access_token).to be_nil
79
+ expect(subject.client_id).to be_nil
80
+ expect(subject.client_secret).to be_nil
81
+ expect(subject.request_host).to be_nil
82
+ expect(subject.user_agent).to eq(SageOne::Configuration::DEFAULT_USER_AGENT)
83
+ expect(subject.auto_traversal).to be_false
84
+ expect(subject.raw_response).to be_false
85
+ end
86
+ end
87
+
88
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne::Connection do
4
+
5
+ let(:client) { SageOne.new }
6
+ let(:basic_middleware) { %w(FaradayMiddleware::EncodeJson FaradayMiddleware::OAuth2 FaradayMiddleware::RaiseSageOneException) }
7
+ let(:non_raw_middleware) { %w(FaradayMiddleware::Mashify FaradayMiddleware::ParseJson) }
8
+
9
+ it "returns a Faraday" do
10
+ expect(client.send(:connection)).to be_a(Faraday::Connection)
11
+ end
12
+
13
+ it "sets up mandatory headers" do
14
+ headers = client.send(:connection).headers
15
+
16
+ { "Accept" => /application\/json/,
17
+ "User-Agent" => /SageOne Ruby Gem/,
18
+ "Content-Type" => /application\/json/ }.each do |header, value|
19
+ expect(headers[header]).to match(value)
20
+ end
21
+ end
22
+
23
+ it "has the correct middleware stack" do
24
+ stack = client.send(:connection).builder.handlers.map(&:name)
25
+ (basic_middleware + non_raw_middleware).each { |mw| expect(stack).to include(mw) }
26
+ end
27
+
28
+ context 'raw connection requested' do
29
+ it 'does not include mashify or parse_json' do
30
+ client.raw_response = true
31
+ stack = client.send(:connection).builder.handlers.map(&:name)
32
+ (non_raw_middleware).each { |mw| expect(stack).to_not include(mw) }
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne::OAuth do
4
+
5
+ let(:client) { SageOne.new(client_id: "CLIENT_ID", client_secret: "CLIENT_SECRET") }
6
+
7
+ describe 'authorize_url' do
8
+ it 'returns a correctly formatted url' do
9
+ expect(client.authorize_url('http://www.example.com/endpoint')).to eq("https://app.sageone.com/oauth/authorize/?client_id=CLIENT_ID&redirect_uri=http%3A%2F%2Fwww.example.com%2Fendpoint&response_type=code")
10
+ end
11
+ end
12
+
13
+ describe 'get_access_token' do
14
+ it 'returns an object containing an access_token' do
15
+
16
+ stub_post("https://app.sageone.com/oauth/token/").
17
+ with(:body => "{\"client_id\":\"CLIENT_ID\",\"client_secret\":\"CLIENT_SECRET\",\"grant_type\":\"authorization_code\",\"code\":\"uuddlrlr\",\"redirect_uri\":\"http://www.example.com/endpoint\"}",
18
+ :headers => {'Accept'=>'application/json; charset=utf-8', 'Content-Type'=>'application/json', 'User-Agent'=>'SageOne Ruby Gem 0.0.1'}).
19
+ to_return(:body => fixture("oauth/oauth_token.json"))
20
+
21
+ expect(client.get_access_token('uuddlrlr', 'http://www.example.com/endpoint').access_token).to eq('IguLPAK5VPvDSw3z4SjrkhHTyRXgnnqAPzt1mLUk')
22
+ end
23
+
24
+ describe 'failure cases' do
25
+ context 'invalid client' do
26
+ before do
27
+ client.client_secret = "SALMON"
28
+ stub_post("https://app.sageone.com/oauth/token/").to_return(status: 401, body: fixture('oauth/invalid_client.json'))
29
+ end
30
+ it { expect { client.get_access_token('uuddlrlr', 'http://www.example.com/endpoint') }.to raise_error(SageOne::Unauthorized, /invalid_client/) }
31
+ end
32
+
33
+ context 'wrong code' do
34
+ before { stub_post("https://app.sageone.com/oauth/token/").to_return(status: 400, body: fixture('oauth/invalid_grant.json')) }
35
+ it { expect { client.get_access_token('', 'http://www.example.com/endpoint') } .to raise_error(SageOne::BadRequest, /invalid_grant/) }
36
+ end
37
+
38
+ context 'wrong callback' do
39
+ before { stub_post("https://app.sageone.com/oauth/token/").to_return(status: 401, body: '') }
40
+ it { expect { client.get_access_token('uuddlrlr', 'http://www.example.com/notendpoint') }.to raise_error(SageOne::Unauthorized, %q{{"method":"post","url":"https://app.sageone.com/oauth/token/","status":401,"body":""}}) }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne::Request do
4
+
5
+ let(:client) { SageOne.new }
6
+
7
+ describe 'helper methods' do
8
+ before { client.stub(:request) }
9
+
10
+ [:get, :delete, :post, :put].each do |meth|
11
+ it "#{meth} exists and delegates to request" do
12
+ client.should_receive(:request).with(meth, 'foo', {})
13
+ client.send(meth, 'foo')
14
+ end
15
+ end
16
+ end
17
+
18
+ describe 'request' do
19
+ context 'get/delete' do
20
+ it "makes a get request" do
21
+ stub_get('sales_invoices')
22
+ client.get('sales_invoices')
23
+ a_get('sales_invoices').should have_been_made.once
24
+ end
25
+
26
+ context 'with options' do
27
+ it 'passes the options to the get request' do
28
+ stub_get('sales_invoices?start_date=2011-12-13')
29
+ client.get('sales_invoices', { start_date: '2011-12-13' })
30
+ a_get('sales_invoices?start_date=2011-12-13').should have_been_made.once
31
+ end
32
+ it 'special-cases start_index' do
33
+ stub_delete('sales_invoices?start_date=2011-12-13&%24startIndex=10')
34
+ client.delete('sales_invoices', { start_date: '2011-12-13', start_index: 10 })
35
+ a_delete('sales_invoices?start_date=2011-12-13&%24startIndex=10').should have_been_made.once
36
+ end
37
+ end
38
+ end
39
+ context 'put/post' do
40
+ it "sets the request path" do
41
+ stub_post('sales_invoices')
42
+ client.post('sales_invoices')
43
+ a_post('sales_invoices').should have_been_made.once
44
+ end
45
+ it "stores the options in the body" do
46
+ stub_put('sales_invoices')
47
+ client.put('sales_invoices', { "void_reason" => nil, "outstanding_amount" => "17.0", "total_net_amount" => "14.17"})
48
+ a_put('sales_invoices').with(body: '{"void_reason":null,"outstanding_amount":"17.0","total_net_amount":"14.17"}').should have_been_made.once
49
+ end
50
+ describe 'auto-conversion of Date-y objects' do
51
+ it "converts any options which are passed which resemble a date into a correctly-formatted date" do
52
+ stub_put('sales_invoices/222')
53
+ client.put('sales_invoices/222', { start_date: Time.new(2012, 10, 20), contents: { another_date: Time.new(2011, 8, 31) }})
54
+ a_put('sales_invoices/222').with(body: '{"start_date":"20/10/2012","contents":{"another_date":"31/08/2011"}}').should have_been_made.once
55
+ end
56
+ it "converts for any type of request, not just puts (regression test)" do
57
+ stub_get('sales_invoices?contents%5Banother_date%5D=31/08/2011&start_date=20/10/2012')
58
+ client.get('sales_invoices', { start_date: Time.new(2012, 10, 20), contents: { another_date: Time.new(2011, 8, 31) }})
59
+ a_get('sales_invoices?contents%5Banother_date%5D=31/08/2011&start_date=20/10/2012').should have_been_made.once
60
+ end
61
+ end
62
+ end
63
+
64
+ it 'Sets a request host if one is specified' do
65
+ client.request_host = "CustomerHost"
66
+ stub_get('sales_invoices')
67
+ client.get('sales_invoices')
68
+ a_get('sales_invoices').with(headers: { "Host" => 'CustomerHost' }).should have_been_made.once
69
+ end
70
+
71
+ describe "response body" do
72
+ context 'raw requested' do
73
+ it "returns a faraday response" do
74
+ stub_get('sales_invoices')
75
+ client.raw_response = true
76
+ expect(client.get('sales_invoices', {})).to be_a(Faraday::Response)
77
+ end
78
+ end
79
+ context 'not raw' do
80
+ it "returns an array of Hashie::Mash-es" do
81
+ stub_get('sales_invoices').to_return(body: fixture('sales_invoices.json'))
82
+ expect(client.get('sales_invoices')).to be_a(Array)
83
+ expect(client.get('sales_invoices').first).to be_a(Hashie::Mash)
84
+ expect(client.get('sales_invoices').first.outstanding_amount).to eq("17.0")
85
+ expect(client.get('sales_invoices').last).to be_a(Hashie::Mash)
86
+ end
87
+ end
88
+ end
89
+
90
+ context 'with auto_traversal turned on' do
91
+ before { client.auto_traversal = true }
92
+ it "recursively calls itself to build a complete result set" do
93
+
94
+ stub_get("sales_invoices").to_return(:status => 200, :body => sdata_fixture('sales_invoices.json', 30, 0, 10))
95
+ stub_get("sales_invoices?$startIndex=10").to_return(:status => 200, :body => sdata_fixture('sales_invoices.json', 30, 10, 10))
96
+ stub_get("sales_invoices?$startIndex=20").to_return(:status => 200, :body => sdata_fixture('sales_invoices.json', 30, 20, 10))
97
+
98
+ result = client.get("sales_invoices")
99
+
100
+ a_get('sales_invoices').should have_been_made.once
101
+ a_get('sales_invoices?$startIndex=10').should have_been_made.once
102
+ a_get('sales_invoices?$startIndex=20').should have_been_made.once
103
+
104
+ # The response should be three copies of the fixture file concatenated, so result[0] == result[2], etc
105
+ expect(result.size).to eq(6)
106
+ expect(result).to be_an(Array)
107
+ expect(result[0]).to be_a(Hashie::Mash)
108
+ expect(result[5]).to be_a(Hashie::Mash)
109
+ expect(result[0]).to eq(result[2])
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne::VERSION do
4
+ it 'sets the VERSION constant' do
5
+ SageOne::VERSION.should_not be_nil
6
+ end
7
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe SageOne do
4
+
5
+ describe '.new' do
6
+ it { SageOne.new.should be_a(SageOne::Client) }
7
+ end
8
+
9
+ describe '.respond_to?' do
10
+ it 'returns true when the method exists' do
11
+ expect(SageOne.respond_to?(:new, true)).to be_true
12
+ end
13
+ it 'returns true when a client responds to the method' do
14
+ expect(SageOne.respond_to?(:sales_invoices)).to be_true
15
+ end
16
+ it 'returns false when the method does not exist' do
17
+ expect(SageOne.respond_to?(:noway, true)).to be_false
18
+ end
19
+ end
20
+
21
+ describe '.method_missing' do
22
+ context "when the client does not respond to the method either" do
23
+ it 'raises a NoMethodError' do
24
+ expect(lambda{ SageOne.noway }).to raise_error(NoMethodError)
25
+ end
26
+ end
27
+ context "when the client does respond to the method" do
28
+ it 'delegates the call to the client, passing any args and block' do
29
+ block = Proc.new { puts "hi" }
30
+ mock_client = mock('SageOne::Client', :my_method => 'called')
31
+ SageOne.should_receive(:new).twice.and_return(mock_client)
32
+ mock_client.should_receive(:my_method).with('abc', block)
33
+ SageOne.my_method('abc', block)
34
+ end
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,76 @@
1
+ unless ENV['CI']
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter "/spec"
5
+ end
6
+ end
7
+
8
+ require 'sage_one'
9
+ require 'rspec'
10
+ require 'webmock/rspec'
11
+
12
+ RSpec.configure do |config|
13
+ config.color_enabled = true
14
+ config.treat_symbols_as_metadata_keys_with_true_values = true
15
+ config.filter_run :focus => true
16
+ config.run_all_when_everything_filtered = true
17
+ end
18
+
19
+ def a_delete(url)
20
+ a_request(:delete, sage_url(url))
21
+ end
22
+
23
+ def a_get(url)
24
+ a_request(:get, sage_url(url))
25
+ end
26
+
27
+ def a_patch(url)
28
+ a_request(:patch, sage_url(url))
29
+ end
30
+
31
+ def a_post(url)
32
+ a_request(:post, sage_url(url))
33
+ end
34
+
35
+ def a_put(url)
36
+ a_request(:put, sage_url(url))
37
+ end
38
+
39
+ def stub_delete(url)
40
+ stub_request(:delete, sage_url(url))
41
+ end
42
+
43
+ def stub_get(url)
44
+ stub_request(:get, sage_url(url))
45
+ end
46
+
47
+ def stub_post(url)
48
+ stub_request(:post, sage_url(url))
49
+ end
50
+
51
+ def stub_put(url)
52
+ stub_request(:put, sage_url(url))
53
+ end
54
+
55
+ def sage_url(url)
56
+ if url =~ /^http/
57
+ url
58
+ else
59
+ "https://app.sageone.com/api/v1/#{url}"
60
+ end
61
+ end
62
+
63
+ def fixture_path
64
+ File.expand_path("../fixtures", __FILE__)
65
+ end
66
+
67
+ def fixture(file)
68
+ File.new(fixture_path + '/' + file)
69
+ end
70
+
71
+ def sdata_fixture(fixture, total_results, start_index, items_per_page)
72
+ raw = fixture(fixture).read
73
+ raw.sub!(/"\$totalResults":(\d+)/, %Q("$totalResults":#{total_results}))
74
+ raw.sub!(/"\$startIndex":(\d+)/, %Q("$startIndex":#{start_index}))
75
+ raw.sub!(/"\$itemsPerPage":(\d+)/, %Q("$itemsPerPage":#{items_per_page}))
76
+ end