netsuite 0.8.5 → 0.8.9

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 (84) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/main.yml +20 -0
  3. data/.ruby-version +1 -1
  4. data/.tool-versions +1 -0
  5. data/Gemfile +1 -5
  6. data/HISTORY.md +32 -0
  7. data/README.md +48 -21
  8. data/Rakefile +1 -1
  9. data/lib/netsuite/configuration.rb +21 -4
  10. data/lib/netsuite/records/accounting_period.rb +2 -2
  11. data/lib/netsuite/records/assembly_unbuild.rb +1 -3
  12. data/lib/netsuite/records/classification.rb +4 -1
  13. data/lib/netsuite/records/contact.rb +1 -1
  14. data/lib/netsuite/records/cost_category.rb +28 -0
  15. data/lib/netsuite/records/credit_memo.rb +1 -1
  16. data/lib/netsuite/records/currency_rate.rb +1 -1
  17. data/lib/netsuite/records/custom_field_list.rb +9 -3
  18. data/lib/netsuite/records/custom_record.rb +1 -1
  19. data/lib/netsuite/records/customer.rb +2 -1
  20. data/lib/netsuite/records/customer_credit_cards.rb +36 -0
  21. data/lib/netsuite/records/customer_credit_cards_list.rb +10 -0
  22. data/lib/netsuite/records/customer_deposit.rb +5 -5
  23. data/lib/netsuite/records/customer_payment.rb +6 -2
  24. data/lib/netsuite/records/customer_payment_credit.rb +17 -0
  25. data/lib/netsuite/records/customer_payment_credit_list.rb +12 -0
  26. data/lib/netsuite/records/employee.rb +1 -1
  27. data/lib/netsuite/records/estimate.rb +42 -0
  28. data/lib/netsuite/records/estimate_item.rb +40 -0
  29. data/lib/netsuite/records/estimate_item_list.rb +11 -0
  30. data/lib/netsuite/records/inventory_item.rb +62 -1
  31. data/lib/netsuite/records/invoice.rb +97 -4
  32. data/lib/netsuite/records/invoice_item.rb +1 -1
  33. data/lib/netsuite/records/item_fulfillment.rb +1 -1
  34. data/lib/netsuite/records/item_fulfillment_item.rb +1 -1
  35. data/lib/netsuite/records/item_receipt_item.rb +1 -1
  36. data/lib/netsuite/records/member_list.rb +0 -2
  37. data/lib/netsuite/records/non_inventory_purchase_item.rb +1 -1
  38. data/lib/netsuite/records/non_inventory_resale_item.rb +2 -1
  39. data/lib/netsuite/records/non_inventory_sale_item.rb +1 -1
  40. data/lib/netsuite/records/opportunity.rb +2 -2
  41. data/lib/netsuite/records/partner.rb +7 -5
  42. data/lib/netsuite/records/phone_call.rb +1 -1
  43. data/lib/netsuite/records/serialized_assembly_item.rb +3 -2
  44. data/lib/netsuite/records/service_resale_item.rb +2 -2
  45. data/lib/netsuite/records/service_sale_item.rb +1 -1
  46. data/lib/netsuite/records/transfer_order_item.rb +1 -1
  47. data/lib/netsuite/records/vendor.rb +6 -5
  48. data/lib/netsuite/records/vendor_currency.rb +26 -0
  49. data/lib/netsuite/records/vendor_currency_list.rb +9 -0
  50. data/lib/netsuite/support/fields.rb +17 -0
  51. data/lib/netsuite/support/records.rb +1 -1
  52. data/lib/netsuite/support/search_result.rb +23 -4
  53. data/lib/netsuite/utilities.rb +2 -1
  54. data/lib/netsuite/version.rb +1 -1
  55. data/lib/netsuite.rb +10 -0
  56. data/netsuite.gemspec +5 -3
  57. data/spec/netsuite/actions/search_spec.rb +22 -0
  58. data/spec/netsuite/configuration_spec.rb +93 -6
  59. data/spec/netsuite/records/basic_record_spec.rb +8 -1
  60. data/spec/netsuite/records/classification_spec.rb +10 -1
  61. data/spec/netsuite/records/cost_category_spec.rb +105 -0
  62. data/spec/netsuite/records/custom_field_list_spec.rb +46 -6
  63. data/spec/netsuite/records/custom_record_spec.rb +1 -1
  64. data/spec/netsuite/records/customer_credit_cards_list_spec.rb +23 -0
  65. data/spec/netsuite/records/customer_payment_credit_list_spec.rb +26 -0
  66. data/spec/netsuite/records/customer_payment_spec.rb +1 -6
  67. data/spec/netsuite/records/customer_spec.rb +22 -1
  68. data/spec/netsuite/records/employee_spec.rb +2 -2
  69. data/spec/netsuite/records/estimate_item_list_spec.rb +26 -0
  70. data/spec/netsuite/records/estimate_item_spec.rb +40 -0
  71. data/spec/netsuite/records/estimate_spec.rb +216 -0
  72. data/spec/netsuite/records/inventory_item_spec.rb +65 -0
  73. data/spec/netsuite/records/invoice_spec.rb +94 -0
  74. data/spec/netsuite/records/non_inventory_resale_item_spec.rb +165 -0
  75. data/spec/netsuite/records/partner_spec.rb +143 -0
  76. data/spec/netsuite/records/service_resale_item_spec.rb +134 -0
  77. data/spec/netsuite/records/vendor_spec.rb +1 -1
  78. data/spec/netsuite/support/fields_spec.rb +36 -1
  79. data/spec/support/fixtures/custom_fields/multi_select.xml +47 -0
  80. data/spec/support/fixtures/search/saved_search_item.xml +55 -0
  81. data/spec/support/fixtures/search/saved_search_joined_custom_customer.xml +15 -1
  82. data/spec/support/search_only_field_matcher.rb +7 -0
  83. metadata +68 -12
  84. data/circle.yml +0 -17
