xeroizer 2.18.1 → 3.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 (133) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +199 -223
  3. data/lib/xeroizer/connection.rb +49 -0
  4. data/lib/xeroizer/exceptions.rb +2 -0
  5. data/lib/xeroizer/generic_application.rb +12 -5
  6. data/lib/xeroizer/http.rb +5 -78
  7. data/lib/xeroizer/http_response.rb +157 -0
  8. data/lib/xeroizer/models/bank_account.rb +1 -0
  9. data/lib/xeroizer/models/bank_transaction.rb +1 -0
  10. data/lib/xeroizer/models/batch_payment.rb +27 -0
  11. data/lib/xeroizer/models/branding_theme.rb +49 -9
  12. data/lib/xeroizer/models/contact.rb +10 -4
  13. data/lib/xeroizer/models/contact_group.rb +45 -0
  14. data/lib/xeroizer/models/credit_note.rb +23 -22
  15. data/lib/xeroizer/models/from_bank_account.rb +1 -0
  16. data/lib/xeroizer/models/history_record.rb +72 -0
  17. data/lib/xeroizer/models/invoice.rb +14 -3
  18. data/lib/xeroizer/models/line_item.rb +17 -5
  19. data/lib/xeroizer/models/manual_journal.rb +2 -1
  20. data/lib/xeroizer/models/option.rb +1 -1
  21. data/lib/xeroizer/models/organisation.rb +2 -0
  22. data/lib/xeroizer/models/payment_service.rb +22 -0
  23. data/lib/xeroizer/models/payroll/address.rb +53 -0
  24. data/lib/xeroizer/models/payroll/bank_account.rb +18 -6
  25. data/lib/xeroizer/models/payroll/benefit_line.rb +26 -0
  26. data/lib/xeroizer/models/payroll/benefit_type.rb +45 -0
  27. data/lib/xeroizer/models/payroll/deduction_line.rb +32 -0
  28. data/lib/xeroizer/models/payroll/deduction_type.rb +49 -0
  29. data/lib/xeroizer/models/payroll/earnings_line.rb +39 -0
  30. data/lib/xeroizer/models/payroll/earnings_type.rb +53 -0
  31. data/lib/xeroizer/models/payroll/employee.rb +30 -8
  32. data/lib/xeroizer/models/payroll/leave_application.rb +27 -0
  33. data/lib/xeroizer/models/payroll/leave_line.rb +30 -0
  34. data/lib/xeroizer/models/payroll/leave_period.rb +15 -0
  35. data/lib/xeroizer/models/payroll/pay_items.rb +22 -0
  36. data/lib/xeroizer/models/payroll/pay_run.rb +33 -0
  37. data/lib/xeroizer/models/payroll/pay_schedule.rb +40 -0
  38. data/lib/xeroizer/models/payroll/pay_template.rb +24 -0
  39. data/lib/xeroizer/models/payroll/payment_method.rb +24 -0
  40. data/lib/xeroizer/models/payroll/paystub.rb +44 -0
  41. data/lib/xeroizer/models/payroll/reimbursement_line.rb +21 -0
  42. data/lib/xeroizer/models/payroll/reimbursement_type.rb +22 -0
  43. data/lib/xeroizer/models/payroll/salary_and_wage.rb +29 -0
  44. data/lib/xeroizer/models/payroll/super_line.rb +40 -0
  45. data/lib/xeroizer/models/payroll/tax_declaration.rb +50 -0
  46. data/lib/xeroizer/models/payroll/time_off_line.rb +20 -0
  47. data/lib/xeroizer/models/payroll/time_off_type.rb +32 -0
  48. data/lib/xeroizer/models/payroll/work_location.rb +25 -0
  49. data/lib/xeroizer/models/prepayment.rb +1 -0
  50. data/lib/xeroizer/models/purchase_order.rb +6 -6
  51. data/lib/xeroizer/models/quote.rb +76 -0
  52. data/lib/xeroizer/models/schedule.rb +1 -0
  53. data/lib/xeroizer/models/tax_component.rb +1 -0
  54. data/lib/xeroizer/models/to_bank_account.rb +1 -0
  55. data/lib/xeroizer/oauth.rb +12 -1
  56. data/lib/xeroizer/oauth2.rb +82 -0
  57. data/lib/xeroizer/oauth2_application.rb +49 -0
  58. data/lib/xeroizer/payroll_application.rb +8 -3
  59. data/lib/xeroizer/record/base.rb +1 -1
  60. data/lib/xeroizer/record/base_model.rb +1 -1
  61. data/lib/xeroizer/record/base_model_http_proxy.rb +4 -0
  62. data/lib/xeroizer/record/model_definition_helper.rb +1 -1
  63. data/lib/xeroizer/record/payroll_base.rb +4 -0
  64. data/lib/xeroizer/record/record_association_helper.rb +4 -4
  65. data/lib/xeroizer/record/validators/associated_validator.rb +1 -0
  66. data/lib/xeroizer/record/xml_helper.rb +18 -18
  67. data/lib/xeroizer/report/aged_receivables_by_contact.rb +1 -1
  68. data/lib/xeroizer/report/cell_xml_helper.rb +13 -13
  69. data/lib/xeroizer/response.rb +22 -17
  70. data/lib/xeroizer/version.rb +1 -1
  71. data/lib/xeroizer.rb +33 -4
  72. data/test/acceptance/about_creating_bank_transactions_test.rb +80 -82
  73. data/test/acceptance/about_creating_prepayment_test.rb +25 -30
  74. data/test/acceptance/about_fetching_bank_transactions_test.rb +12 -12
  75. data/test/acceptance/about_online_invoice_test.rb +6 -10
  76. data/test/acceptance/acceptance_test.rb +28 -26
  77. data/test/acceptance/bank_transfer_test.rb +12 -17
  78. data/test/acceptance/bulk_operations_test.rb +18 -16
  79. data/test/acceptance/connections_test.rb +11 -0
  80. data/test/stub_responses/bad_request.json +6 -0
  81. data/test/stub_responses/connections.json +16 -0
  82. data/test/stub_responses/expired_oauth2_token.json +6 -0
  83. data/test/stub_responses/generic_response_error.json +6 -0
  84. data/test/stub_responses/invalid_oauth2_request_token.json +6 -0
  85. data/test/stub_responses/invalid_tenant_header.json +6 -0
  86. data/test/stub_responses/object_not_found.json +6 -0
  87. data/test/stub_responses/organisations.xml +10 -0
  88. data/test/stub_responses/payment_service.xml +15 -0
  89. data/test/test_helper.rb +16 -11
  90. data/test/unit/generic_application_test.rb +21 -10
  91. data/test/unit/http_test.rb +284 -10
  92. data/test/unit/models/address_test.rb +2 -2
  93. data/test/unit/models/bank_transaction_model_parsing_test.rb +2 -2
  94. data/test/unit/models/bank_transaction_test.rb +1 -1
  95. data/test/unit/models/bank_transaction_validation_test.rb +1 -1
  96. data/test/unit/models/contact_test.rb +2 -2
  97. data/test/unit/models/credit_note_test.rb +8 -8
  98. data/test/unit/models/employee_test.rb +4 -4
  99. data/test/unit/models/invoice_test.rb +12 -12
  100. data/test/unit/models/journal_line_test.rb +6 -6
  101. data/test/unit/models/journal_test.rb +4 -4
  102. data/test/unit/models/line_item_sum_test.rb +1 -1
  103. data/test/unit/models/line_item_test.rb +26 -28
  104. data/test/unit/models/manual_journal_test.rb +3 -3
  105. data/test/unit/models/organisation_test.rb +16 -2
  106. data/test/unit/models/payment_service_test.rb +29 -0
  107. data/test/unit/models/phone_test.rb +7 -7
  108. data/test/unit/models/prepayment_test.rb +4 -4
  109. data/test/unit/models/repeating_invoice_test.rb +3 -3
  110. data/test/unit/models/tax_rate_test.rb +2 -2
  111. data/test/unit/oauth2_test.rb +171 -0
  112. data/test/unit/oauth_config_test.rb +1 -1
  113. data/test/unit/record/base_model_test.rb +13 -13
  114. data/test/unit/record/base_test.rb +15 -4
  115. data/test/unit/record/block_validator_test.rb +1 -1
  116. data/test/unit/record/connection_test.rb +60 -0
  117. data/test/unit/record/model_definition_test.rb +36 -36
  118. data/test/unit/record/parse_params_test.rb +2 -2
  119. data/test/unit/record/parse_where_hash_test.rb +13 -13
  120. data/test/unit/record/record_association_test.rb +14 -14
  121. data/test/unit/record/validators_test.rb +43 -43
  122. data/test/unit/record_definition_test.rb +7 -7
  123. data/test/unit/report_definition_test.rb +7 -7
  124. data/test/unit/report_test.rb +20 -20
  125. data/test/unit_test_helper.rb +16 -0
  126. metadata +100 -25
  127. data/lib/xeroizer/models/payroll/home_address.rb +0 -24
  128. data/lib/xeroizer/partner_application.rb +0 -51
  129. data/lib/xeroizer/private_application.rb +0 -25
  130. data/lib/xeroizer/public_application.rb +0 -21
  131. data/test/unit/http_tsl_12_upgrade_test.rb +0 -31
  132. data/test/unit/oauth_test.rb +0 -118
  133. data/test/unit/private_application_test.rb +0 -20
