fishbowl 0.0.1 → 0.0.2

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 (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