@@ -168,9 +168,31 @@ describe NetSuite::Actions::Search do
168
168
 
169
169
  expect(search.results.size).to eq(2)
170
170
  expect(search.current_page).to eq(1)
171
+ expect(search.results.first.internal_id).to eq('123')
172
+ expect(search.results.first.external_id).to eq('456')
171
173
  expect(search.results.first.alt_name).to eq('A Awesome Name')
174
+ expect(search.results.first.custom_field_list.custitem_stringfield.value).to eq('sample string value')
175
+ expect(search.results.first.custom_field_list.custitem_apcategoryforsales.value.internal_id).to eq('4')
172
176
  expect(search.results.last.email).to eq('alessawesome@gmail.com')
173
177
  end
178
+
179
+ it "should handle an ID search with basic search only field result columns" do
180
+ response = File.read('spec/support/fixtures/search/saved_search_item.xml')
181
+ savon.expects(:search)
182
+ .with(message: {
183
+ "searchRecord"=>{
184
+ "@xsi:type" =>"listAcct:ItemSearchAdvanced",
185
+ "@savedSearchId" =>42,
186
+ :content! =>{"listAcct:criteria"=>{}},
187
+ }
188
+ }).returns(response)
189
+
190
+ search = NetSuite::Records::InventoryItem.search(saved: 42)
191
+
192
+ expect(search.results.first.location_quantity_available).to eq('3307.0')
193
+ expect(search.results.first.location_re_order_point).to eq('2565.0')
194
+ expect(search.results.first.location_quantity_on_order).to eq('40000.0')
195
+ end
174
196
  end
175
197
 
176
198
  context "advanced search" do
@@ -29,10 +29,12 @@ describe NetSuite::Configuration do
29
29
  end
30
30
 
31
31
  describe '#connection' do
32
+ EXAMPLE_ENDPOINT = 'https://1023.suitetalk.api.netsuite.com/services/NetSuitePort_2020_2'
32
33
  before(:each) do
33
34
  # reset clears out the password info
34
35
  config.email 'me@example.com'
35
36
  config.password 'me@example.com'
37
+ config.endpoint EXAMPLE_ENDPOINT
36
38
  config.account 1023
