xeroizer 2.18.1 → 3.0.1

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