fishbowl 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/.travis.yml +9 -4
  2. data/Gemfile +10 -1
  3. data/Guardfile +13 -0
  4. data/lib/fishbowl.rb +13 -15
  5. data/lib/fishbowl/ext.rb +15 -0
  6. data/lib/fishbowl/objects.rb +5 -0
  7. data/lib/fishbowl/objects/account.rb +24 -2
  8. data/lib/fishbowl/objects/address.rb +86 -0
  9. data/lib/fishbowl/objects/base_object.rb +34 -5
  10. data/lib/fishbowl/objects/carrier.rb +15 -0
  11. data/lib/fishbowl/objects/carton.rb +54 -0
  12. data/lib/fishbowl/objects/uom.rb +47 -0
  13. data/lib/fishbowl/objects/user.rb +15 -0
  14. data/lib/fishbowl/requests.rb +6 -0
  15. data/lib/fishbowl/requests/add_inventory.rb +34 -0
  16. data/lib/fishbowl/requests/add_sales_order_item.rb +42 -0
  17. data/lib/fishbowl/requests/adjust_inventory.rb +28 -0
  18. data/lib/fishbowl/requests/get_carrier_list.rb +12 -0
  19. data/lib/fishbowl/version.rb +1 -1
  20. data/spec/examples/account.xml +6 -0
  21. data/spec/examples/address.xml +30 -0
  22. data/spec/examples/carrier.xml +3 -0
  23. data/spec/examples/carton.xml +93 -0
  24. data/spec/examples/contact_information.xml +5 -0
  25. data/spec/examples/contacts.xml +7 -0
  26. data/spec/examples/credit_card.xml +10 -0
  27. data/spec/examples/customer.xml +54 -0
  28. data/spec/examples/location.xml +14 -0
  29. data/spec/examples/location_group.xml +5 -0
  30. data/spec/examples/location_group_string.xml +1 -0
  31. data/spec/examples/order_history.xml +8 -0
  32. data/spec/examples/part.xml +105 -0
  33. data/spec/examples/payment.xml +6 -0
  34. data/spec/examples/pick.xml +265 -0
  35. data/spec/examples/pick_item.xml +236 -0
  36. data/spec/examples/product.xml +159 -0
  37. data/spec/examples/purchase_order.xml +53 -0
  38. data/spec/examples/receipt.xml +146 -0
  39. data/spec/examples/report.xml +10 -0
  40. data/spec/examples/report_tree.xml +7 -0
  41. data/spec/examples/sales_order.xml +47 -0
  42. data/spec/examples/sales_order_item.xml +32 -0
  43. data/spec/examples/shipping.xml +127 -0
  44. data/spec/examples/tag.xml +28 -0
  45. data/spec/examples/tax_rate.xml +10 -0
  46. data/spec/examples/tracking.xml +14 -0
  47. data/spec/examples/tracking_item.xml +12 -0
  48. data/spec/examples/transfer_order.xml +257 -0
  49. data/spec/examples/transfer_order_item.xml +147 -0
  50. data/spec/examples/uom.xml +26 -0
  51. data/spec/examples/uom_conversion.xml +8 -0
  52. data/spec/examples/user.xml +8 -0
  53. data/spec/examples/vendor.xml +19 -0
  54. data/spec/examples/vendor_part_number.xml +3 -0
  55. data/spec/examples/work_order.xml +228 -0
  56. data/spec/examples/work_order_item.xml +172 -0
  57. data/spec/objects/account_spec.rb +53 -6
  58. data/spec/objects/address_information_spec.rb +18 -0
  59. data/spec/objects/address_spec.rb +36 -0
  60. data/spec/objects/base_object_spec.rb +67 -23
  61. data/spec/objects/carrier_spec.rb +15 -0
  62. data/spec/objects/carton_spec.rb +23 -0
  63. data/spec/objects/country_spec.rb +16 -0
  64. data/spec/objects/shipping_item_spec.rb +21 -0
  65. data/spec/objects/state_spec.rb +17 -0
  66. data/spec/objects/uom_conversion_spec.rb +20 -0
  67. data/spec/objects/uom_spec.rb +20 -0
  68. data/spec/objects/user_spec.rb +20 -0
  69. data/spec/requests/add_inventory_spec.rb +79 -0
  70. data/spec/requests/add_sales_order_item_spec.rb +85 -0
  71. data/spec/requests/adjust_inventory_spec.rb +62 -0
  72. data/spec/requests/get_carrier_list_spec.rb +54 -0
  73. data/spec/spec_helper.rb +41 -11
  74. data/spec/support/examples_loader.rb +5 -0
  75. data/spec/support/response_mocks.rb +27 -0
  76. metadata +122 -6
  77. data/spec/support/fake_login.rb +0 -15
