public void TestAlternateTaxTable_AddStateTaxRule_VerifyTaxRateSetsIsSpecified()
        {
            //create a pickup shipping method
            var request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "GBP", 120);

            var taxTable = new AlternateTaxTable("ohio");

            request.AlternateTaxTables.Add(taxTable);
            taxTable.AddStateTaxRule("OH", .05);

            CheckoutShoppingCart roundTrip = EncodeHelper.Deserialize(EncodeHelper.Utf8BytesToString(request.GetXml()),
                                                                      typeof(CheckoutShoppingCart)) as CheckoutShoppingCart;

            var actualTaxTable = roundTrip.checkoutflowsupport.Item.taxtables.alternatetaxtables[0].alternatetaxrules[0];

            Assert.AreEqual(.05, actualTaxTable.rate);
            Assert.IsTrue(actualTaxTable.rateSpecified);
            Assert.AreEqual(typeof(USStateArea), actualTaxTable.taxarea.Item.GetType());
        }
        public void TestAlternateTaxTables()
        {
            CheckoutShoppingCartRequest request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);

            //Ensure the factory works as expected
            AlternateTaxTable ohio1 = new AlternateTaxTable("ohio");

            request.AlternateTaxTables.Add(ohio1);
            AlternateTaxTable ohio2 = request.AlternateTaxTables["ohio"];
            AlternateTaxTable ohio3 = new AlternateTaxTable("ohio", true);

            //Ensure that two Tax tables with the same name are not the same reference
            Assert.AreSame(ohio1, ohio2);
            Assert.IsFalse(object.ReferenceEquals(ohio1, ohio3));
            //Assert.AreEqual(ohio1, ohio3);

            //Now add some rules to the item
            ohio1.AddStateTaxRule("OH", .02);

            //Make sure we can add an item to the cart.
            ShoppingCartItem item = request.AddItem("Item 1", "Cool Candy 1", 2.00M, 1, ohio1);

            try {
                request.AddItem("Item 2", "Cool Candy 2", 2.00M, 1, ohio3);
                Assert.Fail("An exception should have been thrown when we tried to add an item that has a new Tax Reference");
            }
            catch (Exception) {
            }

            //Now this should work fine.
            request.AddItem("Item 3", "Cool Candy 3", string.Empty, 2.00M, 1, ohio2);

            //you could create this as an IShoppingCartItem or ShoppingCartItem
            IShoppingCartItem newItem = new ShoppingCartItem("Item 2", "Cool Candy 2", string.Empty, 2.00M, 2, AlternateTaxTable.Empty, "This is a test of a string of private data");

            //now decide to change your mind on the quantity and price
            newItem.Price    = 20;
            newItem.Quantity = 4;

            request.AddItem(newItem);

            //Console.WriteLine("private data:" + newItem.MerchantPrivateItemData);

            Assert.AreEqual("This is a test of a string of private data", newItem.MerchantPrivateItemData);

            //now change the private data string and compare again.
            newItem.MerchantPrivateItemData = "This is a new String";
            Assert.AreEqual("This is a new String", newItem.MerchantPrivateItemData);

            //now change the private data string and compare again.
            newItem.MerchantPrivateItemData = string.Empty;
            Assert.AreEqual(string.Empty, newItem.MerchantPrivateItemData);

            Assert.AreEqual(1, ohio1.RuleCount);

            DigitalItem emailDigitalItem = new DigitalItem();

            request.AddItem("Email Digital Item", "Cool DigitalItem", 2.00m, 1, emailDigitalItem);

            DigitalItem urlDigitalItem = new DigitalItem(new Uri("http://www.google.com/download.aspx?myitem=1"), "Url Description for item");

            request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, urlDigitalItem);

            DigitalItem keyDigitalItem = new DigitalItem("24-235-sdf-123541-53", "Key Description for item");

            request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, keyDigitalItem);

            DigitalItem keyUrlItem = new DigitalItem("24-235-sdf-123541-53", "http://www.google.com/download.aspx?myitem=1", "Url/Key Description for item");

            request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, keyUrlItem);

            //lets make sure we can add 2 different flat rate shipping amounts

            request.AddFlatRateShippingMethod("UPS Ground", 5);
            request.AddFlatRateShippingMethod("UPS 2 Day Air", 25);
            request.AddFlatRateShippingMethod("Test", 12, new ShippingRestrictions());

            //You can't mix shipping methods
            try {
                request.AddMerchantCalculatedShippingMethod("Test", 12.95m);
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            //lets try adding a Carrier Calculated Shipping Type

            //this should fail because the city is empty
            try {
                request.AddShippingPackage("failedpackage", string.Empty, "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            //The first thing that needs to be done for carrier calculated shipping is we must set the FOB address.
            request.AddShippingPackage("main", "Cleveland", "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);

            //this should fail because two packages exist
            try {
                request.AddShippingPackage("failedpackage", "Cleveland", "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            try {
                request.AddShippingPackage("main", "Cleveland", "OH", "44114");
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            //The next thing we will do is add a Fedex Home Package.
            //We will set the default to 3.99, the Pickup to Regular Pickup, the additional fixed charge to 1.29 and the discount to 2.5%
            CarrierCalculatedShippingOption option
                = request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Home_Delivery, 3.99m, CarrierPickup.REGULAR_PICKUP, 1.29m, -2.5);

            option.AdditionalVariableChargePercent = 0; //make sure we can set it back to 0;
            option.AdditionalFixedCharge           = 0;

            Assert.AreEqual(option.StatedShippingType, ShippingType.Fedex_Home_Delivery);
            Assert.AreEqual(option.Price, 3.99m);

            Assert.AreEqual(option.AdditionalVariableChargePercent, 0);
            Assert.AreEqual(option.AdditionalFixedCharge, 0);

            try {
                option.AdditionalFixedCharge = -1;
                Assert.Fail("Additional charge must be >= 0");
            }
            catch {
            }

            option.AdditionalVariableChargePercent = 2; //make sure we can set it back to 0;
            option.AdditionalFixedCharge           = 3;

            Assert.AreEqual(option.AdditionalVariableChargePercent, 2);
            Assert.AreEqual(option.AdditionalFixedCharge, 3);

            //this should fail
            try {
                request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Home_Delivery, 3.99m, CarrierPickup.REGULAR_PICKUP, 1.29m, -2.5);
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            //verify the rounding works
            CarrierCalculatedShippingOption ccso = request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Ground, 1.993m);

            Assert.AreEqual(1.99m, ccso.Price);
            ccso.Price = 1.975m;
            Assert.AreEqual(1.98m, ccso.Price);
            request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Second_Day, 9.99m, CarrierPickup.REGULAR_PICKUP, 2.34m, -24.5);

            //Ensure we are able to create the cart xml

            byte[] cart = request.GetXml();

            //Console.WriteLine(EncodeHelper.Utf8BytesToString(cart));

            //test to see if the item can desialize
            Assert.IsNotNull(GCheckout.Util.EncodeHelper.Deserialize(cart));
        }
        public void TestAddItem()
        {
            //due to the complexity of the add items. we are going to create a known set of data points and add them to the collection.
            ShoppingCartItem si = new ShoppingCartItem();

            si.Description             = "Description";
            si.DigitalContent          = new DigitalItem("Digital Item Key", "Digital Item Description");
            si.MerchantItemID          = "Merchant Item ID";
            si.MerchantPrivateItemData = "Private Data";

            XmlDocument mpdDoc = new XmlDocument();

            mpdDoc.LoadXml("<data />");
            mpdDoc.DocumentElement.AppendChild(mpdDoc.CreateElement("node1"));
            mpdDoc.DocumentElement.AppendChild(mpdDoc.CreateElement("node2"));
            XmlNode[] mpdNodes = new XmlNode[] { mpdDoc.DocumentElement.ChildNodes[0], mpdDoc.DocumentElement.ChildNodes[1] };

            si.MerchantPrivateItemDataNodes = mpdNodes;
            si.Name     = "Name";
            si.Price    = 0.99m;
            si.Quantity = 1;

            AlternateTaxTable taxTable = new AlternateTaxTable("Example");

            taxTable.AddStateTaxRule("OH", .06);

            si.TaxTable = taxTable;
            si.Weight   = 10.5;

            si.TaxTable.AddCountryTaxRule(GCheckout.AutoGen.USAreas.ALL, 5.0);

            CheckoutShoppingCartRequest request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);

            request.ContinueShoppingUrl            = "http://localhost/";
            request.AnalyticsData                  = "Test data";
            request.PlatformID                     = 1234567890;
            request.EditCartUrl                    = "http://localhost/editcart.aspx";
            request.RequestBuyerPhoneNumber        = true;
            request.MerchantCalculationsUrl        = "http://localhost/calculate.aspx";
            request.AcceptMerchantCoupons          = true;
            request.AcceptMerchantGiftCertificates = true;
            request.SetRoundingPolicy(RoundingMode.FLOOR, RoundingRule.TOTAL);
            request.AddShippingPackage("main", "Cleveland", "OH", "44114");

            request.MerchantPrivateData = "Test Cool Stuff";
            request.AddMerchantPrivateDataNode(mpdNodes[0]);

            XmlNode[] mpdn = request.MerchantPrivateDataNodes;

            Assert.AreSame(mpdn[0], mpdNodes[0]);

            try {
                request.AddItem(null);
                Assert.Fail("Null can't be passed to the AddItem methods");
            }
            catch {
            }

            try {
                MethodInfo mi = typeof(CheckoutShoppingCartRequest).GetMethod("AddItem", new Type[] { typeof(IShoppingCartItem) });
                mi.Invoke(request, new object[] { null });
                Assert.Fail("Null can't be passed to the AddItem methods");
            }
            catch {
            }

            request.AddItem(si);
            request.AddItem(si.Clone() as IShoppingCartItem);

            MethodInfo[] methods = typeof(CheckoutShoppingCartRequest).GetMethods();

            foreach (MethodInfo mi in methods)
            {
                bool cancel = false;
                //we are only working with AddItems
                if (mi.Name == "AddItem")
                {
                    Type             sct        = typeof(ShoppingCartItem);
                    ShoppingCartItem si2        = si.Clone() as ShoppingCartItem;
                    ParameterInfo[]  parameters = mi.GetParameters();
                    object[]         setter     = new object[parameters.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        ParameterInfo pi = parameters[i];
                        if (pi.ParameterType == typeof(ShoppingCartItem) || pi.ParameterType == typeof(IShoppingCartItem))
                        {
                            cancel = true;
                            continue;
                        }
                        //get the property from the object
                        PropertyInfo source;
                        if (pi.Name != "digitalItem")
                        {
                            source = sct.GetProperty(pi.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                        }
                        else
                        {
                            source = sct.GetProperty("DigitalContent");
                        }
                        setter[i] = source.GetValue(si2, null);

                        //we want to split and take the first item
                        if (!pi.ParameterType.IsArray && source.PropertyType.IsArray)
                        {
                            object[] vals = setter[i] as object[];
                            setter[i] = vals[0] as object;
                        }
                    }
                    if (!cancel)
                    {
                        //now call the method
                        ShoppingCartItem called = mi.Invoke(request, setter) as ShoppingCartItem;

                        //this is to fix a params array issue.
                        if (parameters[parameters.Length - 1].Name == "MerchantPrivateItemDataNodes")
                        {
                            called.MerchantPrivateItemDataNodes = si2.MerchantPrivateItemDataNodes;
                        }
                    }
                }
            }

            byte[] toXml = request.GetXml();

            //Make sure we can add an item to the cart.
            ShoppingCartItem item = request.AddItem("Item 1", "Cool Candy 1", "Merchant Item ID", 2.00M, 1);

            item.Weight = 2.2;
            item.MerchantPrivateItemData = null; //perform a null check

            //verify we can't set the price to fractions.

            item.Price = 1.975m;
            Assert.AreEqual(1.98m, item.Price);

            item.Price = 1.994m;
            Assert.AreEqual(1.99m, item.Price);

            Assert.AreEqual(2.2, item.Weight);
            Assert.AreEqual("Merchant Item ID", item.MerchantItemID);

            //this is a very specific test to make sure that if only one node exists, return it. it may be for a reason.

            XmlDocument doc = new XmlDocument();

            doc.LoadXml("<data />");
            doc.DocumentElement.SetAttribute("test", "cool");

            string xml = doc.OuterXml;

            item.MerchantPrivateItemDataNodes = new XmlNode[] { doc.DocumentElement };
            string xmlReturn = item.MerchantPrivateItemData;

            Assert.AreEqual(xml, xmlReturn);

            //create a new node
            XmlNode secondNode = doc.DocumentElement.AppendChild(doc.CreateElement("test"));

            item.MerchantPrivateItemDataNodes = new XmlNode[] { doc.DocumentElement, secondNode };

            xmlReturn = item.MerchantPrivateItemData;
            Assert.AreEqual(null, xmlReturn);

            item.MerchantPrivateItemDataNodes = null;
            Assert.AreEqual(new XmlNode[] { }, item.MerchantPrivateItemDataNodes);

            //this should throw an exception
            try {
                item.Weight = -1;
                Assert.Fail("Weight should not be allowed to be negative.");
            }
            catch {
            }

            //create a new instance of the cart item
            ShoppingCartItem testItem = new ShoppingCartItem();
        }