@@ -0,0 +1,11 @@
1
+ require "test_helper"
2
+ require "acceptance_test"
3
+
4
+ class ConnectionsTest < Test::Unit::TestCase
5
+ include AcceptanceTest
6
+
7
+ should "be able to hit Xero to get current connections via OAuth2" do
8
+ connections = AcceptanceTestHelpers.oauth2_client.current_connections
9
+ assert_not_nil connections.first.tenant_id
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "invalid-request",
3
+ "title": "Invalid Request",
4
+ "status": 400,
5
+ "detail": "For the request field 'StatementLine.ChequeNumber' exceeded the maximum length of 20."
6
+ }
@@ -0,0 +1,16 @@
1
+ [
2
+ {
3
+ "id": "9332e669-0a35-4084-8f05-cd1ff31918c2",
4
+ "tenantId": "7f5fabdd-9565-416a-9b62-d53d852bb2a3",
5
+ "tenantType": "ORGANISATION",
6
+ "createdDateUtc": "2019-12-13T18:10:43.3063640",
7
+ "updatedDateUtc": "2019-12-13T18:10:43.3084790"
8
+ },
9
+ {
10
+ "id": "8774aba8-708f-48d1-865e-zedf93a0d5d5",
11
+ "tenantId": "b4aca7b2-6fab-4ee7-a969-477f9128f636",
12
+ "tenantType": "ORGANISATION",
13
+ "createdDateUtc": "2019-12-13T18:06:31.5600280",
14
+ "updatedDateUtc": "2019-12-13T18:16:38.2095570"
15
+ }
16
+ ]
@@ -0,0 +1,6 @@
1
+ {
2
+ "Title": "Unauthorized",
3
+ "Status": 401,
4
+ "Detail": "TokenExpired: token expired at 01/23/2020 18:21:16",
5
+ "Instance": "eac0fd6e-8d19-4bae-8121-cb7f7549ec67"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "duplicate-statement",
3
+ "title": "Duplicate Statement Received",
4
+ "status": 409,
5
+ "detail": "The received statement was marked as a duplicate."
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "Title": "Unauthorized",
3
+ "Status": 401,
4
+ "Detail": "AuthenticationUnsuccessful",
5
+ "Instance": "51e9d1af-397c-469f-a703-82a3003aef75"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "title": "Forbidden",
3
+ "status": 403,
4
+ "detail": "AuthenticationUnsuccessful",
5
+ "instance": "c375551e-dcbd-472a-af52-cafd73bfb349"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "statement-not-found",
3
+ "title": "Statement Not Found",
4
+ "status": 404,
5
+ "detail": "The statement was not found."
6
+ }
@@ -20,6 +20,16 @@
20
20
  <FinancialYearEndMonth>6</FinancialYearEndMonth>
