"use strict";

var _bluebird = _interopRequireDefault(require("bluebird"));

var types = _interopRequireWildcard(require("../types"));

var cj = _interopRequireWildcard(require("cookiejar"));

var _merlins = require("./merlins");

var _testUtils = require("../utils/test-utils");

var _nock = _interopRequireDefault(require("nock"));

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }

function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

var isIntegrationTest = false;
var _originalMode = undefined;
beforeAll(function () {
  if (_testUtils.isIntegrationTest && !isIntegrationTest) {
    console.warn("You're trying to run the Merlins integration tests, but these have disabled " + "permanently. This is not a problem, it's just informational. The tests will " + "run against pre-recorded HTTP responses instead.");
  }

  _originalMode = _nock["default"].back.currentMode;

  _nock["default"].back.setMode('lockdown');
});
afterAll(function () {
  _nock["default"].back.setMode(_originalMode);
});

if (isIntegrationTest) {
  jest.setTimeout(440000);
}

var orderAddress = {
  firstName: 'Donald',
  lastName: 'Trump',
  phone: '5555555555',
  addressLine1: '1600 Pennsylvania Ave NW',
  countryCode: 'US',
  stateCode: '16',
  city: 'Washington',
  postalCode: '20500'
};
var cartItem = {
  productId: 'Beginners Guide To Transfiguration',
  quantity: 1
};
var payment = {
  id: 'mine',
  amount: 10.5,
  methodId: 'checkmo'
};
describe("The Merlins Connector", function () {
  var connectors;
  beforeEach(function () {
    connectors = [];
  });
  afterEach(function () {
    // JSDOM cleanup
    connectors.forEach(function (connector) {
      return connector.window.close();
    });
  });
  /**
   * Returned object is suitable to pass to createUser() during tests.
   */

  var userFixture = function userFixture(key) {
    var time = isIntegrationTest ? new Date().getTime() : '';
    var createFixture = {
      firstName: "test-".concat(key).concat(time, "-firstName"),
      lastName: "test-".concat(key).concat(time, "-lastName"),
      email: "test-".concat(key).concat(time, "-email@example.com"),
      password: "test-".concat(key).concat(time, "-password")
    };
    var expectedFixture = {
      id: 'me',
      firstName: createFixture.firstName,
      lastName: createFixture.lastName,
      email: createFixture.email
    };
    return [createFixture, expectedFixture];
  };
  /**
   * @param {String} setCookie
   * @returns {String}
   */


  var convertSetCookieToCookie = function convertSetCookieToCookie(setCookie) {
    return new cj.Cookie(setCookie).toValueString();
  };

  test('Should convert a set-cookie header to a cookie header', function () {
    var setCookieHeaders = ['a=a; domain=www.merlinspotions.com; HttpOnly; secure', 'b=b; domain=something-else.com', 'c=c'];
    var cookieHeaders = setCookieHeaders.map(convertSetCookieToCookie);
    expect(cookieHeaders).toEqual(['a=a', 'b=b', 'c=c']);
  });

  var makeConnector = function makeConnector() {
    var basePath = 'https://www.merlinspotions.com';
    return (0, _testUtils.getWindow)(basePath).then(function (_window) {
      var connector = new _merlins.MerlinsConnector({
        window: _window,
        basePath: basePath,
        dondeGeoBasePath: 'https://donde-geo-tools.herokuapp.com',
        dondeApiBasePath: 'https://api.donde.io',
        cookieDomainRewrites: {
          'www.merlinspotions.com': 'www.merlins-proxy.com'
        }
      });
      connectors.push(connector);
      return connector;
    });
  };

  describe('Searching for products', function () {
    var sorts = [undefined, {
      query: 'name',
      key: 'name',
      compare: function compare(a, b) {
        return a.localeCompare(b);
      }
    }, {
      query: 'price',
      key: 'price',
      compare: function compare(a, b) {
        return a - b;
      }
    }];
    sorts.forEach(function (sortOpts) {
      var spec = test("with a sort order [sort: ".concat(sortOpts && sortOpts.query, "]"), function () {
        return (0, _testUtils.record)(spec, function () {
          var query = _objectSpread({
            filters: {
              categoryId: 'potions'
            }
          }, sortOpts && {
            sort: sortOpts.query
          });

          return makeConnector().then(function (connector) {
            return connector.searchProducts(query);
          }).then(function (data) {
            expect((0, _testUtils.propTypeErrors)(types.ProductSearch, data)).toBeFalsy();

            if (sortOpts) {
              var key = sortOpts.key,
                  compare = sortOpts.compare; // eslint-disable-next-line max-nested-callbacks

              var values = data.results.map(function (item) {
                return item[key];
              });
              var expected = values.slice().sort(compare);
              expect(values).toEqual(expected);
            }
          });
        });
      });
    });
    var counts = [4, 8];
    counts.forEach(function (count) {
      var spec = test("with a max count (count: ".concat(count, ")"), function () {
        return (0, _testUtils.record)(spec, function () {
          var query = {
            filters: {
              categoryId: 'potions'
            },
            count: count
          };
          return makeConnector().then(function (connector) {
            return connector.searchProducts(query);
          }).then(function (data) {
            expect((0, _testUtils.propTypeErrors)(types.ProductSearch, data)).toBeFalsy();
            expect(data.results.length).toEqual(count);
          });
        });
      });
    });
    var spec1 = test("with a zero-result search query", function () {
      return (0, _testUtils.record)(spec1, function () {
        var query = {
          query: 'empty'
        };
        return makeConnector().then(function (connector) {
          return connector.searchProducts(query);
        }).then(function (data) {
          expect((0, _testUtils.propTypeErrors)(types.ProductSearch, data)).toBeFalsy();
          expect(data.results.length).toEqual(0);
        });
      });
    });
  });
  describe('Getting a product', function () {
    var spec1 = test('with a valid id should resolve with a Product instance', function () {
      return (0, _testUtils.record)(spec1, function () {
        var connector;
        return makeConnector().then(function (conn) {
          connector = conn;
        }).then(function () {
          return connector.getProduct('eye-of-newt');
        }).then(function (data) {
          expect((0, _testUtils.propTypeErrors)(types.Product, data)).toBeFalsy();
        });
      });
    });
    var spec2 = test('with an invalid id should reject', function () {
      return (0, _testUtils.record)(spec2, function () {
        return makeConnector().then(function (connector) {
          return expect(connector.getProduct('horse-pants')).rejects.toThrow();
        });
      });
    });
  });
  describe('Getting products', function () {
    var spec1 = test('with valid ids should resolve with a ProductList instance with populated data', function () {
      return (0, _testUtils.record)(spec1, function () {
        var validIds = ['eye-of-newt', 'unicorn-blood'];
        return makeConnector().then(function (connector) {
          return connector.getProducts(validIds);
        }).then(function (result) {
          expect((0, _testUtils.propTypeErrors)(types.ProductList, result)).toBeFalsy();
          expect(result.data.length).toEqual(validIds.length);
        });
      });
    });
    var spec2 = test('with invalid ids should resolve with a ProductList instance with empty data', function () {
      return (0, _testUtils.record)(spec2, function () {
        var invalidIds = ['horse-pants', 'wrinkly-ears'];
        return makeConnector().then(function (connector) {
          return connector.getProducts(invalidIds);
        }).then(function (result) {
          expect((0, _testUtils.propTypeErrors)(types.ProductList, result)).toBeFalsy();
          expect(result.data.length).toEqual(0);
        });
      });
    });
    var spec3 = test('with a mix of valid and invalid ids should resolve with a ProductList instance with only valid data', function () {
      return (0, _testUtils.record)(spec3, function () {
        var validIds = ['eye-of-newt', 'unicorn-blood'];
        var invalidIds = ['horse-pants', 'wrinkly-ears'];
        return makeConnector().then(function (connector) {
          return connector.getProducts([].concat(validIds, invalidIds));
        }).then(function (result) {
          expect((0, _testUtils.propTypeErrors)(types.ProductList, result)).toBeFalsy();
          expect(result.data.length).toEqual(validIds.length);
          expect(result.total).toEqual(validIds.length);
          expect(result.count).toEqual(validIds.length);
        });
      });
    });
  });
  var spec2 = test('Getting a store', function () {
    return (0, _testUtils.record)(spec2, function () {
      var id = 'bc/vancouver/948-homer-street';
      return makeConnector().then(function (connector) {
        return connector.getStore(id);
      }).then(function (data) {
        expect((0, _testUtils.propTypeErrors)(types.Store, data)).toBeFalsy();
      });
    });
  });
  describe('Searching for stores', function () {
    // searchStoreRequest is using default values for start and count if not provided
    var spec1 = test('Only longitude provided, missing latitude', function () {
      return (0, _testUtils.record)(spec1, function () {
        var searchStoreRequest = {
          latlon: {
            longitude: -123.08359
          }
        };
        return makeConnector().then(function (connector) {
          expect(function () {
            connector.searchStores(searchStoreRequest);
          }).toThrowError('Provide Latitude and Longitude coordinates');
        });
      });
    });
    var spec2 = test('Only latitude provided, missing longitude', function () {
      return (0, _testUtils.record)(spec2, function () {
        var searchStoreRequest = {
          latlon: {
            latitude: 49.24667
          }
        };
        return makeConnector().then(function (connector) {
          expect(function () {
            connector.searchStores(searchStoreRequest);
          }).toThrowError('Provide Latitude and Longitude coordinates');
        });
      });
    });
    var spec3 = test('Valid latitude and longitude provided', function () {
      return (0, _testUtils.record)(spec3, function () {
        var searchStoreRequest = {
          latlon: {
            latitude: 49.24667,
            longitude: -123.08359
          }
        };
        return makeConnector().then(function (connector) {
          return connector.searchStores(searchStoreRequest);
        }).then(function (data) {
          expect(data.stores).not.toHaveLength(0);
          expect(data.stores).toHaveLength(data.count);
          expect((0, _testUtils.propTypeErrors)(types.StoreSearchResult, data)).toBeFalsy();
        });
      });
    });
    var spec4 = test('0.0, 0.0 geo-coordinates allowed', function () {
      return (0, _testUtils.record)(spec4, function () {
        var searchStoreRequest = {
          latlon: {
            latitude: 0.0,
            longitude: 0.0
          }
        };
        return makeConnector().then(function (connector) {
          return connector.searchStores(searchStoreRequest);
        }).then(function (data) {
          expect(data.stores).not.toHaveLength(0);
          expect(data.stores).toHaveLength(data.count);
          expect((0, _testUtils.propTypeErrors)(types.StoreSearchResult, data)).toBeFalsy();
        });
      });
    });
  });
  describe('Get Product Categories', function () {
    var spec1 = test("getCategory should resolve to a Category instance", function () {
      return (0, _testUtils.record)(spec1, function () {
        var category = 'root';
        return makeConnector().then(function (connector) {
          return connector.getCategory(category);
        }).then(function (data) {
          expect((0, _testUtils.propTypeErrors)(types.Category, data)).toBeFalsy();
          expect(data.id).toEqual(category);
        });
      });
    });
    var spec2 = test("getCategories should resolve to a CategoryList instance", function () {
      return (0, _testUtils.record)(spec2, function () {
        return makeConnector().then(function (connector) {
          return connector.getCategories(['books', 'potions']);
        }).then(function (result) {
          expect((0, _testUtils.propTypeErrors)(types.CategoryList, result)).toBeFalsy();
          expect(result.count).toEqual(2);
        });
      });
    });
  });
  describe('Authentication', function () {
    var spec1 = test("should allow a user to login and logout", function () {
      return (0, _testUtils.record)(spec1, function () {
        var _userFixture = userFixture('auth-login'),
            _userFixture2 = _slicedToArray(_userFixture, 2),
            createUserData = _userFixture2[0],
            expectedUserData = _userFixture2[1];

        var connector;
        return makeConnector().then(function (conn) {
          connector = conn;
        }).then(function () {
          return connector.registerCustomer(createUserData);
        }).then(function () {
          return connector.login(createUserData.email, createUserData.password);
        }).then(function (user) {
          return expect(user).toEqual(expectedUserData);
        }).then(function () {
          return connector.logout();
        }).then(function () {
          return expect(connector.getCustomer('me')).rejects.toEqual(new Error('logged out'));
        });
      });
    });
    var spec2 = test("should allow a session to be restored on a new Connector instance", function () {
      return (0, _testUtils.record)(spec2, function () {
        var _userFixture3 = userFixture('session-restore'),
            _userFixture4 = _slicedToArray(_userFixture3, 2),
            createUserData = _userFixture4[0],
            expectedUserData = _userFixture4[1];

        var connector;
        return makeConnector().then(function (conn) {
          connector = conn;
        }).then(function () {
          return connector.registerCustomer(createUserData);
        }).then(function () {
          return connector.login(createUserData.email, createUserData.password);
        }).then(function () {
          return makeConnector();
        }).then(function (connector2) {
          var cookieString = connector.getCookies().map(convertSetCookieToCookie).join('; ');
          connector2.setCookies(cookieString);
          return connector2.getCustomer('me');
        }).then(function (data) {
          return expect(data).toEqual(expectedUserData);
        });
      });
    });
  });
  describe('Account management', function () {
    var spec1 = test('Should support creating a new user account', function () {
      return (0, _testUtils.record)(spec1, function () {
        var _userFixture5 = userFixture('new-account'),
            _userFixture6 = _slicedToArray(_userFixture5, 2),
            createData = _userFixture6[0],
            expectedData = _userFixture6[1];

        var connector;
        return makeConnector().then(function (conn) {
          connector = conn;
        }).then(function () {
          return connector.registerCustomer(createData);
        }).then(function () {
          return connector.login(createData.email, createData.password);
        }).then(function (user) {
          return expect(user).toEqual(expectedData);
        });
      });
    });
  });
  describe('Cart Integration Test', function () {
    var spec1 = test('Guest User', function () {
      return (0, _testUtils.record)(spec1, function () {
        var anonymousCustomerInformation = {
          id: 'anonymous',
          email: 'engineer@mobify.com'
        };
        var updateInformation = {
          email: 'engineer@mobify.com'
        };
        var cart;
        var connector;
        return makeConnector().then(function (conn) {
          connector = conn;
        }).then(function () {
          return connector.login();
        }) // 1. Create a new cart
        .then(function () {
          return connector.createCart();
        }).then(function (data) {
          expect((0, _testUtils.propTypeErrors)(types.Cart, data)).toBeFalsy();
          cart = data;
        }) // 2. Set customer information
        .then(function () {
          return connector.setCustomerInformation(cart, updateInformation);
        }).then(function (data) {
          expect(data.customerInfo.id).toEqual(anonymousCustomerInformation.id);
          expect(data.customerInfo.email).toEqual(anonymousCustomerInformation.email);
          cart = data; // Update local cart variable
        }) // 3. Add Cart Item
        .then(function () {
          return connector.addCartItem(cart, cartItem);
        }).then(function (data) {
          expect(data.items).toHaveLength(1);
          expect(data.items[0].productId.toLowerCase()).toEqual(cartItem.productId.toLowerCase());
          expect(data.items[0].quantity).toEqual(cartItem.quantity);
          cart = data; // Update local cart variable
        }) // 4. Update Cart Item
        .then(function () {
          return connector.updateCartItem(cart, _objectSpread({}, cart.items[0], {
            quantity: 2
          }));
        }).then(function (data) {
          expect(data.items).toHaveLength(1);
          expect(data.items[0].productId.toLowerCase()).toEqual(cartItem.productId.toLowerCase());
          expect(data.items[0].quantity).toEqual(2);
          cart = data;
        }) // 5. Remove Cart item
        .then(function () {
          return connector.removeCartItem(cart, cart.items[0].id);
        }).then(function (data) {
          expect(data.items).toHaveLength(0);
          cart = data; // Update local cart variable
        }) // 5b. Re-add Cart Item NOTE: We need this because shipping methods requires an items to be present.
        .then(function () {
          return connector.addCartItem(cart, cartItem);
        }).then(function (data) {
          cart = data; // Update local cart variable
        }) // 6. Set Billing Address
        .then(function () {
          return connector.setBillingAddress(cart, orderAddress);
        }).then(function (data) {
          expect(data.billingAddress).toMatchObject(orderAddress);
          expect((0, _testUtils.propTypeErrors)(types.OrderAddress, data.billingAddress)).toBeFalsy();
          cart = data; // Update local cart variable
        }) // 7. Set Shipping Address
        .then(function () {
          return connector.setShippingAddress(cart, orderAddress);
        }).then(function (data) {
          expect(data.shippingAddress).toMatchObject(orderAddress);
          expect((0, _testUtils.propTypeErrors)(types.OrderAddress, data.shippingAddress)).toBeFalsy();
          cart = data; // Update local cart variable
        }) // 8. Get Shipping Methods
        .then(function () {
          return connector.getShippingMethods(cart);
        }).then(function (data) {
          cart.shippingMethods = data;
          expect(data.length).not.toBeLessThan(1);
          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
        }) // 9. Set Shipping Method
        .then(function () {
          return connector.setShippingMethod(cart, cart.shippingMethods[0]);
        }).then(function (data) {
          expect(data.selectedShippingMethodId).toEqual(cart.shippingMethods[0].id);
          expect((0, _testUtils.propTypeErrors)(types.Cart, data)).toBeFalsy();
          cart = data; // Update local cart variable
        }) // 10. Get Payment Methods
        .then(function () {
          return connector.getPaymentMethods(cart);
        }).then(function (data) {
          expect(data.length).not.toBeLessThan(0);
          cart.paymentMethods = data;
          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
        }) // 11. Set Payment
        .then(function () {
          return connector.setPayment(cart, payment);
        }).then(function (data) {
          expect(data.payments).toHaveLength(1);
          expect((0, _testUtils.propTypeErrors)(types.Payment, data.payments[0])).toBeFalsy();
          expect(data.payments[0].methodId).toEqual(payment.methodId);
          cart = data; // Update local cart variable
        }) // 12. Create Order
        .then(function () {
          return connector.createOrder(cart);
        }).then(function (data) {
          expect((0, _testUtils.propTypeErrors)(types.Order, data)).toBeFalsy();
        });
      });
    });
    var spec2 = test("Registered User", function () {
      return (0, _testUtils.record)(spec2, function () {
        var updateInformation = {
          email: 'engineer@mobify.com'
        };
        var cart;
        var connector;

        var _userFixture7 = userFixture('cart-registered-1'),
            _userFixture8 = _slicedToArray(_userFixture7, 2),
            customerFixture = _userFixture8[0],
            expectedData = _userFixture8[1];

        return makeConnector().then(function (conn) {
          connector = conn;
        }).then(function () {
          return connector.registerCustomer(customerFixture);
        }).then(function () {
          return connector.login(customerFixture.email, customerFixture.password);
        }).then(function (user) {
          return expect(user).toEqual(expectedData);
        }) // 2. Create a cart
        .then(function () {
          return connector.createCart();
        }).then(function (data) {
          cart = data; // assign cart to a local var

          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
          expect(cart.customerInfo.id).toBeDefined();
          expect(cart.customerInfo.id).not.toEqual('me');
          expect(cart.customerInfo.email).toEqual(customerFixture.email);
          expect(cart.selectedShippingMethodId).toBeUndefined();
          return null;
        }) // 3. Set customer information (email)
        .then(function () {
          return connector.setCustomerInformation(cart, updateInformation);
        }).then(function (data) {
          cart = data; // update cart

          expect(cart.customerInfo.email).toEqual(updateInformation.email);
        }) // 4. Delete cart items if there are already some on the cart
        .then(function () {
          var promises = [];

          for (var i = 0; i < cart.items.length; i++) {
            var promise = connector.removeCartItem(cart, cart.items[i].id);
            promises.push(promise);
          }

          return _bluebird["default"].all(promises);
        }).then(function () {
          return connector.getCart(cart.id);
        }).then(function (data) {
          cart = data;
          expect(cart.items.length).toEqual(0);
        }) // 5. Add a cart item
        .then(function () {
          return connector.addCartItem(cart, cartItem);
        }).then(function (data) {
          cart = data; // update cart

          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
          expect(cart.items.length).toEqual(1);
          var cartItemUpdated = cart.items[0];
          expect(cartItemUpdated.productId.toLowerCase()).toEqual(cartItem.productId.toLowerCase());
          expect(cartItemUpdated.quantity).toEqual(cartItem.quantity);
          expect(cartItemUpdated.id).toBeDefined();
          return null;
        }) // 5. Update cart item
        .then(function () {
          return connector.updateCartItem(cart, _objectSpread({}, cart.items[0], {
            quantity: 2
          }));
        }).then(function (data) {
          cart = data; // update cart

          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
          expect(cart.items.length).toEqual(1);
          var cartItemUpdated = cart.items[0];
          expect(cartItemUpdated.productId.toLowerCase()).toEqual(cartItem.productId.toLowerCase());
          expect(cartItemUpdated.quantity).toEqual(2);
          expect(cartItemUpdated.id).toBeDefined();
          return null;
        }) // 14. Delete cart item
        .then(function () {
          return connector.removeCartItem(cart, cart.items[0].id);
        }).then(function (data) {
          cart = data;
          expect(cart.items.length).toEqual(0);
        }) // Re-add cart item
        .then(function () {
          return connector.addCartItem(cart, cartItem);
        }) // 7. Set shipping address
        // Shipping address must be set before setting shipping method.
        .then(function () {
          return connector.setShippingAddress(cart, orderAddress);
        }).then(function (data) {
          cart = data; // update cart

          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
          expect(cart.shippingAddress).toMatchObject(orderAddress);
          return null;
        }) // 8. Set billing address
        .then(function () {
          return connector.setBillingAddress(cart, orderAddress);
        }).then(function (data) {
          cart = data;
          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
          expect(cart.billingAddress).toMatchObject(orderAddress);
          return null;
        }) // 9. Update billing address
        .then(function () {
          var billingAddressUpdated = _objectSpread({}, orderAddress, {
            firstName: 'Mickey',
            lastName: 'Mouse',
            phone: '8887776666',
            addressLine1: '1800 Transylvania Ave SE'
          });

          return _bluebird["default"].all([_bluebird["default"].resolve(billingAddressUpdated), connector.setBillingAddress(cart, billingAddressUpdated)]);
        }).then(function (_ref) {
          var _ref2 = _slicedToArray(_ref, 2),
              billingAddressUpdated = _ref2[0],
              data = _ref2[1];

          cart = data;
          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
          expect(cart.billingAddress.id).toBeUndefined();
          expect(cart.billingAddress).toMatchObject(billingAddressUpdated);
          expect(cart.billingAddress.firstName).not.toEqual(orderAddress.firstName);
          expect(cart.billingAddress.lastName).not.toEqual(orderAddress.lastName);
          expect(cart.billingAddress.phone).not.toEqual(orderAddress.phone);
          expect(cart.billingAddress.addressLine1).not.toEqual(orderAddress.addressLine1);
          return null;
        }) // 10. Get shipping methods
        .then(function () {
          return connector.getShippingMethods(cart);
        }).then(function (shippingMethods) {
          expect(shippingMethods.length).toBeGreaterThanOrEqual(1);
          return shippingMethods[0];
        }) // 11. Set shipping method
        .then(function (shippingMethod) {
          return _bluebird["default"].all([shippingMethod, connector.setShippingMethod(cart, shippingMethod)]);
        }).then(function (_ref3) {
          var _ref4 = _slicedToArray(_ref3, 2),
              shippingMethod = _ref4[0],
              data = _ref4[1];

          cart = data; // update cart

          expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
          expect(cart.selectedShippingMethodId).toBeDefined();
          expect(cart.selectedShippingMethodId).toEqual(shippingMethod.id);
        }) // 12. Get payment methods
        .then(function () {
          return connector.getPaymentMethods(cart);
        }) // 13. Set payment
        .then(function (paymentMethods) {
          var method = paymentMethods[0];
          return _bluebird["default"].all([connector.setPayment(cart, {
            methodId: method.id
          }), _bluebird["default"].resolve(method.id)]);
        }).then(function (_ref5) {
          var _ref6 = _slicedToArray(_ref5, 2),
              data = _ref6[0],
              paymentMethodId = _ref6[1];

          if (data) {
            cart = data; // update cart

            expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
            expect(cart.payments.length).toEqual(1);
            var paymentUpdated = cart.payments[0];
            expect(paymentUpdated.id).toBeDefined(); // stub id

            expect(paymentUpdated.amount).toEqual(cart.total); // always set payment amount to cart total.

            expect(paymentUpdated.methodId).toEqual(paymentMethodId);
            expect(paymentUpdated.details).toBeUndefined();
            var cartItemUpdated = cart.items[0];
            expect(cartItemUpdated.baseItemPrice).toBeGreaterThan(0);
            expect(cartItemUpdated.baseLinePrice).toBeGreaterThan(0);
            expect(cartItemUpdated.itemPrice).toBeGreaterThan(0);
            expect(cartItemUpdated.linePrice).toBeGreaterThan(0);
            expect(cart.discounts).toBeGreaterThanOrEqual(0);
            expect(cart.shipping).toBeGreaterThanOrEqual(0);
            expect(cart.tax).toBeGreaterThan(0);
            expect(cart.subtotal).toBeGreaterThan(0);
            expect(cart.total).toBeGreaterThan(0);
          }
        }).then(function () {
          return _bluebird["default"].all([_bluebird["default"].resolve(cart), connector.createOrder(cart)]);
        }).then(function (_ref7) {
          var _ref8 = _slicedToArray(_ref7, 2),
              cart = _ref8[0],
              order = _ref8[1];

          expect((0, _testUtils.propTypeErrors)(types.Order, order)).toBeFalsy();
          expect(order.billingAddress).toMatchObject(cart.billingAddress);
          expect(order.payments[0]).toMatchObject(cart.payments[0]);
          expect(order.items[0]).toMatchObject(cart.items[0]);
          expect(order.discounts).toBeGreaterThanOrEqual(0);
          expect(order.shipping).toBeGreaterThanOrEqual(0);
          expect(order.tax).toBeGreaterThan(0);
          expect(order.subtotal).toBeGreaterThan(0);
          expect(order.total).toBeGreaterThan(0);
          expect(order.status).toBeDefined();
          expect(order.creationDate).toBeDefined();
          expect(order.id).toBeDefined();
          return order;
        }).then(function (order) {
          return _bluebird["default"].all([_bluebird["default"].resolve(order), connector.getOrders([order.id])]);
        }).then(function (_ref9) {
          var _ref10 = _slicedToArray(_ref9, 2),
              order = _ref10[0],
              orders = _ref10[1];

          expect(orders.count).toEqual(1);
          expect(orders.total).toEqual(1);
          expect(orders.data[0].id).toEqual(order.id);
          return null;
        }).then(function () {
          return connector.logout();
        }).then(function () {
          return expect(connector.getCustomer('me')).rejects.toEqual(new Error('logged out'));
        });
      });
    });
  });
  describe('Coupon support', function () {
    var testBody = function testBody(connector) {
      return connector.createCart().then(function (cart) {
        return connector.addCartItem(cart, cartItem);
      }).then(function (cart) {
        return connector.addCouponEntry(cart, 'MAGIC');
      }).then(function (cart) {
        expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
        expect(cart.items.length).toEqual(1);
        expect(cart.couponEntries.length).toEqual(1);
        expect(cart.couponEntries).toEqual([{
          id: 'MAGIC',
          code: 'MAGIC'
        }]);
        expect(cart.discounts).toBeLessThan(0);
        return cart;
      }).then(function (cart) {
        return connector.removeCouponEntry(cart, cart.couponEntries[0].id);
      }).then(function (cart) {
        expect((0, _testUtils.propTypeErrors)(types.Cart, cart)).toBeFalsy();
        expect(cart.items.length).toEqual(1);
        expect(cart.couponEntries).toEqual([]);
        expect(cart.discounts).toBe(0);
      });
    };

    var spec1 = test('Should allow a registered user to add/remove a CouponEntry to/from their cart', function () {
      return (0, _testUtils.record)(spec1, function () {
        var connector;

        var _userFixture9 = userFixture('coupons-2'),
            _userFixture10 = _slicedToArray(_userFixture9, 2),
            customerFixture = _userFixture10[0],
            expectedData = _userFixture10[1];

        return makeConnector().then(function (conn) {
          connector = conn;
        }).then(function () {
          return connector.registerCustomer(customerFixture);
        }).then(function () {
          return connector.login(customerFixture.email, customerFixture.password);
        }).then(function (user) {
          return expect(user).toEqual(expectedData);
        }).then(function () {
          return testBody(connector);
        });
      });
    });
    var spec2 = test('Should allow a guest user to add/remove a CouponEntry to/from their cart', function () {
      return (0, _testUtils.record)(spec2, function () {
        var connector;
        return makeConnector().then(function (conn) {
          connector = conn;
        }).then(function () {
          return connector.login();
        }).then(function () {
          return testBody(connector);
        });
      });
    });
  });
});