37
39
  config.wsdl "my_wsdl"
38
40
  config.api_version "2012_2"
@@ -57,6 +59,19 @@ describe NetSuite::Configuration do
57
59
 
58
60
  expect(config).to have_received(:cached_wsdl)
59
61
  end
62
+
63
+ it 'sets the endpoint on the Savon client' do
64
+ # this is ugly/brittle, but it's hard to see how else to test this
65
+ savon_configs = config.connection.globals.instance_eval {@options}
66
+ expect(savon_configs.fetch(:endpoint)).to eq(EXAMPLE_ENDPOINT)
67
+ end
68
+
69
+ it 'handles a nil endpoint' do
70
+ config.endpoint = nil
71
+ # this is ugly/brittle, but it's hard to see how else to test this
72
+ savon_configs = config.connection.globals.instance_eval {@options}
73
+ expect(savon_configs.fetch(:endpoint)).to eq(nil)
74
+ end
60
75
  end
61
76
 
62
77
  describe '#wsdl' do
@@ -166,6 +181,23 @@ describe NetSuite::Configuration do
166
181
  end
167
182
  end
168
183
 
184
+ describe '#endpoint' do
185
+ it 'can be set with endpoint=' do
186
+ config.endpoint = 42
187
+ expect(config.endpoint).to eq(42)
188
+ end
189
+
190
+ it 'can be set with just endpoint(value)' do
191
+ config.endpoint(42)
192
+ expect(config.endpoint).to eq(42)
193
+ end
194
+
195
+ it 'supports nil endpoints' do
196
+ config.endpoint = nil
197
+ expect(config.endpoint).to eq(nil)
198
+ end
199
+ end
200
+
169
201
  describe '#auth_header' do
170
202
  context 'when doing user authentication' do
171
203
  before do
@@ -326,15 +358,11 @@ describe NetSuite::Configuration do
326
358
 
327
359
  describe "#credentials" do
328
360
  context "when none are defined" do
329
- skip "should properly create the auth credentials" do
330
-
331
- end
361
+ skip "should properly create the auth credentials"
332
362
  end
333
363
 
334
364
  context "when they are defined" do
335
- it "should properly replace the default auth credentials" do
336
-
337
- end
365
+ skip "should properly replace the default auth credentials"
338
366
  end
339
367
  end
340
368
 
@@ -371,6 +399,65 @@ describe NetSuite::Configuration do
371
399
  end
372
400
  end
373
401
 
402
+ describe "#log" do
403
+ it 'allows a file path to be set as the log destination' do
404
+ file_path = Tempfile.new('tmplog').path
405
+ config.log = file_path
406
+ config.logger.info "foo"
407
+
408
+ log_contents = open(file_path).read
409
+ expect(log_contents).to include("foo")
410
+ end
411
+
412
+ it 'allows an IO device to bet set as the log destination' do
413
+ stream = StringIO.new
414
+ config.log = stream
415
+ config.logger.info "foo"
416
+
417
+ expect(stream.string).to include("foo")
418
+ end
419
+ end
420
+
421
+ describe '#log_level' do
422
+ it 'defaults to :debug' do
423
+ expect(config.log_level).to eq(:debug)
424
+ end
425
+
426
+ it 'can be initially set to any log level' do
427
+ config.log_level(:info)
428
+
429
+ expect(config.log_level).to eq(:info)
430
+ end
431
+
432
+ it 'can override itself' do
433
+ config.log_level = :info
434
+
435
+ expect(config.log_level).to eq(:info)
436
+
437
+ config.log_level(:debug)
438
+
439
+ expect(config.log_level).to eq(:debug)
440
+ end
441
+ end
442
+
443
+ describe '#log_level=' do
444
+ it 'can set the initial log_level' do
445
+ config.log_level = :info
446
+
447
+ expect(config.log_level).to eq(:info)
448
+ end
449
+
450
+ it 'can override a previously set log level' do
451
+ config.log_level = :info
452
+
453
+ expect(config.log_level).to eq(:info)
454
+
455
+ config.log_level = :debug
456
+
457
+ expect(config.log_level).to eq(:debug)
458
+ end
459
+ end
460
+
374
461
  describe 'timeouts' do