21
21
  <PeriodLockDate>2008-06-30T00:00:00</PeriodLockDate>
22
22
  <CreatedDateUTC>2011-05-19T05:26:03.95</CreatedDateUTC>
23
+ <PaymentTerms>
24
+ <Bills>
25
+ <Day>4</Day>
26
+ <Type>OFFOLLOWINGMONTH</Type>
27
+ </Bills>
28
+ <Sales>
29
+ <Day>2</Day>
30
+ <Type>OFFOLLOWINGMONTH</Type>
31
+ </Sales>
32
+ </PaymentTerms>
23
33
  </Organisation>
24
34
  </Organisations>
25
35
  </Response>
@@ -0,0 +1,15 @@
1
+ <Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
2
+ <Id>42d8b00c-2fdd-4a8a-9b84-82cfe78ff34a</Id>
3
+ <Status>OK</Status>
4
+ <ProviderName>Test Provider Name</ProviderName>
5
+ <DateTimeUTC>2018-06-18T04:13:44.7828584Z</DateTimeUTC>
6
+ <PaymentServices>
7
+ <PaymentService>
8
+ <PaymentServiceID>4d7f4335-6f16-437a-86e3-a856ebc576b8</PaymentServiceID>
9
+ <PaymentServiceName>Custom Service</PaymentServiceName>
10
+ <PaymentServiceType>Custom</PaymentServiceType>
11
+ <PaymentServiceUrl>http://example.com</PaymentServiceUrl>
12
+ <PayNowText>Pay Me</PayNowText>
13
+ </PaymentService>
14
+ </PaymentServices>
15
+ </Response>
data/test/test_helper.rb CHANGED
@@ -4,10 +4,11 @@ require 'test/unit'
4
4
  require 'mocha'
