sage_one 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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