375
462
  it 'has defaults' do
376
463
  expect(config.read_timeout).to eql(60)
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'basic records' do
4
+ # all records with internal IDs should be added to this list
4
5
  let(:basic_record_list) {
5
6
  [
6
7
  NetSuite::Records::Currency,
@@ -49,6 +50,7 @@ describe 'basic records' do
49
50
  NetSuite::Records::SerializedInventoryItem,
50
51
  NetSuite::Records::DepositApplication,
51
52
  NetSuite::Records::InventoryAdjustment,
53
+ NetSuite::Records::Vendor,
52
54
  NetSuite::Records::VendorReturnAuthorization,
53
55
  NetSuite::Records::AssemblyBuild,
54
56
  NetSuite::Records::AssemblyUnbuild,
@@ -61,6 +63,7 @@ describe 'basic records' do
61
63
  NetSuite::Records::BinTransfer,
62
64
  NetSuite::Records::SerializedAssemblyItem,
63
65
  NetSuite::Records::CustomerStatus,
66
+ NetSuite::Records::CustomerPayment,
64
67
  NetSuite::Records::TransactionBodyCustomField,
65
68
  NetSuite::Records::TransactionColumnCustomField,
66
69
  NetSuite::Records::EntityCustomField
@@ -108,8 +111,12 @@ describe 'basic records' do
108
111
 
109
112
  if !sublist_fields.empty?
110
113
  sublist_fields.each do |sublist_field|
114
+ sublist = record_instance.send(sublist_field)
115
+
111
116
  # TODO make a sublist entry with some fields valid for that sublist item
112
- record_instance.send(sublist_field) << {}
117
+ sublist << {}
118
+
119
+ expect(sublist.send(sublist.sublist_key).count).to be(1)
113
120
  end
114
121
  end
115
122
 
@@ -5,12 +5,21 @@ describe NetSuite::Records::Classification do
5
5
 
6
6
  it 'has all the right fields' do
7
7
  [
8
- :name, :include_children, :is_inactive, :class_translation_list, :custom_field_list
8
+ :name, :include_children, :is_inactive, :class_translation_list
9
9
  ].each do |field|
10
10
  expect(classification).to have_field(field)
11
11
  end
12
12
 
13
13
  expect(classification.subsidiary_list.class).to eq(NetSuite::Records::RecordRefList)
14
+ expect(classification.custom_field_list.class).to eq(NetSuite::Records::CustomFieldList)
15
+ end
16
+
17
+ it 'has all the right record refs' do
18
+ [
19
+ :parent
20
+ ].each do |record_ref|
21
+ expect(classification).to have_record_ref(record_ref)
22
+ end
14
23
  end
15
24
 
16
25
  describe '.get' do
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::CostCategory do
4
+ let(:cost_category) { described_class.new }
5
+
6
+ it 'has all the right fields' do
7
+ [
8
+ :is_inactive,
9
+ :item_cost_type,
10
+ :name,
11
+ ].each do |field|
12
+ expect(cost_category).to have_field(field)
13
+ end
14
+ end
15
+
16
+ it 'has all the right record refs' do
17
+ [
18
+ :account,
19
+ ].each do |record_ref|
20
+ expect(cost_category).to have_record_ref(record_ref)
21
+ end
22
+ end
23
+
24
+ describe '.get' do
25
+ context 'when the response is successful' do
26
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :name => 'CostCategory 1' }) }
27
+
28
+ it 'returns a CostCategory instance populated with the data from the response object' do
29
+ expect(NetSuite::Actions::Get).to receive(:call).with([described_class, {:external_id => 1}], {}).and_return(response)
30
+ cost_category = described_class.get(:external_id => 1)
31
+ expect(cost_category).to be_kind_of(described_class)
32
+ expect(cost_category.name).to eql('CostCategory 1')
33
+ end
34
+ end
35
+
36
+ context 'when the response is unsuccessful' do
37
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
38
+
39
+ it 'raises a RecordNotFound exception' do
40
+ expect(NetSuite::Actions::Get).to receive(:call).with([described_class, {:external_id => 1}], {}).and_return(response)
41
+ expect {
42
+ described_class.get(:external_id => 1)
43
+ }.to raise_error(NetSuite::RecordNotFound,
44
+ /NetSuite::Records::CostCategory with OPTIONS=(.*) could not be found/)
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#add' do
50
+ let(:test_data) { { :name => 'Test CostCategory' } }
51
+
52
+ context 'when the response is successful' do
53
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
54
+
55
+ it 'returns true' do
56
+ cost_category = described_class.new(test_data)
57
+ expect(NetSuite::Actions::Add).to receive(:call).
58
+ with([cost_category], {}).
59
+ and_return(response)
60
+ expect(cost_category.add).to be_truthy
61
+ end
62
+ end
63
+
64
+ context 'when the response is unsuccessful' do
65
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
66
+
67
+ it 'returns false' do
68
+ cost_category = described_class.new(test_data)
69
+ expect(NetSuite::Actions::Add).to receive(:call).
70
+ with([cost_category], {}).
71
+ and_return(response)
72
+ expect(cost_category.add).to be_falsey
73
+ end
74
+ end
75
+ end
76
+
77
+ describe '#delete' do
78
+ let(:test_data) { { :internal_id => '1' } }
79
+
80
+ context 'when the response is successful' do
81
+ let(:response) { NetSuite::Response.new(:success => true, :body => { :internal_id => '1' }) }
82
+
83
+ it 'returns true' do
84
+ cost_category = described_class.new(test_data)
85
+ expect(NetSuite::Actions::Delete).to receive(:call).
86
+ with([cost_category], {}).
87
+ and_return(response)
88
+ expect(cost_category.delete).to be_truthy
89
+ end
90
+ end
91
+
92
+ context 'when the response is unsuccessful' do
93
+ let(:response) { NetSuite::Response.new(:success => false, :body => {}) }
94
+
95
+ it 'returns false' do
96
+ cost_category = described_class.new(test_data)
97
+ expect(NetSuite::Actions::Delete).to receive(:call).
98
+ with([cost_category], {}).
99
+ and_return(response)
100
+ expect(cost_category.delete).to be_falsey
101
+ end
102
+ end
103
+ end
104
+
105
+ end
@@ -3,17 +3,53 @@ require 'spec_helper'
3
3
  describe NetSuite::Records::CustomFieldList do