@@ -14,6 +14,21 @@ describe Fishbowl::Objects::Account do
14
14
 
15
15
  let(:connection) { FakeTCPSocket.instance }
16
16
 
17
+ describe "instances" do
18
+
19
+ let(:account) {
20
+ doc = Nokogiri::XML.parse(example_file('account.xml'))
21
+ Fishbowl::Objects::Account.new(doc.xpath('//Account'))
22
+ }
23
+
24
+ it "should properly initialize from example file" do
25
+ account.name.should eq("Cost Variance")
26
+ account.accounting_id.should eq("8000001B-1310422643")
27
+ account.account_type.should eq("12")
28
+ account.balance.should eq("0")
29
+ end
30
+ end
31
+
17
32
  describe ".get_list" do
18
33
  let(:proper_request) do
19
34
  Nokogiri::XML::Builder.new do |xml|
@@ -26,8 +41,23 @@ describe Fishbowl::Objects::Account do
26
41
  end
27
42
  end
28
43
 
29
- let(:canned_response) do
44
+ before :each do
45
+ canned_response = Nokogiri::XML::Builder.new do |xml|
46
+ xml.response {
47
+ xml.GetAccountListRs(statusCode: '1000', statusMessage: "Success!") {
48
+ (rand(3) + 2).times do |i|
49
+ xml.Account {
50
+ xml.Name "Demo Account #{i}"
51
+ xml.AccountingID "DEMO#{i}"
52
+ xml.AccountType i
53
+ xml.Balance "1200.00"
54
+ }
55
+ end
56
+ }
57
+ }
58
+ end
30
59
 
60
+ mock_the_response(canned_response)
31
61
  end
32
62
 
33
63
  it "should properly format the request" do
@@ -35,10 +65,8 @@ describe Fishbowl::Objects::Account do
35
65
  connection.last_write.should be_equivalent_to(proper_request.to_xml)
36
66
  end
37
67
 
38
- it "should return array of Accounts"
39
-
40
- it "should return empty array when no accounts" do
41
-
68
+ it "should return array of Accounts" do
69
+ Fishbowl::Objects::Account.get_list.should be_an(Array)
42
70
  end
43
71
  end
44
72
 
@@ -56,11 +84,30 @@ describe Fishbowl::Objects::Account do
56
84
  end
57
85
  end
58
86
 
87
+ before :each do
88
+ canned_response = Nokogiri::XML::Builder.new do |xml|
89
+ xml.response {
90
+ xml.GetAccountBalanceRs(statusCode: '1000', statusMessage: "Success!") {
91
+ xml.Account {
92
+ xml.Name "Demo Account"
93
+ xml.AccountingID "DEMO"
94
+ xml.AccountType 9
95
+ xml.Balance "1200.00"
96
+ }
97
+ }
98
+ }
99
+ end
100
+
101
+ mock_the_response(canned_response)
102
+ end
103
+
59
104
  it "should properly format the request" do
60
105
  Fishbowl::Objects::Account.get_balance("General Account")
61
106
  connection.last_write.should be_equivalent_to(proper_request.to_xml)
62
107
  end
63
108
 
64
- it "should return the balance for the requested Account"
109
+ it "should return the balance for the requested Account" do
110
+ Fishbowl::Objects::Account.get_balance("General Account").should be_a(String)
111
+ end
65
112
  end