5
5
  require 'shoulda'
6
6
  require 'pp'
7
+ require 'pry'
7
8
 
8
9
  require File.dirname(__FILE__) + '/../lib/xeroizer.rb'
9
10
 
10
- $: << File.join(File.dirname(__FILE__), "acceptance")
11
+ $: << File.join(File.dirname(__FILE__), "acceptance")
11
12
 
12
13
  module TestHelper
13
14
 
@@ -15,26 +16,31 @@ module TestHelper
15
16
  # environment, and you must have set up a customer key for that account.
16
17
  #
17
18
  # You can then run the tests against the test environment using the commands (linux or mac):
18
- # export STUB_XERO_CALLS=false
19
+ # export STUB_XERO_CALLS=false
19
20
  # rake test
20
21
  # (this probably won't work under OAuth?)
21
22
  #
22
23
 
23
24
  $VERBOSE=nil
24
-
25
+
25
26
  STUB_XERO_CALLS = ENV["STUB_XERO_CALLS"].nil? ? true : (ENV["STUB_XERO_CALLS"] == "true") unless defined? STUB_XERO_CALLS
26
-
27
+
27
28
  CONSUMER_KEY = ENV["CONSUMER_KEY"] || "fake_key" unless defined?(CONSUMER_KEY)
28
29
  CONSUMER_SECRET = ENV["CONSUMER_SECRET"] || "fake_secret" unless defined?(CONSUMER_SECRET)
29
30
  PRIVATE_KEY_PATH = ENV["PRIVATE_KEY_PATH"] || "fake_key" unless defined?(PRIVATE_KEY_PATH)
30
-
31
+
32
+ CLIENT_ID = ENV["XERO_CLIENT_ID"] || "fake_client_id" unless defined?(CLIENT_ID)
33
+ CLIENT_SECRET = ENV["XERO_CLIENT_SECRET"] || "fake_client_secret" unless defined?(CLIENT_SECRET)
34
+ ACCESS_TOKEN = ENV["XERO_ACCESS_TOKEN"] || "fake_access_token" unless defined?(ACCESS_TOKEN)
35
+ TENANT_ID = ENV["XERO_TENANT_ID"] || "fake_tenant_id" unless defined?(TENANT_ID)
36
+
31
37
  # Helper constant for checking regex
32
38
  GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ unless defined?(GUID_REGEX)
33
39
 
34
40
  def get_file_as_string(filename)
35
41
  File.read(File.dirname(__FILE__) + "/stub_responses/" + filename)
36
42
  end
37
-
43
+
38
44
  def get_record_xml(type, id = nil)
39
45
  if id.nil?
40
46
  get_file_as_string("#{type}.xml")
@@ -42,28 +48,27 @@ module TestHelper
42
48
  get_file_as_string("records/#{type}-#{id}.xml")
43
49
  end
44
50
  end
45
-
51
+
46
52
  def get_report_xml(report_type)
47
53
  get_file_as_string("reports/#{report_type.underscore}.xml")
48
54
  end
49
-
55
+
50
56
  def mock_api(model_name)