4
4
  let(:list) { NetSuite::Records::CustomFieldList.new }
5
5
 
6
+ before(:all) { savon.mock! }
7
+ after(:all) { savon.unmock! }
8
+
6
9
  it 'has a custom_fields attribute' do
7
10
  expect(list.custom_fields).to be_kind_of(Array)
8
11
  end
9
12
 
10
13
  it 'accepts a collection of CustomField records' do
11
- field = NetSuite::Records::CustomField.new({:value=>{:internal_id=>"5", :type_id=>"103"},
12
- :script_id=>"custitem_item_category", :"@xsi:type"=>"platformCore:SelectCustomFieldRef"})
14
+ field = NetSuite::Records::CustomField.new({
15
+ :value=>{:internal_id=>"5", :type_id=>"103"},
16
+ :script_id=>"custitem_item_category",
17
+ :"@xsi:type"=>"platformCore:SelectCustomFieldRef"
18
+ })
19
+
13
20
  list = described_class.new(custom_field: [field])
21
+
14
22
  expect(list.custom_fields).to eq([field])
15
23
  end
16
24
 
25
+ it 'properly decodes various custom field types' do
26
+ savon.
27
+ expects(:get).
28
+ with(message: {"platformMsgs:baseRef"=>{"@xsi:type"=>"platformCore:RecordRef", "@internalId"=>123, "@type"=>"creditMemo"}}).
29
+ returns(File.read('spec/support/fixtures/custom_fields/multi_select.xml'))
30
+
31
+ credit_memo_with_custom_fields = NetSuite::Records::CreditMemo.get(123)
32
+
33
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_standard_select.value.internal_id).to eq("2")
34
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_standard_select.value.attributes[:name]).to eq("Manual")
35
+
36
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_date_field.value).to be_a(DateTime)
37
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_date_field.value.to_s).to eq("2021-07-13T22:00:00-07:00")
38
+
39
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_string_field.value).to eq("a very nice string")
40
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_boolean_field.value).to eq(false)
41
+
42
+ # even if there's a single value, it should return an array
43
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_field.value).to be_a(Array)
44
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_field.value.size).to eq(1)
45
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_field.value.first.attributes[:name]).to eq("selection value")
46
+
47
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_with_multiple.value).to be_a(Array)
48
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_with_multiple.value.size).to eq(2)
49
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_with_multiple.value.first.attributes[:name]).to eq("selection value 1")
50
+ expect(credit_memo_with_custom_fields.custom_field_list.custbody_multi_select_with_multiple.value.last.attributes[:name]).to eq("selection value 2")
51
+ end
52
+
17
53
  context 'initializing with custom field attributes without a type' do