66
113
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::AddressInformation do
4
+ describe "instances" do
5
+
6
+ let(:address_info) {
7
+ doc = Nokogiri::XML.parse(example_file('address.xml'))
8
+ Fishbowl::Objects::AddressInformation.new(doc.xpath('//AddressInformation'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ address_info.name.should eq("Main Office")
13
+ address_info.data.should eq("Address Data")
14
+ address_info.default.should eq("true")
15
+ address_info.type.should eq("Home")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::Address do
4
+ before :each do
5
+ mock_tcp_connection
6
+ mock_login_response
7
+ Fishbowl::Connection.connect(host: 'localhost')
8
+ Fishbowl::Connection.login(username: 'johndoe', password: 'secret')
9
+ end
10
+
11
+ after :each do
12
+ unmock_tcp
13
+ end
14
+
15
+ let(:connection) { FakeTCPSocket.instance }
16
+
17
+ describe "instances" do
18
+
19
+ let(:address) {
20
+ doc = Nokogiri::XML.parse(example_file('address.xml'))
21
+ Fishbowl::Objects::Address.new(doc.xpath('//Address'))
22
+ }
23
+
24
+ it "should properly initialize from example file" do
25
+ address.name.should eq("Main Office")
26
+ address.attn.should eq("Attn")
27
+ address.street.should eq("123 Neverland dr.")
28
+
29
+ address.state.should be_a(Fishbowl::Objects::State)
30
+ address.country.should be_a(Fishbowl::Objects::Country)
31
+ address.address_information_list.should be_a(Array)
32
+ address.address_information_list.first.should be_a(Fishbowl::Objects::AddressInformation)
33
+ end
34
+ end
35
+ end
36
+
@@ -3,6 +3,7 @@ require 'spec_helper'
3
3
  describe Fishbowl::Objects::BaseObject do
4
4
  let(:ticket) { "thisisasample" }
5
5
  let(:base_object) { Fishbowl::Objects::BaseObject.new }
6
+ let(:connection) { FakeTCPSocket.instance }
6
7
 
7
8
  let(:empty_ticket_builder) do
8
9
  Nokogiri::XML::Builder.new do |xml|
@@ -10,7 +11,7 @@ describe Fishbowl::Objects::BaseObject do
10
11
  xml.Ticket
11
12
 
12
13
  xml.FbiMsgsRq {
13
- xml.SampleRequest
14
+ xml.SampleRq
14
15
  }
15
16
  }
16
17
  end
@@ -22,43 +23,86 @@ describe Fishbowl::Objects::BaseObject do
22
23
  xml.Ticket ticket
23
24
 
24
25
  xml.FbiMsgsRq {
25
- xml.SampleRequest
26
+ xml.SampleRq
26
27
  }
27
28
  }
28
29
  end
29
30
  end
30
31
 
31
- context "Protected Methods" do
32
- describe "#send_request" do
32
+ before :each do
33
+ mock_tcp_connection
34
+ mock_login_response
35
+ Fishbowl::Connection.connect(host: 'localhost')
36
+ Fishbowl::Connection.login(username: 'johndoe', password: 'secret')
37
+ end
33
38
 
34
- end
39
+ after :each do
40
+ unmock_tcp
35
41
  end
36
42
 
37
- context "Private Methods" do
38
- describe "#build_request" do
39
- it "should build a request document" do
40
- base_object.send(:build_request, "SampleRequest").to_xml.should be_equivalent_to(empty_ticket_builder.to_xml)
41
- end
43
+ describe "#send_request" do
44
+ before :each do
45
+ mock_the_response
46
+ end
42
47
 
43
- it "should accept an XML Builder" do
44
- builder = Nokogiri::XML::Builder.new { |xml| xml.request { xml.SampleRequest } }
45
- base_object.send(:build_request, builder, true).to_xml.should be_equivalent_to(empty_ticket_builder.to_xml)
46
- end
48
+ it "should include the ticket value when it's set" do
49
+ base_object.ticket = ticket
50
+ base_object.send_request("SampleRq", "SampleRs")
51
+ connection.last_write.should be_equivalent_to(ticket_builder.to_xml)
52
+ end
47
53
 
48
- context "when ticket is empty" do
49
- it "should return an empty Nokogiri::XML::Builder" do
50
- base_object.send(:build_request, "SampleRequest").to_xml.should be_equivalent_to(empty_ticket_builder.to_xml)
51
- end
54
+ it "should send the specified request" do
55
+ base_object.send_request("SampleRq", "SampleRs")
56
+ connection.last_write.should be_equivalent_to(empty_ticket_builder.to_xml)
57
+ end
58
+
59
+ it "should get the expected response" do
60
+ code, message, response = base_object.send_request("SampleRq", "SampleRs")
61
+
62
+ code.should_not be_nil
63
+ message.should_not be_nil
64
+ response.should be_equivalent_to(mock_response.to_xml)
65
+ end
66
+ end
67
+
68
+ context "Protected Methods" do
69
+ describe ".attributes" do
70
+ it "should return an array containing 'ID' by default" do
71
+ Fishbowl::Objects::BaseObject.attributes.should eq(["ID"])
52
72
  end
73
+ end
53
74
 
54
- context "when ticket is set" do
55
- before :each do
56
- base_object.ticket = ticket
75
+ describe "#parse_attributes" do
76
+ it "should parse the requested attributes from the supplied xml" do
77
+ parse_xml = Nokogiri::XML::Builder.new do |xml|
78
+ xml.parse {
79
+ xml.ID "5"
80
+ xml.DataID "15"
81
+ xml.Name "Demo"
82
+ xml.SKU "DEMO"
83
+ }
57
84
  end
85
+ parse_xml = Nokogiri::XML.parse(parse_xml.to_xml)
58
86
 
59
- it "should return the ticket wrapped in a Nokogiri::XML::Builder" do
60
- base_object.send(:build_request, "SampleRequest").to_xml.should be_equivalent_to(ticket_builder.to_xml)
87
+ class Fishbowl::Objects::BaseObject
88
+ def self.attributes
89
+ %w{ID DataID Name SKU}
90
+ end
61
91
  end
92
+
93
+ base_object.instance_variable_set("@xml", parse_xml.xpath('parse'))
94
+
95
+ base_object.send(:parse_attributes)
96
+
97
+ base_object.instance_variables.should include(:@db_id)
98
+ base_object.instance_variables.should include(:@data_id)
99
+ base_object.instance_variables.should include(:@name)
100
+ base_object.instance_variables.should include(:@sku)
101
+
102
+ base_object.instance_variable_get(:@db_id).should eq("5")
103
+ base_object.instance_variable_get(:@data_id).should eq("15")
104
+ base_object.instance_variable_get(:@name).should eq("Demo")
105
+ base_object.instance_variable_get(:@sku).should eq("DEMO")
62
106
  end
63
107
  end
64
108
  end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::Carrier do
4
+ describe "instances" do
5
+
6
+ let(:carrier) {
7
+ doc = Nokogiri::XML.parse(example_file('carrier.xml'))
8
+ Fishbowl::Objects::Carrier.new(doc.xpath('//Carrier'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ carrier.name.should eq("Will Call")
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::Carton do
4
+ describe "instances" do
5
+
6
+ let(:carton) {
7
+ doc = Nokogiri::XML.parse(example_file('carton.xml'))
8
+ Fishbowl::Objects::Carton.new(doc.xpath('//Carton'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ carton.db_id.should eq("64")
13
+ carton.ship_id.should eq("63")
14
+ carton.carton_num.should eq("1")
15
+ carton.tracking_num.should be_empty
16
+ carton.freight_weight.should eq("1.2")
17
+ carton.freight_amount.should eq("0")
18
+
19
+ carton.shipping_items.first.should be_a(Fishbowl::Objects::ShippingItem)
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::Country do
4
+ describe "instances" do
5
+
6
+ let(:country) {
7
+ doc = Nokogiri::XML.parse(example_file('address.xml'))
8
+ Fishbowl::Objects::Country.new(doc.xpath('//Country'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ country.name.should eq("United States")
13
+ country.code.should eq("US")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::Carton do
4
+ describe "instances" do
5
+
6
+ let(:shipping_item) {
7
+ doc = Nokogiri::XML.parse(example_file('carton.xml'))
8
+ Fishbowl::Objects::ShippingItem.new(doc.xpath('//ShippingItem'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ shipping_item.ship_item_id.should eq("169")
13
+ shipping_item.product_number.should eq("B201")
14
+
15
+ shipping_item.uom.should be_a(Fishbowl::Objects::UOM)
16
+ shipping_item.weight_uom.should be_a(Fishbowl::Objects::UOM)
17
+ shipping_item.display_weight_uom.should be_a(Fishbowl::Objects::UOM)
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::State do
4
+ describe "instances" do
5
+
6
+ let(:state) {
7
+ doc = Nokogiri::XML.parse(example_file('address.xml'))
8
+ Fishbowl::Objects::State.new(doc.xpath('//State'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ state.name.should eq("Utah")
13
+ state.code.should eq("UT")
14
+ state.country_id.should eq("2")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::UOMConversion do
4
+ describe "instances" do
5
+
6
+ let(:uom_conversion) {
7
+ doc = Nokogiri::XML.parse(example_file('uom_conversion.xml'))
8
+ Fishbowl::Objects::UOMConversion.new(doc.xpath('//UOMConversion'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ uom_conversion.main_uom_id.should eq("1")
13
+ uom_conversion.to_uom_id.should eq("17")
14
+ uom_conversion.to_uom_code.should eq("pr")
15
+ uom_conversion.conversion_multiply.should eq("1.0")
16
+ uom_conversion.conversion_factor.should eq("2.0")
17
+ uom_conversion.to_uom_is_integral.should eq("false")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::UOM do
4
+ describe "instances" do
5
+
6
+ let(:uom) {
7
+ doc = Nokogiri::XML.parse(example_file('uom.xml'))
8
+ Fishbowl::Objects::UOM.new(doc.xpath('//UOM'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ uom.uomid.should eq("1")
13
+ uom.name.should eq("Each")
14
+ uom.code.should eq("ea")
15
+
16
+ uom.uom_conversions.should be_a(Array)
17
+ uom.uom_conversions.first.should be_a(Fishbowl::Objects::UOMConversion)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Objects::User do
4
+ describe "instances" do
5
+
6
+ let(:user) {
7
+ doc = Nokogiri::XML.parse(example_file('user.xml'))
8
+ Fishbowl::Objects::User.new(doc.xpath('//User'))
9
+ }
10
+
11
+ it "should properly initialize from example file" do
12
+ user.db_id.should eq("1")
13
+ user.user_name.should eq("admin")
14
+ user.first_name.should eq("Administrator")
15
+ user.last_name.should eq("Administrator")
16
+ user.initials.should eq("ADM")
17
+ user.active.should eq("true")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fishbowl::Requests do
4
+ describe "#add_inventory" do
5
+ before :each do
6
+ mock_tcp_connection
7
+ mock_login_response
8
+ Fishbowl::Connection.connect(host: 'localhost')
9
+ Fishbowl::Connection.login(username: 'johndoe', password: 'secret')
10
+ end
11
+
12
+ let(:connection) { FakeTCPSocket.instance }
13
+
14
+ let(:valid_options) {
15
+ {
16
+ part_number: "B103",
17
+ quantity: 6,
18
+ uom_id: 1,
19
+ cost: 33.01,
20
+ location_tag_number: 1,
21
+ tag_number: 1
22
+ }
23
+ }
24
+
25
+ it "requires valid options" do
26
+ lambda {
27
+ Fishbowl::Requests.add_inventory(valid_options)
28
+ }.should_not raise_error(ArgumentError)
29
+
30
+ valid_options.each do |excluded_key, excluded_value|
31
+ invalid_options = valid_options.keep_if {|k,v| k != excluded_key}
32
+
33
+ lambda {
34
+ Fishbowl::Requests.add_inventory(invalid_options)
35
+ }.should raise_error(ArgumentError)
36
+ end
37
+ end
38
+
39
+ it "sends proper request" do
40
+ mock_the_response('AddInventoryRs')
41
+ Fishbowl::Requests.add_inventory(valid_options)
42
+ connection.last_write.should be_equivalent_to(expected_request)
43
+ end
44
+
45
+ it "includes note option when supplied" do
46
+ additional_options = { note: 'This is a test' }
47
+
48
+ mock_the_response('AddInventoryRs')
49
+ Fishbowl::Requests.add_inventory(valid_options.merge(additional_options))
50
+ connection.last_write.should be_equivalent_to(expected_request(additional_options))
51
+ end
52
+
53
+ it "includes tracking option when supplied"
54
+
55
+ def expected_request(options = {})
56
+ options = valid_options.merge(options)
57
+
58
+ request = Nokogiri::XML::Builder.new do |xml|
59
+ xml.FbiXml {
60
+ xml.Ticket
61
+ xml.FbiMsgsRq {
62
+ xml.AddInventoryRq {
63
+ xml.PartNum options[:part_number]
64
+ xml.Quantity options[:quantity]
65
+ xml.UOMID options[:uom_id]
66
+ xml.Cost options[:cost]
67
+ xml.Note options[:note] unless options[:note].nil?
68
+ xml.Tracking options[:tracking] unless options[:tracking].nil?
69
+ xml.LocationTagNum valid_options[:location_tag_number]
70
+ xml.TagNum valid_options[:tag_number]
71
+ }
72
+ }
73
+ }
74
+ end
75
+
76
+ request.to_xml
77
+ end
78
+ end
79
+ end