51
57
  @client.stubs(:http_get).with {|client, url, params| url =~ /#{model_name}$/ }.returns(get_record_xml(model_name.underscore.pluralize.to_s.to_sym))
52
58
  @client.send(model_name.singularize.to_s.to_sym).all.each do | record |
53
59
  @client.stubs(:http_get).with {|client, url, params| url =~ /#{model_name}\/#{record.id}$/ }.returns(get_record_xml(model_name.underscore.singularize.to_s.to_sym, record.id))
54
60
  end
55
61
  end
56
-
62
+
57
63
  def mock_report_api(report_type)
58
64
  @client.stubs(:http_get).with { | client, url, params | url =~ /Reports\/#{report_type}$/ }.returns(get_report_xml(report_type))
59
65
  end
60
-
61
66
  end
62
67
 
63
68
  Shoulda::Context::ClassMethods.class_eval do
64
69
  %w{it must can}.each do |m|
65
70
  alias_method m, :should
66
71
  end
67
-
72
+
68
73
  alias_method :must_eventually, :should_eventually
69
74
  end
@@ -1,26 +1,37 @@
1
- require 'test_helper'
1
+ require 'unit_test_helper'
2
2
 
3
3
  class GenericApplicationTest < Test::Unit::TestCase
4
4
  include TestHelper
5
5
 
6
- def setup
6
+ setup do
7
7
  @headers = {"User-Agent" => "Xeroizer/2.15.5"}
8
8
  @unitdp = 4
9
- @client = Xeroizer::GenericApplication.new(CONSUMER_KEY, CONSUMER_SECRET, :default_headers => @headers, :unitdp => @unitdp)
9
+ @options = {
10
+ default_headers: @headers,
11
+ unitdp: @unitdp
12
+ }
10
13
  end
11
14
 
12
- context "initialization" do
15
+ it "fails when provided an invalid client" do
16
+ client = "an invalid client"
17
+
18
+ assert_raises Xeroizer::InvalidClientError do
19
+ Xeroizer::GenericApplication.new(client, {})
20
+ end
21
+ end
22
+
23
+ context "oauth 2" do
24
+ setup do
25
+ client = Xeroizer::OAuth2.new(CLIENT_ID, CLIENT_SECRET, @options)
26
+ @application = Xeroizer::GenericApplication.new(client, @options)
27
+ end
13
28
 
14
29
  should "pass default headers" do
15
- assert_equal(@headers, @client.default_headers)
30
+ assert_equal(@headers, @application.default_headers)
16
31
  end
17
32
 
18
33
  should "pass unitdp value" do
19
- assert_equal(@unitdp, @client.unitdp)
34
+ assert_equal(@unitdp, @application.unitdp)
20
35
  end
21
-
22
36
  end
23
-
24
37
  end
25
-
26
-
@@ -1,18 +1,292 @@
1
- require 'test_helper'
1
+ require 'unit_test_helper'
2
2
 
3
- class HttpTest < Test::Unit::TestCase
3
+ class HttpTest < UnitTestCase
4
4
  include TestHelper
5
5
 
6
- def setup
7
- @headers = {"User-Agent" => "Xeroizer/2.15.5"}
8
- @application = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET, :default_headers => @headers)
6
+ setup do
7
+ @uri = "https://api.xero.com/path"
9
8
  end
10
9
 
11
- context "default_headers" do
12
- should "recognize default_headers" do
13
- Xeroizer::OAuth.any_instance.expects(:get).with("/test", has_entry(@headers)).returns(stub(:plain_body => "", :code => "200"))
14
- @application.http_get(@application.client, "http://example.com/test")
10
+ context "errors" do
11
+ setup do
12
+ @application = Xeroizer::OAuth2Application.new(CLIENT_ID, CLIENT_SECRET, tenant_id: TENANT_ID, access_token: ACCESS_TOKEN)
13
+ end
14
+
15
+ context "400" do
16
+ setup do
17
+ status_code = 400
18
+ @body = get_file_as_string("credit_note_not_found_error.xml")
19
+ stub_request(:get, @uri).to_return(status: status_code, body: @body)
20
+ end
21
+
22
+ should "raise an ApiException" do
23
+ error = assert_raises(Xeroizer::ApiException) { @application.http_get(@application.client, @uri) }
24
+ assert_equal ": \n Generated by the following XML: \n #{@body}", error.message
25
+ end
26
+ end
27
+
28
+ context "401" do
29
+ setup do
30
+ @status_code = 401
31
+ end
32
+
33
+ context "token_expired" do
34
+ setup do
35
+ body = get_file_as_string("token_expired")
36
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
37
+ end
38
+
39
+ should "raise an OAuth::TokenExpired" do
40
+ error = assert_raises(Xeroizer::OAuth::TokenExpired) { @application.http_get(@application.client, @uri) }
41
+ assert_equal "Unexpected token", error.message
42
+ end
43
+ end
44
+
45
+ context "token_rejected" do
46
+ setup do
47
+ body = "oauth_problem_advice=some advice&oauth_problem=token_rejected"
48
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
49
+ end
50
+
51
+ should "raise an OAuth::TokenInvalid" do
52
+ error = assert_raises(Xeroizer::OAuth::TokenInvalid) { @application.http_get(@application.client, @uri) }
53
+ assert_equal "some advice", error.message
54
+ end
55
+ end
56
+
57
+ context "rate limit exceeded" do
58
+ setup do
59
+ body = get_file_as_string("rate_limit_exceeded")
60
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
61
+ end
62
+
63
+ should "raise an OAuth::RateLimitExceeded" do
64
+ error = assert_raises(Xeroizer::OAuth::RateLimitExceeded) { @application.http_get(@application.client, @uri) }
65
+ assert_equal "please wait before retrying the xero api\n", error.message
66
+ end
67
+ end
68
+
69
+ context "consumer_key_unknown" do
70
+ setup do
71
+ body = "oauth_problem_advice=some more advice&oauth_problem=consumer_key_unknown"
72
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
73
+ end
74
+
75
+ should "raise an OAuth::ConsumerKeyUnknown" do
76
+ error = assert_raises(Xeroizer::OAuth::ConsumerKeyUnknown) { @application.http_get(@application.client, @uri) }
77
+ assert_equal "some more advice", error.message
78
+ end
79
+ end
80
+
81
+ context "nonce_used" do
82
+ setup do
83
+ body = get_file_as_string("nonce_used")
84
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
85
+ end
86
+
87
+ should "raise an OAuth::NonceUsed" do
88
+ error = assert_raises(Xeroizer::OAuth::NonceUsed) { @application.http_get(@application.client, @uri) }
89
+ assert_equal "The nonce value \"potatocakes\" has already been used ", error.message
90
+ end
91
+ end
92
+
93
+ context "organisation offline" do
94
+ setup do
95
+ body = "oauth_problem_advice=organisational advice&oauth_problem=organisation offline"
96
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
97
+ end
98
+
99
+ should "raise an OAuth::OrganisationOffline" do
100
+ error = assert_raises(Xeroizer::OAuth::OrganisationOffline) { @application.http_get(@application.client, @uri) }
101
+ assert_equal "organisational advice", error.message
102
+ end
103
+ end
104
+
105
+ context "unknown error" do
106
+ setup do
107
+ body = "oauth_problem_advice=unknown advice&oauth_problem=unknown error"
108
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
109
+ end
110
+
111
+ should "raise an OAuth::UnknownError" do
112
+ error = assert_raises(Xeroizer::OAuth::UnknownError) { @application.http_get(@application.client, @uri) }
113
+ assert_equal "unknown error:unknown advice", error.message
114
+ end
115
+ end
116
+ end
117
+
118
+ context "404" do
119
+ setup do
120
+ @status_code = 404
121
+ end
122
+
123
+ context "invoices" do
124
+ setup do
125
+ @uri = "https://api.xero.com/Invoices"
126
+ body = get_file_as_string("invoice_not_found_error.xml")
127
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
128
+ end
129
+
130
+ should "raise an InvoiceNotFoundError" do
131
+ error = assert_raises(Xeroizer::InvoiceNotFoundError) { @application.http_get(@application.client, @uri) }
132
+ assert_equal "Invoice not found in Xero.", error.message
133
+ end
134
+ end
135
+
136
+ context "credit notes" do
137
+ setup do
138
+ @uri = "https://api.xero.com/CreditNotes"
139
+ body = get_file_as_string("credit_note_not_found_error.xml")
140
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
141
+ end
142
+
143
+ should "raise an CreditNoteNotFoundError" do
144
+ error = assert_raises(Xeroizer::CreditNoteNotFoundError) { @application.http_get(@application.client, @uri) }
145
+ assert_equal "Credit Note not found in Xero.", error.message
146
+ end
147
+ end
148
+
149
+ context "anything else" do
150
+ setup do
151
+ stub_request(:get, @uri).to_return(status: @status_code, body: "body")
152
+ end
153
+
154
+ should "raise an ObjectNotFound" do
155
+ error = assert_raises(Xeroizer::ObjectNotFound) { @application.http_get(@application.client, @uri) }
156
+ assert_equal "Couldn't find object for API Endpoint #{@uri}", error.message
157
+ end
158
+ end
159
+ end
160
+
161
+ context "429" do
162
+ setup do
163
+ @status_code = 429
164
+ end
165
+
166
+ context "rate_limit_exceeded" do
167
+ setup do
168
+ stub_request(:get, @uri).to_return(
169
+ status: @status_code,
170
+ body: "",
171
+ headers: {
172
+ "x-daylimit-remaining" => "328",
173
+ "retry-after" => "42",
174
+ }
175
+ )
176
+ end
177
+
178
+ should "raise an OAuth::RateLimitExceeded" do
179
+ error = assert_raises(Xeroizer::OAuth::RateLimitExceeded){ @application.http_get(@application.client, @uri) }
180
+ assert_match /rate limit exceeded/i, error.message
181
+ assert_match /328 requests left for the day/i, error.message
182
+ assert_match /42 seconds until you can make another request/i, error.message
183
+ assert_equal 42, error.retry_after
184
+ assert_equal 328, error.daily_limit_remaining
185
+ end
186
+ end
187
+ end
188
+
189
+ context "503" do
190
+ setup do
191
+ @status_code = 503
192
+ end
193
+
194
+ context "token_expired" do
195
+ setup do
196
+ body = get_file_as_string("token_expired")
197
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
198
+ end
199
+
200
+ should "raise an OAuth::TokenExpired" do
201
+ error = assert_raises(Xeroizer::OAuth::TokenExpired) { @application.http_get(@application.client, @uri) }
202
+ assert_equal "Unexpected token", error.message
203
+ end
204
+ end
205
+
206
+ context "token_rejected" do
207
+ setup do
208
+ body = "oauth_problem_advice=some advice&oauth_problem=token_rejected"
209
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
210
+ end
211
+
212
+ should "raise an OAuth::TokenInvalid" do
213
+ error = assert_raises(Xeroizer::OAuth::TokenInvalid) { @application.http_get(@application.client, @uri) }
214
+ assert_equal "some advice", error.message
215
+ end
216
+ end
217
+
218
+ context "rate limit exceeded" do
219
+ setup do
220
+ body = get_file_as_string("rate_limit_exceeded")
221
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
222
+ end
223
+
224
+ should "raise an OAuth::RateLimitExceeded" do
225
+ error = assert_raises(Xeroizer::OAuth::RateLimitExceeded) { @application.http_get(@application.client, @uri) }
226
+ assert_equal "please wait before retrying the xero api\n", error.message
227
+ end
228
+ end
229
+
230
+ context "consumer_key_unknown" do
231
+ setup do
232
+ body = "oauth_problem_advice=some more advice&oauth_problem=consumer_key_unknown"
233
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
234
+ end
235
+
236
+ should "raise an OAuth::ConsumerKeyUnknown" do
237
+ error = assert_raises(Xeroizer::OAuth::ConsumerKeyUnknown) { @application.http_get(@application.client, @uri) }
238
+ assert_equal "some more advice", error.message
239
+ end
240
+ end
241
+
242
+ context "nonce_used" do
243
+ setup do
244
+ body = get_file_as_string("nonce_used")
245
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
246
+ end
247
+
248
+ should "raise an OAuth::NonceUsed" do
249
+ error = assert_raises(Xeroizer::OAuth::NonceUsed) { @application.http_get(@application.client, @uri) }
250
+ assert_equal "The nonce value \"potatocakes\" has already been used ", error.message
251
+ end
252
+ end
253
+
254
+ context "organisation offline" do
255
+ setup do
256
+ body = "oauth_problem_advice=organisational advice&oauth_problem=organisation offline"
257
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
258
+ end
259
+
260
+ should "raise an OAuth::OrganisationOffline" do
261
+ error = assert_raises(Xeroizer::OAuth::OrganisationOffline) { @application.http_get(@application.client, @uri) }
262
+ assert_equal "organisational advice", error.message
263
+ end
264
+ end
265
+
266
+ context "unknown error" do
267
+ setup do
268
+ body = "oauth_problem_advice=unknown advice&oauth_problem=unknown error"
269
+ stub_request(:get, @uri).to_return(status: @status_code, body: body)
270
+ end
271
+
272
+ should "raise an OAuth::UnknownError" do
273
+ error = assert_raises(Xeroizer::OAuth::UnknownError) { @application.http_get(@application.client, @uri) }
274
+ assert_equal "unknown error:unknown advice", error.message
275
+ end
276
+ end
277
+ end
278
+
279
+ context "other status" do
280
+ setup do
281
+ body = get_file_as_string("token_expired")
282
+ stub_request(:get, @uri).to_return(status: 418, body: body)
283
+ end
284
+
285
+ should "raise an BadRespone" do
286
+ error = assert_raises(Xeroizer::BadResponse) { @application.http_get(@application.client, @uri) }
287
+ assert_equal "Unknown response code: 418", error.message
288
+ end
289
+
15
290
  end
16
291
  end
17
292
  end
18
-
@@ -1,10 +1,10 @@
1
- require 'test_helper'
1
+ require 'unit_test_helper'
2
2
 
3
3
  class AddressTest < Test::Unit::TestCase
4
4
  include TestHelper
5
5
 
6
6
  def setup
7
- @client = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET)
7
+ @client = Xeroizer::OAuth2Application.new(CLIENT_ID, CLIENT_SECRET)
8
8
  @contact = @client.Contact.build
9
9
  end
10
10
 
@@ -1,4 +1,4 @@
1
- require "test_helper"
1
+ require 'unit_test_helper'
2
2
 
3
3
  class BankTransactionModelParsingTest < Test::Unit::TestCase
4
4
  def setup
@@ -33,7 +33,7 @@ class BankTransactionModelParsingTest < Test::Unit::TestCase
33
33
  assert_equal "Inclusive", the_bank_transaction.line_amount_types
34
34
 
35
35
  assert_equal(Time.parse("2008-02-20T12:19:56.657Z"), the_bank_transaction.updated_date_utc)
36
-
36
+
37
37
  assert_equal Date.parse("2010-07-30T00:00:00"), the_bank_transaction.fully_paid_on_date
38
38
  assert_equal "d20b6c54-7f5d-4ce6-ab83-55f609719126", the_bank_transaction.bank_transaction_id
39
39
  assert_equal "SPEND", the_bank_transaction.type
@@ -1,4 +1,4 @@
1
- require "test_helper"
1
+ require 'unit_test_helper'
2
2
 
3
3
  class BankTransactionTest < Test::Unit::TestCase
4
4
  include Xeroizer::Record
@@ -1,4 +1,4 @@
1
- require "test_helper"
1
+ require 'unit_test_helper'
2
2
 
3
3
  class BankTransactionValidationTest < Test::Unit::TestCase
4
4
  include Xeroizer::Record
@@ -1,10 +1,10 @@
1
- require 'test_helper'
1
+ require 'unit_test_helper'
2
2
 
3
3
  class ContactTest < Test::Unit::TestCase
4
4
  include TestHelper
5
5
 
6
6
  def setup
7
- @client = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET)
7
+ @client = Xeroizer::OAuth2Application.new(CLIENT_ID, CLIENT_SECRET)
8
8
  end