18
54
  it 'does not mutate the attributes' do
19
55
  field = {:value=>{:internal_id=>"5", :type_id=>"103"},
@@ -28,7 +64,9 @@ describe NetSuite::Records::CustomFieldList do
28
64
  it 'does not mutate the attributes' do
29
65
  field = {:value=>{:internal_id=>"5", :type_id=>"103"},
30
66
  :script_id=>"custitem_item_category", :"@xsi:type"=>"platformCore:SelectCustomFieldRef"}
67
+
31
68
  described_class.new(custom_field: [field])
69
+
32
70
  expect(field).to eq({:value=>{:internal_id=>"5", :type_id=>"103"},
33
71
  :script_id=>"custitem_item_category", :"@xsi:type"=>"platformCore:SelectCustomFieldRef"})
34
72
  end
@@ -37,9 +75,11 @@ describe NetSuite::Records::CustomFieldList do
37
75
  context 'writing convience methods' do
38
76
  it "should create a custom field entry when none exists" do
39
77
  list.custrecord_somefield = 'a value'
40
- list.custom_fields.size.should == 1
41
- list.custom_fields.first.value.should == 'a value'
42
- list.custom_fields.first.type.should == 'platformCore:StringCustomFieldRef'
78
+ custom_fields = list.custom_fields
79
+
80
+ expect(custom_fields.size).to eq(1)
81
+ expect(custom_fields.first.value).to eq('a value')
82
+ expect(custom_fields.first.type).to eq('platformCore:StringCustomFieldRef')
43
83
  end
44
84
 
45
85
  # https://github.com/NetSweet/netsuite/issues/325
@@ -116,7 +156,7 @@ describe NetSuite::Records::CustomFieldList do
116
156
  end
117
157
 
118
158
  it "should raise an error if custom field entry does not exist" do
119
- expect{ list.nonexisting_custom_field }.to raise_error
159
+ expect{ list.nonexisting_custom_field }.to raise_error(NoMethodError)
120
160
  end
121
161
  end
122
162
  end
@@ -18,7 +18,7 @@ describe NetSuite::Records::CustomRecord do
18
18
 
19
19
  it 'has all the right record_refs' do
20
20
  [
21
- :custom_form, :owner
21
+ :custom_form, :owner, :rec_type, :parent
22
22
  ].each do |record_ref|
23
23
  expect(record).to have_record_ref(record_ref)
24
24
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe NetSuite::Records::CustomerCreditCardsList do
4
+ let(:list) { NetSuite::Records::CustomerCreditCardsList.new }
5
+
6
+ it 'has a credit_cards attribute' do
7
+ expect(list.credit_cards).to be_kind_of(Array)
8
+ end
9
+
10
+ describe '#to_record' do
11
+ it 'can represent itself as a SOAP record' do
12
+ list.replace_all = true
13
+
14
+ record = {
15
+ 'listRel:creditCards' => [],
16
+ 'listRel:replaceAll' => true
17
+ }
18
+
19
+ expect(list.to_record).to eql(record)
20
+ end
21
+ end
22
+
23
+ end