9
9
 
10
10
  context "contact validators" do
@@ -1,16 +1,16 @@
1
- require 'test_helper'
1
+ require 'unit_test_helper'
2
2
 
3
3
  class CreditNoteTest < Test::Unit::TestCase
4
4
  include TestHelper
5
-
5
+
6
6
  def setup
7
- @client = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET)
7
+ @client = Xeroizer::OAuth2Application.new(CLIENT_ID, CLIENT_SECRET)
8
8
  mock_api("CreditNotes")
9
9
  @credit_note = @client.CreditNote.first
10
10
  end
11
-
11
+
12
12
  context "credit note totals" do
13
-
13
+
14
14
  should "raise error when trying to set totals directly" do
15
15
  assert_raises Xeroizer::SettingTotalDirectlyNotSupported do
16
16
  @credit_note.sub_total = 500.0
@@ -22,7 +22,7 @@ class CreditNoteTest < Test::Unit::TestCase
22
22
  @credit_note.total = 550.0
23
23
  end
24
24
  end
25
-
25
+
26
26
  should "large-scale testing from API XML" do
27
27
  credit_notes = @client.CreditNote.all
28
28
  credit_notes.each do | credit_note |
@@ -31,7 +31,7 @@ class CreditNoteTest < Test::Unit::TestCase
31
31
  assert_equal(credit_note.attributes[:total], credit_note.total)
32
32
  end
33
33
  end
34
-
34
+
35
35
  end
36
-
36
+
37
37
  end
@@ -1,11 +1,11 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
1
+ require 'unit_test_helper'
2
2
 
3
3
  class EmployeeTest < Test::Unit::TestCase
4
4
  include TestHelper
5
5
  include Xeroizer::Record
6
-
6
+
7
7
  def setup
8
- @client = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET)
8
+ @client = Xeroizer::OAuth2Application.new(CLIENT_ID, CLIENT_SECRET)
9
9
  @employee = @client.Employee.build
10
10
 
11
11
  @employee.employee_id = 'GUID'
@@ -25,7 +25,7 @@ class EmployeeTest < Test::Unit::TestCase
25
25
  @employee.employee_group_name = "TEAM A"
26
26
  @doc = Nokogiri::XML(@employee.to_xml)
27
27
  end
28
-
28
+
29
29
  it "should render" do
30
30
  assert_equal "GUID", @doc.xpath("//EmployeeID").text
31
31
  assert_equal "ACTIVE", @doc.xpath("//Status").text