diff --git a/.gitignore b/.gitignore index 9fee9bdd0..719baadc8 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ coverage/ config/config.js dist .DS_Store -.vscode \ No newline at end of file +.vscode +typings/ \ No newline at end of file diff --git a/config/karma.conf.js b/config/karma.conf.js index 320fb7b7d..8edd0d443 100644 --- a/config/karma.conf.js +++ b/config/karma.conf.js @@ -82,7 +82,12 @@ module.exports = function(config){ 'public/js/app/products/services/price-service.js', 'public/js/app/products/services/price-product-rest.js', 'public/js/app/products/services/category-service.js', - 'public/js/app/products/services/product-attribute-service.js', + 'public/js/app/products/services/product-extension-service.js', + 'public/js/app/products/utils/product-extension-helper.js', + 'public/js/app/products/utils/product-extension-item-helper.js', + 'public/js/app/products/utils/product-factory.js', + 'public/js/app/products/options/product-options-helper.js', + 'public/js/app/products/options/product-options.js', 'public/js/app/cart/cart-index.js', 'public/js/app/cart/controllers/cart-ctrl.js', @@ -123,6 +128,7 @@ module.exports = function(config){ 'public/js/app/account/controllers/account-ctrl.js', 'public/js/app/account/controllers/account-order-detail-ctrl.js', 'public/js/app/account/controllers/dialogs/address-remove-dialog-ctrl.js', + 'public/js/app/account/controllers/dialogs/order-cancel-dialog-ctrl.js', 'public/js/app/account/controllers/modals/edit-user-email-dialog-ctrl.js', 'public/js/app/account/controllers/modals/edit-user-name-dialog-ctrl.js', 'public/js/app/account/directives/customer-details/customer-details-directive.js', diff --git a/config/protractor-conf.js b/config/protractor-conf.js index 051328c0f..2d981111f 100644 --- a/config/protractor-conf.js +++ b/config/protractor-conf.js @@ -7,12 +7,12 @@ exports.config = { sauceKey: process.env.SAUCE_ACCESS_KEY, specs: [ - - '../test/e2e/cart-tests.js', - '../test/e2e/checkout-tests.js', - '../test/e2e/coupon-tests.js', - '../test/e2e/login-tests.js', - '../test/e2e/product-tests.js' + '../test/e2e/cart/cart.spec.js', + '../test/e2e/checkout/checkout.desktop.spec.js', + '../test/e2e/checkout/checkout.mobile.spec.js', + '../test/e2e/coupon/coupon.spec.js', + '../test/e2e/account/account.spec.js', + '../test/e2e/product/product.spec.js' ], @@ -56,7 +56,6 @@ exports.config = { baseUrl: 'https://storefront-demo.yaas.io/', - framework: 'jasmine', jasmineNodeOpts: { diff --git a/package.json b/package.json index 140c957e4..ad4875635 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "grunt-contrib-watch": "0.5.3", "grunt-env": "latest", "grunt-express": "~1.3.5", - "grunt-karma": "~0.8.3", + "grunt-karma": "~2.0.0", "grunt-ngmin": "~0.0.2", "grunt-rev": "~0.1.0", "grunt-text-replace": "0.4.0", @@ -59,7 +59,7 @@ "grunt-json-minify": "^0.4.0", "istanbul": "0.3.0", "jasmine-reporters": "^1.0.0", - "karma": "^0.12.31", + "karma": "~0.13.22", "karma-chrome-launcher": "~0.1.3", "karma-coffee-preprocessor": "^0.1.3", "karma-coverage": "~0.2.1", @@ -70,7 +70,8 @@ "karma-phantomjs-launcher": "^0.1.4", "karma-script-launcher": "~0.1.0", "phantomcss": "^0.4.5", - "phantomjs": "^1.9.15", + "phantomjs": "~2.1.3", + "phantomjs-prebuilt": "~2.1.4", "protractor": "^1.8.0", "protractor-screenshot-reporter": "0.0.5", "resemblejs": "^1.0.1", diff --git a/public/index.html b/public/index.html index 1e3a77bf1..2cfc4e33a 100644 --- a/public/index.html +++ b/public/index.html @@ -95,6 +95,7 @@ + @@ -116,11 +117,15 @@ - - - - + + + + + + + + @@ -158,6 +163,7 @@ + diff --git a/public/js/app/account/controllers/account-ctrl.js b/public/js/app/account/controllers/account-ctrl.js index 5d69937da..b0c9c4252 100644 --- a/public/js/app/account/controllers/account-ctrl.js +++ b/public/js/app/account/controllers/account-ctrl.js @@ -17,6 +17,8 @@ angular.module('ds.account') function ($scope, addresses, account, orders, OrderListSvc, AccountSvc, $modal, GlobalData, $translate) { + var self = this; + self.allOrdersLoaded = false; var modalInstance; var customerNumber = !!account ? account.customerNumber : null; @@ -185,30 +187,27 @@ angular.module('ds.account') $scope.showAllOrdersButton = !$scope.showAllOrdersButton; var parms = { - pageSize: 100 + pageSize: GlobalData.orders.meta.total }; - OrderListSvc.query(parms).then(function (orders) { - $scope.orders = orders; - - // show filtered list or show all orders. Hide if all data is shown within filter. + if (self.allOrdersLoaded) { $scope.showOrdersFilter = $scope.showAllOrdersButton ? $scope.showOrdersDefault : $scope.orders.length; $scope.showOrderButtons = ($scope.orders.length > $scope.showOrdersDefault); - }); + } else { + OrderListSvc.query(parms).then(function (orders) { + $scope.orders = orders; + + // show filtered list or show all orders. Hide if all data is shown within filter. + $scope.showOrdersFilter = $scope.showAllOrdersButton ? $scope.showOrdersDefault : $scope.orders.length; + $scope.showOrderButtons = ($scope.orders.length > $scope.showOrdersDefault); + self.allOrdersLoaded = true; + }); + } }; $scope.showAllAddresses = function () { $scope.showAllAddressButton = !$scope.showAllAddressButton; - - var parms = { - pageSize: GlobalData.addresses.meta.total - }; - AccountSvc.getAddresses(parms).then(function (addresses) { - $scope.addresses = addresses; - - // show filtered list or show all addresses. Hide if all data is shown within filter. - $scope.showAddressFilter = $scope.showAllAddressButton ? $scope.showAddressDefault : $scope.addresses.length; - $scope.showAddressButtons = ($scope.addresses.length > $scope.showAddressDefault); - }); + $scope.showAddressFilter = $scope.showAllAddressButton ? $scope.showAddressDefault : $scope.addresses.length; + $scope.showAddressButtons = ($scope.addresses.length > $scope.showAddressDefault); }; /* diff --git a/public/js/app/account/controllers/account-order-detail-ctrl.js b/public/js/app/account/controllers/account-order-detail-ctrl.js index 1579477aa..a6066ae99 100644 --- a/public/js/app/account/controllers/account-order-detail-ctrl.js +++ b/public/js/app/account/controllers/account-order-detail-ctrl.js @@ -13,7 +13,8 @@ 'use strict'; angular.module('ds.account') - .controller('AccountOrderDetailCtrl', ['$scope', 'order', '$stateParams', 'GlobalData', function($scope, order, $stateParams, GlobalData) { + .controller('AccountOrderDetailCtrl', ['$scope', 'order', '$stateParams', 'GlobalData', '$modal', + function($scope, order, $stateParams, GlobalData, $modal) { $scope.order = order; $scope.order.id = $stateParams.orderId; @@ -38,4 +39,27 @@ angular.module('ds.account') $scope.payment = getPaymentInfo(); + $scope.cancelOrder = function () { + $modal.open({ + templateUrl: 'js/app/account/templates/dialogs/order-cancel-dialog.html', + controller: 'OrderCancelDialogCtrl', + backdrop: 'static', + resolve: { + order: function () { + return order; + } + } + }).result.then(function (response) { + $scope.order.status = response.status; + }); + }; + + $scope.showCancelBtn = function (order) { + if (!!order.status && (order.status === 'CREATED' || order.status === 'CONFIRMED')) { + return true; + } else { + return false; + } + }; + }]); diff --git a/public/js/app/account/controllers/dialogs/order-cancel-dialog-ctrl.js b/public/js/app/account/controllers/dialogs/order-cancel-dialog-ctrl.js new file mode 100644 index 000000000..dbff20a84 --- /dev/null +++ b/public/js/app/account/controllers/dialogs/order-cancel-dialog-ctrl.js @@ -0,0 +1,34 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ +(function () { + 'use strict'; + + angular.module('ds.account') + .controller('OrderCancelDialogCtrl', ['$scope', '$modalInstance', 'order', 'OrderDetailSvc', '$translate', + function ($scope, $modalInstance, order, OrderDetailSvc, $translate) { + + $scope.orderCancelError = ''; + + $scope.cancelOrder = function () { + OrderDetailSvc.cancelOrder(order.id).then(function (response) { + $modalInstance.close({status: response.status}); + }, function () { + $scope.orderCancelError = $translate.instant('ORDER_CANCEL_ERROR'); + }); + }; + + $scope.closeCancelOrderDialog = function () { + $modalInstance.dismiss('cancel'); + }; + + }]); +})(); \ No newline at end of file diff --git a/public/js/app/account/directives/customer-details/customer-details-ctrl.js b/public/js/app/account/directives/customer-details/customer-details-ctrl.js index 3acdfc05e..d6b15f2e6 100644 --- a/public/js/app/account/directives/customer-details/customer-details-ctrl.js +++ b/public/js/app/account/directives/customer-details/customer-details-ctrl.js @@ -14,8 +14,8 @@ 'use strict'; angular.module('ds.account') - .controller('CustomerDetailsCtrl', ['$scope', 'AuthDialogManager', '$modal', - function ($scope, AuthDialogManager, $modal) { + .controller('CustomerDetailsCtrl', ['$scope', 'AuthDialogManager', '$modal', 'AccountSvc', + function ($scope, AuthDialogManager, $modal, AccountSvc) { $scope.modalInstance = {}; @@ -55,6 +55,8 @@ AuthDialogManager.showUpdatePassword(); }; + $scope.isItSocialAccount = AccountSvc.isItSocialAccount($scope.account); + // handle dialog dismissal if user select back button, etc $scope.$on('$destroy', function () { if ($scope.modalInstance && $scope.modalInstance.dismiss) { diff --git a/public/js/app/account/directives/customer-details/customer-details.html b/public/js/app/account/directives/customer-details/customer-details.html index c1ad122d8..14066ffa6 100644 --- a/public/js/app/account/directives/customer-details/customer-details.html +++ b/public/js/app/account/directives/customer-details/customer-details.html @@ -26,24 +26,25 @@

-
+
{{'NAME' | translate}} {{account.title|translate}} {{account.firstName}} {{account.middleName}} {{account.lastName}}
-
+
{{'EMAIL' | translate}} {{account.contactEmail}}
- - -
- {{'PASSWORD' | translate}} - ●●●●●●● +
+ +
+ {{'PASSWORD' | translate}} + ●●●●●●● +
@@ -66,17 +67,19 @@

{{account.contactEmail}}

-
+
-
-
- {{'PASSWORD' | translate}} - ●●●●●●● +
+
+
+ {{'PASSWORD' | translate}} + ●●●●●●● +
+
+
+
-
-
-
diff --git a/public/js/app/account/services/account-service.js b/public/js/app/account/services/account-service.js index f6bec57e3..62b7fd3b9 100644 --- a/public/js/app/account/services/account-service.js +++ b/public/js/app/account/services/account-service.js @@ -43,13 +43,8 @@ angular.module('ds.account') /** * Retrieve addresses of logged in customer. */ - getAddresses: function(query) { - var addressesPromise = AuthREST.Customers.all('me').all('addresses').getList(query); - addressesPromise.then(function(response) { - if (response.headers) { - GlobalData.addresses.meta.total = parseInt(response.headers[settings.headers.paging.total.toLowerCase()], 10) || 0; - } - }); + getAddresses: function() { + var addressesPromise = AuthREST.Customers.all('me').all('addresses').getList(); return addressesPromise; }, @@ -134,6 +129,17 @@ angular.module('ds.account') token: token }; return AuthREST.Customers.all('me').all('accounts').all('internal').all('email').all('change').customPOST(data, 'confirm'); + }, + + isItSocialAccount: function (account) { + if (!!account) { + for (var i = 0; i < account.accounts.length; i++) { + if (account.accounts[i].providerId === 'google' || account.accounts[i].providerId === 'facebook') { + return true; + } + } + } + return false; } }; diff --git a/public/js/app/account/templates/account.html b/public/js/app/account/templates/account.html index 23ee1e3d9..19f6c5192 100644 --- a/public/js/app/account/templates/account.html +++ b/public/js/app/account/templates/account.html @@ -63,7 +63,7 @@

{{'ORDER_HISTORY' | translate}}

{{m_order.totalPrice | currency: m_order.currencySymbol}}

-

{{m_order.status}}

+

{{m_order.status | translate}}

@@ -83,12 +83,12 @@

{{'ORDER_HISTORY' | translate}}

- - {{xrder.created | date: 'medium'}} - {{xrder.id}} - {{xrder.entries|sumByKey:'amount'|showNoOfItems}} - {{xrder.totalPrice | currency: xrder.currencySymbol}} - {{xrder.status}} + + {{orderRow.created | date: 'medium'}} + {{orderRow.id}} + {{orderRow.entries|sumByKey:'amount'|showNoOfItems}} + {{orderRow.totalPrice | currency: orderRow.currencySymbol}} + {{orderRow.status | translate}} diff --git a/public/js/app/account/templates/addresses-dialog.html b/public/js/app/account/templates/addresses-dialog.html index 5ac410e59..df8afe585 100644 --- a/public/js/app/account/templates/addresses-dialog.html +++ b/public/js/app/account/templates/addresses-dialog.html @@ -3,7 +3,7 @@ @@ -136,7 +136,7 @@

{{'STEP_2_BILLING_INFORMATION' | translate}}
-
@@ -252,7 +252,7 @@

{{'STEP_3_PAYMENT' | translate}} - diff --git a/public/js/app/confirmation/controllers/confirmation-ctrl.js b/public/js/app/confirmation/controllers/confirmation-ctrl.js index e804fb528..27a420ea0 100644 --- a/public/js/app/confirmation/controllers/confirmation-ctrl.js +++ b/public/js/app/confirmation/controllers/confirmation-ctrl.js @@ -68,7 +68,5 @@ angular.module('ds.confirmation') }); $scope.$on('$destroy', unbindConfirmAccount); - - }]); \ No newline at end of file diff --git a/public/js/app/confirmation/services/order-details-svc.js b/public/js/app/confirmation/services/order-details-svc.js index f71183985..73be1eab5 100644 --- a/public/js/app/confirmation/services/order-details-svc.js +++ b/public/js/app/confirmation/services/order-details-svc.js @@ -16,7 +16,7 @@ * Encapsulates access to the "order" service. */ angular.module('ds.confirmation') - .factory('OrderDetailSvc', ['OrderREST', function(OrderREST){ + .factory('OrderDetailSvc', ['OrderREST', '$q', function (OrderREST, $q) { /** Issues a GET request for the 'order' resource * @param orderId @@ -86,6 +86,19 @@ angular.module('ds.confirmation') return confirmationDetails; }); + }, + + cancelOrder: function (orderId) { + var deferred = $q.defer(); + OrderREST.Orders.one('orders', orderId).all('transitions').post({status: 'DECLINED'}).then( + function () { + deferred.resolve({status: 'DECLINED'}); + }, + function () { + deferred.reject(); + }); + return deferred.promise; } + }; }]); \ No newline at end of file diff --git a/public/js/app/confirmation/templates/confirmation.html b/public/js/app/confirmation/templates/confirmation.html index 2278d3170..038473dc2 100644 --- a/public/js/app/confirmation/templates/confirmation.html +++ b/public/js/app/confirmation/templates/confirmation.html @@ -22,11 +22,11 @@

{{'ORDER' | translate}} # {{'ORDER' | translate}}# {{ orderInfo.orderId }}

-
+

{{'THE_SHIPMENT_IS_SCHEDULED_TO_ARRIVE_AT_THE_FOLLOWING_LOCATION' | translate}}:

-
+
{{confirmationDetails.shippingAddressName}}
{{confirmationDetails.shippingAddressCompanyName}}
{{confirmationDetails.shippingAddressStreetLine1}} @@ -117,9 +117,8 @@

Create An Account

-
-
{{'LOG_IN_WITH_GOOGLE_PLUS' | translate}}
- +
+
{{'LOG_IN_WITH_GOOGLE' | translate}}
@@ -159,7 +158,10 @@

Create An Account

{{entry.product.name}} {{entry.product.sku}} - {{entry.unitPrice | currency: currencySymbol}} + + {{entry.unitPrice | currency: currencySymbol}} + {{entry.measurementUnit.value}} {{entry.measurementUnit.unit}} + {{entry.amount}} {{entry.totalPrice |currency: currencySymbol}} @@ -182,7 +184,7 @@

Create An Account

{{'DISCOUNT' | translate}} - -{{confirmationDetails.discountAmount | currency: currencySymbol}} + -{{confirmationDetails.discountAmount | currency: currencySymbol}} @@ -196,7 +198,7 @@

Create An Account

{{'ORDER_TOTAL' | translate}} - {{ confirmationDetails.totalPrice | currency: currencySymbol}} + {{ confirmationDetails.totalPrice | currency: currencySymbol}} @@ -213,11 +215,14 @@

Create An Account

- {{entry.product.name}}
- {{'SKU' | translate}}: {{entry.product.sku}}
- {{'ITEM_PRICE' | translate}}: {{entry.unitPrice | currency: currencySymbol}}
- {{'QTY' | translate}}: {{entry.amount}}
- {{'TOTAL_PRICE' | translate}}: {{entry.totalPrice |currency: currencySymbol}} +
{{entry.product.name}}
+
{{'SKU' | translate}}: {{entry.product.sku}}
+
+ {{'ITEM_PRICE' | translate}}: {{entry.unitPrice | currency: currencySymbol}} + {{entry.measurementUnit.value}} {{entry.measurementUnit.unit}} +
+
{{'QTY' | translate}}: {{entry.amount}}
+
{{'TOTAL_PRICE' | translate}}: {{entry.totalPrice |currency: currencySymbol}}
diff --git a/public/js/app/products/controllers/product-detail-ctrl.js b/public/js/app/products/controllers/product-detail-ctrl.js index ad0741f57..04fc1dd40 100644 --- a/public/js/app/products/controllers/product-detail-ctrl.js +++ b/public/js/app/products/controllers/product-detail-ctrl.js @@ -17,11 +17,21 @@ angular.module('ds.products') * Listens to the 'cart:updated' event. Once the item has been added to the cart, and the updated * cart information has been retrieved from the service, the 'cart' view will be shown. */ - .controller('ProductDetailCtrl', ['$scope', '$rootScope', 'CartSvc', 'product', 'lastCatId', 'settings', 'GlobalData', 'CategorySvc','$filter', 'ProductAttributeSvc', '$modal', 'shippingZones', 'Notification', 'CommittedMediaFilter', - function($scope, $rootScope, CartSvc, product, lastCatId, settings, GlobalData, CategorySvc, $filter, ProductAttributeSvc, $modal, shippingZones, Notification, CommittedMediaFilter) { + .controller('ProductDetailCtrl', ['$scope', '$rootScope', 'CartSvc', 'product', 'lastCatId', 'GlobalData', 'CategorySvc','$filter', '$modal', 'shippingZones', 'Notification', 'ProductExtensionHelper', 'variants', 'variantPrices', 'productFactory', + function($scope, $rootScope, CartSvc, product, lastCatId, GlobalData, CategorySvc, $filter, $modal, shippingZones, Notification, ProductExtensionHelper, variants, variantPrices, productFactory) { var modalInstance; + + $scope.activeTab = 'description'; + $scope.openTab = function (tabName) { + $scope.activeTab = tabName; + }; - $scope.product = product; + $scope.productMixins = ProductExtensionHelper.resolveMixins(product.product); + $scope.productMixinsDefinitions = product.product.metadata.mixins; + + $scope.product = productFactory.fromProduct(product.product, product.prices, variants.length === 0); + $scope.variants = variants; + $scope.shippingZones = shippingZones; $scope.noShippingRates = true; $scope.currencySymbol = GlobalData.getCurrencySymbol(); @@ -31,6 +41,15 @@ angular.module('ds.products') $scope.taxConfiguration = GlobalData.getCurrentTaxConfiguration(); + /* + we need to shorten the tax label if it contains more than 60 characters, and give users the option of + clicking a 'see more' link to view the whole label. + */ + if ($scope.taxConfiguration && $scope.taxConfiguration.label && $scope.taxConfiguration.label.length > 60) { + $scope.taxConfiguration.shortenedLabel = $scope.taxConfiguration.label.substring(0, 59); + $scope.taxConfiguration.seeMoreClicked = false; + } + if(!!lastCatId) { if(lastCatId === 'allProducts'){ var allProductsName = $filter('translate')('ALL_PRODUCTS'); @@ -69,16 +88,6 @@ angular.module('ds.products') $scope.currencySymbol = GlobalData.getCurrencySymbol(); $scope.error=null; - if (angular.isArray($scope.product.product.media)) { - $scope.product.product.media = CommittedMediaFilter.filter($scope.product.product.media); - } else { - $scope.product.product.media = []; - } - - if ($scope.product.product.media.length === 0) { - $scope.product.product.media.push({ id: settings.placeholderImageId, url: settings.placeholderImage }); - } - //input default values must be defined in controller, not html, if tied to ng-model $scope.productDetailQty = 1; $scope.buyButtonEnabled = true; @@ -120,7 +129,8 @@ angular.module('ds.products') $scope.addToCartFromDetailPage = function () { $scope.error = false; $scope.buyButtonEnabled = false; - CartSvc.addProductToCart(product.product, product.prices, $scope.productDetailQty, { closeCartAfterTimeout: true, opencartAfterEdit: false }) + // todo: this should be fixed to use $scope.product + CartSvc.addProductToCart(product.product, $scope.product.prices, $scope.productDetailQty, { closeCartAfterTimeout: true, opencartAfterEdit: false }) .then(function(){ var productsAddedToCart = $filter('translate')('PRODUCTS_ADDED_TO_CART'); Notification.success({message: $scope.productDetailQty + ' ' + productsAddedToCart, delay: 3000}); @@ -139,8 +149,20 @@ angular.module('ds.products') } }; - $scope.hasAnyOfAttributesSet = function(product){ - return ProductAttributeSvc.hasAnyOfAttributesSet(product); - }; + function filterPricesForVariant(variantId) { + return variantPrices.filter(function (price) { + var foundVariantId = price.itemYrn.split(';').pop(); + return variantId === foundVariantId; + }); + } + + $scope.onActiveVariantChanged = function (activeVariant) { + if (_.isObject(activeVariant)) { + var prices = filterPricesForVariant(activeVariant.id); + $scope.product = productFactory.fromProductVariant(product.product, activeVariant, prices); + } else { + $scope.product = productFactory.fromProduct(product.product, product.prices, false); + } + }; }]); diff --git a/public/js/app/products/directives/product-attribute-group.js b/public/js/app/products/directives/product-attribute-group.js deleted file mode 100644 index 9b4f8ddcb..000000000 --- a/public/js/app/products/directives/product-attribute-group.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * [y] hybris Platform - * - * Copyright (c) 2000-2015 hybris AG - * All rights reserved. - * - * This software is the confidential and proprietary information of hybris - * ("Confidential Information"). You shall not disclose such Confidential - * Information and shall use it only in accordance with the terms of the - * license agreement you entered into with hybris. - */ - -(function () { - 'use strict'; - - angular.module('ds.products') - .directive('productAttributeGroup', function () { - return { - restrict: 'E', - templateUrl: 'js/app/products/templates/product-attribute-group.html', - scope: { - group: '=' - }, - controller: ['$scope', 'ProductAttributeSvc', function ($scope, ProductAttributeSvc) { - ProductAttributeSvc.getSchema($scope.group.schema).then(function (response) { - $scope.properties = response.properties; - }); - }] - }; - }); -})(); \ No newline at end of file diff --git a/public/js/app/products/directives/product-attribute-groups.js b/public/js/app/products/directives/product-attribute-groups.js deleted file mode 100644 index 0d870beff..000000000 --- a/public/js/app/products/directives/product-attribute-groups.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * [y] hybris Platform - * - * Copyright (c) 2000-2015 hybris AG - * All rights reserved. - * - * This software is the confidential and proprietary information of hybris - * ("Confidential Information"). You shall not disclose such Confidential - * Information and shall use it only in accordance with the terms of the - * license agreement you entered into with hybris. - */ - -(function () { - 'use strict'; - - angular.module('ds.products') - .directive('productAttributeGroups', function () { - return { - restrict: 'E', - templateUrl: 'js/app/products/templates/product-attribute-groups.html', - scope: { - product: '=' - }, - controller: ['$scope', 'ProductAttributeSvc', function ($scope, ProductAttributeSvc) { - $scope.attributeGroups = ProductAttributeSvc.getAttributeGroups($scope.product); - }] - }; - }); -})(); \ No newline at end of file diff --git a/public/js/app/products/directives/product-attribute.js b/public/js/app/products/directives/product-attribute.js deleted file mode 100644 index cc4d2d495..000000000 --- a/public/js/app/products/directives/product-attribute.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * [y] hybris Platform - * - * Copyright (c) 2000-2015 hybris AG - * All rights reserved. - * - * This software is the confidential and proprietary information of hybris - * ("Confidential Information"). You shall not disclose such Confidential - * Information and shall use it only in accordance with the terms of the - * license agreement you entered into with hybris. - */ - -(function () { - 'use strict'; - - angular.module('ds.products') - .directive('productAttribute', ['ProductAttributeSvc', function (ProductAttributeSvc) { - return { - restrict: 'E', - templateUrl: 'js/app/products/templates/product-attribute.html', - scope: { - definition: '=', - value: '=' - }, - controller: ['$scope', function ($scope) { - $scope.dateFormatting = ProductAttributeSvc.dateFormatting; - }] - }; - }]); -})(); \ No newline at end of file diff --git a/public/js/app/products/directives/product-extension-item.js b/public/js/app/products/directives/product-extension-item.js new file mode 100644 index 000000000..239898041 --- /dev/null +++ b/public/js/app/products/directives/product-extension-item.js @@ -0,0 +1,49 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2015 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.products') + .directive('productExtensionItem', [function () { + return { + restrict: 'E', + templateUrl: 'js/app/products/templates/product-extension-item.html', + scope: { + name: '@', value: '=', definition: '=' + }, + controller: ['$scope', 'ProductExtensionItemHelper', + function ($scope, ProductExtensionItemHelper) { + + // handle legacy attribute groups, to be removed in future + if (/^attribute_*/.test($scope.name) && angular.isArray($scope.definition.oneOf)) { + $scope.displayedName = $scope.definition.oneOf[0].title; + $scope.type = $scope.definition.oneOf[0].type; + $scope.stringFormat = $scope.definition.oneOf[0].format; + + return; + } + + $scope.displayedName = ProductExtensionItemHelper.resolveName($scope.definition, $scope.name); + $scope.type = ProductExtensionItemHelper.resolveType($scope.definition, $scope.value); + + if ($scope.type === 'string') { + $scope.stringFormat = $scope.definition.format; + } + if ($scope.type === 'object') { + $scope.propertyOrder = ProductExtensionItemHelper.toOrderArray($scope.definition.properties); + } + }] + }; + }]) + ; +})(); \ No newline at end of file diff --git a/public/js/app/products/directives/product-extension.js b/public/js/app/products/directives/product-extension.js new file mode 100644 index 000000000..6588be4b6 --- /dev/null +++ b/public/js/app/products/directives/product-extension.js @@ -0,0 +1,38 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2015 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.products') + .directive('productExtension', ['ProductExtensionSvc', function (ProductExtensionSvc) { + return { + restrict: 'E', + templateUrl: 'js/app/products/templates/product-extension.html', + scope: { + schemaUrl: '@', mixin: '=' + }, + controller: ['$scope', '$q', function ($scope, $q) { + + $q.all([ + ProductExtensionSvc.getSchema($scope.schemaUrl), + ProductExtensionSvc.getSchemaMetadata($scope.schemaUrl) + ]) + .then(function (responses) { + $scope.definition = responses[0].plain(); + $scope.name = responses[1].metadata.name; + }); + + }] + }; + }]); +})(); \ No newline at end of file diff --git a/public/js/app/products/directives/product-img-carousel.js b/public/js/app/products/directives/product-img-carousel.js index 679d62522..680e90f6a 100644 --- a/public/js/app/products/directives/product-img-carousel.js +++ b/public/js/app/products/directives/product-img-carousel.js @@ -28,6 +28,7 @@ for (var i = 0; i < images.length; i++) { if (images[i].className.indexOf('product-image') > -1) { images[i].style.transform = 'translateX(' + i * 100 + '%)'; + images[i].style.width = '100%'; } } }; @@ -64,6 +65,7 @@ scope.enlargeImage = function () { var image = elem[0].querySelector('.product-images').children[scope.currentIndex]; image.style.transform = 'translateX(0)'; + image.style.width = 'inherit'; if (image.requestFullscreen) { image.requestFullscreen(); } else if (image.msRequestFullscreen) { @@ -75,8 +77,10 @@ } }; - $timeout(positionImages, 0); - $timeout(positionMobileThumbs, 0); + scope.$watchCollection('images', function(){ + $timeout(positionImages, 0); + $timeout(positionMobileThumbs, 0); + }); } diff --git a/public/js/app/products/options/product-options-helper.js b/public/js/app/products/options/product-options-helper.js new file mode 100644 index 000000000..1d3798b2f --- /dev/null +++ b/public/js/app/products/options/product-options-helper.js @@ -0,0 +1,121 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.products') + + .factory('ProductOptionsHelper', [ + function () { + + function isComplexAttribute(attribute) { + return _.isObject(attribute) || _.isArray(attribute); + } + + function findOption(options, optionKey, attributeKey) { + return _.find(options, function (o) { + return o.optionKey === optionKey && o.attributeKey === attributeKey; + }); + } + + function findAttribute(attributes, value) { + return _.find(attributes, function (a) { + return a.value === value; + }); + } + + function prepareOptions(variants) { + var options = []; + + for (var variantIndex = 0; variantIndex < variants.length; variantIndex++) { + + for (var optionKey in variants[variantIndex].options) { + if (!variants[variantIndex].options.hasOwnProperty(optionKey)) { continue; } + + for (var attributeKey in variants[variantIndex].options[optionKey]) { + if (!variants[variantIndex].options[optionKey].hasOwnProperty(attributeKey)) { continue; } + if (isComplexAttribute(variants[variantIndex].options[optionKey][attributeKey])) { continue; } + + var option = findOption(options, optionKey, attributeKey); + + if (_.isUndefined(option)) { + option = { + optionKey: optionKey, + attributeKey: attributeKey, + attributes: [] + }; + options.push(option); + } + + var attribute = findAttribute(option.attributes, variants[variantIndex].options[optionKey][attributeKey]); + + if (_.isUndefined(attribute)) { + attribute = { + value: variants[variantIndex].options[optionKey][attributeKey], + variantIds: [], + disabled: false + }; + option.attributes.push(attribute); + } + + attribute.variantIds.push(variants[variantIndex].id); + } + } + } + + return options; + } + + function getSelectedAttributes(optionsSelected) { + return _.filter(optionsSelected, function (o) { return _.isObject(o); }); + } + + function getIdsOfMatchingVariants(attributesSelected) { + var variantIdsCollection = _.map(attributesSelected, function (a) { + return a.variantIds; + }); + + return _.intersection.apply(_, variantIdsCollection); + } + + function getIdsOfAllVariants(variants) { + return _.map(variants, function (v) { return v.id; }); + } + + function updateOptions(options, idsOfMAtchingVariants) { + + for (var optionIndex = 0; optionIndex < options.length; optionIndex++) { + for (var attributeIndex = 0; attributeIndex < options[optionIndex].attributes.length; attributeIndex++) { + + var commonVariants = _.intersection(idsOfMAtchingVariants, options[optionIndex].attributes[attributeIndex].variantIds); + if (commonVariants.length > 0) { + options[optionIndex].attributes[attributeIndex].disabled = false; + } else { + options[optionIndex].attributes[attributeIndex].disabled = true; + } + + } + } + + return options; + } + + return { + prepareOptions: prepareOptions, + getSelectedAttributes: getSelectedAttributes, + getIdsOfMatchingVariants: getIdsOfMatchingVariants, + getIdsOfAllVariants: getIdsOfAllVariants, + updateOptions: updateOptions + }; + }]); +})(); \ No newline at end of file diff --git a/public/js/app/products/options/product-options.js b/public/js/app/products/options/product-options.js new file mode 100644 index 000000000..874fef6d5 --- /dev/null +++ b/public/js/app/products/options/product-options.js @@ -0,0 +1,68 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.products') + .directive('productOptions', [function () { + return { + restrict: 'E', + templateUrl: 'js/app/products/templates/product-options/product-options.html', + scope: { + variants: '=', + onActiveVariantChanged: '&' + }, + controller: ['$scope', 'ProductOptionsHelper', + function productOptionsCtrl($scope, ProductOptionsHelper) { + + $scope.options = ProductOptionsHelper.prepareOptions($scope.variants); + $scope.optionsSelected = []; + + function getIdsOfMatchingVariants(attributesSelected) { + return attributesSelected.length === 0 ? + ProductOptionsHelper.getIdsOfAllVariants($scope.variants) : + ProductOptionsHelper.getIdsOfMatchingVariants(attributesSelected); + } + + function getVariant(varaintId) { + return _.find($scope.variants, function (v) { return v.id === varaintId; }); + } + + $scope.resolveActiveVariantAndUpdateOptions = function () { + var attributesSelected = ProductOptionsHelper.getSelectedAttributes($scope.optionsSelected); + var idsOfMatchingVariants = getIdsOfMatchingVariants(attributesSelected); + + $scope.options = ProductOptionsHelper.updateOptions($scope.options, idsOfMatchingVariants); + + var activeVariant; + if (attributesSelected.length === $scope.options.length) { + activeVariant = getVariant(idsOfMatchingVariants[0]); + } + + $scope.onActiveVariantChanged({ activeVariant: activeVariant }); + }; + + $scope.omitSelectionAndUpdateOptions = function (omittedIndex) { + var omitted = _.union([], $scope.optionsSelected); + omitted[omittedIndex] = null; + + var attributesSelected = ProductOptionsHelper.getSelectedAttributes(omitted); + var idsOfMatchingVariants = getIdsOfMatchingVariants(attributesSelected); + + $scope.options = ProductOptionsHelper.updateOptions($scope.options, idsOfMatchingVariants); + }; + + }] + }; + }]); +})(); \ No newline at end of file diff --git a/public/js/app/products/services/product-attribute-service.js b/public/js/app/products/services/product-attribute-service.js deleted file mode 100644 index 687aa4b5a..000000000 --- a/public/js/app/products/services/product-attribute-service.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * [y] hybris Platform - * - * Copyright (c) 2000-2015 hybris AG - * All rights reserved. - * - * This software is the confidential and proprietary information of hybris - * ("Confidential Information"). You shall not disclose such Confidential - * Information and shall use it only in accordance with the terms of the - * license agreement you entered into with hybris. - */ - -(function () { - 'use strict'; - - angular.module('ds.products') - .factory('ProductAttributeSvc', ['Restangular', function (Restangular) { - return { - getSchema: function (schemaPath) { - return Restangular.oneUrl('schema', schemaPath).get(); - }, - - getAttributeGroups: function (product) { - var groups = []; - - for (var prop in product.mixins) { - if (/^attributegroup_*/.test(prop)) { - groups.push({ - schema: product.metadata.mixins[prop], - attributes: product.mixins[prop] - }); - } - } - - return groups; - }, - - hasAnyOfAttributesSet: function (product) { - var groupsWithAtLeastOneAttributeSet = this.getAttributeGroups(product) - .filter(function (group) { - var hasAttributeSet = false; - - for (var prop in group.attributes) { - if (group.attributes[prop] !== null) { - hasAttributeSet = true; - break; - } - } - - return hasAttributeSet; - }); - - return groupsWithAtLeastOneAttributeSet.length > 0; - }, - - dateFormatting: { - date: 'd/M/yyyy', - time: 'hh:mm a', - dateTime: 'MM/dd/yyyy hh:mm a' - } - }; - }]); -})(); \ No newline at end of file diff --git a/public/js/app/products/services/product-extension-service.js b/public/js/app/products/services/product-extension-service.js new file mode 100644 index 000000000..517bc9572 --- /dev/null +++ b/public/js/app/products/services/product-extension-service.js @@ -0,0 +1,28 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2015 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.products') + .factory('ProductExtensionSvc', ['Restangular', + function (Restangular) { + return { + getSchema: function (schemaUrl) { + return Restangular.oneUrl('schema', schemaUrl).get(); + }, + getSchemaMetadata: function (schemaUrl) { + return Restangular.oneUrl('schema', schemaUrl + '/metadata').get(); + } + }; + }]); +})(); \ No newline at end of file diff --git a/public/js/app/products/services/product-service.js b/public/js/app/products/services/product-service.js index 3da9a6ce9..4858eae60 100644 --- a/public/js/app/products/services/product-service.js +++ b/public/js/app/products/services/product-service.js @@ -18,30 +18,13 @@ angular.module('ds.products') .factory('ProductSvc', ['PriceProductREST', function(PriceProductREST){ - /** Executes a product query and extracts the "total" product count meta data and stores it in the - * GlobalData service. - * */ - var getProducts = function (parms) { - return PriceProductREST.Products.all('products').getList(parms); - }; - var getProductDetailsList = function (parms) { return PriceProductREST.ProductDetails.all('productdetails').getList(parms); }; return { - /** - * Issues a query request on the product resource. - * @param {parms} query parameters - optional - * @return The result array as returned by Angular $resource.query(). - */ - query: function(parms) { - return getProducts(parms); - }, - queryProductDetailsList: function(parms) { return getProductDetailsList(parms); } - }; }]); diff --git a/public/js/app/products/templates/product-attribute-group.html b/public/js/app/products/templates/product-attribute-group.html deleted file mode 100644 index b5523eeb4..000000000 --- a/public/js/app/products/templates/product-attribute-group.html +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/public/js/app/products/templates/product-attribute-groups.html b/public/js/app/products/templates/product-attribute-groups.html deleted file mode 100644 index 1ddc1fdac..000000000 --- a/public/js/app/products/templates/product-attribute-groups.html +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/public/js/app/products/templates/product-attribute.html b/public/js/app/products/templates/product-attribute.html deleted file mode 100644 index a9c61e425..000000000 --- a/public/js/app/products/templates/product-attribute.html +++ /dev/null @@ -1,28 +0,0 @@ -
-
- {{definition.title}} -
- -
- - - - {{value | date:dateFormatting.date}} - - {{value | date:dateFormatting.time}} - - {{value | date:dateFormatting.dateTime}} - - {{value}} - - - - - - - - - {{value}} - -
-
\ No newline at end of file diff --git a/public/js/app/products/templates/product-detail.html b/public/js/app/products/templates/product-detail.html index 4aa2e9a55..040edecef 100644 --- a/public/js/app/products/templates/product-detail.html +++ b/public/js/app/products/templates/product-detail.html @@ -1,4 +1,3 @@ - @@ -10,7 +9,7 @@
@@ -18,86 +17,134 @@
- + -

{{product.product.name}}

+

{{product.name}}

- -
- {{ product.prices[0].originalAmount | currency: currencySymbol }} - {{product.prices[0].effectiveAmount | currency: currencySymbol}} - {{product.prices[0].measurementUnit.quantity}} {{product.prices[0].measurementUnit.unitCode}} -
+
+ +
+ {{ product.prices[0].originalAmount | currency: currencySymbol }} + {{product.prices[0].effectiveAmount | currency: currencySymbol}} + {{product.prices[0].measurementUnit.quantity}} {{product.prices[0].measurementUnit.unitCode}} +
- -
- {{product.prices[0].effectiveAmount | currency: currencySymbol}} - {{product.prices[0].measurementUnit.quantity}} {{product.prices[0].measurementUnit.unitCode}} -
- - -
- + +
+ {{product.prices[0].effectiveAmount | currency: currencySymbol}} + {{product.prices[0].measurementUnit.quantity}} {{product.prices[0].measurementUnit.unitCode}} +
- +
- {{taxConfiguration.label}} +
+ {{taxConfiguration.label}} +
+
+ {{taxConfiguration.shortenedLabel}}... + {{'MORE' | translate}} +
- -
- - -
-
-
- - + + + + + +
+ + + +
+
+
+ + +
-
- -
- - -
-
- - {{'ERROR_ADDING_TO_CART' | translate}} - + +
+ + +
+
+ + {{'ERROR_ADDING_TO_CART' | translate}} + +
+
+ + +
+ +
+ + +
+ - -
- - + +
+
+
- - - + + +
+
+
- -
+ +
+
+ +
- - -
{{'PRODUCT_DESCRIPTION' | translate}}
-
- {{product.product.description}} +
+
+ +
{{'PRODUCT_DESCRIPTION' | translate}}
+ +
+ {{product.description}} +
+
+ +
+ +
{{'PRODUCT_DETAILS' | translate}}
+ + +
-
@@ -107,6 +154,4 @@

{{product.product.name}}

- - - + \ No newline at end of file diff --git a/public/js/app/products/templates/product-extension-item.html b/public/js/app/products/templates/product-extension-item.html new file mode 100644 index 000000000..16b4c5e01 --- /dev/null +++ b/public/js/app/products/templates/product-extension-item.html @@ -0,0 +1,13 @@ +
+
+
+ +
+
+ +
+
+ +
+
+
\ No newline at end of file diff --git a/public/js/app/products/templates/product-extension-item/_array.html b/public/js/app/products/templates/product-extension-item/_array.html new file mode 100644 index 000000000..2431cef74 --- /dev/null +++ b/public/js/app/products/templates/product-extension-item/_array.html @@ -0,0 +1,7 @@ +

{{displayedName}}

+ +
+
+ +
+
\ No newline at end of file diff --git a/public/js/app/products/templates/product-extension-item/_default.html b/public/js/app/products/templates/product-extension-item/_default.html new file mode 100644 index 000000000..57afea473 --- /dev/null +++ b/public/js/app/products/templates/product-extension-item/_default.html @@ -0,0 +1,28 @@ +
+
+ {{displayedName}} +
+ +
+
+
+ + +
+ +
+ + {{value | defaultDate}} + {{value | defaultTime}} + {{value | defaultDateTime}} + + {{value}} + +
+ +
+ {{value}} +
+
+
+
\ No newline at end of file diff --git a/public/js/app/products/templates/product-extension-item/_object.html b/public/js/app/products/templates/product-extension-item/_object.html new file mode 100644 index 000000000..5fc36840b --- /dev/null +++ b/public/js/app/products/templates/product-extension-item/_object.html @@ -0,0 +1,3 @@ +

{{displayedName}}

+ + \ No newline at end of file diff --git a/public/js/app/products/templates/product-extension.html b/public/js/app/products/templates/product-extension.html new file mode 100644 index 000000000..f0f0337af --- /dev/null +++ b/public/js/app/products/templates/product-extension.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/js/app/products/templates/product-list.html b/public/js/app/products/templates/product-list.html index ba68984d5..005366387 100644 --- a/public/js/app/products/templates/product-list.html +++ b/public/js/app/products/templates/product-list.html @@ -115,20 +115,24 @@

{{ category.n on-finish-render-ng-repeat on-finish-render-ng-repeat-event="initialViewportCheck"> - -
- -
-
-
{{ product.product.name }}
-
- {{ prices[product.product.id].originalAmount | currency: currencySymbol }} - {{prices[product.product.id].effectiveAmount | currency: currencySymbol}} - {{prices[product.product.id].measurementUnit.quantity}} {{prices[product.product.id].measurementUnit.unitCode}} +
+
+
-
- {{prices[product.product.id].effectiveAmount | currency: currencySymbol}} - {{prices[product.product.id].measurementUnit.quantity}} {{prices[product.product.id].measurementUnit.unitCode}} +
+
{{ product.product.name }}
+ +
+
+ {{ prices[product.product.id].originalAmount | currency: currencySymbol }} + {{prices[product.product.id].effectiveAmount | currency: currencySymbol}} + {{prices[product.product.id].measurementUnit.quantity}} {{prices[product.product.id].measurementUnit.unitCode}} +
+
+ {{prices[product.product.id].effectiveAmount | currency: currencySymbol}} + {{prices[product.product.id].measurementUnit.quantity}} {{prices[product.product.id].measurementUnit.unitCode}} +
+
diff --git a/public/js/app/products/templates/product-options/product-options.html b/public/js/app/products/templates/product-options/product-options.html new file mode 100644 index 000000000..f5236b422 --- /dev/null +++ b/public/js/app/products/templates/product-options/product-options.html @@ -0,0 +1,18 @@ +
+
+
+
+ + + + {{$select.selected.value}} + + + {{attribute.value}} + + +
+
+
+
+
diff --git a/public/js/app/products/utils/product-extension-helper.js b/public/js/app/products/utils/product-extension-helper.js new file mode 100644 index 000000000..73e0d7151 --- /dev/null +++ b/public/js/app/products/utils/product-extension-helper.js @@ -0,0 +1,39 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.products') + + .constant('ExcludedMixins', ['inventory']) + + .factory('ProductExtensionHelper', ['ExcludedMixins', + function (ExcludedMixins) { + + function resolveMixins(product) { + var effectiveMixins = {}; + + angular.forEach(product.mixins, function (mixin, id) { + if (ExcludedMixins.indexOf(id) === -1) { + effectiveMixins[id] = mixin; + } + }); + + return effectiveMixins; + } + + return { + resolveMixins: resolveMixins + }; + }]); +})(); \ No newline at end of file diff --git a/public/js/app/products/utils/product-extension-item-helper.js b/public/js/app/products/utils/product-extension-item-helper.js new file mode 100644 index 000000000..522e9f1c5 --- /dev/null +++ b/public/js/app/products/utils/product-extension-item-helper.js @@ -0,0 +1,69 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.products') + .factory('ProductExtensionItemHelper', [function () { + return { + resolveName: function (definition, name) { + if (definition.title) { + return definition.title; + } + + return name; + }, + + resolveType: function (definition, value) { + if (definition.type) { + return definition.type; + } + + if (angular.isObject(value)) { + return 'object'; + } + if (angular.isArray(value)) { + return 'array'; + } + }, + + toOrderArray: function (object) { + var array = []; + + angular.forEach(object, function (value, key) { + array.push({ 'key': key, 'value': value }); + }); + + array.sort(function (lItem, rItem) { + if (angular.isUndefined(lItem.value.order) && angular.isUndefined(rItem.value.order)) { + return 0; + } + + if (angular.isUndefined(lItem.value.order)) { + return 1; + } + + if (angular.isUndefined(rItem.value.order)) { + return -1; + } + + return lItem.value.order - rItem.value.order; + }); + + return array.map(function (item) { + return item.key; + }); + } + }; + }]); +})(); \ No newline at end of file diff --git a/public/js/app/products/utils/product-factory.js b/public/js/app/products/utils/product-factory.js new file mode 100644 index 000000000..d2fa0cbf7 --- /dev/null +++ b/public/js/app/products/utils/product-factory.js @@ -0,0 +1,85 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.products') + .factory('productFactory', ['CommittedMediaFilter', 'settings', + function (CommittedMediaFilter, settings) { + + function resolveMediaForProduct(product) { + return Array.isArray(product.media) ? product.media : []; + } + + function fromProduct(product, prices, isBuyable) { + + var media = resolveMediaForProduct(product); + + var createdProduct = { + id: product.id, + code: product.code, + name: product.name, + description: product.description, + media: CommittedMediaFilter.filter(media), + isBuyable: isBuyable, + inStock: product.mixins && product.mixins.inventory && product.mixins.inventory.inStock, + prices: prices + }; + + if (createdProduct.media.length === 0) { + createdProduct.media.push({ id: settings.placeholderImageId, url: settings.placeholderImage }); + } + + return createdProduct; + } + + function resolveMediaForProductVariant(product, variant) { + var media = []; + + if (Array.isArray(variant.media) && variant.media.length > 0) { + media = variant.media; + } else if (Array.isArray(product.media)) { + media = product.media; + } + + return media; + } + + function fromProductVariant(product, variant, prices) { + + var media = resolveMediaForProductVariant(product, variant); + + var createdProduct = { + id: variant.id, + code: variant.code, + name: variant.name ? variant.name : product.name, + description: product.description, + media: CommittedMediaFilter.filter(media), + isBuyable: true, + inStock: variant.mixins && variant.mixins.inventory && variant.mixins.inventory.inStock, + prices: prices + }; + + if (createdProduct.media.length === 0) { + createdProduct.media.push({ id: settings.placeholderImageId, url: settings.placeholderImage }); + } + + return createdProduct; + } + + return { + fromProduct: fromProduct, + fromProductVariant: fromProductVariant + }; + }]); +})(); \ No newline at end of file diff --git a/public/js/app/search/templates/search-list.html b/public/js/app/search/templates/search-list.html index d92a7334c..ae0fbeff8 100644 --- a/public/js/app/search/templates/search-list.html +++ b/public/js/app/search/templates/search-list.html @@ -120,17 +120,18 @@

+
+
+ -
- - -
-
-
{{ product.product.name }}
-
{{ prices[product.product.id].effectiveAmount | currency: currencySymbol}}
-
- {{prices[product.product.id].effectiveAmount | currency: currencySymbol}} - {{prices[product.product.id].measurementUnit.quantity}} {{prices[product.product.id].measurementUnit.unitCode}} +
+
+
{{ product.product.name }}
+
{{ prices[product.product.id].effectiveAmount | currency: currencySymbol}}
+
+ {{prices[product.product.id].effectiveAmount | currency: currencySymbol}} + {{prices[product.product.id].measurementUnit.quantity}} {{prices[product.product.id].measurementUnit.unitCode}} +
diff --git a/public/js/app/shared/directives/infinite-scrolling-visible-items.js b/public/js/app/shared/directives/infinite-scrolling-visible-items.js index a0dd6283a..c2703ec6d 100644 --- a/public/js/app/shared/directives/infinite-scrolling-visible-items.js +++ b/public/js/app/shared/directives/infinite-scrolling-visible-items.js @@ -14,7 +14,8 @@ //Used for determing the current visible items indexes //It is checking if the details (name and price) part of item is visible angular.module('ds.shared') - .directive('infiniteScrollVisibleItems', ['$window', function ($window) { + .constant('PRODUCT_VIEWPORT_OFFSET', 0.15) + .directive('infiniteScrollVisibleItems', ['$window', 'PRODUCT_VIEWPORT_OFFSET', function ($window, PRODUCT_VIEWPORT_OFFSET) { return { restrict: 'A', link: function (scope, element) { @@ -25,16 +26,14 @@ angular.module('ds.shared') var elements = []; var i = 0; var offset = 0; + var refineHeight = 0; //Function that checks if the element is visible in viewport var isElementInViewport = function (el) { + var viewportHeight = (window.innerHeight || document.documentElement.clientHeight); var rect = el.getBoundingClientRect(); - return ( - //Used 100 instead of 0 because of the top navigation - rect.top >= 100 && - rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) - ); + return (rect.top + rect.height * (1 - PRODUCT_VIEWPORT_OFFSET) > refineHeight && rect.bottom - rect.height * (1 - PRODUCT_VIEWPORT_OFFSET) < viewportHeight); }; //Function that determines the direction of users scroll @@ -50,25 +49,17 @@ angular.module('ds.shared') }; //Function that handles events and calculates - var handler = function (e) { - + var handler = function () { + if ($('#refineAffix') && $('#refineAffix')[0]) { // FIXME: the henaler is added globaly and handle events even it is not necessary + refineHeight = $('#refineAffix')[0].clientHeight; + } var firstVisibleIndex = 0; var lastVisibleIndex = 0; firstIndex = scope.pagination.productsFrom; if (scrollDirectionUp()) { - //console.log('Scroll up'); - - //If it is scroll event then the checking is done only on small part of elements based - //on last visible items (if it is scroll up then the next visible items 100% have <= indexes - //than last one) - if (e.type === 'scroll') { - //Get all elements that have index smaller than scope.productsTo - elements = element.querySelectorAll('.productInfoContainer').slice(0, scope.pagination.productsTo); - } - else { - //Loop over all elements - elements = element.querySelectorAll('.productInfoContainer'); - } + + elements = element.querySelectorAll('.productContainer'); + if(elements.length > 0) { for (i = elements.length - 1; i >= 0; i--) { @@ -96,22 +87,11 @@ angular.module('ds.shared') } } else { - //console.log('Scroll down'); + //Loop over all elements + elements = element.querySelectorAll('.productContainer'); - if (e.type === 'scroll') { - //Get all elements from currently shown index - 3 until the end - // elements = element.querySelectorAll(':nth-child(n+' + queryIndex + ') .productInfoContainer'); - elements = element.querySelectorAll('.productInfoContainer').slice(scope.pagination.productsFrom - 1); - - offset = firstIndex; - } - else { - //Loop over all elements - elements = element.querySelectorAll('.productInfoContainer'); - - //Set offset to 1 because looping is done over all elements - offset = 1; - } + //Set offset to 1 because looping is done over all elements + offset = 1; if(elements.length > 0) { diff --git a/public/js/app/shared/directives/site-selector/site-selector.html b/public/js/app/shared/directives/site-selector/site-selector.html index e55236bb8..19a27b959 100644 --- a/public/js/app/shared/directives/site-selector/site-selector.html +++ b/public/js/app/shared/directives/site-selector/site-selector.html @@ -16,7 +16,7 @@
-
    +
    • diff --git a/public/js/app/shared/directives/y-tracking.js b/public/js/app/shared/directives/y-tracking.js index c0bbdb3b5..8b4edd1ba 100644 --- a/public/js/app/shared/directives/y-tracking.js +++ b/public/js/app/shared/directives/y-tracking.js @@ -101,9 +101,9 @@ angular.module('ds.ytracking', []) */ var apiPath = appConfig.dynamicDomain(); var tenantId = appConfig.storeTenant(); - - var piwikUrl = 'https://' + apiPath + '/hybris/profile-piwik/b2/' + tenantId + '/events'; - var consentUrl = 'https://' + apiPath + '/hybris/profile-consent/b2/' + tenantId + '/consentReferences'; + + var piwikUrl = 'https://' + apiPath + '/hybris/profile-edge/v1' + '/events'; + var consentUrl = 'https://' + apiPath + '/hybris/profile-consent/v1/' + tenantId + '/consentReferences'; var getConsentReference = function () { var consentReferenceCookie = CookieSvc.getConsentReferenceCookie(); diff --git a/public/js/app/shared/filters/date-filters.js b/public/js/app/shared/filters/date-filters.js new file mode 100644 index 000000000..e69fd7f2a --- /dev/null +++ b/public/js/app/shared/filters/date-filters.js @@ -0,0 +1,43 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +(function () { + 'use strict'; + + angular.module('ds.shared') + + .constant('DateFormats', { + date: 'MM/dd/yyyy', + time: 'hh:mm a', + dateTime: 'MM/dd/yyyy hh:mm a' + }) + + .filter('defaultDate', ['$filter', 'DateFormats', function ($filter, DateFormats) { + return function (data) { + return $filter('date')(data, DateFormats.date); + }; + }]) + + .filter('defaultTime', ['$filter', 'DateFormats', function ($filter, DateFormats) { + return function (data) { + return $filter('date')(data, DateFormats.time); + }; + }]) + + .filter('defaultDateTime', ['$filter', 'DateFormats', function ($filter, DateFormats) { + return function (data) { + return $filter('date')(data, DateFormats.dateTime); + }; + }]) + + ; +})(); \ No newline at end of file diff --git a/public/js/app/shared/i18n/dev/dev_de.json b/public/js/app/shared/i18n/dev/dev_de.json index 9fa3df8f3..696fb59bf 100644 --- a/public/js/app/shared/i18n/dev/dev_de.json +++ b/public/js/app/shared/i18n/dev/dev_de.json @@ -8,6 +8,15 @@ //XFLD "es": "Spanisch", + //XFLD + //------------------------------------------------- + // Global + //------------------------------------------------- + //XBUT + "YES": "Yes", + //XBUT + "NO": "No", + //XFLD //------------------------------------------------- // Cart @@ -356,6 +365,8 @@ "PRODUCT_DETAILS": "Produktdetails", //XBUT "OUT_OF_STOCK": "nicht vorrätig", + //XBUT + "UNAVAILABLE": "Unavailable", //XFLD "QTY": "Menge", //XMSG @@ -367,6 +378,14 @@ //XMSG "ERROR_ADDING_TO_CART": "Hinzufügen zum Warenkorb war nicht erfolgreich. Versuchen Sie es noch einmal.", + //XTBS + "DESCRIPTION_TAB": "Description", + //XTBS + "DETAILS_TAB": "Details", + + //XBUT + "MORE": "More", + //XFLD //------------------------------------------------- // Product List Page @@ -443,6 +462,10 @@ "CONFIRM_DELETE_ADDRESS_TITLE": "Delete Address", //XMSG "CONFIRM_ADDRESS_REMOVAL": "Are you sure you want to delete this address?", + //XTIT + "CONFIRM_ORDER_CANCEL_TITLE": "Cancel Order", + //XMSG + "CONFIRM_CANCEL_ORDER": "Are you sure you want to cancel your order?", //XFLD "FULL_NAME": "Vollständiger Name", //XFLD @@ -468,6 +491,10 @@ //XFLD "ORDER_STATUS": "Bestellstatus", //XFLD + "ORDER_CANCEL": "Cancel Order", + //XFLD + "ORDER_CANCEL_ERROR": "Cancelation failed, please contact customer service or try again later", + //XFLD "FAIL_ORDER": "Die Bestellungen sind nicht verfügbar. Versuchen Sie es später noch einmal.", //XFLD "NO_ORDERS": "Sie haben keine Bestellungen gespeichert", @@ -481,6 +508,8 @@ //XBUT "SAVE": "Sichern", //XBUT + "SUBMIT": "Submit", + //XBUT "UPDATE_PASSWORD": "Kennwort aktualisieren", //XBUT "CURRENT_PASSWORD": "Aktuelles Kennwort", @@ -664,7 +693,7 @@ //XSEL "CREATED": "Angelegt", //XSEL - "DECLINED": "Abgelehnt", + "DECLINED": "Cancelled", //XSEL "SHIPPED": "Versendet", @@ -702,7 +731,7 @@ //XGRP "RESULTS": "Ergebnisse", //XLNK - "SEE_ALL": "Alle anzeigen", + "SEE_ALL": "See All Results", //XMSG "SEARCH_UNAVAILABLE": "Die Suche ist zurzeit nicht verfügbar.", //XMSG diff --git a/public/js/app/shared/i18n/dev/dev_en.json b/public/js/app/shared/i18n/dev/dev_en.json index 31d7e71c1..eb6d230c0 100644 --- a/public/js/app/shared/i18n/dev/dev_en.json +++ b/public/js/app/shared/i18n/dev/dev_en.json @@ -8,6 +8,15 @@ //XFLD "es": "Spanish", + //XFLD + //------------------------------------------------- + // Global + //------------------------------------------------- + //XBUT + "YES": "Yes", + //XBUT + "NO": "No", + //XFLD //------------------------------------------------- // Cart @@ -355,6 +364,8 @@ "PRODUCT_DETAILS": "Product Details", //XBUT "OUT_OF_STOCK": "out of stock", + //XBUT + "UNAVAILABLE": "Unavailable", //XFLD "QTY": "Qty", //XMSG @@ -365,6 +376,14 @@ "NO_LIMIT": "No Limit", //XMSG "ERROR_ADDING_TO_CART": "Add to Cart was not successful. Please try again.", + + //XTBS + "DESCRIPTION_TAB": "Description", + //XTBS + "DETAILS_TAB": "Details", + + //XBUT + "MORE": "More", //XFLD //------------------------------------------------- @@ -442,6 +461,10 @@ "CONFIRM_DELETE_ADDRESS_TITLE": "Delete Address", //XMSG "CONFIRM_ADDRESS_REMOVAL": "Are you sure you want to delete this address?", + //XTIT + "CONFIRM_ORDER_CANCEL_TITLE": "Cancel Order", + //XMSG + "CONFIRM_CANCEL_ORDER": "Are you sure you want to cancel your order?", //XFLD "FULL_NAME": "Full Name", //XFLD @@ -467,6 +490,10 @@ //XFLD "ORDER_STATUS": "Order Status", //XFLD + "ORDER_CANCEL": "Cancel Order", + //XFLD + "ORDER_CANCEL_ERROR": "Cancelation failed, please contact customer service or try again later", + //XFLD "FAIL_ORDER": "Orders not available. Try again later.", //XFLD "NO_ORDERS": "You have no orders stored", @@ -480,6 +507,8 @@ //XBUT "SAVE": "Save", //XBUT + "SUBMIT": "Submit", + //XBUT "UPDATE_PASSWORD": "Update password", //XBUT "CURRENT_PASSWORD": "Current password", @@ -665,7 +694,7 @@ //XSEL "CREATED": "Created", //XSEL - "DECLINED": "Declined", + "DECLINED": "Cancelled", //XSEL "SHIPPED": "Shipped", @@ -703,7 +732,7 @@ //XGRP "RESULTS": "Results", //XLNK - "SEE_ALL": "See All", + "SEE_ALL": "See All Results", //XMSG "SEARCH_UNAVAILABLE": "Search is currently unavailable.", //XMSG diff --git a/public/js/app/shared/i18n/lang/lang_de.json b/public/js/app/shared/i18n/lang/lang_de.json index b8a692564..9634e8af8 100644 --- a/public/js/app/shared/i18n/lang/lang_de.json +++ b/public/js/app/shared/i18n/lang/lang_de.json @@ -1 +1 @@ -{"en":"Englisch","de":"Deutsch","fr":"Französisch","es":"Spanisch","BACK_TO_CHECKOUT":"Zurück zur Kasse","CHECKOUT":"Kasse","CANCEL":"Cancel","CONTINUE_SHOPPING":"Einkauf fortsetzen","NOTE":"Note","ADD_NOTE":"Add Note","EDIT_NOTE":"Edit Note","DELETE_NOTE":"Delete Note","UNABLE_TO_SAVE_NOTE":"Unable to save note","SHOP":"Einkaufen","EST_ORDER_TOTAL":"Geschätzte Bestellsumme","PREVIEW_ORDER":"Preview Order","PAYMENT_REVIEW":"Payment & Review","PLEASE_CORRECT_MESSAGE_ERRORS":"Something went wrong, please try again","FREE_SHIPPING":"Versand und Rücksendung in den USA kostenlos","ITEM":"Position","ITEM_PRICE":"Positionspreis","TOTAL_PRICE":"Gesamtpreis","CART_UNAVAILABLE":"Der Warenkorb ist zurzeit nicht verfügbar. Versuchen Sie es noch einmal.","CART_EMPTY":"Ihr Warenkorb ist leer","CART_ITEM_UPDATE_ERROR":"Die Aktualisierung war nicht erfolgreich. Versuchen Sie es noch einmal.","ESTIMATE_TAX":"Steuern schätzen","APPLY":"Anwenden","ESTIMATE_TAX_ERROR":"Felder \"Postleitzahl\" und \"Ländercode\" sind erforderlich","ADDITIONAL_SHIPPING_OPTIONS":"Additional shipping options are available in checkout.","SELECT_A_COUNTRY":"Land auswählen","ADDRESS":"Adresse","ADDRESS_LINE_1":"Adresszeile 1","ADDRESS_LINE_2":"Adresszeile 2","CANT_BE_SHIPPED":"Items cannot be shipped to this location","BILLING_ADDRESS":"Rechnungsadresse","CITY":"Ort","PROVINCE":"Provinz/Bundesland","CONTINUE":"Weiter","COST":"Cost","COUNTRY":"Land","CREDIT_CARD_NUMBER":"Kreditkartennummer","CVC_NUMBER":"Prüfnummer","DELIVERY_METHOD":"Liefermethode","EMAIL":"E-Mail","EDIT":"Bearbeiten","FIRST_NAME":"Vorname","FREE_STANDARD_SHIPPING":"Kostenloser Standardversand","FLAT_RATE_SHPPING":"Pauschale","INVALID_EXPIRATION_DATE":"Ungültiges Ablaufdatum","ITEMS":"Positionen","LAST_NAME":"Nachname","LAST_NAME_REQUIRED":"Nachname erforderlich","METHOD":"Versandart","MIDDLE_NAME":"Zweiter Vorname","MONTH":"Monat","NAME":"Name","NO_ITEMS_IN_CART":"Ihr Warenkorb enthält keine Positionen.","OPTIONAL":"Optional","ORDER_DETAILS":"Bestelldetails","ORDER_DATE":"Bestelldatum","ORDER_PENDING":"Einen Augenblick bitte... Ihre Bestellung wird ausgeführt","ORDER_TOTAL":"Bestellsumme","PAYMENT":"Zahlung","PHONE_REQUIRED":"Telefon erforderlich","PLACE_ORDER":"Bestellen","PLACED_AT":"Bestellt am","PLEASE_CORRECT_ERRORS":"Korrigieren Sie vor dem Bestellen die oben aufgeführten Fehler.","PLEASE_CORRECT_ERRORS_PREVIEW":"Please correct the errors above before previewing your order.","PLEASE_CORRECT_ERRORS_ADDRESS":"Please correct the address details before previewing your order.","PLEASE_ENTER_VALID_CC":"Geben Sie eine gültige Kreditkartennummer ein","PLEASE_ENTER_VALID_CODE":"Geben Sie einen gültigen Code ein","PLEASE_ENTER_VALID_EMAIL":"Geben Sie eine gültige E-Mail-Adresse im Format name@beispiel.com ein","REQUIRED":"Erforderlich","SAME_AS_SHIPPING_ADDRESS":"Same As Shipping Address","SECURE_CHECKOUT":"Sichere Kaufabwicklung","SELECT_FROM_ADDRESS_BOOK":"Aus Adressbuch auswählen","ADDRESS_BOOK":"Address Book","SHIPPING":"Versand","SHIPPING_ADDRESS":"Lieferadresse","SIMPLE_3_STEP_CHECKOUT":"Einfache Kaufabwicklung in 3 Schritten","SIMPLE_4_STEP_CHECKOUT":"Einfache Kaufabwicklung in 4 Schritten","STATE":"Bundesstaat","STEP_1_MY_DETAILS":"Schritt 1: Meine Details","STEP_2_BILLING_INFORMATION":"Schritt 2: Billing Information","STEP_3_PAYMENT":"Schritt 3: Zahlung","STEP_4_REVIEW_ORDER":"Schritt 4: Bestellung prüfen","SUBTOTAL":"Zwischensumme","DISCOUNT":"Rabatt","TAX":"Steuern","TOTAL":"Summe","YEAR":"Jahr","DEFAULT":"Standard","DISTRICT":"Stadtbezirk","STREET_NAME":"Straße/Hausnummer","BUILDING_NAME":"Gebäudename/-nummer","ROOM_NUMBER":"Zimmernummer","PREFECTURE":"Präfektur","POSTAL_CODE":"Postleitzahl","ZIP":"Postleitzahl","CITY_VILLAGE":"Stadt/Dorf/Stadtbezirk","SUBAREA":"Stadtteil","FURTHER_SUBAREA":"Stadtteilabschnitt, Blocknummer/Hausnummer","COUPON_APPLY":"Anwenden","COUPON_APPLIED":"Angewendet","COUPON_NOT_APPLIED":"Not Applied","COUPON_CODE":"Couponcode hinzufügen","COUPON_ERROR":"Coupon nicht gültig.","COUPON_NOT_ACTIVE":"The coupon is not active","COUPON_EXPIRED":"The coupon is not active","COUPON_REDEMPTIONS_EXCEEDED":"Coupon has reached maximum number of redemptions","COUPON_REDEMPTION_FORBIDDEN":"Current customer is not allowed to redeem the coupon","COUPON_ORDER_TOTAL_TOO_LOW":"The order value is too low for this coupon","COUPON_CURRENCY_INCORRECT":"Currency inconsistent with coupon","COUPON_DISCOUNT_CURRENCY_INCORRECT":"Discount currency invalid inconsistent coupon","COUPON_DISCOUNT_AMOUNT_INCORRECT":"Discount amount exceeds allowed coupon discount","COUPON_ERR_CURRENCY":"Währung für Coupon ungültig","COUPON_ERR_ANONYMOUS":"Melden Sie sich an, um den Couponcode zu verwenden","COUPON_ERR_UNAVAILABLE":"Coupon nicht mehr verfügbar","COUPON_MINIMUM_NOT_MET":"Aktuelle Bestellsumme entspricht nicht der erforderlichen Mindestsumme für diesen Coupon","COUPON_NOT_VALID":"Coupon nicht gültig","COUPONS":"Coupon Code","A_COPY_OF_YOUR_ORDER_DETAILS_HAS_BEEN_SENT_TO":"

      Eine Kopie Ihrer Bestelldetails wurde gesendet an {{emailAddress}}

      ","ENJOY_YOUR_ITEMS":"Viel Freude an Ihrem Einkauf!","FOR_YOUR_ORDER":"für Ihre Bestellung!","ITEM_IN_YOUR_ORDER":"Position in Ihrer Bestellung","ITEMS_IN_YOUR_ORDER":"Positionen in Ihrer Bestellung","QUESTIONS":"

      Bei Fragen kontaktieren Sie uns unter {{contactInfo}}.

      ","ORDER":"Bestellung","RETURN_TO_SHOPPING":"Zurück zum Einkauf","SUCCESS":"Vorgang war erfolgreich!","ACCOUNT_SUCCESS":"Ihr Konto wurde erfolgreich angelegt.","THANK_YOU":"Vielen Dank","THANK_YOU_FOR_YOUR_ORDER":"Vielen Dank
      für Ihre Bestellung!","THE_SHIPMENT_IS_SCHEDULED_TO_ARRIVE_AT_THE_FOLLOWING_LOCATION":"Die Bestellung wird geliefert an","YOUR_ORDER_IS":"Ihre Bestellnummer lautet ","ONE_MORE_STEP":"Nur ein weiterer Schritt zum Anlegen eines Kontos mit schneller Kaufabwicklung und einem einfachen Zugriff auf frühere Bestellungen","SKU":"Lagermengeneinheit","YOUR_CHECKOUT_HAS_BEEN_ACCEPTED_ORDER_NOT_CREATED":"Ihre Kaufabwicklung wurde angenommen, aber die Bestellung wurde nicht angelegt. Verwenden Sie zur Verfolgung folgende Kaufabwicklungs-ID-Nummer: ","YOUR_ORDER_WILL_BE_CREATED":"Ihre Bestellung wird so schnell wie möglich angelegt.","PRODUCTS":"Produkte","BACK_TO":"Zurück zu","REGION":"Region","SHIPPING_INFORMATION":"Shipping information","SHIPPING_ZONE":"Shipping Zone","STANDARD_SHIPPING":"Standard Shipping","SHIPPING_RATE":"Shipping Rate","ZONE":"Zone","BUY":"Kaufen","ADD_TO_CART":"In den Warenkorb","PRODUCTS_ADDED_TO_CART":"product(s) successfully added to your cart","PRODUCT_DESCRIPTION":"Produktbeschreibung","PRODUCT_DETAILS":"Produktdetails","OUT_OF_STOCK":"nicht vorrätig","QTY":"Menge","INCLUDES":"Includes","NO_LIMIT":"No Limit","DESTINATION_COUNTRY":"Destination country(s)","ERROR_ADDING_TO_CART":"Hinzufügen zum Warenkorb war nicht erfolgreich. Versuchen Sie es noch einmal.","NEWEST":"neueste","OF":"von","PRICE_HIGH_LOW":"Preis (höchster - niedrigster)","PRICE_LOW_HIGH":"Preis (niedrigster - höchster)","SORT_BY":"Sortieren nach","VIEWING":"Anzeigen","PRODUCTS_FROM_TO":"
      {{productsFrom}}-{{productsTo}} von {{total}}
      ","ALL_PRODUCTS":"Alle Produkte","EMPTY_MSG":"Demo-Filiale - demnächst verfügbar","LANGUAGES":"Sprachen","SELECT_LANGUAGE":"Sprache auswählen","SIGN_OUT":"Abmelden","SIGN_IN":"Anmelden","SIGN_IN_WITH_FACEBOOK":"Über Facebook anmelden","LOG_IN_WITH_GOOGLE":"Über Google anmelden","MY_ACCOUNT":"Mein Konto","CREATE_ACCOUNT":"Konto anlegen","CONTINUE_AS_GUEST":"Weiter als Gast","UPDATE_ACCOUNT_DETAILS":"Kontodetails aktualisieren","UPDATE_EMAIL":"E-Mail aktualisieren","ADD":"Hinzufügen","REGION_PREFERENCES":"Regionspräferenzen","NEW_EMAIL":"Neue E-Mail","CURRENT_EMAIL":"Current Email","ADDRESSBOOK":"Adressbuch","NO_ADDRESSES":"Sie haben keine Adressen gespeichert.","FAIL_ADDRESSES":"Die Adressen sind nicht verfügbar. Versuchen Sie es später noch einmal.","ADD_ADDRESS":"Adresse hinzufügen","CLOSE":"Schließen","COMPANY_NAME":"Unternehmen","CONFIRM_DELETE_ADDRESS_TITLE":"Delete Address","CONFIRM_ADDRESS_REMOVAL":"Are you sure you want to delete this address?","FULL_NAME":"Vollständiger Name","CONTACT_PHONE":"Telefon","FAIL_CUSTOMER_DETAILS":"Die Kundendetails sind nicht verfügbar. Versuchen Sie es später noch einmal.","DATE":"Datum","NAME_REQUIRED":"Name erforderlich","STREET":"Straße","STREET_NUMBER":"Hausnummer","WELCOME":"Willkommen","NOT_SET":"Nicht festgelegt","ORDER_HISTORY":"Bestellhistorie","ORDER_NUMBER":"Bestellnummer","ORDER_STATUS":"Bestellstatus","FAIL_ORDER":"Die Bestellungen sind nicht verfügbar. Versuchen Sie es später noch einmal.","NO_ORDERS":"Sie haben keine Bestellungen gespeichert","ORDER_ITEM_COUNT":"{{number}} Position","ORDER_ITEMS_COUNT":"{{number}} Positionen","SHIPPING_DETAILS":"VERSANDDETAILS","SAVE":"Sichern","UPDATE_PASSWORD":"Kennwort aktualisieren","CURRENT_PASSWORD":"Aktuelles Kennwort","NEW_PASSWORD":"Neues Kennwort","CONFIRM_NEW_PASSWORD":"Neues Kennwort bestätigen","PASSWORDS_NO_MATCH":"Kennwörter stimmen nicht überein","WRONG_CURRENT_PASSWORD":"Geben Sie ein korrektes aktuelles Kennwort an.","PASSWORD_TOO_SHORT":"Kennwort zu kurz","SHOW_ALL":"Alles anzeigen","SHOW_LESS":"Weniger anzeigen","ITEMS_IN_ORDER":"Positionen in Bestellung","SAVE_ADDRESS_ERROR":"Es ist ein Fehler aufgetreten; die Aktualisierungen wurden nicht gesichert. Sichern Sie die Aktualisierungen.","REMOVE_ADDRESS_ERROR":"Löschen der Adresse fehlgeschlagen. Versuchen Sie es noch einmal.","UPDATE_DEFAULT_ADDRESS_ERROR":"Aktualisieren der Standardadresse fehlgeschlagen. Versuchen Sie es noch einmal.","EDIT_EMAIL_UPDATED":"Your email is being updated...","EDIT_EMAIL_SUCESSFULLY_UPDATED":"Email sucessfully updated","EDIT_EMAIL_CHANGED_MSG":"Your email has changed. You must sign in with your updated email","OOPS_MSG":"Oops!","EDIT_EMAIL_CHANGE_FAILED":"Something went wrong. Please reset your email again","RESET_EMAIL":"RESET EMAIL","EDIT_EMAIL_PASSWORD_NOT_CORRECT":"Password is not correct. Try again","EDIT_EMAIL_ALREADY_IN_USE":"This email is already in use. Try again","EDIT_EMAIL_SOMETHING_WENT_WRONG":"Something went wrong. Try again","FORGOT_PW":"Kennwort vergessen?","PASSWORD":"Kennwort","PASSWORD_MINCHAR":"Mindestens 6 Zeichen","CONFIRM_PASSWORD":"Kennwort bestätigen","TOKEN":"Token","RESET_PASSWORD":"Kennwort zurücksetzen","RESET_PW_TITLE":"Kennwort zurücksetzen","RESET_PW_INSTRUCT":"Legen Sie ein neues Kennwort an.","FORGOT_PW_INSTRUCT":"Geben Sie unten die E-Mail-Adresse Ihres Kontos an. Sie erhalten eine E-Mail mit einem Link zum Zurücksetzen Ihres Kennworts.","REQUEST_PW_EXPIRED":"Anforderung zum Zurücksetzen des Kennworts abgelaufen","REQUEST_PW_EXPIRED_MSG":"Die Anforderung zum Zurücksetzen Ihres Kennworts ist abgelaufen. Geben Sie Ihre E-Mail ein, um eine neue Anforderung zu übermitteln.","CHECK_EMAIL":"Überprüfen Sie Ihre E-Mail","CHECK_EMAIL_INSTRUCT":"... und wählen Sie den Link, um Ihr Kennwort zurückzusetzen. Der Link ist 24 Stunden gültig.","CHECK_EMAIL_INSTRUCT_CHANGE_EMAIL":"...and follow the link to confirm change of your email. The link will be valid for 24 hours.","COOKIES_ENABLED_ERROR":"Cookies must be enabled in your browser to sign in. To find out more, see the Help or Preferences area of your browser. Once enabled, sign in.","CREATE_ACCOUNT_ERROR":"Customer account was created successfully, but cookies must be enabled to login. To find out more, see the Help or Preferences area of your browser. Once enabled, sign in.","PASSWORD_REQUIRED":"Das Kennwort muss mindestens 6 Zeichen haben.","PASSWORDS_MUST_MATCH":"Die Kennwörter müssen übereinstimmen.","PW_SUCCESS":"Erfolgreich","PW_CHANGED_MSG":"Ihr Kennwort wurde zurückgesetzt. Sie können sich nun an Ihrem Konto anmelden.","INVALID_TOKEN":"Der Link zum Zurücksetzen des Kennworts ist nicht mehr gültig. Fordern Sie einen neuen Link an.","PW_CHANGE_FAILED":"Aktualisierung des Kennworts fehlgeschlagen.","RESET_PW_REPEAT":"Fordern Sie erneut einen Link zum Zurücksetzen des Kennworts an.","FIELD_REQUIRED":"Das Feld ist erforderlich.","FIELD_TOO_SHORT":"Das Feld ist zu kurz.","FIELDS_NOT_MATCHING":"Die Felder stimmen nicht überein.","SERVER_UNAVAILABLE":"Der Server ist nicht verfügbar, versuchen Sie es später erneut.","INVALID_CREDENTIALS":"Sie haben eine ungültige E-Mail-Adresse oder ein ungültiges Kennwort eingegeben.","PASSWORD_INVALID":"Kennwort ungültig - mindestens 6 Zeichen erforderlich.","ACCOUNT_LOCKED":"Das Konto wurde gesperrt, weil die Anzahl der ungültigen Anmeldeversuche überschritten wurde. Versuchen Sie es nach 5 Minuten noch einmal.","ACCOUNT_ALREADY_EXISTS":"E-Mail-Adresse wird für das vorhandene Konto bereits verwendet.","FORGOT_PASSWORD":"Kennwort vergessen?","EMAIL_NOT_FOUND":"Dieser E-Mail-Adresse ist kein Konto zugeordnet.","ENTER_EMAIL":"E-Mail-Adresse eingeben","ENTER_EXISTING_EMAIL":"Geben Sie die E-Mail-Adresse eines vorhandenen Kontos ein","LOGIN_FAILED":"Anmeldung fehlgeschlagen","ACCOUNT_EMAIL":"E-Mail-Adresse für Konto","ERROR_TITLE":"Interner Fehler","ERROR_MESSAGE":"Hoppla, es ist ein Problem aufgetreten.","ERROR_TITLE_401":"Keine Berechtigung","ERROR_MESSAGE_401":"Hoppla, es ist ein Problem aufgetreten. Ihre Anmeldedaten lassen keinen Zugriff auf diese Seite zu.","ERROR_TITLE_404":"Seite nicht gefunden","ERROR_MESSAGE_404":"Hoppla, es ist ein Problem aufgetreten. Diese Seite ist nicht vorhanden.","ERROR_REDIRECT":"Hier ist eine Seite, die Ihnen weiterhilft.","ERROR_BUTTON_TEXT":"STARTSEITE","DR":"Dr.","MR":"Herr","MRS":"Frau","MS":"Frau","TITLE":"Anrede","COMPLETED":"Abgeschlossen","CONFIRMED":"Bestätigt","CREATED":"Angelegt","DECLINED":"Abgelehnt","SHIPPED":"Versendet","CREDIT_CARD":"Kreditkarte","ON":"am","QUANTITY":"Menge","SHIPPED_BY_ON":"Geliefert von: {{carrier}} am {{shippedDate}}","TRACKING_NUMBER":"Verfolgungsnummer: {{trackingNumber}}","FOUND_FOR":"{{total}} gefunden für {{searchString}}","SEARCH":"Suchen","SEARCH_RESULTS":"Suchergebnisse","MOST_RELEVANT":"Relevanteste","RESULTS":"Ergebnisse","SEE_ALL":"Alle anzeigen","SEARCH_UNAVAILABLE":"Die Suche ist zurzeit nicht verfügbar.","NO_RESULTS_FOUND":"Keine Ergebnisse gefunden.","IN":"im","TERMS_AND_CONDITIONS":"Geschäftsbedingungen","CONTACT_US":"Kontakt","SITE_MAP":"Sitemap"} \ No newline at end of file +{"en":"Englisch","de":"Deutsch","fr":"Französisch","es":"Spanisch","YES":"Yes","NO":"No","BACK_TO_CHECKOUT":"Zurück zur Kasse","CHECKOUT":"Kasse","CANCEL":"Cancel","CONTINUE_SHOPPING":"Einkauf fortsetzen","NOTE":"Note","ADD_NOTE":"Add Note","EDIT_NOTE":"Edit Note","DELETE_NOTE":"Delete Note","UNABLE_TO_SAVE_NOTE":"Unable to save note","SHOP":"Einkaufen","EST_ORDER_TOTAL":"Geschätzte Bestellsumme","PREVIEW_ORDER":"Preview Order","PAYMENT_REVIEW":"Payment & Review","PLEASE_CORRECT_MESSAGE_ERRORS":"Something went wrong, please try again","FREE_SHIPPING":"Versand und Rücksendung in den USA kostenlos","ITEM":"Position","ITEM_PRICE":"Positionspreis","TOTAL_PRICE":"Gesamtpreis","CART_UNAVAILABLE":"Der Warenkorb ist zurzeit nicht verfügbar. Versuchen Sie es noch einmal.","CART_EMPTY":"Ihr Warenkorb ist leer","CART_ITEM_UPDATE_ERROR":"Die Aktualisierung war nicht erfolgreich. Versuchen Sie es noch einmal.","ESTIMATE_TAX":"Steuern schätzen","APPLY":"Anwenden","ESTIMATE_TAX_ERROR":"Felder \"Postleitzahl\" und \"Ländercode\" sind erforderlich","ADDITIONAL_SHIPPING_OPTIONS":"Additional shipping options are available in checkout.","SELECT_A_COUNTRY":"Land auswählen","ADDRESS":"Adresse","ADDRESS_LINE_1":"Adresszeile 1","ADDRESS_LINE_2":"Adresszeile 2","CANT_BE_SHIPPED":"Items cannot be shipped to this location","BILLING_ADDRESS":"Rechnungsadresse","CITY":"Ort","PROVINCE":"Provinz/Bundesland","CONTINUE":"Weiter","COST":"Cost","COUNTRY":"Land","CREDIT_CARD_NUMBER":"Kreditkartennummer","CVC_NUMBER":"Prüfnummer","DELIVERY_METHOD":"Liefermethode","EMAIL":"E-Mail","EDIT":"Bearbeiten","FIRST_NAME":"Vorname","FREE_STANDARD_SHIPPING":"Kostenloser Standardversand","FLAT_RATE_SHPPING":"Pauschale","INVALID_EXPIRATION_DATE":"Ungültiges Ablaufdatum","ITEMS":"Positionen","LAST_NAME":"Nachname","LAST_NAME_REQUIRED":"Nachname erforderlich","METHOD":"Versandart","MIDDLE_NAME":"Zweiter Vorname","MONTH":"Monat","NAME":"Name","NO_ITEMS_IN_CART":"Ihr Warenkorb enthält keine Positionen.","OPTIONAL":"Optional","ORDER_DETAILS":"Bestelldetails","ORDER_DATE":"Bestelldatum","ORDER_PENDING":"Einen Augenblick bitte... Ihre Bestellung wird ausgeführt","ORDER_TOTAL":"Bestellsumme","PAYMENT":"Zahlung","PHONE_REQUIRED":"Telefon erforderlich","PLACE_ORDER":"Bestellen","PLACED_AT":"Bestellt am","PLEASE_CORRECT_ERRORS":"Korrigieren Sie vor dem Bestellen die oben aufgeführten Fehler.","PLEASE_CORRECT_ERRORS_PREVIEW":"Please correct the errors above before previewing your order.","PLEASE_CORRECT_ERRORS_ADDRESS":"Please correct the address details before previewing your order.","PLEASE_ENTER_VALID_CC":"Geben Sie eine gültige Kreditkartennummer ein","PLEASE_ENTER_VALID_CODE":"Geben Sie einen gültigen Code ein","PLEASE_ENTER_VALID_EMAIL":"Geben Sie eine gültige E-Mail-Adresse im Format name@beispiel.com ein","REQUIRED":"Erforderlich","SAME_AS_SHIPPING_ADDRESS":"Same As Shipping Address","SECURE_CHECKOUT":"Sichere Kaufabwicklung","SELECT_FROM_ADDRESS_BOOK":"Aus Adressbuch auswählen","ADDRESS_BOOK":"Address Book","SHIPPING":"Versand","SHIPPING_ADDRESS":"Lieferadresse","SIMPLE_3_STEP_CHECKOUT":"Einfache Kaufabwicklung in 3 Schritten","SIMPLE_4_STEP_CHECKOUT":"Einfache Kaufabwicklung in 4 Schritten","STATE":"Bundesstaat","STEP_1_MY_DETAILS":"Schritt 1: Meine Details","STEP_2_BILLING_INFORMATION":"Schritt 2: Billing Information","STEP_3_PAYMENT":"Schritt 3: Zahlung","STEP_4_REVIEW_ORDER":"Schritt 4: Bestellung prüfen","SUBTOTAL":"Zwischensumme","DISCOUNT":"Rabatt","TAX":"Steuern","TOTAL":"Summe","YEAR":"Jahr","DEFAULT":"Standard","DISTRICT":"Stadtbezirk","STREET_NAME":"Straße/Hausnummer","BUILDING_NAME":"Gebäudename/-nummer","ROOM_NUMBER":"Zimmernummer","PREFECTURE":"Präfektur","POSTAL_CODE":"Postleitzahl","ZIP":"Postleitzahl","CITY_VILLAGE":"Stadt/Dorf/Stadtbezirk","SUBAREA":"Stadtteil","FURTHER_SUBAREA":"Stadtteilabschnitt, Blocknummer/Hausnummer","COUPON_APPLY":"Anwenden","COUPON_APPLIED":"Angewendet","COUPON_NOT_APPLIED":"Not Applied","COUPON_CODE":"Couponcode hinzufügen","COUPON_ERROR":"Coupon nicht gültig.","COUPON_NOT_ACTIVE":"The coupon is not active","COUPON_EXPIRED":"The coupon is not active","COUPON_REDEMPTIONS_EXCEEDED":"Coupon has reached maximum number of redemptions","COUPON_REDEMPTION_FORBIDDEN":"Current customer is not allowed to redeem the coupon","COUPON_ORDER_TOTAL_TOO_LOW":"The order value is too low for this coupon","COUPON_CURRENCY_INCORRECT":"Currency inconsistent with coupon","COUPON_DISCOUNT_CURRENCY_INCORRECT":"Discount currency invalid inconsistent coupon","COUPON_DISCOUNT_AMOUNT_INCORRECT":"Discount amount exceeds allowed coupon discount","COUPON_ERR_CURRENCY":"Währung für Coupon ungültig","COUPON_ERR_ANONYMOUS":"Melden Sie sich an, um den Couponcode zu verwenden","COUPON_ERR_UNAVAILABLE":"Coupon nicht mehr verfügbar","COUPON_MINIMUM_NOT_MET":"Aktuelle Bestellsumme entspricht nicht der erforderlichen Mindestsumme für diesen Coupon","COUPON_NOT_VALID":"Coupon nicht gültig","COUPONS":"Coupon Code","A_COPY_OF_YOUR_ORDER_DETAILS_HAS_BEEN_SENT_TO":"

      Eine Kopie Ihrer Bestelldetails wurde gesendet an {{emailAddress}}

      ","ENJOY_YOUR_ITEMS":"Viel Freude an Ihrem Einkauf!","FOR_YOUR_ORDER":"für Ihre Bestellung!","ITEM_IN_YOUR_ORDER":"Position in Ihrer Bestellung","ITEMS_IN_YOUR_ORDER":"Positionen in Ihrer Bestellung","QUESTIONS":"

      Bei Fragen kontaktieren Sie uns unter {{contactInfo}}.

      ","ORDER":"Bestellung","RETURN_TO_SHOPPING":"Zurück zum Einkauf","SUCCESS":"Vorgang war erfolgreich!","ACCOUNT_SUCCESS":"Ihr Konto wurde erfolgreich angelegt.","THANK_YOU":"Vielen Dank","THANK_YOU_FOR_YOUR_ORDER":"Vielen Dank
      für Ihre Bestellung!","THE_SHIPMENT_IS_SCHEDULED_TO_ARRIVE_AT_THE_FOLLOWING_LOCATION":"Die Bestellung wird geliefert an","YOUR_ORDER_IS":"Ihre Bestellnummer lautet ","ONE_MORE_STEP":"Nur ein weiterer Schritt zum Anlegen eines Kontos mit schneller Kaufabwicklung und einem einfachen Zugriff auf frühere Bestellungen","SKU":"Lagermengeneinheit","YOUR_CHECKOUT_HAS_BEEN_ACCEPTED_ORDER_NOT_CREATED":"Ihre Kaufabwicklung wurde angenommen, aber die Bestellung wurde nicht angelegt. Verwenden Sie zur Verfolgung folgende Kaufabwicklungs-ID-Nummer: ","YOUR_ORDER_WILL_BE_CREATED":"Ihre Bestellung wird so schnell wie möglich angelegt.","PRODUCTS":"Produkte","BACK_TO":"Zurück zu","REGION":"Region","SHIPPING_INFORMATION":"Shipping information","SHIPPING_ZONE":"Shipping Zone","STANDARD_SHIPPING":"Standard Shipping","SHIPPING_RATE":"Shipping Rate","ZONE":"Zone","BUY":"Kaufen","ADD_TO_CART":"In den Warenkorb","PRODUCTS_ADDED_TO_CART":"product(s) successfully added to your cart","PRODUCT_DESCRIPTION":"Produktbeschreibung","PRODUCT_DETAILS":"Produktdetails","OUT_OF_STOCK":"nicht vorrätig","UNAVAILABLE":"Unavailable","QTY":"Menge","INCLUDES":"Includes","NO_LIMIT":"No Limit","DESTINATION_COUNTRY":"Destination country(s)","ERROR_ADDING_TO_CART":"Hinzufügen zum Warenkorb war nicht erfolgreich. Versuchen Sie es noch einmal.","DESCRIPTION_TAB":"Description","DETAILS_TAB":"Details","MORE":"More","NEWEST":"neueste","OF":"von","PRICE_HIGH_LOW":"Preis (höchster - niedrigster)","PRICE_LOW_HIGH":"Preis (niedrigster - höchster)","SORT_BY":"Sortieren nach","VIEWING":"Anzeigen","PRODUCTS_FROM_TO":"
      {{productsFrom}}-{{productsTo}} von {{total}}
      ","ALL_PRODUCTS":"Alle Produkte","EMPTY_MSG":"Demo-Filiale - demnächst verfügbar","LANGUAGES":"Sprachen","SELECT_LANGUAGE":"Sprache auswählen","SIGN_OUT":"Abmelden","SIGN_IN":"Anmelden","SIGN_IN_WITH_FACEBOOK":"Über Facebook anmelden","LOG_IN_WITH_GOOGLE":"Über Google anmelden","MY_ACCOUNT":"Mein Konto","CREATE_ACCOUNT":"Konto anlegen","CONTINUE_AS_GUEST":"Weiter als Gast","UPDATE_ACCOUNT_DETAILS":"Kontodetails aktualisieren","UPDATE_EMAIL":"E-Mail aktualisieren","ADD":"Hinzufügen","REGION_PREFERENCES":"Regionspräferenzen","NEW_EMAIL":"Neue E-Mail","CURRENT_EMAIL":"Current Email","ADDRESSBOOK":"Adressbuch","NO_ADDRESSES":"Sie haben keine Adressen gespeichert.","FAIL_ADDRESSES":"Die Adressen sind nicht verfügbar. Versuchen Sie es später noch einmal.","ADD_ADDRESS":"Adresse hinzufügen","CLOSE":"Schließen","COMPANY_NAME":"Unternehmen","CONFIRM_DELETE_ADDRESS_TITLE":"Delete Address","CONFIRM_ADDRESS_REMOVAL":"Are you sure you want to delete this address?","CONFIRM_ORDER_CANCEL_TITLE":"Cancel Order","CONFIRM_CANCEL_ORDER":"Are you sure you want to cancel your order?","FULL_NAME":"Vollständiger Name","CONTACT_PHONE":"Telefon","FAIL_CUSTOMER_DETAILS":"Die Kundendetails sind nicht verfügbar. Versuchen Sie es später noch einmal.","DATE":"Datum","NAME_REQUIRED":"Name erforderlich","STREET":"Straße","STREET_NUMBER":"Hausnummer","WELCOME":"Willkommen","NOT_SET":"Nicht festgelegt","ORDER_HISTORY":"Bestellhistorie","ORDER_NUMBER":"Bestellnummer","ORDER_STATUS":"Bestellstatus","ORDER_CANCEL":"Cancel Order","ORDER_CANCEL_ERROR":"Cancelation failed, please contact customer service or try again later","FAIL_ORDER":"Die Bestellungen sind nicht verfügbar. Versuchen Sie es später noch einmal.","NO_ORDERS":"Sie haben keine Bestellungen gespeichert","ORDER_ITEM_COUNT":"{{number}} Position","ORDER_ITEMS_COUNT":"{{number}} Positionen","SHIPPING_DETAILS":"VERSANDDETAILS","SAVE":"Sichern","SUBMIT":"Submit","UPDATE_PASSWORD":"Kennwort aktualisieren","CURRENT_PASSWORD":"Aktuelles Kennwort","NEW_PASSWORD":"Neues Kennwort","CONFIRM_NEW_PASSWORD":"Neues Kennwort bestätigen","PASSWORDS_NO_MATCH":"Kennwörter stimmen nicht überein","WRONG_CURRENT_PASSWORD":"Geben Sie ein korrektes aktuelles Kennwort an.","PASSWORD_TOO_SHORT":"Kennwort zu kurz","SHOW_ALL":"Alles anzeigen","SHOW_LESS":"Weniger anzeigen","ITEMS_IN_ORDER":"Positionen in Bestellung","SAVE_ADDRESS_ERROR":"Es ist ein Fehler aufgetreten; die Aktualisierungen wurden nicht gesichert. Sichern Sie die Aktualisierungen.","REMOVE_ADDRESS_ERROR":"Löschen der Adresse fehlgeschlagen. Versuchen Sie es noch einmal.","UPDATE_DEFAULT_ADDRESS_ERROR":"Aktualisieren der Standardadresse fehlgeschlagen. Versuchen Sie es noch einmal.","EDIT_EMAIL_UPDATED":"Your email is being updated...","EDIT_EMAIL_SUCESSFULLY_UPDATED":"Email sucessfully updated","EDIT_EMAIL_CHANGED_MSG":"Your email has changed. You must sign in with your updated email","OOPS_MSG":"Oops!","EDIT_EMAIL_CHANGE_FAILED":"Something went wrong. Please reset your email again","RESET_EMAIL":"RESET EMAIL","EDIT_EMAIL_PASSWORD_NOT_CORRECT":"Password is not correct. Try again","EDIT_EMAIL_ALREADY_IN_USE":"This email is already in use. Try again","EDIT_EMAIL_SOMETHING_WENT_WRONG":"Something went wrong. Try again","FORGOT_PW":"Kennwort vergessen?","PASSWORD":"Kennwort","PASSWORD_MINCHAR":"Mindestens 6 Zeichen","CONFIRM_PASSWORD":"Kennwort bestätigen","TOKEN":"Token","RESET_PASSWORD":"Kennwort zurücksetzen","RESET_PW_TITLE":"Kennwort zurücksetzen","RESET_PW_INSTRUCT":"Legen Sie ein neues Kennwort an.","FORGOT_PW_INSTRUCT":"Geben Sie unten die E-Mail-Adresse Ihres Kontos an. Sie erhalten eine E-Mail mit einem Link zum Zurücksetzen Ihres Kennworts.","REQUEST_PW_EXPIRED":"Anforderung zum Zurücksetzen des Kennworts abgelaufen","REQUEST_PW_EXPIRED_MSG":"Die Anforderung zum Zurücksetzen Ihres Kennworts ist abgelaufen. Geben Sie Ihre E-Mail ein, um eine neue Anforderung zu übermitteln.","CHECK_EMAIL":"Überprüfen Sie Ihre E-Mail","CHECK_EMAIL_INSTRUCT":"... und wählen Sie den Link, um Ihr Kennwort zurückzusetzen. Der Link ist 24 Stunden gültig.","CHECK_EMAIL_INSTRUCT_CHANGE_EMAIL":"...and follow the link to confirm change of your email. The link will be valid for 24 hours.","COOKIES_ENABLED_ERROR":"Cookies must be enabled in your browser to sign in. To find out more, see the Help or Preferences area of your browser. Once enabled, sign in.","CREATE_ACCOUNT_ERROR":"Customer account was created successfully, but cookies must be enabled to login. To find out more, see the Help or Preferences area of your browser. Once enabled, sign in.","PASSWORD_REQUIRED":"Das Kennwort muss mindestens 6 Zeichen haben.","PASSWORDS_MUST_MATCH":"Die Kennwörter müssen übereinstimmen.","PW_SUCCESS":"Erfolgreich","PW_CHANGED_MSG":"Ihr Kennwort wurde zurückgesetzt. Sie können sich nun an Ihrem Konto anmelden.","INVALID_TOKEN":"Der Link zum Zurücksetzen des Kennworts ist nicht mehr gültig. Fordern Sie einen neuen Link an.","PW_CHANGE_FAILED":"Aktualisierung des Kennworts fehlgeschlagen.","RESET_PW_REPEAT":"Fordern Sie erneut einen Link zum Zurücksetzen des Kennworts an.","FIELD_REQUIRED":"Das Feld ist erforderlich.","FIELD_TOO_SHORT":"Das Feld ist zu kurz.","FIELDS_NOT_MATCHING":"Die Felder stimmen nicht überein.","SERVER_UNAVAILABLE":"Der Server ist nicht verfügbar, versuchen Sie es später erneut.","INVALID_CREDENTIALS":"Sie haben eine ungültige E-Mail-Adresse oder ein ungültiges Kennwort eingegeben.","PASSWORD_INVALID":"Kennwort ungültig - mindestens 6 Zeichen erforderlich.","ACCOUNT_LOCKED":"Das Konto wurde gesperrt, weil die Anzahl der ungültigen Anmeldeversuche überschritten wurde. Versuchen Sie es nach 5 Minuten noch einmal.","ACCOUNT_ALREADY_EXISTS":"E-Mail-Adresse wird für das vorhandene Konto bereits verwendet.","FORGOT_PASSWORD":"Kennwort vergessen?","EMAIL_NOT_FOUND":"Dieser E-Mail-Adresse ist kein Konto zugeordnet.","ENTER_EMAIL":"E-Mail-Adresse eingeben","ENTER_EXISTING_EMAIL":"Geben Sie die E-Mail-Adresse eines vorhandenen Kontos ein","LOGIN_FAILED":"Anmeldung fehlgeschlagen","ACCOUNT_EMAIL":"E-Mail-Adresse für Konto","ERROR_TITLE":"Interner Fehler","ERROR_MESSAGE":"Hoppla, es ist ein Problem aufgetreten.","ERROR_TITLE_401":"Keine Berechtigung","ERROR_MESSAGE_401":"Hoppla, es ist ein Problem aufgetreten. Ihre Anmeldedaten lassen keinen Zugriff auf diese Seite zu.","ERROR_TITLE_404":"Seite nicht gefunden","ERROR_MESSAGE_404":"Hoppla, es ist ein Problem aufgetreten. Diese Seite ist nicht vorhanden.","ERROR_REDIRECT":"Hier ist eine Seite, die Ihnen weiterhilft.","ERROR_BUTTON_TEXT":"STARTSEITE","DR":"Dr.","MR":"Herr","MRS":"Frau","MS":"Frau","TITLE":"Anrede","COMPLETED":"Abgeschlossen","CONFIRMED":"Bestätigt","CREATED":"Angelegt","DECLINED":"Cancelled","SHIPPED":"Versendet","CREDIT_CARD":"Kreditkarte","ON":"am","QUANTITY":"Menge","SHIPPED_BY_ON":"Geliefert von: {{carrier}} am {{shippedDate}}","TRACKING_NUMBER":"Verfolgungsnummer: {{trackingNumber}}","FOUND_FOR":"{{total}} gefunden für {{searchString}}","SEARCH":"Suchen","SEARCH_RESULTS":"Suchergebnisse","MOST_RELEVANT":"Relevanteste","RESULTS":"Ergebnisse","SEE_ALL":"See All Results","SEARCH_UNAVAILABLE":"Die Suche ist zurzeit nicht verfügbar.","NO_RESULTS_FOUND":"Keine Ergebnisse gefunden.","IN":"im","TERMS_AND_CONDITIONS":"Geschäftsbedingungen","CONTACT_US":"Kontakt","SITE_MAP":"Sitemap"} \ No newline at end of file diff --git a/public/js/app/shared/i18n/lang/lang_en.json b/public/js/app/shared/i18n/lang/lang_en.json index 4902dac89..9c892063c 100644 --- a/public/js/app/shared/i18n/lang/lang_en.json +++ b/public/js/app/shared/i18n/lang/lang_en.json @@ -1 +1 @@ -{"en":"English","de":"German","fr":"French","es":"Spanish","BACK_TO_CHECKOUT":"Back to checkout","CANCEL":"Cancel","CHECKOUT":"Checkout","CONTINUE_SHOPPING":"Continue shopping","SHOP":"Shop","NOTE":"Note","ADD_NOTE":"Add Note","EDIT_NOTE":"Edit Note","DELETE_NOTE":"Delete Note","UNABLE_TO_SAVE_NOTE":"Unable to save note","EST_ORDER_TOTAL":"Est. order total","PREVIEW_ORDER":"Preview Order","PAYMENT_REVIEW":"Payment & Review","PLEASE_CORRECT_MESSAGE_ERRORS":"Something went wrong, please try again","FREE_SHIPPING":"Free Shipping and Returns in the US","ITEM":"Item","ITEM_PRICE":"Item Price","TOTAL_PRICE":"Total Price","CART_UNAVAILABLE":"The cart is currently unavailable. Please try again.","CART_EMPTY":"Your cart is empty","CART_ITEM_UPDATE_ERROR":"The update was not successful. Please try again.","ESTIMATE_TAX":"Estimate Tax","APPLY":"Apply","ESTIMATE_TAX_ERROR":"Zip/Postal Code and Country Code fields are required","ADDITIONAL_SHIPPING_OPTIONS":"Additional shipping options are available in checkout.","SELECT_A_COUNTRY":"Select a country","ADDRESS":"Address","ADDRESS_LINE_1":"Address Line 1","ADDRESS_LINE_2":"Address Line 2","CANT_BE_SHIPPED":"Items cannot be shipped to this location","BILLING_ADDRESS":"Billing Address","CITY":"City","PROVINCE":"Province","CONTINUE":"Continue","COST":"Cost","COUNTRY":"Country","CREDIT_CARD_NUMBER":"Credit Card Number","CVC_NUMBER":"CVC Number","DELIVERY_METHOD":"Delivery Method","EMAIL":"Email","EDIT":"Edit","FIRST_NAME":"First Name","FREE_STANDARD_SHIPPING":"Free Standard Shipping","FLAT_RATE_SHPPING":"Flat Rate","INVALID_EXPIRATION_DATE":"Invalid Expiration Date","ITEMS":"Items","LAST_NAME":"Last Name","LAST_NAME_REQUIRED":"Last Name Required","METHOD":"Method","MIDDLE_NAME":"Middle Name","MONTH":"Month","NAME":"Name","NO_ITEMS_IN_CART":"There are no items in your cart.","OPTIONAL":"Optional","ORDER_DETAILS":"Order Details","ORDER_DATE":"Order Date","ORDER_PENDING":"One moment... Placing your order","ORDER_TOTAL":"Order Total","PAYMENT":"Payment","PHONE_REQUIRED":"Phone Required","PLACE_ORDER":"Place Order","PLACED_AT":"Placed At","PLEASE_CORRECT_ERRORS":"Please correct the errors above before placing your order.","PLEASE_CORRECT_ERRORS_PREVIEW":"Please correct the errors above before previewing your order.","PLEASE_CORRECT_ERRORS_ADDRESS":"Please correct the address details before previewing your order.","PLEASE_ENTER_VALID_CC":"Please enter a valid credit card number","PLEASE_ENTER_VALID_CODE":"Please enter a valid code","PLEASE_ENTER_VALID_EMAIL":"Please enter a valid email in the format name@example.com","REQUIRED":"Required","SAME_AS_SHIPPING_ADDRESS":"Same As Shipping Address","SECURE_CHECKOUT":"Secure Checkout","SELECT_FROM_ADDRESS_BOOK":"Select from address book","ADDRESS_BOOK":"Address Book","SHIPPING":"Shipping","SHIPPING_ADDRESS":"Shipping Address","SIMPLE_3_STEP_CHECKOUT":"Simple 3 Step Checkout","SIMPLE_4_STEP_CHECKOUT":"Simple 4 Step Checkout","STATE":"State","STEP_1_MY_DETAILS":"Step 1. My Details","STEP_2_BILLING_INFORMATION":"Step 2. Billing Information","STEP_3_PAYMENT":"Step 3. Payment","STEP_4_REVIEW_ORDER":"Step 4. Review Order","SUBTOTAL":"Subtotal","DISCOUNT":"Discount","TAX":"Tax","TOTAL":"Total","YEAR":"Year","DEFAULT":"Default","DISTRICT":"District","STREET_NAME":"Street Name/ Number","BUILDING_NAME":"Building Name/ Number","ROOM_NUMBER":"Room Number","PREFECTURE":"Prefecture","POSTAL_CODE":"Postal Code","ZIP":"Zip/ Postal Code","CITY_VILLAGE":"City/ Village/ City Ward","SUBAREA":"Subarea","FURTHER_SUBAREA":"Further Subarea, Block #/ House #","COUPON_APPLY":"Apply","COUPON_APPLIED":"Applied","COUPON_NOT_APPLIED":"Not Applied","COUPON_CODE":"Add Coupon Code","COUPON_NOT_ACTIVE":"The coupon is not active","COUPON_EXPIRED":"The coupon is not active","COUPON_REDEMPTIONS_EXCEEDED":"Coupon has reached maximum number of redemptions","COUPON_REDEMPTION_FORBIDDEN":"Current customer is not allowed to redeem the coupon","COUPON_ORDER_TOTAL_TOO_LOW":"The order value is too low for this coupon","COUPON_CURRENCY_INCORRECT":"Currency inconsistent with coupon","COUPON_DISCOUNT_CURRENCY_INCORRECT":"Discount currency invalid inconsistent coupon","COUPON_DISCOUNT_AMOUNT_INCORRECT":"Discount amount exceeds allowed coupon discount","COUPON_ERROR":"Coupon not valid.","COUPON_ERR_CURRENCY":"Currency invalid with coupon","COUPON_ERR_ANONYMOUS":"Sign in to use coupon code","COUPON_ERR_UNAVAILABLE":"Coupon no longer available","COUPON_MINIMUM_NOT_MET":"Current order total does not meet the required minimum for this coupon","COUPON_NOT_VALID":"Coupon Not Valid","COUPONS":"Coupon Code","A_COPY_OF_YOUR_ORDER_DETAILS_HAS_BEEN_SENT_TO":"

      A copy of your order details has been sent to {{emailAddress}}

      ","ENJOY_YOUR_ITEMS":"Enjoy your items!","FOR_YOUR_ORDER":"for your order!","ITEM_IN_YOUR_ORDER":"Item in your order","ITEMS_IN_YOUR_ORDER":"Items in your order","QUESTIONS":"

      If you have any questions, contact us at {{contactInfo}}.

      ","ORDER":"Order","RETURN_TO_SHOPPING":"Return to shopping","SUCCESS":"Success!","ACCOUNT_SUCCESS":"Your account was successfully created!","THANK_YOU":"Thank you","THANK_YOU_FOR_YOUR_ORDER":"Thank you
      for your order!","THE_SHIPMENT_IS_SCHEDULED_TO_ARRIVE_AT_THE_FOLLOWING_LOCATION":"The order will be shipped to","YOUR_ORDER_IS":"Your order # is ","ONE_MORE_STEP":"One More Step to Create an Account for a Fast Checkout and Easy Access to Previous Orders","SKU":"SKU","YOUR_CHECKOUT_HAS_BEEN_ACCEPTED_ORDER_NOT_CREATED":"Your checkout has been accepted, but the order has not been created. For tracking purposes, please use the following checkout ID number: ","YOUR_ORDER_WILL_BE_CREATED":"Your order will be created as soon as possible.","PRODUCTS":"Products","BACK_TO":"Back To","REGION":"Region","SHIPPING_INFORMATION":"Shipping information","SHIPPING_ZONE":"Shipping Zone","STANDARD_SHIPPING":"Standard Shipping","SHIPPING_RATE":"Shipping Rate","ZONE":"Zone","BUY":"Buy","ADD_TO_CART":"Add to Cart","PRODUCTS_ADDED_TO_CART":"product(s) successfully added to your cart","PRODUCT_DESCRIPTION":"Product Description","PRODUCT_DETAILS":"Product Details","OUT_OF_STOCK":"out of stock","QTY":"Qty","INCLUDES":"Includes","DESTINATION_COUNTRY":"Destination country(s)","NO_LIMIT":"No Limit","ERROR_ADDING_TO_CART":"Add to Cart was not successful. Please try again.","NEWEST":"newest","OF":"of","PRICE_HIGH_LOW":"price high - low","PRICE_LOW_HIGH":"price low - high","SORT_BY":"Sort by","VIEWING":"Viewing","PRODUCTS_FROM_TO":"
      {{productsFrom}}-{{productsTo}} of {{total}}
      ","ALL_PRODUCTS":"All Products","EMPTY_MSG":"Demo Store - Coming Soon","LANGUAGES":"Languages","SELECT_LANGUAGE":"Select a language","SIGN_OUT":"Sign Out","SIGN_IN":"Sign In","SIGN_IN_WITH_FACEBOOK":"Sign in with Facebook","LOG_IN_WITH_GOOGLE":"Sign in with Google","MY_ACCOUNT":"My Account","CREATE_ACCOUNT":"Create Account","CONTINUE_AS_GUEST":"Continue as our guest","UPDATE_ACCOUNT_DETAILS":"Update Account details","UPDATE_EMAIL":"Update Email","ADD":"Add","REGION_PREFERENCES":"Region Preferences","NEW_EMAIL":"New Email","CURRENT_EMAIL":"Current Email","ADDRESSBOOK":"Addressbook","NO_ADDRESSES":"You have no addresses stored!","FAIL_ADDRESSES":"Addresses not available. Try again later.","ADD_ADDRESS":"Add Address","CLOSE":"Close","COMPANY_NAME":"Company","CONFIRM_DELETE_ADDRESS_TITLE":"Delete Address","CONFIRM_ADDRESS_REMOVAL":"Are you sure you want to delete this address?","FULL_NAME":"Full Name","CONTACT_PHONE":"Phone","FAIL_CUSTOMER_DETAILS":"Customer details not available. Try again later.","DATE":"Date","NAME_REQUIRED":"Name Required","STREET":"Street","STREET_NUMBER":"Street Number","WELCOME":"Welcome","NOT_SET":"Not Set","ORDER_HISTORY":"Order History","ORDER_NUMBER":"Order Number","ORDER_STATUS":"Order Status","FAIL_ORDER":"Orders not available. Try again later.","NO_ORDERS":"You have no orders stored","ORDER_ITEM_COUNT":"{{number}} Item","ORDER_ITEMS_COUNT":"{{number}} Items","SHIPPING_DETAILS":"SHIPPING DETAILS","SAVE":"Save","UPDATE_PASSWORD":"Update password","CURRENT_PASSWORD":"Current password","NEW_PASSWORD":"New password","CONFIRM_NEW_PASSWORD":"Confirm new password","PASSWORDS_NO_MATCH":"Passwords do not match","WRONG_CURRENT_PASSWORD":"Please provide correct current password!","PASSWORD_TOO_SHORT":"Password too short","SHOW_ALL":"Show all","SHOW_LESS":"Show less","ITEMS_IN_ORDER":"Items in Order","SAVE_ADDRESS_ERROR":"An error occured and updates not saved. Save updates.","REMOVE_ADDRESS_ERROR":"Deleting address failed. Please try again.","UPDATE_DEFAULT_ADDRESS_ERROR":"Updating default address failed. Please try again.","EDIT_EMAIL_UPDATED":"Your email is being updated...","EDIT_EMAIL_SUCESSFULLY_UPDATED":"Email sucessfully updated","EDIT_EMAIL_CHANGED_MSG":"Your email has changed. You must sign in with your updated email","OOPS_MSG":"Oops!","EDIT_EMAIL_CHANGE_FAILED":"Something went wrong. Please reset your email again","RESET_EMAIL":"RESET EMAIL","EDIT_EMAIL_PASSWORD_NOT_CORRECT":"Password is not correct. Try again","EDIT_EMAIL_ALREADY_IN_USE":"This email is already in use. Try again","EDIT_EMAIL_SOMETHING_WENT_WRONG":"Something went wrong. Try again","FORGOT_PW":"Forgot your password?","PASSWORD":"Password","PASSWORD_MINCHAR":"Min. 6 characters","CONFIRM_PASSWORD":"Confirm Password","TOKEN":"Token","RESET_PASSWORD":"Reset Password","RESET_PW_TITLE":"Reset Your Password","RESET_PW_INSTRUCT":"Please create a new password.","FORGOT_PW_INSTRUCT":"Please enter your account email address below. An email will be sent to you with a link to reset your password.","REQUEST_PW_EXPIRED":"Reset Password Request Expired","REQUEST_PW_EXPIRED_MSG":"The request to reset your password has expired. Please enter your email to make a new request.","CHECK_EMAIL":"Check Your Email","CHECK_EMAIL_INSTRUCT":"...and follow the link to reset your password. The link will be valid for 24 hours.","CHECK_EMAIL_INSTRUCT_CHANGE_EMAIL":"...and follow the link to confirm change of your email. The link will be valid for 24 hours.","COOKIES_ENABLED_ERROR":"Cookies must be enabled in your browser to sign in. To find out more, see the Help or Preferences area of your browser. Once enabled, sign in.","CREATE_ACCOUNT_ERROR":"Customer account was created successfully, but cookies must be enabled to login. To find out more, see the Help or Preferences area of your browser. Once enabled, sign in.","PASSWORD_REQUIRED":"Password with 6 character minimum required.","PASSWORDS_MUST_MATCH":"Passwords must match.","PW_SUCCESS":"Success","PW_CHANGED_MSG":"Your password has been reset. You can now sign into your account.","INVALID_TOKEN":"This reset-password link is no longer valid. Please request a new one.","PW_CHANGE_FAILED":"Update of password failed.","RESET_PW_REPEAT":"Request another reset-password link.","FIELD_REQUIRED":"Field is required!","FIELD_TOO_SHORT":"Field too short!","FIELDS_NOT_MATCHING":"Fields not matching!","SERVER_UNAVAILABLE":"Server is unavailable, please try again later.","INVALID_CREDENTIALS":"You entered an invalid email or password.","PASSWORD_INVALID":"Password invalid - minimum of 6 characters required.","ACCOUNT_LOCKED":"Account has been locked due to excessive number of invalid login attempts. Please wait 5 minutes and try again.","ACCOUNT_ALREADY_EXISTS":"Email address already in use for existing account.","FORGOT_PASSWORD":"Forgot password?","EMAIL_NOT_FOUND":"There is no account associated with that email address.","ENTER_EMAIL":"Enter Email","ENTER_EXISTING_EMAIL":"Enter the email address of an existing account","LOGIN_FAILED":"Login failed","ACCOUNT_EMAIL":"Account Email","ERROR_TITLE":"Internal Error","ERROR_MESSAGE":"Oops! There's a problem.","ERROR_TITLE_401":"Unauthorized","ERROR_MESSAGE_401":"Oops! There's a problem. Your login credentials don't allow access to this page.","ERROR_TITLE_404":"Page not found","ERROR_MESSAGE_404":"Oops! There's a problem. This page doesn't exist.","ERROR_REDIRECT":"Here is a page to help you get back on track.","ERROR_BUTTON_TEXT":"HOMEPAGE","DR":"Dr.","MR":"Mr.","MRS":"Mrs.","MS":"Ms.","TITLE":"Title","COMPLETED":"Completed","CONFIRMED":"Confirmed","CREATED":"Created","DECLINED":"Declined","SHIPPED":"Shipped","CREDIT_CARD":"Credit Card","ON":"on","QUANTITY":"Quantity","SHIPPED_BY_ON":"Shipped by: {{carrier}} on {{shippedDate}}","TRACKING_NUMBER":"Tracking Number: {{trackingNumber}}","FOUND_FOR":"{{total}} found for {{searchString}}","SEARCH":"Search","SEARCH_RESULTS":"Search results","MOST_RELEVANT":"Most Relevant","RESULTS":"Results","SEE_ALL":"See All","SEARCH_UNAVAILABLE":"Search is currently unavailable.","NO_RESULTS_FOUND":"No results found.","IN":"in","TERMS_AND_CONDITIONS":"Terms & Conditions","CONTACT_US":"Contact Us","SITE_MAP":"Site Map"} \ No newline at end of file +{"en":"English","de":"German","fr":"French","es":"Spanish","YES":"Yes","NO":"No","BACK_TO_CHECKOUT":"Back to checkout","CANCEL":"Cancel","CHECKOUT":"Checkout","CONTINUE_SHOPPING":"Continue shopping","SHOP":"Shop","NOTE":"Note","ADD_NOTE":"Add Note","EDIT_NOTE":"Edit Note","DELETE_NOTE":"Delete Note","UNABLE_TO_SAVE_NOTE":"Unable to save note","EST_ORDER_TOTAL":"Est. order total","PREVIEW_ORDER":"Preview Order","PAYMENT_REVIEW":"Payment & Review","PLEASE_CORRECT_MESSAGE_ERRORS":"Something went wrong, please try again","FREE_SHIPPING":"Free Shipping and Returns in the US","ITEM":"Item","ITEM_PRICE":"Item Price","TOTAL_PRICE":"Total Price","CART_UNAVAILABLE":"The cart is currently unavailable. Please try again.","CART_EMPTY":"Your cart is empty","CART_ITEM_UPDATE_ERROR":"The update was not successful. Please try again.","ESTIMATE_TAX":"Estimate Tax","APPLY":"Apply","ESTIMATE_TAX_ERROR":"Zip/Postal Code and Country Code fields are required","ADDITIONAL_SHIPPING_OPTIONS":"Additional shipping options are available in checkout.","SELECT_A_COUNTRY":"Select a country","ADDRESS":"Address","ADDRESS_LINE_1":"Address Line 1","ADDRESS_LINE_2":"Address Line 2","CANT_BE_SHIPPED":"Items cannot be shipped to this location","BILLING_ADDRESS":"Billing Address","CITY":"City","PROVINCE":"Province","CONTINUE":"Continue","COST":"Cost","COUNTRY":"Country","CREDIT_CARD_NUMBER":"Credit Card Number","CVC_NUMBER":"CVC Number","DELIVERY_METHOD":"Delivery Method","EMAIL":"Email","EDIT":"Edit","FIRST_NAME":"First Name","FREE_STANDARD_SHIPPING":"Free Standard Shipping","FLAT_RATE_SHPPING":"Flat Rate","INVALID_EXPIRATION_DATE":"Invalid Expiration Date","ITEMS":"Items","LAST_NAME":"Last Name","LAST_NAME_REQUIRED":"Last Name Required","METHOD":"Method","MIDDLE_NAME":"Middle Name","MONTH":"Month","NAME":"Name","NO_ITEMS_IN_CART":"There are no items in your cart.","OPTIONAL":"Optional","ORDER_DETAILS":"Order Details","ORDER_DATE":"Order Date","ORDER_PENDING":"One moment... Placing your order","ORDER_TOTAL":"Order Total","PAYMENT":"Payment","PHONE_REQUIRED":"Phone Required","PLACE_ORDER":"Place Order","PLACED_AT":"Placed At","PLEASE_CORRECT_ERRORS":"Please correct the errors above before placing your order.","PLEASE_CORRECT_ERRORS_PREVIEW":"Please correct the errors above before previewing your order.","PLEASE_CORRECT_ERRORS_ADDRESS":"Please correct the address details before previewing your order.","PLEASE_ENTER_VALID_CC":"Please enter a valid credit card number","PLEASE_ENTER_VALID_CODE":"Please enter a valid code","PLEASE_ENTER_VALID_EMAIL":"Please enter a valid email in the format name@example.com","REQUIRED":"Required","SAME_AS_SHIPPING_ADDRESS":"Same As Shipping Address","SECURE_CHECKOUT":"Secure Checkout","SELECT_FROM_ADDRESS_BOOK":"Select from address book","ADDRESS_BOOK":"Address Book","SHIPPING":"Shipping","SHIPPING_ADDRESS":"Shipping Address","SIMPLE_3_STEP_CHECKOUT":"Simple 3 Step Checkout","SIMPLE_4_STEP_CHECKOUT":"Simple 4 Step Checkout","STATE":"State","STEP_1_MY_DETAILS":"Step 1. My Details","STEP_2_BILLING_INFORMATION":"Step 2. Billing Information","STEP_3_PAYMENT":"Step 3. Payment","STEP_4_REVIEW_ORDER":"Step 4. Review Order","SUBTOTAL":"Subtotal","DISCOUNT":"Discount","TAX":"Tax","TOTAL":"Total","YEAR":"Year","DEFAULT":"Default","DISTRICT":"District","STREET_NAME":"Street Name/ Number","BUILDING_NAME":"Building Name/ Number","ROOM_NUMBER":"Room Number","PREFECTURE":"Prefecture","POSTAL_CODE":"Postal Code","ZIP":"Zip/ Postal Code","CITY_VILLAGE":"City/ Village/ City Ward","SUBAREA":"Subarea","FURTHER_SUBAREA":"Further Subarea, Block #/ House #","COUPON_APPLY":"Apply","COUPON_APPLIED":"Applied","COUPON_NOT_APPLIED":"Not Applied","COUPON_CODE":"Add Coupon Code","COUPON_NOT_ACTIVE":"The coupon is not active","COUPON_EXPIRED":"The coupon is not active","COUPON_REDEMPTIONS_EXCEEDED":"Coupon has reached maximum number of redemptions","COUPON_REDEMPTION_FORBIDDEN":"Current customer is not allowed to redeem the coupon","COUPON_ORDER_TOTAL_TOO_LOW":"The order value is too low for this coupon","COUPON_CURRENCY_INCORRECT":"Currency inconsistent with coupon","COUPON_DISCOUNT_CURRENCY_INCORRECT":"Discount currency invalid inconsistent coupon","COUPON_DISCOUNT_AMOUNT_INCORRECT":"Discount amount exceeds allowed coupon discount","COUPON_ERROR":"Coupon not valid.","COUPON_ERR_CURRENCY":"Currency invalid with coupon","COUPON_ERR_ANONYMOUS":"Sign in to use coupon code","COUPON_ERR_UNAVAILABLE":"Coupon no longer available","COUPON_MINIMUM_NOT_MET":"Current order total does not meet the required minimum for this coupon","COUPON_NOT_VALID":"Coupon Not Valid","COUPONS":"Coupon Code","A_COPY_OF_YOUR_ORDER_DETAILS_HAS_BEEN_SENT_TO":"

      A copy of your order details has been sent to {{emailAddress}}

      ","ENJOY_YOUR_ITEMS":"Enjoy your items!","FOR_YOUR_ORDER":"for your order!","ITEM_IN_YOUR_ORDER":"Item in your order","ITEMS_IN_YOUR_ORDER":"Items in your order","QUESTIONS":"

      If you have any questions, contact us at {{contactInfo}}.

      ","ORDER":"Order","RETURN_TO_SHOPPING":"Return to shopping","SUCCESS":"Success!","ACCOUNT_SUCCESS":"Your account was successfully created!","THANK_YOU":"Thank you","THANK_YOU_FOR_YOUR_ORDER":"Thank you
      for your order!","THE_SHIPMENT_IS_SCHEDULED_TO_ARRIVE_AT_THE_FOLLOWING_LOCATION":"The order will be shipped to","YOUR_ORDER_IS":"Your order # is ","ONE_MORE_STEP":"One More Step to Create an Account for a Fast Checkout and Easy Access to Previous Orders","SKU":"SKU","YOUR_CHECKOUT_HAS_BEEN_ACCEPTED_ORDER_NOT_CREATED":"Your checkout has been accepted, but the order has not been created. For tracking purposes, please use the following checkout ID number: ","YOUR_ORDER_WILL_BE_CREATED":"Your order will be created as soon as possible.","PRODUCTS":"Products","BACK_TO":"Back To","REGION":"Region","SHIPPING_INFORMATION":"Shipping information","SHIPPING_ZONE":"Shipping Zone","STANDARD_SHIPPING":"Standard Shipping","SHIPPING_RATE":"Shipping Rate","ZONE":"Zone","BUY":"Buy","ADD_TO_CART":"Add to Cart","PRODUCTS_ADDED_TO_CART":"product(s) successfully added to your cart","PRODUCT_DESCRIPTION":"Product Description","PRODUCT_DETAILS":"Product Details","OUT_OF_STOCK":"out of stock","UNAVAILABLE":"Unavailable","QTY":"Qty","INCLUDES":"Includes","DESTINATION_COUNTRY":"Destination country(s)","NO_LIMIT":"No Limit","ERROR_ADDING_TO_CART":"Add to Cart was not successful. Please try again.","DESCRIPTION_TAB":"Description","DETAILS_TAB":"Details","MORE":"More","NEWEST":"newest","OF":"of","PRICE_HIGH_LOW":"price high - low","PRICE_LOW_HIGH":"price low - high","SORT_BY":"Sort by","VIEWING":"Viewing","PRODUCTS_FROM_TO":"
      {{productsFrom}}-{{productsTo}} of {{total}}
      ","ALL_PRODUCTS":"All Products","EMPTY_MSG":"Demo Store - Coming Soon","LANGUAGES":"Languages","SELECT_LANGUAGE":"Select a language","SIGN_OUT":"Sign Out","SIGN_IN":"Sign In","SIGN_IN_WITH_FACEBOOK":"Sign in with Facebook","LOG_IN_WITH_GOOGLE":"Sign in with Google","MY_ACCOUNT":"My Account","CREATE_ACCOUNT":"Create Account","CONTINUE_AS_GUEST":"Continue as our guest","UPDATE_ACCOUNT_DETAILS":"Update Account details","UPDATE_EMAIL":"Update Email","ADD":"Add","REGION_PREFERENCES":"Region Preferences","NEW_EMAIL":"New Email","CURRENT_EMAIL":"Current Email","ADDRESSBOOK":"Addressbook","NO_ADDRESSES":"You have no addresses stored!","FAIL_ADDRESSES":"Addresses not available. Try again later.","ADD_ADDRESS":"Add Address","CLOSE":"Close","COMPANY_NAME":"Company","CONFIRM_DELETE_ADDRESS_TITLE":"Delete Address","CONFIRM_ADDRESS_REMOVAL":"Are you sure you want to delete this address?","CONFIRM_ORDER_CANCEL_TITLE":"Cancel Order","CONFIRM_CANCEL_ORDER":"Are you sure you want to cancel your order?","FULL_NAME":"Full Name","CONTACT_PHONE":"Phone","FAIL_CUSTOMER_DETAILS":"Customer details not available. Try again later.","DATE":"Date","NAME_REQUIRED":"Name Required","STREET":"Street","STREET_NUMBER":"Street Number","WELCOME":"Welcome","NOT_SET":"Not Set","ORDER_HISTORY":"Order History","ORDER_NUMBER":"Order Number","ORDER_STATUS":"Order Status","ORDER_CANCEL":"Cancel Order","ORDER_CANCEL_ERROR":"Cancelation failed, please contact customer service or try again later","FAIL_ORDER":"Orders not available. Try again later.","NO_ORDERS":"You have no orders stored","ORDER_ITEM_COUNT":"{{number}} Item","ORDER_ITEMS_COUNT":"{{number}} Items","SHIPPING_DETAILS":"SHIPPING DETAILS","SAVE":"Save","SUBMIT":"Submit","UPDATE_PASSWORD":"Update password","CURRENT_PASSWORD":"Current password","NEW_PASSWORD":"New password","CONFIRM_NEW_PASSWORD":"Confirm new password","PASSWORDS_NO_MATCH":"Passwords do not match","WRONG_CURRENT_PASSWORD":"Please provide correct current password!","PASSWORD_TOO_SHORT":"Password too short","SHOW_ALL":"Show all","SHOW_LESS":"Show less","ITEMS_IN_ORDER":"Items in Order","SAVE_ADDRESS_ERROR":"An error occured and updates not saved. Save updates.","REMOVE_ADDRESS_ERROR":"Deleting address failed. Please try again.","UPDATE_DEFAULT_ADDRESS_ERROR":"Updating default address failed. Please try again.","EDIT_EMAIL_UPDATED":"Your email is being updated...","EDIT_EMAIL_SUCESSFULLY_UPDATED":"Email sucessfully updated","EDIT_EMAIL_CHANGED_MSG":"Your email has changed. You must sign in with your updated email","OOPS_MSG":"Oops!","EDIT_EMAIL_CHANGE_FAILED":"Something went wrong. Please reset your email again","RESET_EMAIL":"RESET EMAIL","EDIT_EMAIL_PASSWORD_NOT_CORRECT":"Password is not correct. Try again","EDIT_EMAIL_ALREADY_IN_USE":"This email is already in use. Try again","EDIT_EMAIL_SOMETHING_WENT_WRONG":"Something went wrong. Try again","FORGOT_PW":"Forgot your password?","PASSWORD":"Password","PASSWORD_MINCHAR":"Min. 6 characters","CONFIRM_PASSWORD":"Confirm Password","TOKEN":"Token","RESET_PASSWORD":"Reset Password","RESET_PW_TITLE":"Reset Your Password","RESET_PW_INSTRUCT":"Please create a new password.","FORGOT_PW_INSTRUCT":"Please enter your account email address below. An email will be sent to you with a link to reset your password.","REQUEST_PW_EXPIRED":"Reset Password Request Expired","REQUEST_PW_EXPIRED_MSG":"The request to reset your password has expired. Please enter your email to make a new request.","CHECK_EMAIL":"Check Your Email","CHECK_EMAIL_INSTRUCT":"...and follow the link to reset your password. The link will be valid for 24 hours.","CHECK_EMAIL_INSTRUCT_CHANGE_EMAIL":"...and follow the link to confirm change of your email. The link will be valid for 24 hours.","COOKIES_ENABLED_ERROR":"Cookies must be enabled in your browser to sign in. To find out more, see the Help or Preferences area of your browser. Once enabled, sign in.","CREATE_ACCOUNT_ERROR":"Customer account was created successfully, but cookies must be enabled to login. To find out more, see the Help or Preferences area of your browser. Once enabled, sign in.","PASSWORD_REQUIRED":"Password with 6 character minimum required.","PASSWORDS_MUST_MATCH":"Passwords must match.","PW_SUCCESS":"Success","PW_CHANGED_MSG":"Your password has been reset. You can now sign into your account.","INVALID_TOKEN":"This reset-password link is no longer valid. Please request a new one.","PW_CHANGE_FAILED":"Update of password failed.","RESET_PW_REPEAT":"Request another reset-password link.","FIELD_REQUIRED":"Field is required!","FIELD_TOO_SHORT":"Field too short!","FIELDS_NOT_MATCHING":"Fields not matching!","SERVER_UNAVAILABLE":"Server is unavailable, please try again later.","INVALID_CREDENTIALS":"You entered an invalid email or password.","PASSWORD_INVALID":"Password invalid - minimum of 6 characters required.","ACCOUNT_LOCKED":"Account has been locked due to excessive number of invalid login attempts. Please wait 5 minutes and try again.","ACCOUNT_ALREADY_EXISTS":"Email address already in use for existing account.","FORGOT_PASSWORD":"Forgot password?","EMAIL_NOT_FOUND":"There is no account associated with that email address.","ENTER_EMAIL":"Enter Email","ENTER_EXISTING_EMAIL":"Enter the email address of an existing account","LOGIN_FAILED":"Login failed","ACCOUNT_EMAIL":"Account Email","ERROR_TITLE":"Internal Error","ERROR_MESSAGE":"Oops! There's a problem.","ERROR_TITLE_401":"Unauthorized","ERROR_MESSAGE_401":"Oops! There's a problem. Your login credentials don't allow access to this page.","ERROR_TITLE_404":"Page not found","ERROR_MESSAGE_404":"Oops! There's a problem. This page doesn't exist.","ERROR_REDIRECT":"Here is a page to help you get back on track.","ERROR_BUTTON_TEXT":"HOMEPAGE","DR":"Dr.","MR":"Mr.","MRS":"Mrs.","MS":"Ms.","TITLE":"Title","COMPLETED":"Completed","CONFIRMED":"Confirmed","CREATED":"Created","DECLINED":"Cancelled","SHIPPED":"Shipped","CREDIT_CARD":"Credit Card","ON":"on","QUANTITY":"Quantity","SHIPPED_BY_ON":"Shipped by: {{carrier}} on {{shippedDate}}","TRACKING_NUMBER":"Tracking Number: {{trackingNumber}}","FOUND_FOR":"{{total}} found for {{searchString}}","SEARCH":"Search","SEARCH_RESULTS":"Search results","MOST_RELEVANT":"Most Relevant","RESULTS":"Results","SEE_ALL":"See All Results","SEARCH_UNAVAILABLE":"Search is currently unavailable.","NO_RESULTS_FOUND":"No results found.","IN":"in","TERMS_AND_CONDITIONS":"Terms & Conditions","CONTACT_US":"Contact Us","SITE_MAP":"Site Map"} \ No newline at end of file diff --git a/public/js/app/shared/router.js b/public/js/app/shared/router.js index d086f255f..20579eaf6 100644 --- a/public/js/app/shared/router.js +++ b/public/js/app/shared/router.js @@ -15,8 +15,8 @@ angular.module('ds.router', []) /** Sets up the routes for UI Router. */ - .config(['$stateProvider', '$urlRouterProvider', '$locationProvider', 'TranslationProvider', 'SiteConfigSvcProvider', - function($stateProvider, $urlRouterProvider, $locationProvider, TranslationProvider, siteConfig) { + .config(['$stateProvider', '$urlRouterProvider', '$locationProvider', + function($stateProvider, $urlRouterProvider, $locationProvider) { // States definition @@ -143,6 +143,34 @@ angular.module('ds.router', []) } }], + + variants: ['$stateParams', 'initialized', '$http', 'SiteConfigSvc', + function ($stateParams, initialized, $http, SiteConfigSvc) { + if (initialized) { + // $http used since 'option' property in response body is not handled correctly by Restangular + return $http.get(SiteConfigSvc.apis.products.baseUrl + '/products/' + $stateParams.productId + '/variants', { + params: { + pageNumber: 1, pageSize: 9999 + } + }).then(function (response) { + return response.data; + }); + } + }], + + variantPrices: ['$stateParams', 'initialized', '$http', 'SiteConfigSvc', 'GlobalData', + function ($stateParams, initialized, $http, SiteConfigSvc, GlobalData) { + if (initialized) { + return $http.get(SiteConfigSvc.apis.prices.baseUrl + '/prices', { + params: { + group: $stateParams.productId, + currency: GlobalData.getCurrencyId() + } + }).then(function (response) { + return response.data; + }); + } + }], lastCatId: function ($stateParams) { if($stateParams.lastCatId !== 'lastCatId') { @@ -153,9 +181,9 @@ angular.module('ds.router', []) } }, - shippingZones: ['ShippingSvc', 'initialized', 'GlobalData', function (ShippingSvc, initialized, GlobalData) { + shippingZones: ['ShippingSvc', 'initialized', function (ShippingSvc, initialized) { if(initialized){ - return ShippingSvc.getSiteShippingZones(GlobalData.getSiteCode()); + return ShippingSvc.getSiteShippingZones(); } }] @@ -176,11 +204,6 @@ angular.module('ds.router', []) order: ['CheckoutSvc', function (CheckoutSvc) { return CheckoutSvc.getDefaultOrder(); }], - shippingCountries: ['ShippingSvc', 'initialized', function (ShippingSvc, initialized) { - if (initialized) { // parent resolve - if-check to make usage explicit - return ShippingSvc.getShipToCountries(); - } - }], shippingZones: ['ShippingSvc', 'initialized', function (ShippingSvc, initialized) { if (initialized) { return ShippingSvc.getSiteShippingZones(); @@ -237,11 +260,7 @@ angular.module('ds.router', []) return AccountSvc.account(); }], addresses: ['AccountSvc', function(AccountSvc) { - var query = { - pageNumber: 1, - pageSize: siteConfig.apis.account.addresses.initialPageSize - }; - return AccountSvc.getAddresses(query).then( + return AccountSvc.getAddresses().then( function (response) { return response; }, diff --git a/public/js/app/shared/site-config.js b/public/js/app/shared/site-config.js index 0b5798e28..75092b77f 100644 --- a/public/js/app/shared/site-config.js +++ b/public/js/app/shared/site-config.js @@ -76,7 +76,7 @@ angular.module('ds.shared') }, products: { - baseUrl: 'https://' + apiPath + '/hybris/product/v1/' + tenantId, + baseUrl: 'https://' + apiPath + '/hybris/product/v2/' + tenantId, pageSize: 10 }, diff --git a/public/js/app/shared/templates/ysearch.html b/public/js/app/shared/templates/ysearch.html index 20955e37a..569c68a2f 100644 --- a/public/js/app/shared/templates/ysearch.html +++ b/public/js/app/shared/templates/ysearch.html @@ -20,8 +20,9 @@
{{'SEE_ALL' | translate}} {{search.numberOfHits}} - {{'RESULTS' | translate}} + ui-sref="base.search({ searchString:search.text })">{{'SEE_ALL' | translate}} ({{search.numberOfHits}}) + +
{{'SEARCH_UNAVAILABLE' | translate}}
diff --git a/public/js/app/shipping/services/shipping-service.js b/public/js/app/shipping/services/shipping-service.js index 618d58ee7..7f3ab3959 100644 --- a/public/js/app/shipping/services/shipping-service.js +++ b/public/js/app/shipping/services/shipping-service.js @@ -19,24 +19,16 @@ angular.module('ds.checkout') .factory('ShippingSvc', ['ShippingREST', '$q', 'GlobalData', function (ShippingREST, $q, GlobalData) { - var getShipToCountries = function () { - var deferred = $q.defer(); - var shippingZones; - var site = GlobalData.getSiteCode(); + var getShipToCountries = function (zones) { var shipToCountries = []; - ShippingREST.ShippingZones.all(site).all('zones').getList({ expand: 'methods', activeMethods: true}).then(function(zones){ - shippingZones = zones.length ? zones.plain() : []; - for (var i = 0; i < shippingZones.length; i++) { - for (var j = 0; j < shippingZones[i].shipTo.length; j++) { - if (shipToCountries.indexOf(shippingZones[i].shipTo[j]) < 0) { - shipToCountries.push(shippingZones[i].shipTo[j]); - } + for (var i = 0; i < zones.length; i++) { + for (var j = 0; j < zones[i].shipTo.length; j++) { + if (shipToCountries.indexOf(zones[i].shipTo[j]) < 0) { + shipToCountries.push(zones[i].shipTo[j]); } } - deferred.resolve(shipToCountries); - }); - - return deferred.promise; + } + return shipToCountries; }; var getSiteShippingZones = function () { @@ -51,16 +43,25 @@ angular.module('ds.checkout') return deferred.promise; }; - var getMinimumShippingCost = function (item) { - var deferred = $q.defer(); - var site = GlobalData.getSiteCode(); - var minCost; - ShippingREST.ShippingZones.one(site).one('quote').all('minimum').post(item).then(function(result){ - minCost = result.plain(); - deferred.resolve(minCost); - }); - - return deferred.promise; + var getMinimumShippingCost = function (costs) { + var zoneId; + var minObject = {}; + var minValue; + for (var i = 0; i < costs.length; i++) { + zoneId = costs[i].zone.id; + for (var j = 0; j < costs[i].methods.length; j++) { + if (!minValue || costs[i].methods[j].fee.amount < minValue) { + minValue = costs[i].methods[j].fee.amount; + minObject = { + fee: costs[i].methods[j].fee, + id: costs[i].methods[j].id, + name: costs[i].methods[j].name, + zoneId: zoneId + }; + } + } + } + return minObject; }; var getShippingCosts = function (item) { @@ -88,8 +89,8 @@ angular.module('ds.checkout') return { - getShipToCountries: function () { - return getShipToCountries(); + getShipToCountries: function (zones) { + return getShipToCountries(zones); }, getSiteShippingZones: function () { diff --git a/public/less/_account.less b/public/less/_account.less index 264a76b54..d62299ae9 100644 --- a/public/less/_account.less +++ b/public/less/_account.less @@ -219,6 +219,12 @@ float: none; } } + + .cancel-order { + @media screen and (max-width: @screen-xs-max) { + width: 100%; + } + } .desktopUserInfo{ margin-top: 40px; @@ -229,6 +235,9 @@ border-top: 1px solid #e5e5e5; padding-top: 30px; padding-bottom: 75px; + a { + cursor: pointer; + } } .desktopUserInfo.userInfoRow{ @@ -277,22 +286,24 @@ } + .panel{ + height: 183px; + } } .default-address .contactName{ font-weight: bold; } - +.addresses div[address-decorator] > div:not(.disableAddress){ + cursor: pointer; +} .disableAddress { - background-color: lightgrey; - } + background-color: lightgrey; + cursor: not-allowed; +} .default-address .defaultLabel{ color:#016aab; } -.panel{ - height: 183px; - -} .panel.defaultAddress{ border: 1px solid #016aab; diff --git a/public/less/_cart.less b/public/less/_cart.less index 30dc690a7..da10e774d 100644 --- a/public/less/_cart.less +++ b/public/less/_cart.less @@ -58,6 +58,7 @@ } /* CART ITEM */ + .cart-item{ border-bottom: 1px solid @grey-border; padding-bottom: 20px; @@ -67,6 +68,10 @@ margin: 0; } + .item-attr .priceUnit { + font-size: 80%; + } + /* QTY SELECTOR */ .input-group{ max-width: 145px; @@ -117,7 +122,7 @@ .item-attr{ color: @darkergrey; - span{ + span:not(.priceUnit){ font-size: 16px; color: @darkestgrey; } diff --git a/public/less/_global.less b/public/less/_global.less index c8132d8e4..814b51520 100644 --- a/public/less/_global.less +++ b/public/less/_global.less @@ -42,6 +42,9 @@ table .error{ } } +a{ + cursor: pointer; +} // GET RID OF THE SPINNER IN INPUT TYPE NUMBER @@ -222,6 +225,7 @@ section{ } .priceUnit{ + text-transform: none; font-weight: 200; font-size: 80%; color: #202122; diff --git a/public/less/_pdp.less b/public/less/_pdp.less index bcbcb3df9..fe498f05a 100644 --- a/public/less/_pdp.less +++ b/public/less/_pdp.less @@ -43,6 +43,10 @@ .taxMessage{ margin: 0 0 20px 0; + word-wrap: break-word; + a { + text-transform: lowercase; + } } .quantity{ @@ -56,6 +60,39 @@ } } + .product-options{ + + .input-group{ + width: 100% !important; + height: 48px; + border-left-width: 0; + padding: 0; + box-shadow: 0 0 0; + } + + .input-group-addon{ + min-width: 100px; + text-align: left; + text-transform: uppercase; + padding:15px; + } + + .form-control{ + height: 48px; + font-weight: bold; + } + + .ui-select-placeholder{ + opacity: .5; + font-weight: normal; + } + + .quantity{ + width: 100%; + } + + } + .cartPanel{ .shipping-rate{ a{ @@ -148,6 +185,10 @@ } } + + .product-extension-item { + padding: 10px; + } } .product-gallery{ diff --git a/public/less/_product-img-carousel.less b/public/less/_product-img-carousel.less index 3f26ab31b..e1db62288 100644 --- a/public/less/_product-img-carousel.less +++ b/public/less/_product-img-carousel.less @@ -1,5 +1,5 @@ .image-carousel img{ - max-width: 100%; + width: 100%; } .product-image { position: absolute; diff --git a/static-manifest.yml b/static-manifest.yml index 536a32ad3..062b9813c 100644 --- a/static-manifest.yml +++ b/static-manifest.yml @@ -5,4 +5,4 @@ applications: memory: 64M host: store-template-simple instances: 1 - path: dist \ No newline at end of file + path: dist/public \ No newline at end of file diff --git a/test/e2e/account/account.po.js b/test/e2e/account/account.po.js new file mode 100644 index 000000000..fab79be60 --- /dev/null +++ b/test/e2e/account/account.po.js @@ -0,0 +1,320 @@ +'use strict'; + +var utils = require('../utils/utils.js'); + +var AccountPageObject = function () { + + var inputFields = { + contactName: element(by.id('contactName')), + street: element(by.id('street')), + streetAppendix: element(by.id('streetAppendix')), + city: element(by.id('city')), + zipCode: element(by.id('zipCode')), + contactPhone: element(by.id('contactPhone')), + loginUser: { + username: element(by.id('usernameInput')), + password: element(by.id('passwordInput')) + }, + createUser: { + username: element(by.id('emailInput')), + password: element(by.id('newPasswordInput')) + }, + state: element(by.id('state')), + accountDetails: { + firstNameElements: element.all(by.model('account.firstName')), + middleName: element(by.id('middleNameAccount')), + lastNameElements: element.all(by.model('account.lastName')), + currentPassword: element(by.id('currentPassword')), + newPassword: element(by.id('newPassword')), + newPasswordConfirm: element(by.id('confirmNewPassword')), + newEmail: element(by.id('newEmail')), + newEmailPassword: element(by.id('password')) + } + }; + + var buttons = { + signInMobile: element(by.css('.mobileNav .signin')), + signInDesktop: element(by.id('sign-in-button')), + createAccount: element(by.id('create-acct-btn')), + logout: element(by.id('logout-btn')), + editUserInfo: element(by.id('edit-user-info')), + saveUserInfo: element(by.id('save-btn')), + accountDetails: { + updatePassword: element(by.id('update-password')), + view: element(by.id('my-account-link')), + updateToNewPassword: element(by.id('update-password-btn')), + passwordUpdateModalClose: element(by.id('passwordUpdate-close')), + updateEmail: element(by.id('update-email')), + saveEmail: element(by.id('save-btn')) + }, + address: { + add: element(by.id('add-address-btn')), + save: element(by.id('save-address-btn')), + setDefault: element(by.id("set-default-btn")), + delete: element(by.id("delete-address-btn")), + confirmDelete: element(by.id("confirm-delete-address-btn")) + } + }; + + var links = { + signIn: element(by.id('login-btn')), + createAccount: element(by.id('create-account')) + }; + + var textDisplays = { + contactEmail: element(by.id("account-contact-email")), + errorMessage: element(by.binding("error.message")), + accountDetails: { + fullName: element(by.id('account-name')), + firstName: element(by.binding("account.firstName")), + middleName: element(by.binding("account.middleName")), + lastName: element(by.binding("account.lastName")) + }, + modalContent: element(by.css('.modal-content')), + checkEmailModal: element(by.binding('CHECK_EMAIL')) + }; + + var dropdowns = { + account: element(by.id('my-account-dropdown')), + country: element(by.model('address.country')) + }; + + + this.getAccountModalErrorMessage = function() { + return textDisplays.errorMessage.getText(); + }; + + var orderRowElement = function(elem,rowNumber) { + return element(by.repeater('orderRow in orders').row(rowNumber).column('orderRow.' + elem)); + }; + + this.orderRow = { + getCreationDate: function(rowNumber) { + return orderRowElement('created',rowNumber).getText(); + }, + + getTotalPrice: function(rowNumber) { + return orderRowElement('totalPrice',rowNumber).getText(); + }, + + getOrderStatus: function(rowNumber) { + return orderRowElement('status',rowNumber).getText().getText(); + } + }; + + var addressElement = function(elem,rowNumber) { + return element.all(by.repeater('address in addresses').row(rowNumber).column('address.' + elem)).first(); + }; + + var address = { + getStreet: function(rowNumber) { + return addressElement('street',rowNumber).getText(); + }, + waitForModal: function() { + browser.wait(function () { + return textDisplays.modalContent.isPresent(); + }); + }, + getCity: function(rowNumber) { + return addressElement('city',rowNumber).getText(); + }, + getCountry: function(rowNumber) { + return addressElement('country',rowNumber).getText(); + }, + getContactName: function(rowNumber) { + return addressElement('contactName',rowNumber).getText(); + }, + getContactPhone: function(rowNumber) { + return addressElement('contactPhone',rowNumber).getText(); + }, + setDefault: function() { + buttons.address.setDefault.click(); + }, + waitForDeleteButton: function() { + browser.wait(function() { + return buttons.address.delete.isPresent(); + }); + }, + isDeleteButtonPresent: function () { + return buttons.address.delete.isPresent(); + } + }; + + address.delete = function() { + buttons.address.delete.click(); + browser.switchTo().defaultContent(); + address.waitForModal(); + buttons.address.confirmDelete.click(); + }; + + this.address = address; + + this.populateAddress = function(address) { + buttons.address.add.click(); + + browser.sleep(300); + + var selectSort = dropdowns.country.element(by.css('.ui-select-search')); + dropdowns.country.click(); + selectSort.clear(); + selectSort.sendKeys(address.country); + element.all(by.css('.ui-select-choices-row-inner span')).first().click(); + + inputFields.contactName.clear(); + inputFields.contactName.sendKeys(address.contactName); + + inputFields.street.clear(); + inputFields.street.sendKeys(address.street); + + inputFields.streetAppendix.clear(); + inputFields.streetAppendix.sendKeys(address.aptNumber); + + inputFields.city.clear(); + inputFields.city.sendKeys(address.city); + + if ((address.country == 'United States') || (address.country == 'Canada')) { + utils.selectOption('address.state',address.state) + } else { + inputFields.state.sendKeys(address.state); + } + + inputFields.zipCode.clear(); + inputFields.zipCode.sendKeys(address.zipCode); + + inputFields.contactPhone.clear(); + inputFields.contactPhone.sendKeys(address.contactPhone); + + buttons.address.save.click(); + }; + + + this.createAccount = function (user,openModal) { + var timestamp = Number(new Date()); + + if(openModal === true) { + links.signIn.click(); + this.waitForSignInForm(); + links.createAccount.click(); + } + + inputFields.createUser.username.clear(); + inputFields.createUser.username.sendKeys(user.name + timestamp + '@yaastest.com'); + inputFields.createUser.password.clear(); + inputFields.createUser.password.sendKeys(user.password); + + buttons.createAccount.click(); + + browser.waitForAngular(); + }; + + this.accountDetails = { + getPage: function() { + dropdowns.account.click(); + buttons.accountDetails.view.click(); + }, + getFullName: function() { + return textDisplays.accountDetails.fullName.getText(); + }, + getContactEmail: function () { + return textDisplays.contactEmail.getText(); + }, + closePasswordUpdateModal: function () { + buttons.accountDetails.passwordUpdateModalClose.click(); + }, + updatePassword: function (passwordUpdate) { + buttons.accountDetails.updatePassword.click(); + + inputFields.accountDetails.currentPassword.clear(); + inputFields.accountDetails.currentPassword.sendKeys(passwordUpdate.current); + + inputFields.accountDetails.newPassword.clear(); + inputFields.accountDetails.newPassword.sendKeys(passwordUpdate.new); + + inputFields.accountDetails.newPasswordConfirm.clear(); + inputFields.accountDetails.newPasswordConfirm.sendKeys(passwordUpdate.confirm); + }, + + clickUpdatePasswordButton: function () { + buttons.accountDetails.updateToNewPassword.click(); + browser.waitForAngular(); + }, + + updateEmail: function (newEmail,password) { + buttons.accountDetails.updateEmail.click(); + + inputFields.accountDetails.newEmail.clear(); + inputFields.accountDetails.newEmail.sendKeys(newEmail); + + inputFields.accountDetails.newEmailPassword.clear(); + inputFields.accountDetails.newEmailPassword.sendKeys(password); + + buttons.accountDetails.saveEmail.click(); + }, + + isCheckEmailModalPresent: function() { + return textDisplays.checkEmailModal.isPresent(); + }, + + closeCheckEmailModal: function () { + browser.refresh(); + }, + + isUpdatePasswordButtonEnabled: function () { + return buttons.accountDetails.updateToNewPassword.isEnabled(); + }, + editDetails: function(name) { + buttons.editUserInfo.click(); + + inputFields.accountDetails.firstNameElements.first().clear(); + inputFields.accountDetails.firstNameElements.last().click(); //To get around the validation + inputFields.accountDetails.firstNameElements.first().sendKeys(name.first); + + inputFields.accountDetails.middleName.clear(); + inputFields.accountDetails.middleName.sendKeys(name.middle); + + inputFields.accountDetails.lastNameElements.first().clear(); + inputFields.accountDetails.lastNameElements.last().click(); //To get around the validation + inputFields.accountDetails.lastNameElements.first().sendKeys(name.last); + + buttons.saveUserInfo.click(); + } + }; + + this.waitForSignInComplete = function() { + browser.wait(function () { + return dropdowns.account.isPresent(); + }); + }; + + this.logoutUser = function() { + dropdowns.account.click(); + buttons.logout.click(); + }; + + this.loginUser = function (user) { + links.signIn.click(); + + this.waitForSignInForm(); + + inputFields.loginUser.username.clear(); + inputFields.loginUser.username.sendKeys(user.username); + inputFields.loginUser.password.clear(); + inputFields.loginUser.password.sendKeys(user.password); + + buttons.signInDesktop.click(); + }; + + this.waitForSignInLink = function () { + browser.wait(function () { + return links.signIn.isPresent(); + }); + }; + + this.waitForSignInForm = function () { + browser.wait(function () { + return buttons.signInDesktop.isPresent(); + }); + }; +}; + +module.exports = AccountPageObject; \ No newline at end of file diff --git a/test/e2e/account/account.spec.js b/test/e2e/account/account.spec.js new file mode 100644 index 000000000..26f34bdda --- /dev/null +++ b/test/e2e/account/account.spec.js @@ -0,0 +1,221 @@ +'use strict'; + +var desktopSiteConfig = require('../config/desktop-site.json'); + +var TI = require('./account.test-input.json'); +var utils = require('../utils/utils.js'); +var AccountPageObject = require('./account.po.js'); +var SitePageObject = require('../site/site.po.js'); + + +describe('account:', function() { + + var accountPO, + sitePO; + + var testUsers = TI.users; + + describe('verify login functionality', function() { + + beforeEach(function() { + utils.deleteCookies(); + utils.setWindowSize(desktopSiteConfig.windowDetails.width, desktopSiteConfig.windowDetails.height); + + accountPO = new AccountPageObject(); + sitePO = new SitePageObject(); + + sitePO.getHomePage(); + }); + + it('should not allow invalid user to login', function() { + accountPO.loginUser(testUsers.bad); + expect(accountPO.getAccountModalErrorMessage()).toEqual(TI.errorMessages.INVALIDUSER.EN); + }); + + it('should allow an existing user to login', function() { + accountPO.loginUser(testUsers.cool); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + expect(accountPO.accountDetails.getFullName()).toContain(testUsers.cool.name.full); + }); + + it('should allow user to update account info', function() { + accountPO.loginUser(testUsers.cool); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + expect(accountPO.accountDetails.getFullName()).toContain(testUsers.cool.name.full); + + accountPO.accountDetails.editDetails(testUsers.cool.alternateName); + + expect(accountPO.accountDetails.getFullName()).toContain(testUsers.cool.alternateName.full); + + accountPO.accountDetails.editDetails(testUsers.cool.name); + + expect(accountPO.accountDetails.getFullName()).toContain(testUsers.cool.name.full); + }); + + it('should be able to create a new user', function() { + accountPO.createAccount(testUsers.bad,true); + + expect(accountPO.getAccountModalErrorMessage()).toEqual(TI.errorMessages.WEAKPASSWORD.EN); + + var newUser = { + name: 'cool', + password: 'coolio' + }; + + accountPO.createAccount(newUser,false); + + accountPO.accountDetails.getPage(); + + expect(accountPO.accountDetails.getContactEmail()).toContain(newUser.name); + + }); + + it('should allow existing user to manage addresses', function() { + accountPO.createAccount(testUsers.addressTest,true); + + accountPO.accountDetails.getPage(); + + accountPO.populateAddress(testUsers.addressTest.address1); + + expect(accountPO.address.getStreet(0)).toEqual(testUsers.addressTest.address1.street + ', ' + + testUsers.addressTest.address1.aptNumber); + + expect(accountPO.address.getCity(0)).toEqual(testUsers.addressTest.address1.cityStateZipCode); + expect(accountPO.address.getCountry(0)).toEqual(testUsers.addressTest.address1.countryAcronym); + expect(accountPO.address.getContactPhone(0)).toEqual(testUsers.addressTest.address1.contactPhone); + + accountPO.populateAddress(testUsers.addressTest.address2); + + expect(accountPO.address.getContactName(1)).toEqual(testUsers.addressTest.address2.contactName); + expect(accountPO.address.getStreet(1)).toEqual(testUsers.addressTest.address2.street + ', ' + + testUsers.addressTest.address2.aptNumber); + expect(accountPO.address.getCity(1)).toEqual(testUsers.addressTest.address2.cityStateZipCode); + expect(accountPO.address.getCountry(1)).toEqual(testUsers.addressTest.address2.countryAcronym); + expect(accountPO.address.getContactPhone(1)).toEqual(testUsers.addressTest.address2.contactPhone); + + accountPO.address.setDefault(); + + expect(accountPO.address.getStreet(0)).toEqual(testUsers.addressTest.address2.street + ', ' + + testUsers.addressTest.address2.aptNumber); + + accountPO.address.setDefault(); + + expect(accountPO.address.getStreet(0)).toEqual(testUsers.addressTest.address1.street + ', ' + + testUsers.addressTest.address1.aptNumber); + + accountPO.address.delete(); + + // Confirm delete address + accountPO.address.waitForDeleteButton(); + + accountPO.address.delete(); + + // Confirm delete address + expect(accountPO.address.isDeleteButtonPresent()).toBe(false); + }); + + it('should not allow user to update password with an incorrect original password', function() { + accountPO.loginUser(testUsers.cool); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + accountPO.accountDetails.updatePassword(TI.passwordTestVectors.vector1); + + accountPO.accountDetails.clickUpdatePasswordButton(); + + expect(accountPO.getAccountModalErrorMessage()).toEqual(TI.errorMessages.WRONGPASSWORD.EN); + }); + + it('should not allow user to update their password if it less than 6 chars', function() { + accountPO.loginUser(testUsers.cool); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + accountPO.accountDetails.updatePassword(TI.passwordTestVectors.vector2); + + expect(accountPO.accountDetails.isUpdatePasswordButtonEnabled()).toBe(false); + }); + + it('should not allow user to update their password if it does not match confirmation', function() { + accountPO.loginUser(testUsers.cool); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + accountPO.accountDetails.updatePassword(TI.passwordTestVectors.vector3); + + expect(accountPO.accountDetails.isUpdatePasswordButtonEnabled()).toBe(false); + }); + + it('should allow user to update their password provided the new password is valid', function() { + accountPO.loginUser(testUsers.cool); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + accountPO.accountDetails.updatePassword(TI.passwordTestVectors.vector4); + + accountPO.accountDetails.clickUpdatePasswordButton(); + + accountPO.logoutUser(); + + var coolUser = { + username: testUsers.cool.username, + password: 'password' + }; + + accountPO.loginUser(coolUser); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + accountPO.accountDetails.updatePassword(TI.passwordTestVectors.vector5); + + accountPO.accountDetails.clickUpdatePasswordButton(); + }); + + it('should allow user to update their email', function() { + accountPO.loginUser(testUsers.cool); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + accountPO.accountDetails.updateEmail(testUsers.cool.newEmail, testUsers.cool.password); + + expect(accountPO.accountDetails.isCheckEmailModalPresent()).toBe(true); + + accountPO.accountDetails.closeCheckEmailModal(); + + accountPO.logoutUser(); + + // Verify the user still can login in with the old email, as the new one was not confirmed + accountPO.loginUser(testUsers.cool); + + accountPO.waitForSignInComplete(); + + accountPO.accountDetails.getPage(); + + expect(accountPO.accountDetails.getContactEmail()).toContain(testUsers.cool.username); + + }); + + }); + +}); + diff --git a/test/e2e/account/account.test-input.json b/test/e2e/account/account.test-input.json new file mode 100644 index 000000000..8681fb604 --- /dev/null +++ b/test/e2e/account/account.test-input.json @@ -0,0 +1,99 @@ +{ + "users": { + "bad": { + "username": "bad@bad.com", + "email": "bad@bad.com", + "name":"bad", + "password": "bad" + }, + + "addressTest": { + "name": "addresstest", + "password": "password", + "address1": { + "countryAcronym": "US", + "country": "United States", + "contactName": "Address Test", + "street": "123 fake place", + "aptNumber": "apt 419", + "city": "Boulder", + "state": "CO", + "zipCode": "80301", + "cityStateZipCode": "Boulder, CO 80301", + "contactPhone": "303-303-3333" + }, + "address2": { + "countryAcronym": "CA", + "country": "Canada", + "contactName": "2nd Test", + "street": "321 phony street", + "aptNumber": "apt 420", + "city": "Toronto", + "state": "ON", + "zipCode": "M4M 1H7", + "cityStateZipCode": "Toronto, ON M4M 1H7", + "contactPhone": "720-555-1234" + } + }, + + "cool": { + "username": "cool@cool.com", + "newEmail": "cool_new@yaastest.com", + "password": "coolio", + "name": { + "full": "Joe C Cool", + "first": "Joe", + "middle": "C", + "last": "Cool" + }, + + "alternateName": { + "full": "first middle last", + "first": "first", + "middle": "middle", + "last": "last" + } + } + }, + + "passwordTestVectors": { + "vector1": { + "current": "incorrect", + "new": "notnew", + "confirm": "notnew" + }, + "vector2": { + "current": "coolio", + "new": "123", + "confirm": "123" + }, + "vector3": { + "current": "coolio", + "new": "incorrect1", + "confirm": "incorrect2" + }, + "vector4": { + "current": "coolio", + "new": "password", + "confirm": "password" + }, + "vector5": { + "current": "password", + "new": "coolio", + "confirm": "coolio" + } + }, + + "errorMessages": { + "INVALIDUSER": { + "EN": "You entered an invalid email or password." + }, + "WEAKPASSWORD": { + "EN": "Password invalid - minimum of 6 characters required." + }, + + "WRONGPASSWORD": { + "EN": "Please provide correct current password!" + } + } +} \ No newline at end of file diff --git a/test/e2e/cart-tests.js b/test/e2e/cart-tests.js deleted file mode 100644 index 981fd97d1..000000000 --- a/test/e2e/cart-tests.js +++ /dev/null @@ -1,205 +0,0 @@ -var fs = require('fs'); -var tu = require('./protractor-utils.js'); - -describe("cart:", function () { - - beforeEach(function () { - browser.manage().deleteAllCookies(); - // ENSURE WE'RE TESTING AGAINST THE FULL SCREEN VERSION - browser.driver.manage().window().setSize(1200, 1100); - browser.get(tu.tenant + '/#!/ct/'); - // browser.switchTo().alert().then( - // function (alert) { alert.dismiss(); }, - // function (err) { } - // ); - }); - - afterEach(function () { - //dismisses any alerts left open - browser.switchTo().alert().then( - function (alert) { - alert.dismiss(); - }, - function (err) { - } - ); - }); - - describe("verify cart functionality", function () { - - - it('should load one product into cart', function () { - tu.loadProductIntoCartAndVerifyCart('1', '$20.62'); - tu.clickElement('id', tu.removeFromCart); - browser.wait(function () { - return element(by.xpath("//*[@id='cart']/div/div[2]")).isDisplayed(); //checks to see if cart text is displayed - }); - expect(element(by.xpath("//*[@id='cart']/div/div[2]")).getText()).toEqual('YOUR CART IS EMPTY'); - }); - - it('should load one product into cart in Euros', function () { - browser.wait(function () { - return element(by.xpath(tu.whiteCoffeeMug)).isPresent(); - }); - browser.sleep(500); - tu.clickElement('xpath', tu.whiteCoffeeMug); - tu.switchSite('Sushi Demo Store Germany'); - var category = element(by.repeater('top_category in categories').row(1).column('top_category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - tu.loadProductIntoCartAndVerifyCart('1', '€12.99'); - tu.clickElement('id', tu.removeFromCart); - browser.wait(function () { - return element(by.xpath("//div[@id='cart']/div/div[2]")).isDisplayed(); - }); - expect(element(by.xpath("//div[@id='cart']/div/div[2]")).getText()).toEqual('IHR WARENKORB IST LEER'); - }); - - it('should load one product into cart in USD and change to Euros', function () { - tu.loadProductIntoCartAndVerifyCart('1', '$20.62'); - tu.clickElement('binding', 'CONTINUE_SHOPPING'); - browser.sleep(1000); - tu.switchSite('Sushi Demo Store Germany'); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(1000); - tu.verifyCartTotal('€12.99'); - }); - - it('should load multiple products into cart', function () { - tu.loadProductIntoCartAndVerifyCart('1', '$20.62'); - tu.clickElement('binding', 'CONTINUE_SHOPPING'); - // must hover before click - var category = element(by.repeater('top_category in categories').row(1).column('top_category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - browser.wait(function () { - return element(by.xpath(tu.whiteThermos)).isDisplayed(); - }); - tu.clickElement('xpath', tu.whiteThermos); - browser.sleep(200); - tu.clickElement('id', tu.buyButton); - browser.sleep(5500); - browser.wait(function () { - return element(by.id(tu.cartButtonId)).isDisplayed(); - }); - browser.sleep(1000); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(500); - tu.verifyCartTotal("$36.66"); - }); - - - it('should update quantity', function () { - tu.loadProductIntoCartAndVerifyCart('1', '$20.62'); - tu.clickElement('binding', 'CONTINUE_SHOPPING'); - browser.sleep(250); - tu.clickElement('id', tu.buyButton); - browser.sleep(5000); - browser.wait(function () { - return element(by.id(tu.cartButtonId)).isDisplayed(); - }); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(1000); - tu.verifyCartAmount('2'); - browser.sleep(2000); - tu.verifyCartTotal('$32.04'); - tu.sendKeys('xpath', tu.cartQuantity, '5'); - tu.clickElement('binding', 'EST_ORDER_TOTAL'); - browser.sleep(1000); - tu.clickElement('binding', 'EST_ORDER_TOTAL'); - browser.sleep(1000); - tu.verifyCartAmount("5"); - tu.verifyCartTotal("$60.28"); - tu.sendKeys('xpath', tu.cartQuantity, '10'); - tu.clickElement('binding', 'EST_ORDER_TOTAL'); - browser.sleep(1000); - tu.clickElement('binding', 'EST_ORDER_TOTAL'); - browser.sleep(1000); - tu.verifyCartAmount("10"); - tu.verifyCartTotal("$115.24"); - }); - - it('should have out of stock button disabled', function () { - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - expect(element(by.binding('CART_EMPTY')).getText()).toEqual('YOUR CART IS EMPTY'); - tu.clickElement('binding', 'CONTINUE_SHOPPING'); - browser.wait(function () { - return element(by.xpath(tu.blackCoffeeMug)).isDisplayed(); - }); - tu.clickElement('xpath', tu.blackCoffeeMug); - browser.wait(function () { - return element(by.id('out-of-stock-btn')).isDisplayed(); - }); - - var outOfOrder = element(by.id('out-of-stock-btn')); - expect(outOfOrder.isEnabled()).toBe(false); - - }); - - it('should retrieve previous cart', function () { - tu.loginHelper('cart@hybristest.com', 'password'); //existing user with previous cart - tu.clickElement('id', tu.cartButtonId); - browser.sleep(250); - tu.verifyCartTotal('$13.47'); - }); - - it('should calculate taxes', function () { - browser.wait(function () { - return element(by.xpath(tu.whiteCoffeeMug)).isPresent(); - }); - browser.sleep(500); - tu.clickElement('xpath', tu.whiteCoffeeMug); - tu.switchSite('Avalara'); - var category = element(by.repeater('top_category in categories').row(1).column('top_category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - tu.loadProductIntoCartAndVerifyCart('1', '$10.67'); - tu.clickElement('binding', 'ESTIMATE_TAX'); - tu.sendKeys('id', 'zipCode', '98101'); - tu.selectOption('calculateTax.countryCode', 'US'); - tu.clickElement('id', 'apply-btn'); - //expect(element(by.binding('cart.totalTax.amount ')).getText()).toEqual('$1.85'); - expect(element(by.binding('cart.totalTax.amount ')).isPresent()).toBe(true); - - }); - - it('should add and modify the note in cart item after adding an item to cart', function () { - var noteText = "The item should be gift wrapped"; - tu.loadProductIntoCartAndVerifyCart('1', '$20.62'); - tu.clickElement('id', 'addEditNote'); - tu.sendKeys('id', 'cartItemNote', noteText); - tu.clickElement('id', 'saveCartItemNote'); - - browser.wait(function () { - return element(by.id('addEditNote')).isDisplayed(); - }); - - tu.clickElement('id', 'addEditNote'); - tu.sendKeys('id', 'cartItemNote', noteText + ",please."); - tu.clickElement('id', 'saveCartItemNote'); - browser.wait(function () { - return element(by.id('addEditNote')).isDisplayed(); - }); - //expect(element(by.binding('item.mixins.note.comment')).getText()).toEqual(noteText + ",please."); - expect(element(by.css('.note-display.ng-binding')).getText()).toEqual(noteText + ",please."); - }); - - xit('should automatically close when mousing off', function () { - tu.loadProductIntoCartAndVerifyCart('1', '$10.67'); - browser.driver.actions().mouseMove(element(by.binding('item.product.name'))).perform(); - // wait over 3 seconds - browser.sleep(4500); - browser.driver.actions().mouseMove(element(by.css('div.content-mask'))).perform(); - expect(element(by.binding('CONTINUE_SHOPPING')).isDisplayed()).toBe(false); - }); - - }); -}); - diff --git a/test/e2e/cart/cart.po.js b/test/e2e/cart/cart.po.js new file mode 100644 index 000000000..37a27f4e3 --- /dev/null +++ b/test/e2e/cart/cart.po.js @@ -0,0 +1,164 @@ +'use strict'; + +var utils = require('../utils/utils.js'); + +var CartPageObject = function () { + + var buttons = { + removeCartItem: element(by.id('remove-product')), + showCart: element(by.id('full-cart-btn')), + continueShopping: element(by.id('continue-shopping')), + checkout: element(by.binding('CHECKOUT')), + guestContinue: element(by.id('guest-continue')), + showCartMobile: element(by.id('mobile-cart-btn')), + outOfStock: element(by.id('out-of-stock-btn')), + applyTax: element(by.id('apply-btn')), + saveCartItemNote: element(by.id('saveCartItemNote')) + }; + + var textDisplays = { + cartTotal: element(by.binding('cart.totalPrice.amount')), + cartDiscount: element(by.css('#cart .discount')), + cartQuantity: element(by.xpath("(//input[@type='number'])[2]")), + cartMessage: element(by.xpath("//*[@id='cart']/div/div[2]")), + taxOverride: element(by.repeater('taxLine in cart.taxAggregate.lines').row(1)), + orderEstimatedTotal: element(by.binding('EST_ORDER_TOTAL')), + totalTax: element(by.id('total-tax')) + }; + + var inputFields = { + cartQuantity: element(by.id('qtyCart')), + taxZipCode: element(by.id('zipCode')), + cartItemNote: element(by.id('cartItemNote')) + }; + + var links = { + estimateTax: element(by.id('tax-estimation-link')), + addEditNote: element(by.id('addEditNote')) + }; + + this.addNote = function (noteText) { + links.addEditNote.click(); + inputFields.cartItemNote.clear(); + inputFields.cartItemNote.sendKeys(noteText); + buttons.saveCartItemNote.click(); + }; + + this.getItemNote = function () { + return element(by.css('.note-display.ng-binding')).getText(); + }; + + this.setTaxCountry = function(country) { + utils.selectOption('calculateTax.countryCode', country); + }; + + this.isTotalTaxPresent = function() { + return textDisplays.totalTax.isPresent(); + }; + + this.showEstimateTaxFields = function () { + links.estimateTax.click(); + }; + + this.applyTax = function () { + buttons.applyTax.click(); + }; + + this.isOutOfStockButtonPresent = function () { + return buttons.outOfStock.isPresent() + }; + + this.setTaxZipCode = function(zipCode) { + inputFields.taxZipCode.clear(); + inputFields.taxZipCode.sendKeys(zipCode); + }; + + this.waitForGoToCheckoutModal = function() { + browser.wait(function () { + return buttons.guestContinue.isPresent(); + }); + }; + + this.goToCheckout = function (isLoggedIn) { + buttons.checkout.click(); + if(!isLoggedIn) { + this.waitForGoToCheckoutModal(); + buttons.guestContinue.click(); + } + }; + + this.updateOrderTotal = function () { + textDisplays.orderEstimatedTotal.click(); + }; + + this.getTaxOverride = function() { + return textDisplays.taxOverride.getText(); + }; + + this.showCart = function (isMobile) { + if(isMobile === true) { + buttons.showCartMobile.click(); + } + else { + buttons.showCart.click(); + } + }; + + this.continueShopping = function () { + buttons.continueShopping.click(); + }; + + this.setCartQuantity = function (quantity) { + inputFields.cartQuantity.clear(); + inputFields.cartQuantity.sendKeys(quantity); + }; + + this.updateItemQuantity = function (quantity) { + this.setCartQuantity(quantity); + textDisplays.cartTotal.click(); + }; + + this.getCartItemQuantity = function () { + return inputFields.cartQuantity.getAttribute('value'); + }; + + this.waitUntilShowCartButtonIsDisplayed = function () { + browser.wait(function () { + return buttons.showCart.isDisplayed(); + }); + }; + + this.waitUntilNotificationIsDissmised = function () { + browser.sleep(6001); + }; + + this.waitForCartMessage = function () { + browser.wait(function () { + return textDisplays.cartMessage.isDisplayed(); + }); + }; + + this.waitUntilCartTotalIsDisplayed = function () { + browser.wait(function () { + return textDisplays.cartTotal.isDisplayed(); + }); + }; + + this.getCartMessage = function () { + return textDisplays.cartMessage.getText(); + }; + + this.getCartTotalAmount = function () { + return textDisplays.cartTotal.getText(); + }; + + this.getCartDiscountAmount = function () { + return textDisplays.cartDiscount.getText(); + }; + + this.emptyCart = function () { + buttons.removeCartItem.click(); + }; +}; + +module.exports = CartPageObject; \ No newline at end of file diff --git a/test/e2e/cart/cart.spec.js b/test/e2e/cart/cart.spec.js new file mode 100644 index 000000000..d9a3cd371 --- /dev/null +++ b/test/e2e/cart/cart.spec.js @@ -0,0 +1,214 @@ +'use strict'; + +var desktopSiteConfig = require('../config/desktop-site.json'); + +var TI = require('./cart.test-input.json'); +var utils = require('../utils/utils.js'); +var CartPageObject = require('./cart.po.js'); +var ProductDetailsPageObject = require('../product/product-details.po.js'); +var AccountPageObject = require('../account/account.po.js'); +var SitePageObject = require('../site/site.po.js'); + +describe("cart:", function () { + + var cartPO, + productDetailsPO, + accountPO, + sitePO; + + var isMobile = false; + + var testProducts = TI.products; + var testUsers = TI.users; + + beforeEach(function () { + utils.deleteCookies(); + utils.setWindowSize(desktopSiteConfig.windowDetails.width, desktopSiteConfig.windowDetails.height); + + cartPO = new CartPageObject(); + productDetailsPO = new ProductDetailsPageObject(); + accountPO = new AccountPageObject(); + sitePO = new SitePageObject(); + }); + + describe("verify cart functionality", function () { + + it('should load one product into cart', function () { + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.one.totalPriceUS); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.cartMessages.EMPTY.EN); + }); + + it('should load one product into cart in Euros', function () { + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + sitePO.waitForSiteSelector(); + + sitePO.setSite(TI.sites.SushiGermany); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.one.totalPriceDE); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.cartMessages.EMPTY.DE); + }); + + it('should load one product into cart in USD and change to Euros', function () { + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.one.totalPriceUS); + + cartPO.continueShopping(); + + sitePO.waitForSiteSelector(); + + sitePO.setSite(TI.sites.SushiGermany); + + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.one.totalPriceDE); + }); + + it('should load multiple products into cart', function () { + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(5); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.five.totalPriceUS); + }); + + + it('should update quantity', function () { + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.one.totalPriceUS); + + cartPO.continueShopping(); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartItemQuantity()).toEqual('2'); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.two.totalPriceUS); + + cartPO.updateItemQuantity(5); + + cartPO.updateOrderTotal(); + + expect(cartPO.getCartItemQuantity()).toEqual('5'); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.five.totalPriceUS); + + cartPO.updateItemQuantity(10); + + cartPO.updateOrderTotal(); + + expect(cartPO.getCartItemQuantity()).toEqual('10'); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.ten.totalPriceUS); + }); + + it('should have out of stock button disabled', function () { + productDetailsPO.get(testProducts.blackCoffeeMug.id); + + expect(cartPO.isOutOfStockButtonPresent()).toBe(true); + }); + + it('should retrieve previous cart', function () { + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + accountPO.loginUser(testUsers.cartUser); + + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.one.itemPriceUSWithTax); + }); + + it('should calculate taxes', function () { + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + sitePO.waitForSiteSelector(); + + sitePO.setSite(TI.sites.Avalara); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(testProducts.whiteCoffeeMug.one.itemPriceUS); + + cartPO.showEstimateTaxFields(); + + cartPO.setTaxZipCode(TI.taxCodes.US.taxZipCode); + + cartPO.setTaxCountry(TI.taxCodes.US.countryCode); + + cartPO.applyTax(); + + expect(cartPO.isTotalTaxPresent()).toBe(true); + }); + + it('should add and modify the note in cart item after adding an item to cart', function () { + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + cartPO.addNote(TI.cartNote); + + cartPO.addNote(TI.cartNote + ",please."); + + expect(cartPO.getItemNote()).toEqual(TI.cartNote + ",please."); + }); + + }); +}); + + diff --git a/test/e2e/cart/cart.test-input.json b/test/e2e/cart/cart.test-input.json new file mode 100644 index 000000000..b114ec5e6 --- /dev/null +++ b/test/e2e/cart/cart.test-input.json @@ -0,0 +1,66 @@ +{ + "products":{ + "whiteCoffeeMug": { + "id": "55d76ce63a0eafb30e5540c8", + "one": { + "itemPriceUS": "$10.67", + "totalPriceUS": "$20.62", + "totalPriceDE": "€12.99", + "itemPriceUSWithTax": "$13.47" + }, + + "two": { + "totalPriceUS": "$32.04" + }, + "five": { + "totalPriceUS": "$59.11" + }, + "ten": { + "totalPriceUS": "$116.19" + } + }, + "blackCoffeeMug": { + "id": "55d76cec264ebd7a318c236c" + }, + "whiteThermos": { + "id": "55d76cf53a0eafb30e5540cc", + "one": { + "itemPriceUS": "$10.67", + "totalPriceUS": "$36.66" + } + } + }, + "taxCodes": { + "US": { + "countryCode": "US", + "taxZipCode": "98101" + } + }, + + "cartMessages": { + "EMPTY": { + "EN": "YOUR CART IS EMPTY", + "DE": "IHR WARENKORB IST LEER" + } + }, + + "users": { + "cartUser": { + "username": "cart@hybristest.com", + "password": "password" + } + }, + + "cartNote": "The item should be gift wrapped", + + "sites": { + "SushiGermany": { + "siteName": "Sushi Demo Store Germany", + "mode": "Desktop" + }, + "Avalara": { + "siteName": "Avalara", + "mode": "Desktop" + } + } +} \ No newline at end of file diff --git a/test/e2e/checkout-tests.js b/test/e2e/checkout-tests.js deleted file mode 100644 index 41e202dcd..000000000 --- a/test/e2e/checkout-tests.js +++ /dev/null @@ -1,543 +0,0 @@ -var fs = require('fs'); -var tu = require('./protractor-utils.js'); - -var date = Date(); -var month = date.substr(4, 3); -var d = new Date(); -var curr_date = d.getDate(); -var curr_year = d.getFullYear(); -var currentDate = month + " " + curr_date + ", " + curr_year; -var timestamp = Number(new Date()); - -function continueAsGuest() { - tu.clickElement('binding', 'CONTINUE_AS_GUEST'); -} - -function fillCheckoutFormExceptEmail(form) { - browser.wait(function () { - return element(by.id('address1' + form)).isPresent(); - }); - browser.sleep(500); - - if (form != 'Bill') { - tu.selectOption('order.' + form.toLowerCase() + 'To.country', 'united states'); - } - - tu.selectOption('order.' + form.toLowerCase() + 'To.state', 'colorado'); - - //element(by.id('country' + form)).sendKeys('USA'); - //element(by.id('state' + form)).sendKeys('colorado'); - tu.sendKeys('id', 'zipCode' + form, '80301'); - tu.sendKeys('id', 'address1' + form, '123'); - tu.sendKeys('id', 'address2' + form, '321'); - tu.sendKeys('id', 'city' + form, 'Boulder'); -} - - -function verifyCartContents(itemPrice, totalPrice, quantity) { - - tu.sendKeys('id', 'email', 'mike@yaastest.com'); - tu.sendKeys('id', 'firstNameAccount', 'Mike'); - tu.sendKeys('id', 'lastNameAccount', 'Night'); - tu.selectOption('order.account.title', 'MR'); - - fillCheckoutFormExceptEmail('Ship'); - browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - browser.sleep(2000); - tu.clickElement('id', 'preview-order-btn'); - }); - browser.sleep(2000); - browser.executeScript('window.scrollTo(0, ' + 1200 + ');').then(function () { - browser.sleep(2000); - expect(element(by.binding('item.price.effectiveAmount')).getText()).toContain(itemPrice); - expect(element(by.binding('cart.totalPrice.amount')).getText()).toContain(totalPrice); - expect(element(by.binding('item.quantity')).getText()).toContain(quantity); - }); - - -} - -function validateField(field, form, text, buttonType, button) { - element(by.id(field + form)).clear(); - tu.clickElement(buttonType, button); - browser.sleep(500); - browser.executeScript("document.getElementById('" + field + form + "').style.display='block';"); //forces 2nd input to display after error - browser.sleep(200); - tu.sendKeys('id', field + form, text); -} - -function verifyValidationForEachField(form, elementType, button) { - validateField('zipCode', form, '80301', elementType, button); - validateField('contactName', form, 'Mike Night', elementType, button); - validateField('address1', form, '123', elementType, button); - validateField('city', form, 'Boulder', elementType, button); - -} - - -function loginAndContinueToCheckout(account) { - tu.clickElement('id', tu.contineShopping); - browser.sleep(500); - tu.loginHelper(account, 'password'); - browser.sleep(500); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(500); - tu.clickElement('binding', 'CHECKOUT'); - browser.wait(function () { - return element(by.id("ccNumber")).isPresent(); - }); -} - - -// not validated yet - selectors may not be accurate - TODO -function verifyOrderOnAccountPageMobile(account, total) { - tu.clickElement('id', tu.removeFromCart); - tu.clickElement('id', tu.contineShopping); - tu.loginHelper(account, 'password'); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account'); - tu.waitForAccountPage(); - expect(element(by.repeater('m_order in orders').row(0).column('m_order.created')).getText()).toContain(currentDate); - expect(element(by.repeater('m_order in orders').row(0).column('m_order.totalPrice')).getText()).toEqual(total); - expect(element(by.repeater('m_order in orders').row(0).column('m_order.status')).getText()).toEqual("Created"); - element(by.repeater('m_order in orders').row(0).column('m_order.created')).click(); - expect(element(by.repeater('m_order in orders').row(0).column('m_order.status')).getText()).toEqual("Created"); - tu.clickElement('id', "logout-btn"); -} - -function verifyOrderOnAccountPageBigScreen(account, total) { - tu.clickElement('id', tu.contineShopping); - tu.loginHelper(account, 'password'); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - tu.waitForAccountPage(); - expect(element(by.repeater('xrder in orders').row(0).column('xrder.created')).getText()).toContain(currentDate); - expect(element(by.repeater('xrder in orders').row(0).column('xrder.totalPrice')).getText()).toEqual(total); - expect(element(by.repeater('xrder in orders').row(0).column('xrder.status')).getText()).toEqual("CREATED"); - element(by.repeater('xrder in orders').row(0).column('xrder.created')).click(); - expect(element(by.repeater('xrder in orders').row(0).column('xrder.status')).getText()).toEqual("CREATED"); -} - -function clickOnModal() { - browser.wait(function () { - return element(by.binding('CONTINUE_AS_GUEST')).isPresent(); - }); - tu.clickElement('binding', 'CONTINUE_AS_GUEST'); -} - -describe("checkout:", function () { - - - describe("verify checkout functionality", function () { - - beforeEach(function () { - browser.manage().deleteAllCookies(); - browser.driver.manage().window().setSize(1100, 1200); - browser.get(tu.tenant + '/#!/products/55d76ce63a0eafb30e5540c8/'); - browser.switchTo().alert().then( - function (alert) { - alert.dismiss(); - }, - function (err) { - } - ); - browser.wait(function () { - return element(by.id(tu.buyButton)).isPresent(); - }); - tu.clickElement('id', tu.buyButton); - //wait for cart to close - browser.sleep(6500); - browser.wait(function () { - return element(by.id(tu.cartButtonId)).isDisplayed(); - }); - browser.sleep(1000); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(2000); - }); - - //dumps logs, if there are failing services uncomment - // afterEach(function() { - // browser.manage().logs().get('browser').then(function(browserLog) { - // console.log('log: ' + require('util').inspect(browserLog)); - // }); - // }); - - // - it('should load one product into cart and move to checkout', function () { - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - verifyCartContents('$10.67', '$20.62', '1'); - - }); - - //Comment out this test as back to checkout is not available anymore for now - xit('should update cart quantity on checkout page', function () { - var backToCheckoutButton = "//div[@id='cart']/div[2]/button"; - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - verifyCartContents('$10.67', '$20.62', '1'); - tu.clickElement('id', 'checkout-cart-btn'); - browser.wait(function () { - return element(by.binding('BACK_TO_CHECKOUT')).isPresent(); - }); - tu.sendKeys('xpath', "//input[@type='number']", '5'); - tu.clickElement('binding', 'BACK_TO_CHECKOUT'); - verifyCartContents('$10.67', '$57.08', '5'); - }); - // - it('should load 2 of one product into cart and move to checkout', function () { - tu.sendKeys('xpath', tu.cartQuantity, '2'); - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - browser.wait(function () { - return element(by.binding("ORDER_TOTAL")).isPresent(); - }); - verifyCartContents('$10.67', '$32.04', '2'); - }); - - it('should load 2 different products into cart and move to checkout', function () { - tu.clickElement('id', tu.contineShopping); - var category = element(by.repeater('top_category in categories').row(1).column('top_category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - browser.wait(function () { - return element(by.xpath(tu.whiteThermos)).isPresent(); - }); - tu.clickElement('xpath', tu.whiteThermos); - browser.wait(function () { - return element(by.id(tu.buyButton)).isPresent(); - }); - tu.clickElement('id', tu.buyButton); - //wait for cart to close - browser.sleep(5000); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(1000); - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - verifyCartContents('$10.67', '$36.66', '1'); - }); - - it('should display tax overide on cart checkout and order', function () { - tu.clickElement('id', tu.removeFromCart); - tu.clickElement('id', tu.contineShopping); - var category = element(by.repeater('top_category in categories').row(2).column('top_category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - - tu.scrollToProduct(tu.rollerPen).then(function () { - tu.clickElement('xpath', tu.rollerPen); - }); - browser.wait(function () { - return element(by.id(tu.buyButton)).isPresent(); - }); - - tu.clickElement('id', tu.buyButton); - //wait for cart to close - browser.sleep(5000); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(1000); - // Verify that the tax override is there - expect(element(by.repeater('taxLine in cart.taxAggregate.lines').row(1)).getText()).toEqual('10.01% FOR PROTRACTOR $0.20'); - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - tu.sendKeys('id', 'email', 'mike@yaastest.com'); - tu.sendKeys('id', 'firstNameAccount', 'Mike'); - tu.sendKeys('id', 'lastNameAccount', 'Night'); - fillCheckoutFormExceptEmail('Ship'); - browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - browser.sleep(2000); - tu.clickElement('id', 'preview-order-btn'); - }); - // Verify that the tax override is there - expect(element(by.repeater('taxLine in cart.taxAggregate.lines').row(1)).getText()).toEqual('10.01% FOR PROTRACTOR $0.20'); - tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - tu.clickElement('id', 'place-order-btn'); - tu.verifyOrderConfirmation('mike@yaastest.com', 'MIKE NIGHT', '123', 'BOULDER, CO 80301', '$11.39'); - expect(element(by.binding('taxLine.name')).getText()).toEqual('10.01% FOR PROTRACTOR'); - expect(element(by.binding('taxLine.amount')).getText()).toEqual('$0.60'); - }); - - - it('should allow all fields to be editable', function () { - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - fillCheckoutFormExceptEmail('Ship'); - tu.sendKeys('id', 'email', 'mike@hybristest.com'); - tu.sendKeys('id', 'firstNameAccount', 'Mike'); - tu.sendKeys('id', 'lastNameAccount', 'Night'); - tu.selectOption('order.account.title', 'MR'); - //element(by.id('titleAccount')).sendKeys('Mr.'); - browser.sleep(500); - expect(element(by.binding(" order.shipTo.address1 ")).getText()).toEqual('123'); - tu.clickElement('id', 'shipTo'); - tu.sendKeys('id', 'contactNameBill', 'Mike Night'); - fillCheckoutFormExceptEmail('Bill'); - tu.clickElement('id', 'preview-order-btn'); - browser.sleep(500); - tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - tu.clickElement('id', 'place-order-btn'); - tu.verifyOrderConfirmation('mike@hybristest.com', 'MIKE NIGHT', '123', 'BOULDER, CO 80301', '$20.62'); - }); - - - it('should allow user to create account after checkout', function () { - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - fillCheckoutFormExceptEmail('Ship'); - tu.sendKeys('id', 'email', 'checkoutacct' + timestamp + '@hybristest.com'); - tu.sendKeys('id', 'firstNameAccount', 'Mike'); - tu.sendKeys('id', 'lastNameAccount', 'Night'); - tu.selectOption('order.account.title', 'MR'); - //element(by.id('titleAccount')).sendKeys('Mr.'); - browser.sleep(500); - expect(element(by.binding(" order.shipTo.address1 ")).getText()).toEqual('123'); - tu.clickElement('id', 'shipTo'); - tu.sendKeys('id', 'contactNameBill', 'Mike Night'); - fillCheckoutFormExceptEmail('Bill'); - tu.clickElement('id', 'preview-order-btn'); - tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - tu.clickElement('id', 'place-order-btn'); - tu.verifyOrderConfirmation('checkoutacct', 'MIKE NIGHT', '123', 'BOULDER, CO 80301', '$20.62'); - tu.sendKeys('id', 'newPasswordInput', 'password'); - tu.clickElement('id', 'create-acct-btn'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - expect(element(by.binding("account.contactEmail")).getText()).toContain('checkoutacct'); - }); - - // TO DO: investigate why this test fails after select-ui changes; skip for now - xit('should have basic validation on all fields', function () { - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - fillCheckoutFormExceptEmail('Ship'); - tu.sendKeys('id', 'email', 'mike@place.com'); - tu.sendKeys('id', 'firstNameAccount', 'Mike'); - tu.sendKeys('id', 'lastNameAccount', 'Night'); - tu.selectOption('order.account.title', 'MR'); - //element(by.id('titleAccount')).sendKeys('Mr.'); - browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - browser.sleep(2000); - tu.clickElement('id', 'preview-order-btn'); - }); - tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - validateField('email', '', 'mike@hybristest.com', 'id', 'place-order-btn'); - browser.sleep(10000); - expect(element(by.binding(" order.shipTo.address1 ")).getText()).toEqual('123'); - tu.clickElement('id', 'shipTo'); - tu.sendKeys('id', 'contactNameBill', 'Mike Night'); - //fillCheckoutFormExceptEmail('Bill'); - //verifyValidationForEachField('Bill', 'id', 'preview-order-btn'); - browser.sleep(200); - tu.clickElement('id', 'preview-order-btn'); - //validateField('cvc', '', '00', 'id', 'place-order-btn'); - tu.clickElement('id', 'place-order-btn'); - expect(element(by.binding('PLEASE_ENTER_VALID_CODE')).getText()).toContain('Please enter a valid code'); - browser.executeScript("document.getElementById('cvc').style.display='block';"); - validateField('cvc', '', '123', 'id', 'place-order-btn'); - validateField('ccNumber', '', '0000000000000000', 'id', 'place-order-btn'); - tu.clickElement('id', 'place-order-btn'); - browser.executeScript("document.getElementById('ccNumber').style.display='block';"); - validateField('ccNumber', '', '5555555555554444', 'id', 'place-order-btn'); - tu.clickElement('id', 'place-order-btn'); - tu.clickElement('id', 'place-order-btn'); - tu.verifyOrderConfirmation('MIKE@HYBRISTEST.COM', 'MIKE NIGHT', '123', 'BOULDER, CO 80301', '$10.67'); - }); - - it('should allow user to select address', function () { - loginAndContinueToCheckout('address@hybristest.com'); - expect(element(by.id('address1Ship')).getAttribute('value')).toEqual('123 Take out'); - tu.clickElement('id', 'select-address-btn-1'); - browser.wait(function () { - return element(by.id('myModalLabel')).isPresent(); - }); - expect(element(by.repeater('address in addresses').row(0)).getText()).toContain('Shipping'); - expect(element(by.repeater('address in addresses').row(1)).getText()).toContain('Billing'); - var address2 = element(by.repeater('address in addresses').row(1).column('address.streetNumber')); - address2.click(); - expect(element(by.id('address1Bill')).getAttribute('value')).toEqual('123 Dine in'); - }); - - it('should populate with existing address for logged in user', function () { - loginAndContinueToCheckout('order@hybristest.com'); - browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - browser.sleep(2000); - tu.clickElement('id', 'preview-order-btn'); - }); - tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - browser.sleep(500); - tu.clickElement('id', 'place-order-btn'); - tu.verifyOrderConfirmation('order@hybristest.com', 'MIKE', '123', 'BOULDER, CO 80301', '$20.62'); - tu.clickElement('binding', 'orderInfo.orderId'); - expect(element(by.binding('order.shippingAddress.contactName')).getText()).toContain("123 fake street"); - }); - - it('should create order on account page', function () { - tu.removeItemFromCart(); - verifyOrderOnAccountPageBigScreen(tu.accountWithOrderEmail, '$20.62'); - }); - - // This test is skipped for now, defect KIWIS-2511 opened - xit('should checkout in Euros', function () { - tu.clickElement('id', tu.contineShopping); - browser.sleep(1000); - tu.switchSite('Sushi Demo Store Germany'); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(2000); - loginAndContinueToCheckout('euro-order@hybristest.com'); - browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - browser.sleep(2000); - tu.clickElement('id', 'preview-order-btn'); - }); - tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - browser.sleep(500); - tu.clickElement('id', 'place-order-btn'); - tu.verifyOrderConfirmation('euro-order@hybristest.com', 'MIKE', '123', 'MUNICH, 80301', '€12.94'); - tu.clickElement('binding', 'orderInfo.orderId'); - expect(element(by.binding('order.shippingAddress.contactName')).getText()).toContain("123 fake street"); - }); - - // This test is skipped for now, defect KIWIS-2511 opened - xit('should create order on account page in Euros', function () { - tu.removeItemFromCart(); - verifyOrderOnAccountPageBigScreen('euro-order@hybristest.com', '€12.99'); - }); - - it('should merge carts and checkout for logged in user', function () { - tu.clickElement('id', tu.contineShopping); - tu.loginHelper('checkout@hybristest.com', 'password'); - browser.driver.actions().mouseMove(element(by.repeater('top_category in categories').row(1).column('top_category.name'))).perform(); - browser.sleep(200); - element(by.repeater('top_category in categories').row(1).column('top_category.name')).click(); - tu.clickElement('xpath', tu.whiteThermos); - browser.wait(function () { - return element(by.id(tu.buyButton)).isPresent(); - }); - tu.clickElement('id', tu.buyButton); - //wait for cart to close - browser.sleep(6500); - browser.wait(function () { - return element(by.id(tu.cartButtonId)).isDisplayed(); - }); - browser.sleep(1000); - tu.clickElement('id', tu.cartButtonId); - browser.wait(function () { - return element(by.binding('CHECKOUT')).isPresent(); - }); - browser.sleep(1000); - tu.clickElement('binding', 'CHECKOUT'); - //verifyCartContents('$10.67', '$27.46', '1'); -- commented out for now, need to evaluate if needed - browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - browser.sleep(2000); - tu.clickElement('id', 'preview-order-btn'); - }); - tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - browser.sleep(500); - tu.clickElement('id', 'place-order-btn'); - tu.verifyOrderConfirmation('CHECKOUT@HYBRISTEST.COM', 'CHECKOUT', '123', 'BOULDERADO, CO 80800', '$36.66'); - tu.clickElement('binding', 'orderInfo.orderId'); - expect(element(by.binding('order.shippingAddress.street')).getText()).toContain("123 fake place"); - // tu.clickElement('id', "logout-btn"); - }); - - }); -}); - -describe("mobile checkout:", function () { - - beforeEach(function () { - browser.driver.manage().window().setSize(750, 1200); - }); - - describe("verify mobile checkout functionality", function () { - - beforeEach(function () { - browser.manage().deleteAllCookies(); - browser.get(tu.tenant + '/#!/products/55d76ce63a0eafb30e5540c8/'); - browser.switchTo().alert().then( - function (alert) { - alert.accept(); - }, - function (err) { - } - ); - browser.sleep(500); - tu.clickElement('id', tu.buyButton); - //wait for cart to close - browser.sleep(6000); - browser.wait(function () { - return element(by.id('mobile-cart-btn')).isDisplayed(); - }); - tu.clickElement('id', 'mobile-cart-btn'); - tu.waitForCart(); - browser.sleep(2000); - tu.clickElement('binding', 'CHECKOUT'); - clickOnModal(); - tu.sendKeys('id', 'email', 'mike@hybristest.com'); - tu.sendKeys('id', 'firstNameAccount', 'Mike'); - tu.sendKeys('id', 'lastNameAccount', 'Night'); - tu.selectOption('order.account.title', 'MR'); - //element(by.id('titleAccount')).sendKeys('Mr.'); - fillCheckoutFormExceptEmail('Ship'); - - }); - - var continueButton1 = '//div[8]/button'; - var continueButton2 = '//div[4]/button'; - var paymentButton = "//button[@type='submit']"; - - // DR - Comment out these 2 tests for now, to be re-executed after KIWIS-2584 is done - //it('should allow all fields to be editable on mobile', function () { - // tu.clickElement('xpath', continueButton1); - // browser.sleep(500); - // expect(element(by.binding(" order.shipTo.address1 ")).getText()).toEqual('123'); - // tu.clickElement('id', 'shipTo'); - // tu.sendKeys('id', 'contactNameBill', 'Mike Night'); - // fillCheckoutFormExceptEmail('Bill'); - // tu.clickElement('xpath', continueButton2); - // tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - // tu.clickElement('xpath', paymentButton); - // tu.clickElement('id', "place-order-btn"); - // browser.sleep(10000); - // browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - // browser.sleep(2000); - // tu.verifyOrderConfirmation('MIKE@HYBRISTEST.COM', 'MIKE NIGHT', '123', 'BOULDER, CO 80301', 'Total Price: $10.67'); - // }); - // //tu.verifyOrderConfirmation('MIKE@HYBRISTEST.COM', 'MIKE NIGHT', '123', 'BOULDER, CO 80301', 'Total Price: $10.67'); - //}); - - //it('should have basic validation on mobile', function () { - // verifyValidationForEachField('Ship', 'xpath', continueButton1); - // validateField('email', '', 'mike@hybristest.com', 'xpath', continueButton1); - // tu.clickElement('xpath', continueButton1); - // browser.sleep(500); - // expect(element(by.binding(" order.shipTo.address1 ")).getText()).toEqual('123'); - // tu.clickElement('id', 'shipTo'); - // tu.sendKeys('id', 'contactNameBill', 'Mike Night'); - // fillCheckoutFormExceptEmail('Bill'); - // verifyValidationForEachField('Bill', 'xpath', continueButton2); - // tu.clickElement('xpath', continueButton2); - // tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - // tu.clickElement('xpath', paymentButton); - // tu.clickElement('id', "place-order-btn"); - // tu.verifyOrderConfirmation('MIKE@HYBRISTEST.COM', 'MIKE NIGHT', '123', 'BOULDER, CO 80301', '$10.67'); - //}); - - // TODO - mobile login slightly more complex due to account drop-down - xit('should create order on account page mobile', function () { - verifyOrderOnAccountPageMobile('order@hybristest.com', '$24.61') - }); - - xit('should create order on account page in Euros mobile', function () { - verifyOrderOnAccountPageMobile('euro-order@hybristest.com', '€22.52') - }); - - }); -}); diff --git a/test/e2e/checkout/checkout.desktop.spec.js b/test/e2e/checkout/checkout.desktop.spec.js new file mode 100644 index 000000000..07f9c69b4 --- /dev/null +++ b/test/e2e/checkout/checkout.desktop.spec.js @@ -0,0 +1,436 @@ +var desktopSiteConfig = require('../config/desktop-site.json'); + +var TI = require('./checkout.test-input.json'); +var utils = require('../utils/utils.js'); +var CartPageObject = require('../cart/cart.po.js'); +var ProductDetailsPageObject = require('../product/product-details.po.js'); +var AccountPageObject = require('../account/account.po.js'); +var SitePageObject = require('../site/site.po.js'); +var CouponPageObject = require('../coupon/coupon.po.js') +var CheckoutPageObject = require('./checkout.po.js'); +var ConfirmationPageObject = require('../confirmation/confirmation.po.js'); +var OrderDetailsPageObject = require('./order-details.po.js'); + +var utils = require('../utils/utils.js'); + +var testProducts = TI.products; +var testUsers = TI.users; + +describe("checkout:", function () { + + var cartPO, + productDetailsPO, + accountPO, + sitePO, + couponPO, + checkoutPO, + confirmationPO, + orderDetailsPO; + + var isMobile = false; + var isLoggedIn; + + describe("verify checkout functionality", function () { + + beforeEach(function () { + utils.deleteCookies(); + + utils.setWindowSize(desktopSiteConfig.windowDetails.width, desktopSiteConfig.windowDetails.height); + + cartPO = new CartPageObject(); + couponPO = new CouponPageObject(); + productDetailsPO = new ProductDetailsPageObject(); + accountPO = new AccountPageObject(); + sitePO = new SitePageObject(); + checkoutPO = new CheckoutPageObject(); + confirmationPO = new ConfirmationPageObject(); + orderDetailsPO = new OrderDetailsPageObject(); + + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + }); + + + it('should load one product into cart and move to checkout', function () { + isLoggedIn = false; + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForForm(); + + checkoutPO.fillNameAndEmailFields(TI.selectModel,testUsers.main.name,testUsers.main.email); + + checkoutPO.fillAddressFields(TI.addressType.SHIPPING); + checkoutPO.goToPreviewOrder(); + + expect(checkoutPO.orderPreview.getItemEffectiveAmount()).toContain(testProducts.whiteCoffeeMug.one.itemPriceUS); + expect(checkoutPO.orderPreview.getTotalPrice()).toContain(testProducts.whiteCoffeeMug.one.totalPriceUS); + expect(checkoutPO.orderPreview.getItemQuantity()).toContain('1'); + }); + + it('should load 2 of one product into cart and move to checkout', function () { + isLoggedIn = false; + + cartPO.setCartQuantity(2); + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForForm(); + + checkoutPO.fillNameAndEmailFields(TI.selectModel,testUsers.main.name,testUsers.main.email); + + checkoutPO.fillAddressFields(TI.addressType.SHIPPING); + checkoutPO.goToPreviewOrder(); + + expect(checkoutPO.orderPreview.getItemEffectiveAmount()).toContain(testProducts.whiteCoffeeMug.one.itemPriceUS); + expect(checkoutPO.orderPreview.getTotalPrice()).toContain(testProducts.whiteCoffeeMug.two.totalPriceUS); + expect(checkoutPO.orderPreview.getItemQuantity()).toContain('2'); + }); + + it('should load 2 different products into cart and move to checkout', function () { + isLoggedIn = false; + + cartPO.continueShopping(); + + productDetailsPO.get(testProducts.whiteThermos.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForForm(); + + checkoutPO.fillNameAndEmailFields(TI.selectModel,testUsers.main.name,testUsers.main.email); + checkoutPO.fillAddressFields(TI.addressType.SHIPPING); + + checkoutPO.goToPreviewOrder(); + + expect(checkoutPO.orderPreview.getItemEffectiveAmount()).toContain(testProducts.whiteThermos.one.itemPriceUS); + expect(checkoutPO.orderPreview.getTotalPrice()).toContain(testProducts.whiteThermos.one.totalPriceUS); + expect(checkoutPO.orderPreview.getItemQuantity()).toContain('1'); + }); + + it('should display tax overide on cart checkout and order', function () { + isLoggedIn = false; + + cartPO.emptyCart(); + cartPO.continueShopping(); + + productDetailsPO.get(testProducts.blueRollerPen.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getTaxOverride()).toEqual(testProducts.blueRollerPen.taxOverride); + + cartPO.goToCheckout(isLoggedIn); + checkoutPO.waitForForm(); + + checkoutPO.fillNameAndEmailFields(TI.selectModel,testUsers.main.name,testUsers.main.email); + checkoutPO.fillAddressFields(TI.addressType.SHIPPING); + + checkoutPO.goToPreviewOrder(); + + expect(checkoutPO.orderPreview.getTaxOverride()).toEqual(testProducts.blueRollerPen.taxOverride); + + checkoutPO.fillCreditCardFields(TI.creditCard); + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.main,testProducts.blueRollerPen.one.totalPriceUS,isMobile); + + expect(confirmationPO.getTaxLine()).toEqual(testProducts.blueRollerPen.taxLine); + expect(confirmationPO.getTaxLineAmount()).toEqual(testProducts.blueRollerPen.taxAmount); + }); + + + it('should allow all fields to be editable', function () { + isLoggedIn = false; + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForForm(); + + checkoutPO.fillNameAndEmailFields(TI.selectModel,testUsers.main.name,testUsers.main.email); + + checkoutPO.fillAddressFields(TI.addressType.SHIPPING); + + expect(checkoutPO.getShippingAddressLine1Address()).toEqual(testUsers.main.address.street.split(' ')[0]); + + checkoutPO.changeBillingAddressToShippingAddressState(); + + checkoutPO.fillBillingAddressNameField(testUsers.main.fullName); + + checkoutPO.fillAddressFields(TI.addressType.BILLING); + + checkoutPO.goToPreviewOrder(); + + checkoutPO.fillCreditCardFields(TI.creditCard); + + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.main,testProducts.whiteCoffeeMug.one.totalPriceUS,isMobile); + }); + + it('should allow user to create account after checkout', function () { + isLoggedIn = false; + + var timestamp = Number(new Date()); + + var mainUserEmailFields = testUsers.main.email.split('@'); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForForm(); + + checkoutPO.fillNameAndEmailFields(TI.selectModel,testUsers.main.name,mainUserEmailFields[0] + timestamp + '@' + mainUserEmailFields[1]); + + checkoutPO.fillAddressFields(TI.addressType.SHIPPING); + + expect(checkoutPO.getShippingAddressLine1Address()).toEqual(testUsers.main.address.street.split(' ')[0]); + + checkoutPO.changeBillingAddressToShippingAddressState(); + + checkoutPO.fillBillingAddressNameField(testUsers.main.fullName); + + checkoutPO.fillAddressFields(TI.addressType.BILLING); + + checkoutPO.goToPreviewOrder(); + + checkoutPO.fillCreditCardFields(TI.creditCard); + + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.main,testProducts.whiteCoffeeMug.one.totalPriceUS,isMobile); + + confirmationPO.createAccount(); + + accountPO.accountDetails.getPage(); + + expect(accountPO.accountDetails.getContactEmail()).toContain(mainUserEmailFields[0]); + }); + + it('should allow user to select address', function () { + isLoggedIn = true; + + cartPO.continueShopping(); + + accountPO.waitForSignInLink(); + + accountPO.loginUser(testUsers.hybrisTestUser); + + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForCreditCardField(); + + expect(checkoutPO.getLoggedInShippingAddress()).toEqual(testUsers.hybrisTestUser.address.first); + + checkoutPO.addressModal.get(); + + expect(checkoutPO.addressModal.getShippingAddressLabel()).toContain(TI.addressType.SHIPPING); + expect(checkoutPO.addressModal.getBillingAddressLabel()).toContain(TI.addressType.BILLING); + + checkoutPO.addressModal.setShippingAddress(2); + + expect(checkoutPO.getLoggedInShippingAddress()).toEqual(testUsers.hybrisTestUser.address.second); + }); + + it('should populate with existing address for logged in user', function () { + isLoggedIn = true; + + cartPO.continueShopping(); + + accountPO.waitForSignInLink(); + + accountPO.loginUser(testUsers.orderHybrisTestUser); + + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.goToPreviewOrder(); + + checkoutPO.fillCreditCardFields(TI.creditCard); + + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.orderHybrisTestUser,testProducts.whiteCoffeeMug.one.totalPriceUS,isMobile); + + confirmationPO.goToOrderDetails(); + + expect(orderDetailsPO.getShippingAddress()).toContain(testUsers.orderHybrisTestUser.address.street); + }); + + it('should create order on account page', function () { + //This test depends on state created by the previous test + cartPO.emptyCart(); + + cartPO.continueShopping(); + + accountPO.waitForSignInLink(); + + accountPO.loginUser(testUsers.orderHybrisTestUser); + + accountPO.accountDetails.getPage(); + + var date = Date(); + var month = date.substr(4, 3); + var d = new Date(); + var currentDate = month + " " + d.getDate() + ", " + d.getFullYear(); + + expect(accountPO.orderRow.getCreationDate(0)).toContain(currentDate); + expect(accountPO.orderRow.getTotalPrice(0)).toEqual(testProducts.whiteCoffeeMug.one.totalPriceUS); + expect(accountPO.orderRow.getOrderStatus(0)).toEqual(TI.orderMessages.CREATED); + }); + + it('should allow customer to cancel order if not shipped yet', function () { + isLoggedIn = true; + + cartPO.continueShopping(); + + accountPO.waitForSignInLink(); + + accountPO.loginUser(testUsers.orderHybrisTestUser); + + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.goToPreviewOrder(); + + checkoutPO.fillCreditCardFields(TI.creditCard); + + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.orderHybrisTestUser,testProducts.whiteCoffeeMug.one.totalPriceUS,isMobile); + + confirmationPO.goToOrderDetails(); + + expect(orderDetailsPO.getShippingAddress()).toContain(testUsers.orderHybrisTestUser.address.street); + + orderDetailsPO.cancelOrder(); + + expect(orderDetailsPO.getOrderStatus()).toContain(TI.orderMessages.CANCELLED); + }); + + it('should checkout in Euros', function () { + isLoggedIn = true; + + cartPO.continueShopping(); + + sitePO.waitForSiteSelector(); + + sitePO.setSite(TI.sites.SushiGermany); + + accountPO.waitForSignInLink(); + + accountPO.loginUser(testUsers.euroOrderUser); + + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.goToPreviewOrder(); + + checkoutPO.fillCreditCardFields(TI.creditCard); + + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.euroOrderUser,testProducts.whiteCoffeeMug.one.totalPriceDE,isMobile); + + confirmationPO.goToOrderDetails(); + + expect(orderDetailsPO.getShippingAddress()).toContain(testUsers.euroOrderUser.address.street); + }); + + + it('should create order on account page in Euros', function () { + //This test depends on state created by the previous test + cartPO.emptyCart(); + + cartPO.continueShopping(); + + accountPO.waitForSignInLink(); + + accountPO.loginUser(testUsers.euroOrderUser); + + accountPO.accountDetails.getPage(); + + var date = Date(); + var month = date.substr(4, 3); + var d = new Date(); + var currentDate = month + " " + d.getDate() + ", " + d.getFullYear(); + + expect(accountPO.orderRow.getCreationDate(0)).toContain(currentDate); + expect(accountPO.orderRow.getTotalPrice(0)).toEqual(testProducts.whiteCoffeeMug.one.totalPriceDE); + expect(accountPO.orderRow.getOrderStatus(0)).toEqual(TI.orderMessages.CREATED); + + }); + + it('should merge carts and checkout for logged in user', function () { + isLoggedIn = true; + + cartPO.continueShopping(); + + accountPO.waitForSignInLink(); + + accountPO.loginUser(testUsers.orderHybrisTestUser); + + accountPO.waitForSignInComplete(); + + productDetailsPO.get(testProducts.whiteThermos.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.goToPreviewOrder(); + + checkoutPO.fillCreditCardFields(TI.creditCard); + + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.orderHybrisTestUser,testProducts.whiteThermos.one.totalPriceUS,isMobile); + + confirmationPO.goToOrderDetails(); + + expect(orderDetailsPO.getShippingAddress()).toContain(testUsers.orderHybrisTestUser.address.street); + }); + + }); +}); + diff --git a/test/e2e/checkout/checkout.mobile.spec.js b/test/e2e/checkout/checkout.mobile.spec.js new file mode 100644 index 000000000..d0a76612c --- /dev/null +++ b/test/e2e/checkout/checkout.mobile.spec.js @@ -0,0 +1,132 @@ +'use strict'; + +var mobileSiteConfig = require('../config/mobile-site.json'); + +var TI = require('./checkout.test-input.json'); + +var utils = require('../utils/utils.js'); +var CartPageObject = require('../cart/cart.po.js'); +var ProductDetailsPageObject = require('../product/product-details.po.js'); +var AccountPageObject = require('../account/account.po.js'); +var SitePageObject = require('../site/site.po.js'); +var CouponPageObject = require('../coupon/coupon.po.js') +var CheckoutPageObject = require('./checkout.po.js'); +var ConfirmationPageObject = require('../confirmation/confirmation.po.js'); + +var testUsers = TI.users; +var testProducts = TI.products; + + +describe("mobile checkout:", function () { + + var cartPO, + productDetailsPO, + accountPO, + sitePO, + couponPO, + checkoutPO, + confirmationPO; + + var isMobile = true; + var isLoggedIn = false; + + beforeEach(function () { + utils.setWindowSize(mobileSiteConfig.windowDetails.width, mobileSiteConfig.windowDetails.height); + }); + + describe("verify mobile checkout functionality", function () { + + beforeEach(function () { + utils.deleteCookies(); + + cartPO = new CartPageObject(); + couponPO = new CouponPageObject(); + productDetailsPO = new ProductDetailsPageObject(); + accountPO = new AccountPageObject(); + sitePO = new SitePageObject(); + checkoutPO = new CheckoutPageObject(); + confirmationPO = new ConfirmationPageObject(); + + productDetailsPO.get(testProducts.whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.fillNameAndEmailFields(TI.selectModel,testUsers.main.name, testUsers.main.email); + + checkoutPO.waitForForm(); + + checkoutPO.fillAddressFields(TI.addressType.SHIPPING); + + }); + + it('should allow all fields to be editable on mobile', function () { + checkoutPO.mobile.continueToBilling(); + + expect(checkoutPO.getShippingAddressLine1Address()).toEqual(testUsers.main.address.street.split(' ')[0]); + + checkoutPO.changeBillingAddressToShippingAddressState() + + checkoutPO.fillBillingAddressNameField(testUsers.main.fullName); + + checkoutPO.fillAddressFields(TI.addressType.BILLING); + + checkoutPO.mobile.continueToPayment(); + + checkoutPO.fillCreditCardFields(TI.creditCard); + + checkoutPO.mobile.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.main,'Total Price: ' + testProducts.whiteCoffeeMug.one.itemPriceUS,isMobile); + }); + + it('should have basic validation on mobile', function () { + + var c1 = 'toBilling'; + var c2 = 'toPayment'; + + checkoutPO.mobile.validate('zipCodeShip', '80301', c1); + checkoutPO.mobile.validate('contactNameShip', 'Mike Night', c1); + checkoutPO.mobile.validate('address1Ship', '123',c1); + checkoutPO.mobile.validate('cityShip', 'Boulder', c1); + checkoutPO.mobile.validate('email','mike@yaastest.com', c1); + + checkoutPO.mobile.continueToBilling(); + + expect(checkoutPO.getShippingAddressLine1Address()).toEqual(testUsers.main.address.street.split(' ')[0]); + + checkoutPO.changeBillingAddressToShippingAddressState(); + + checkoutPO.fillBillingAddressNameField(testUsers.main.fullName); + + checkoutPO.fillAddressFields(TI.addressType.BILLING); + + checkoutPO.mobile.validate('zipCodeBill', '80301', c2); + checkoutPO.mobile.validate('contactNameBill', 'Mike Night', c2); + checkoutPO.mobile.validate('address1Bill', '123', c2); + checkoutPO.mobile.validate('cityBill', 'Boulder', c2); + + + checkoutPO.mobile.continueToPayment(); + + checkoutPO.fillCreditCardFields(TI.creditCard); + + checkoutPO.mobile.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.main,'Total Price: ' + testProducts.whiteCoffeeMug.one.itemPriceUS,isMobile); + + }); + + }); +}); + + diff --git a/test/e2e/checkout/checkout.po.js b/test/e2e/checkout/checkout.po.js new file mode 100644 index 000000000..4993e2950 --- /dev/null +++ b/test/e2e/checkout/checkout.po.js @@ -0,0 +1,231 @@ +'use strict'; + +var utils = require('../utils/utils.js'); + +var CheckoutPageObject = function () { + + var buttons = { + previewOrder: element(by.id('preview-order-btn')), + placeOrder: element(by.id('place-order-btn')), + loggedIn: { + shippingAddressSelect: element(by.id('select-address-btn-1')), + }, + mobile: { + toBilling: element(by.id('continue-to-billing')), + toPayment: element(by.id('continue-to-payment-method')), + toPlaceOrder: element(by.id('mobile-place-order-btn')) + } + }; + + var inputFields = { + billingAddress: { + contactName: element(by.id('contactNameBill')), + }, + firstName: element(by.id("firstNameAccount")), + lastName: element(by.id("lastNameAccount")), + creditCardNumber: element(by.id("ccNumber")), + cvcCode: element(by.id("cvc")), + email: element(by.id("email")), + loggedIn: { + shippingAddress1: element(by.id('address1Ship')) + } + }; + + var textDisplays = { + + shipmentDestination: element(by.id('shipment-destination')), + + orderPreview: { + itemQuantity: element.all(by.className('item-quantity')).first(), + totalPrice: element.all(by.className('cart-totalPrice')).first(), + taxLines: element(by.repeater('taxLine in cart.taxAggregate.lines').row(1)), + itemEffectiveAmount: element.all(by.className('item-effectiveAmount')).first(), + totalDiscount: element.all(by.className('cart-totalDiscount')).first() + }, + + shippingAddress1: element(by.id('order-shipTo-address1')) + }; + + var checkboxes = { + shipTo: element(by.id('shipTo')) + }; + + var links = { + addressBookModal: element(by.id('myModalLabel')), + confirmation: { + orderDetails: element(by.binding('orderInfo.orderId')) + } + }; + + var waitForAddressBookModal = function() { + browser.wait(function () { + return links.addressBookModal.isPresent(); + }); + }; + + this.getLoggedInShippingAddress = function() { + return inputFields.loggedIn.shippingAddress1.getAttribute('value'); + }; + + this.getShippingAddressLine1Address = function() { + return textDisplays.shippingAddress1.getText(); + }; + + this.fillNameAndEmailFields = function(model, name, email) { + this.fillNameFields(model,name); + inputFields.email.sendKeys(email); + }; + + this.fillNameFields = function(model,name) { + utils.selectOption(model, name.designation); + + inputFields.firstName.clear(); + inputFields.firstName.sendKeys(name.firstName); + + inputFields.lastName.clear(); + inputFields.lastName.sendKeys(name.lastName); + }; + + this.waitForForm = function() { + browser.wait(function () { + return inputFields.firstName.isPresent(); + }); + browser.sleep(500); + }; + + this.changeBillingAddressToShippingAddressState = function () { + checkboxes.shipTo.click(); + }; + + this.fillBillingAddressNameField = function(name) { + inputFields.billingAddress.contactName.clear(); + inputFields.billingAddress.contactName.sendKeys(name); + }; + + this.placeOrder = function() { + utils.scrollTo(buttons.placeOrder); + buttons.placeOrder.click(); + }; + + this.fillAddressFields = function(type) { + var idFragment = null; + if(type === 'Billing') { + idFragment = 'Bill'; + } + else if(type === 'Shipping') { + idFragment = 'Ship'; + } + + if(idFragment != 'Bill') { + utils.selectOption('order.' + idFragment.toLowerCase() + 'To.country', 'united states'); + } + + browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { + utils.selectOption('order.' + idFragment.toLowerCase() + 'To.state', 'colorado'); + + element(by.id('zipCode' + idFragment)).sendKeys('80301'); + element(by.id('address1' + idFragment)).sendKeys('123'); + element(by.id('address2' + idFragment)).sendKeys('321'); + element(by.id('city' + idFragment)).sendKeys('Boulder'); + }); + }; + + this.fillCreditCardFields = function(creditCard) { + + inputFields.creditCardNumber.clear(); + inputFields.creditCardNumber.sendKeys(creditCard.cardNumber); + + utils.selectOption('order.creditCard.expMonth', creditCard.expiryMonth); + utils.selectOption('order.creditCard.expYear', creditCard.expiryYear); + + inputFields.cvcCode.clear(); + inputFields.cvcCode.sendKeys(creditCard.cvcCode); + }; + + this.waitForConfirmationPage = function () { + browser.wait(function () { + return textDisplays.shipmentDestination.isPresent(); + }); + }; + + this.goToPreviewOrder = function() { + utils.scrollTo(buttons.previewOrder); + buttons.previewOrder.click(); + }; + + this.waitForCreditCardField = function () { + browser.wait(function () { + return inputFields.creditCardNumber.isPresent(); + }); + }; + + this.orderPreview = { + getTaxOverride: function () { + return textDisplays.orderPreview.taxLines.getText(); + }, + + getItemEffectiveAmount: function () { + return textDisplays.orderPreview.itemEffectiveAmount.getText(); + }, + + getTotalDiscount: function () { + return textDisplays.orderPreview.totalDiscount.getText(); + }, + + getTotalPrice: function () { + return textDisplays.orderPreview.totalPrice.getText(); + }, + + getItemQuantity: function () { + return textDisplays.orderPreview.itemQuantity.getText(); + } + }; + + this.mobile = { + continueToBilling: function () { + buttons.mobile.toBilling.click(); + }, + continueToPayment: function () { + utils.scrollTo(buttons.mobile.toPayment); + buttons.mobile.toPayment.click(); + }, + placeOrder: function () { + buttons.mobile.toPlaceOrder.click(); + buttons.placeOrder.click(); + }, + validate: function (elem, text, nextPageButton) { + var e = element(by.id(elem)); + e.clear(); + if(nextPageButton === 'toBilling') { + buttons.mobile.toBilling.click(); + } + else if(nextPageButton === 'toPayment') { + buttons.mobile.toPayment.click(); + } + browser.executeScript("document.getElementById('" + elem + "').style.display='block';"); //forces 2nd input to display after error + e.sendKeys(text); + } + }; + + this.addressModal = { + getShippingAddressLabel: function () { + return element(by.repeater('address in addresses').row(0)).getText(); + }, + + getBillingAddressLabel: function () { + return element(by.repeater('address in addresses').row(1)).getText() + }, + + get: function () { + buttons.loggedIn.shippingAddressSelect.click(); + waitForAddressBookModal(); + }, + + setShippingAddress: function (addressNumber) { + element(by.repeater('address in addresses').row(addressNumber - 1).column('address.streetNumber')).click(); + } + }; + +}; + +module.exports = CheckoutPageObject; \ No newline at end of file diff --git a/test/e2e/checkout/checkout.test-input.json b/test/e2e/checkout/checkout.test-input.json new file mode 100644 index 000000000..e46631e8b --- /dev/null +++ b/test/e2e/checkout/checkout.test-input.json @@ -0,0 +1,132 @@ +{ + "products":{ + "whiteCoffeeMug": { + "id": "55d76ce63a0eafb30e5540c8", + "one": { + "itemPriceUS": "$10.67", + "totalPriceUS": "$20.62", + "totalPriceDE": "€12.99" + }, + + "two": { + "totalPriceUS": "$32.04" + }, + "five": { + "totalPriceUS": "$54.58" + } + }, + "whiteThermos": { + "id": "55d76cf53a0eafb30e5540cc", + "one": { + "itemPriceUS": "$10.67", + "totalPriceUS": "$36.66" + } + }, + "blueRollerPen": { + "id": "55d76d19264ebd7a318c237e", + "taxOverride": "10.01% FOR PROTRACTOR $0.20", + "taxLine": "10.01% FOR PROTRACTOR", + "taxAmount": "$0.60", + "one": { + "totalPriceUS": "$11.39" + } + } + }, + + "addressType": { + "SHIPPING": "Shipping", + "BILLING": "Billing" + }, + + "orderMessages":{ + "CREATED": "Created", + "CANCELLED": "Cancelled" + }, + + "users": { + "main": { + "name": { + "designation": "MR", + "firstName": "Mike", + "lastName": "Night" + }, + "fullName": "Mike Night", + "email": "mike@yaastest.com", + "username": "mike@yaastest.com", + "address": { + "country": "United States", + "contactName": "MIKE NIGHT", + "street": "123 fake place", + "aptNumber": "apt 419", + "city": "Boulder", + "state": "CO", + "zipCode": "80301", + "cityStateZipCode": "BOULDER, CO 80301", + "contactPhone": "303-303-3333" + } + }, + + "hybrisTestUser": { + "username":"address@hybristest.com", + "password":"password", + "address": { + "first": "123 Take out", + "second": "123 Dine in" + } + }, + + "orderHybrisTestUser": { + "username": "order@hybristest.com", + "email": "order@hybristest.com", + "password":"password", + "address": { + "country": "United States", + "contactName": "MIKE NIGHT", + "street": "123 fake street", + "aptNumber": "apt 419", + "city": "Boulder", + "state": "CO", + "zipCode": "80301", + "cityStateZipCode": "BOULDER, CO 80301", + "contactPhone": "303-303-3333" + } + }, + + "couponUser": { + "username": "coupon@hybristest.com", + "password": "password" + }, + + "euroOrderUser": { + "username": "euro-order@hybristest.com", + "password": "password", + "email": "euro-order@hybristest.com", + "address": { + "contactName": "MIKE", + "street": "123 fake street", + "aptNumber": "apt 419", + "city": "Boulder", + "state": "CO", + "zipCode": "80301", + "cityStateZipCode": "MUNICH, 80301", + "contactPhone": "303-303-3333" + } + } + }, + + "creditCard": { + "cardNumber": 5555555555554444, + "expiryMonth": "06", + "expiryYear": 2019, + "cvcCode": "000" + }, + + "sites": { + "SushiGermany": { + "siteName": "Sushi Demo Store Germany", + "mode": "Desktop" + } + }, + + "selectModel": "order.account.title" +} \ No newline at end of file diff --git a/test/e2e/checkout/order-details.po.js b/test/e2e/checkout/order-details.po.js new file mode 100644 index 000000000..bf90577e3 --- /dev/null +++ b/test/e2e/checkout/order-details.po.js @@ -0,0 +1,54 @@ +'use strict'; + +var utils = require('../utils/utils.js'); + +var OrderDetailsPageObject = function () { + + var buttons = { + cancelOrder: { + modalOpen: element(by.id('cancelOrder')), + confirmCancel: element(by.id('confirm-order-cancel-btn')) + } + }; + + var textDisplays = { + cancelOrder: { + modalContent: element(by.css('.modal-content')) + }, + + status: element(by.binding('order.status')), + + shippingAddressName: element(by.binding('order.shippingAddress.contactName')) + }; + + this.getShippingAddress = function () { + return textDisplays.orderDetails.shippingAddressName.getText(); + }; + + this.waitForOrderStatus = function () { + browser.wait(function () { + return textDisplays.status.isPresent(); + }); + }; + + this.getOrderStatus = function () { + return textDisplays.status.getText(); + }; + + this.getShippingAddress = function () { + return textDisplays.shippingAddressName.getText(); + }; + + this.cancelOrder = function () { + buttons.cancelOrder.modalOpen.click(); + browser.switchTo().defaultContent(); + browser.waitForAngular(); + browser.wait(function () { + return textDisplays.cancelOrder.modalContent.isPresent(); + }); + buttons.cancelOrder.confirmCancel.click(); + }; + +}; + +module.exports = OrderDetailsPageObject; diff --git a/test/e2e/config/desktop-site.json b/test/e2e/config/desktop-site.json new file mode 100644 index 000000000..13e3a6770 --- /dev/null +++ b/test/e2e/config/desktop-site.json @@ -0,0 +1,11 @@ +{ + "tenantId": "basqa", + "windowDetails": { + "width": 1200, + "height": 1000 + }, + "productListPage": { + "productCounterInitial": "1-3 OF 38" + }, + "user": {} +} \ No newline at end of file diff --git a/test/e2e/config/mobile-site.json b/test/e2e/config/mobile-site.json new file mode 100644 index 000000000..0fc9491d7 --- /dev/null +++ b/test/e2e/config/mobile-site.json @@ -0,0 +1,10 @@ +{ + "tenantId": "basqa", + "windowDetails": { + "width": 750, + "height": 1200 + }, + "productListPage": { + "productCounterInitial": "1-4 OF 38" + } +} \ No newline at end of file diff --git a/test/e2e/confirmation/confirmation.po.js b/test/e2e/confirmation/confirmation.po.js new file mode 100644 index 000000000..f8b3824c8 --- /dev/null +++ b/test/e2e/confirmation/confirmation.po.js @@ -0,0 +1,91 @@ +'use strict'; + +var utils = require('../utils/utils.js'); + +var ConfirmationPageObject = function () { + + var buttons = { + createAccount: element(by.id('create-acct-btn')), + }; + + var inputFields = { + newAccountPassword: element(by.id('newPasswordInput')), + }; + + var textDisplays = { + totalPrice: element(by.id('confirmation-totalPrice')), + totalDiscount: element(by.id('discount-amount')), + orderDetails: element(by.binding('orderInfo.orderId')), + taxLines: by.exactRepeater('taxLine in confirmationDetails.tax.lines'), + successMessage: element(by.id('confirmation-success-message')), + totalPriceMobile: element(by.css('td.text-left.product-details-mobile > div:nth-child(5) > strong')), + shippingAddress: { + address1: element(by.binding('confirmationDetails.shippingAddressStreetLine1')), + name: element(by.binding('confirmationDetails.shippingAddressName')), + cityStateZipCode: element(by.binding('confirmationDetails.shippingAddressCityStateZip')) + } + }; + + var links = { + orderDetails: element(by.binding('orderInfo.orderId')) + }; + + this.goToOrderDetails = function () { + links.orderDetails.click(); + }; + + this.getTaxLine = function () { + return element(textDisplays.taxLines.row(1).column('taxLine.name')).getText(); + }; + + this.getTaxLineAmount = function () { + return element(textDisplays.taxLines.row(0).column('taxLine.amount')).getText(); + }; + + this.getSuccessMessage = function() { + return textDisplays.successMessage.getText(); + }; + + this.verifyCustomerDetails = function (customer,orderTotal,isMobile) { + expect(this.getSuccessMessage()).toContain(customer.email.split('@')[0]); + expect(this.getCustomerNameOnShippingAddress()).toContain(customer.address.contactName.toUpperCase()); + expect(this.getShippingAddress()).toContain(customer.address.street.split(' ')[0]); + expect(this.getShippingAddressCityStateZipCode()).toContain(customer.address.cityStateZipCode); + expect(this.getTotalPrice(isMobile)).toEqual(orderTotal); + + }; + + this.getShippingAddressCityStateZipCode = function() { + return textDisplays.shippingAddress.cityStateZipCode.getText(); + }; + + this.getShippingAddress = function () { + return textDisplays.shippingAddress.address1.getText(); + }; + + this.getTotalPrice = function (isMobile) { + if(isMobile === true) { + return textDisplays.totalPriceMobile.getText(); + } + else if(isMobile === false) { + return textDisplays.totalPrice.getText(); + } + }; + + this.getCustomerNameOnShippingAddress = function () { + return textDisplays.shippingAddress.name.getText(); + }; + + this.getTotalDiscount = function () { + return textDisplays.totalDiscount.getText(); + }; + + this.createAccount = function () { + inputFields.newAccountPassword.clear(); + inputFields.newAccountPassword.sendKeys('password'); + buttons.createAccount.click(); + }; + +}; + +module.exports = ConfirmationPageObject; diff --git a/test/e2e/coupon-tests.js b/test/e2e/coupon-tests.js deleted file mode 100644 index b15008892..000000000 --- a/test/e2e/coupon-tests.js +++ /dev/null @@ -1,280 +0,0 @@ -var fs = require('fs'); -var tu = require('./protractor-utils.js'); - - -describe('coupons:', function () { - - function addProductandApplyCoupon(couponCode, price) { - tu.loadProductIntoCart('1', price); - tu.clickElement('id', 'coupon-code'); - tu.sendKeys('id', 'coupon-code', couponCode); - tu.clickElement('id', 'apply-coupon'); - } - - function verifyCartDetails(cartAmount, totalAmount, discountAmount) { - tu.verifyCartAmount(cartAmount); - tu.verifyCartTotal(totalAmount); - tu.verifyCartDiscount(discountAmount); - } - - function removeFromCart() { - tu.clickElement('id', tu.removeFromCart); - browser.wait(function () { - return element(by.xpath("//div[@id='cart']/div/div[2]")).isDisplayed(); - }); - expect(element(by.xpath("//div[@id='cart']/div/div[2]")).getText()).toEqual('YOUR CART IS EMPTY'); - } - - function couponCheckoutTest(couponCode, price, discount) { - var category = element(by.repeater('top_category in categories').row(1).column('top_category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - addProductandApplyCoupon(couponCode, price); - verifyCartDetails('1', price, discount); - tu.clickElement('binding', 'CHECKOUT'); - browser.wait(function () { - return element(by.id("ccNumber")).isPresent(); - /**/ - }); - tu.sendKeys('id', 'firstNameAccount', 'Mike'); - tu.sendKeys('id', 'lastNameAccount', 'Night'); - tu.selectOption('order.account.title', 'MR'); - //element(by.id('titleAccount')).sendKeys('Mr.'); - - browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - browser.sleep(2000); - tu.clickElement('id', 'preview-order-btn'); - }); - - // Verify the price and discount on the checkout page - expect(element(by.binding('cart.totalPrice.amount')).getText()).toContain(price); - expect(element(by.binding('cart.totalDiscount.amount')).getText()).toContain(discount); - - - browser.sleep(2000); - browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { - tu.fillCreditCardForm('5555555555554444', '06', '2019', '000'); - browser.sleep(500); - tu.clickElement('id', 'place-order-btn'); - }); - } - - describe('verify coupons', function () { - - beforeEach(function () { - browser.manage().deleteAllCookies(); - browser.driver.manage().window().setSize(1200, 1000); - browser.get(tu.tenant + '/#!/ct/'); - browser.switchTo().alert().then( - function (alert) { - alert.accept(); - }, - function (err) { - } - ); - }); - - it('should not allow user to add coupon if not logged in', function () { - tu.loadProductIntoCart('1', '$11.42'); - tu.clickElement('id', 'coupon-code'); - tu.sendKeys('id', 'coupon-code', 'SIGNEDIN'); - tu.clickElement('id', 'apply-coupon'); - expect(element(by.binding('couponErrorMessage')).getText()).toEqual('SIGN IN TO USE COUPON CODE'); - }); - - // TP-4483 opened - xit('should not allow user to add coupon below minimum on cart', function () { - tu.loadProductIntoCartAndVerifyCart('1', '$20.62'); - tu.clickElement('id', 'coupon-code'); - tu.sendKeys('id', 'coupon-code', '20MINIMUM'); - tu.clickElement('id', 'apply-coupon'); - expect(element(by.binding('couponErrorMessage')).getText()).toEqual('THE ORDER VALUE IS TOO LOW FOR THIS COUPON.'); - browser.sleep(1000); - removeFromCart(); - browser.sleep(500); - }); - - it('should not allow user to add coupon with incorrect currency', function () { - browser.wait(function () { - return element(by.xpath(tu.whiteCoffeeMug)).isPresent(); - }); - browser.sleep(500); - tu.clickElement('xpath', tu.whiteCoffeeMug); - tu.switchSite('Sushi Demo Store Germany'); - var category = element(by.repeater('top_category in categories').row(1).column('top_category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - tu.loadProductIntoCartAndVerifyCart('1', '€12.99'); - tu.clickElement('id', 'coupon-code'); - tu.sendKeys('id', 'coupon-code', '10DOLLAR'); - tu.clickElement('id', 'apply-coupon'); - // - //expect(element(by.binding('couponErrorMessage')).getText()).toEqual('WÄHRUNG FÜR COUPON UNGÜLTIG'); - expect(element.all(by.css('.error')).first().getText()).toEqual('WÄHRUNG FÜR COUPON UNGÜLTIG'); - browser.sleep(1000); - tu.clickElement('id', tu.removeFromCart); - browser.sleep(500); - }); - - it('should not allow other customers to use specific coupon', function () { - tu.loginHelper('coupon@hybristest.com', 'password'); - tu.loadProductIntoCart('1', '$11.42'); - tu.clickElement('id', 'coupon-code'); - tu.sendKeys('id', 'coupon-code', 'SPECIFIC'); - tu.clickElement('id', 'apply-coupon'); - expect(element(by.binding('couponErrorMessage')).getText()).toEqual('COUPON NOT VALID'); - browser.sleep(1000); - removeFromCart(); - browser.sleep(500); - }); - - it('should add percentage off coupon on cart', function () { - addProductandApplyCoupon('10PERCENT', '$19.27'); - verifyCartDetails('1', '$19.47', '-$1.07'); - tu.clickElement('id', 'remove-coupon'); - removeFromCart(); - }); - - it('should add dollar off coupon on cart', function () { - addProductandApplyCoupon('10DOLLAR', '$19.27'); - verifyCartDetails('1', '$9.92', '-$10.00'); - tu.clickElement('id', 'remove-coupon'); - removeFromCart(); - }); - - it('update coupon totals when item is added and removed from cart', function () { - addProductandApplyCoupon('10PERCENT', '$19.27'); - verifyCartDetails('1', '$19.47', '-$1.07'); - tu.clickElement('id', 'continue-shopping'); - var category = element(by.repeater('top_category in categories').row(1).column('top_category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - browser.sleep(250); - tu.clickElement('xpath', tu.whiteThermos); - browser.sleep(200); - tu.clickElement('id', tu.buyButton); - browser.sleep(5500); - browser.wait(function () { - return element(by.id(tu.cartButtonId)).isDisplayed(); - }); - browser.sleep(1000); - tu.clickElement('id', tu.cartButtonId); - tu.waitForCart(); - browser.sleep(500); - verifyCartDetails('1', '$33.91', '-$2.57'); - tu.clickElement('id', tu.removeFromCart); - verifyCartDetails('1', '$23.64', '-$1.50'); - browser.sleep(1000); - tu.clickElement('id', 'remove-coupon'); - removeFromCart(); - browser.sleep(500); - - }); - - it('should update coupon totals when quantity is changed', function () { - addProductandApplyCoupon('10PERCENT', '$19.27'); - verifyCartDetails('1', '$19.47', '-$1.07'); - tu.sendKeys('xpath', tu.cartQuantity, '5'); - tu.clickElement('binding', 'EST_ORDER_TOTAL'); - browser.sleep(1000); - verifyCartDetails('5', '$54.58', '-$5.34'); - tu.clickElement('id', 'remove-coupon'); - removeFromCart(); - }); - - it('should remove coupon on cart', function () { - addProductandApplyCoupon('10PERCENT', '$20.62'); - verifyCartDetails('1', '$19.47', '-$1.07'); - tu.clickElement('id', 'remove-coupon'); - tu.verifyCartAmount('1'); - tu.verifyCartTotal('$20.62'); - removeFromCart(); - }); - - // TP-4483 opened - xit('should not allow user to use expired coupon on cart', function () { - addProductandApplyCoupon('EXPIRED', '$11.42'); - expect(element(by.binding('couponErrorMessage')).getText()).toEqual('COUPON HAS EXPIRED.'); - removeFromCart(); - }); - - // Comment out this test, as Coupon is not available in checkout page at the moment(following changes for shipping rates - xit('should not allow purchase under minimum at checkout', function () { - tu.createAccount('coupontestmin1'); - tu.populateAddress('0', 'Coupon Test', '123 fake place', 'apt 419', 'Boulder', 'CO', '80301', '303-303-3333'); - browser.sleep(1000); - var category = element(by.repeater('top_category in categories').row(1).column('category.name')); - browser.driver.actions().mouseMove(category).perform(); - browser.sleep(200); - category.click(); - tu.loadProductIntoCartAndVerifyCart('1', '$19.27'); - tu.clickElement('binding', 'CHECKOUT'); - browser.wait(function () { - return element(by.id("ccNumber")).isPresent(); - }); - tu.sendKeys('id', 'firstNameAccount', 'Mike'); - tu.sendKeys('id', 'lastNameAccount', 'Night'); - element(by.id('titleAccount')).sendKeys('Mr.'); - tu.clickElement('linkText', 'Add Coupon Code'); - tu.sendKeys('id', 'coupon-code', '20MINIMUM'); - tu.clickElement('id', 'apply-coupon'); - browser.wait(function () { - return element(by.binding('couponErrorMessage')).isPresent(); - }); - expect(element(by.binding('couponErrorMessage')).getText()).toContain('The order value is too low for this coupon.'); - - }); - - it('should allow purchase over minimum', function () { - tu.createAccount('coupontestmin2'); - tu.populateAddress('United States', 'Coupon Test', '123 fake place', 'apt 419', 'Boulder', 'CO', '80301', '303-303-3333'); - couponCheckoutTest('MINIMUM', '$20.05', '-$0.53'); - tu.verifyOrderConfirmation('COUPONTEST', 'COUPON TEST', '123', 'BOULDER, CO 80301', '$20.05'); - expect(element(by.css('span.error.ng-binding')).getText()).toEqual('-$0.53'); - }); - - it('should allow coupon larger than purchase price', function () { - tu.createAccount('coupontestmax2'); - tu.populateAddress('United States', 'Coupon Test', '123 fake place', 'apt 419', 'Boulder', 'CO', '80301', '303-303-3333'); - couponCheckoutTest('20DOLLAR', '$9.20', '-$10.67'); - tu.verifyOrderConfirmation('COUPONTEST', 'COUPON TEST', '123', 'BOULDER, CO 80301', '$9.20'); - expect(element(by.css('span.error.ng-binding')).getText()).toEqual('-$10.67'); - }); - - it('should allow percentage off on checkout', function () { - tu.createAccount('coupontestpercent'); - tu.populateAddress('United States', 'Coupon Test', '123 fake place', 'apt 419', 'Boulder', 'CO', '80301', '303-303-3333'); - couponCheckoutTest('10PERCENT', '$19.47', '-$1.07'); - tu.verifyOrderConfirmation('COUPONTEST', 'COUPON TEST', '123', 'BOULDER, CO 80301', '$19.47'); - expect(element(by.css('span.error.ng-binding')).getText()).toEqual('-$1.07'); - }); - - it('should allow dollar off on checkout', function () { - tu.createAccount('coupontestdollar'); - tu.populateAddress('United States', 'Coupon Test', '123 fake place', 'apt 419', 'Boulder', 'CO', '80301', '303-303-3333'); - couponCheckoutTest('10DOLLAR', '$9.92', '-$10.00'); - tu.verifyOrderConfirmation('COUPONTEST', 'COUPON TEST', '123', 'BOULDER, CO 80301', '$9.92'); - expect(element(by.css('span.error.ng-binding')).getText()).toEqual('-$10.00'); - }); - - xit('should allow customer to use specific coupon', function () { - tu.loginHelper('specific@hybristest.com', 'password'); - couponCheckoutTest('SPECIFIC', '$11.42', 0); - tu.verifyOrderConfirmation('SPECIFIC', 'SPECIFIC PERSON', '123', 'BOULDER, CO 80301', '$10.67'); - expect(element(by.css('span.error.ng-binding')).getText()).toEqual('-$2.13'); - }); - - xit('should allow euro off on checkout', function () { - tu.createAccount('coupontesteuro'); - tu.populateAddress('0', 'Coupon Test', '123 fake place', 'apt 419', 'Boulder', 'CO', '80301', '303-303-3333'); - tu.selectCurrency('EURO'); - couponCheckoutTest('5EURO', '€7.99', 0); - tu.verifyOrderConfirmation('COUPONTEST', 'COUPON TEST', '123', 'BOULDER, CO 80301', '€7.99'); - expect(element(by.css('span.error.ng-binding')).getText()).toEqual('-€5.00'); - }); - }); -}); - diff --git a/test/e2e/coupon/coupon.po.js b/test/e2e/coupon/coupon.po.js new file mode 100644 index 000000000..46c8ac987 --- /dev/null +++ b/test/e2e/coupon/coupon.po.js @@ -0,0 +1,33 @@ +'use strict'; + +var CouponPageObject = function () { + + var buttons = { + applyCoupon: element(by.id('apply-coupon')), + removeCoupon: element(by.id('remove-coupon')) + }; + + var inputFields = { + couponCode: element(by.id('coupon-code')) + }; + + var textDisplays = { + errorMessage: element(by.binding('couponErrorMessage')) + }; + + this.applyCoupon = function (couponCode) { + inputFields.couponCode.click(); + inputFields.couponCode.sendKeys(couponCode); + buttons.applyCoupon.click(); + }; + + this.removeCoupon = function () { + buttons.removeCoupon.click(); + }; + + this.getErrorMessage = function () { + return textDisplays.errorMessage.getText(); + }; +}; + +module.exports = CouponPageObject; \ No newline at end of file diff --git a/test/e2e/coupon/coupon.spec.js b/test/e2e/coupon/coupon.spec.js new file mode 100644 index 000000000..c82381912 --- /dev/null +++ b/test/e2e/coupon/coupon.spec.js @@ -0,0 +1,485 @@ +'use strict'; + +var desktopSiteConfig = require('../config/desktop-site.json'); + +var TI = require('./coupon.test-input.json'); +var utils = require('../utils/utils.js'); +var CouponPageObject = require('./coupon.po.js'); +var CartPageObject = require('../cart/cart.po.js'); +var ProductDetailsPageObject = require('../product/product-details.po.js'); +var AccountPageObject = require('../account/account.po.js'); +var SitePageObject = require('../site/site.po.js'); +var CheckoutPageObject = require('../checkout/checkout.po.js'); +var ConfirmationPageObject = require('../confirmation/confirmation.po.js'); + + +describe('Coupon Tests :', function () { + + var cartPO, + productDetailsPO, + accountPO, + sitePO, + couponPO, + checkoutPO, + confirmationPO; + + var testCoupons = TI.coupons; + var whiteCoffeeMug = TI.whiteCoffeeMug; + var testUsers = TI.users; + + var isMobile = false; + var isLoggedIn = true; + var openModal = true; + + describe('cart', function () { + + beforeEach(function () { + utils.deleteCookies(); + + utils.setWindowSize(desktopSiteConfig.windowDetails.width, desktopSiteConfig.windowDetails.height); + + cartPO = new CartPageObject(); + couponPO = new CouponPageObject(); + productDetailsPO = new ProductDetailsPageObject(); + accountPO = new AccountPageObject(); + sitePO = new SitePageObject(); + checkoutPO = new CheckoutPageObject(); + confirmationPO = new ConfirmationPageObject(); + }); + + it('should not allow user to add certain coupons if not logged in', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.signedIn.name); + + expect(couponPO.getErrorMessage()).toEqual(testCoupons.signedIn.errorMessageEN); + }); + + it('should not allow user to add coupon below minimum', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.twentyMinimum.name); + + expect(couponPO.getErrorMessage()).toEqual(testCoupons.twentyMinimum.errorMessageEN); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.EN); + }); + + it('should not allow user to add coupon with incorrect currency', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + sitePO.waitForSiteSelector(); + + sitePO.setSite(TI.sites.SushiGermany); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceDE); + + couponPO.applyCoupon(testCoupons.tenDollar.name); + + expect(couponPO.getErrorMessage()).toEqual(testCoupons.tenDollar.errorMessageDE); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.DE); + }); + + it('should not allow other customers to use specific coupon', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + accountPO.loginUser(testUsers.couponUser); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.specific.name); + + expect(couponPO.getErrorMessage()).toEqual(testCoupons.specific.errorMessageEN); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.EN); + }); + + it('should add percentage off coupon', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.tenPercent.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.differenceUS); + + couponPO.removeCoupon(); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.EN); + }); + + it('should add dollar off coupon on cart', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.tenDollar.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.tenDollar.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.tenDollar.whiteCoffeeMug.differenceUS); + + couponPO.removeCoupon(); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.EN); + }); + + it('update coupon totals when an item is added and removed', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.tenPercent.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.differenceUS); + + cartPO.continueShopping(); + + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(TI.whiteCoffeeMug.two.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(TI.whiteCoffeeMug.two.discountUS); + + couponPO.removeCoupon(); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.EN); + }); + + it('should update coupon totals when quantity is changed', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.tenPercent.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.differenceUS); + + cartPO.updateItemQuantity(5); + + expect(cartPO.getCartTotalAmount()).toEqual(TI.whiteCoffeeMug.five.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(TI.whiteCoffeeMug.five.discountUS); + + couponPO.removeCoupon(); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.EN); + }); + + it('should remove coupon', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.tenPercent.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.differenceUS); + + couponPO.removeCoupon(); + + expect(cartPO.getCartItemQuantity()).toEqual('1'); + + expect(cartPO.getCartTotalAmount()).toEqual(TI.whiteCoffeeMug.one.priceUS); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.EN); + }); + + it('should not allow user to use expired coupon', function () { + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + + expect(cartPO.getCartTotalAmount()).toEqual(whiteCoffeeMug.one.priceUS); + + couponPO.applyCoupon(testCoupons.expired.name); + + expect(couponPO.getErrorMessage()).toEqual(testCoupons.expired.errorMessageEN); + + cartPO.emptyCart(); + + cartPO.waitForCartMessage(); + + expect(cartPO.getCartMessage()).toEqual(TI.emptyCartMessage.EN); + + }); + + it('should allow purchase over minimum', function () { + sitePO.getHomePage(); + + accountPO.createAccount(testUsers.couponTestUser,openModal); + + accountPO.accountDetails.getPage(); + + accountPO.populateAddress(testUsers.couponTestUser.address); + + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + + couponPO.applyCoupon(testCoupons.minimum.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.minimum.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.minimum.whiteCoffeeMug.differenceUS); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForCreditCardField(); + + checkoutPO.fillNameFields(TI.selectModel,testUsers.main.name); + + checkoutPO.goToPreviewOrder(); + + expect(checkoutPO.orderPreview.getTotalPrice()).toContain(testCoupons.minimum.whiteCoffeeMug.priceUS); + expect(checkoutPO.orderPreview.getTotalDiscount()).toContain(testCoupons.minimum.whiteCoffeeMug.differenceUS); + + checkoutPO.fillCreditCardFields(TI.creditCard); + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.couponTestUser,testCoupons.minimum.whiteCoffeeMug.priceUS,isMobile); + + expect(confirmationPO.getTotalDiscount()).toEqual(testCoupons.minimum.whiteCoffeeMug.differenceUS); + }); + + it('should allow coupon larger than purchase price', function () { + sitePO.getHomePage(); + + accountPO.createAccount(testUsers.couponTestUser,openModal); + + accountPO.accountDetails.getPage(); + + accountPO.populateAddress(testUsers.couponTestUser.address); + + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + + couponPO.applyCoupon(testCoupons.twentyDollar.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.twentyDollar.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.twentyDollar.whiteCoffeeMug.differenceUS); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForCreditCardField(); + + checkoutPO.fillNameFields(TI.selectModel, testUsers.main.name); + + checkoutPO.goToPreviewOrder(); + + expect(checkoutPO.orderPreview.getTotalPrice()).toContain(testCoupons.twentyDollar.whiteCoffeeMug.priceUS); + expect(checkoutPO.orderPreview.getTotalDiscount()).toContain(testCoupons.twentyDollar.whiteCoffeeMug.differenceUS); + + checkoutPO.fillCreditCardFields(TI.creditCard); + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.couponTestUser,testCoupons.twentyDollar.whiteCoffeeMug.priceUS,isMobile); + + expect(confirmationPO.getTotalDiscount()).toEqual(testCoupons.twentyDollar.whiteCoffeeMug.differenceUS); + + }); + + it('should allow percentage off on checkout', function () { + sitePO.getHomePage(); + + accountPO.createAccount(testUsers.couponTestUser,openModal); + + accountPO.accountDetails.getPage(); + + accountPO.populateAddress(testUsers.couponTestUser.address); + + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + + couponPO.applyCoupon(testCoupons.tenPercent.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.differenceUS); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForCreditCardField(); + + checkoutPO.fillNameFields(TI.selectModel, testUsers.main.name); + + checkoutPO.goToPreviewOrder(); + + expect(checkoutPO.orderPreview.getTotalPrice()).toContain(testCoupons.tenPercent.whiteCoffeeMug.priceUS); + expect(checkoutPO.orderPreview.getTotalDiscount()).toContain(testCoupons.tenPercent.whiteCoffeeMug.differenceUS); + + checkoutPO.fillCreditCardFields(TI.creditCard); + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.couponTestUser,testCoupons.tenPercent.whiteCoffeeMug.priceUS,isMobile); + + expect(confirmationPO.getTotalDiscount()).toEqual(testCoupons.tenPercent.whiteCoffeeMug.differenceUS); + }); + + it('should allow dollar off on checkout', function () { + sitePO.getHomePage(); + + accountPO.createAccount(testUsers.couponTestUser,openModal); + + accountPO.accountDetails.getPage(); + + accountPO.populateAddress(testUsers.couponTestUser.address); + + productDetailsPO.get(whiteCoffeeMug.id); + + productDetailsPO.addProductToCart(1); + cartPO.waitUntilNotificationIsDissmised(); + cartPO.showCart(isMobile); + + cartPO.waitUntilCartTotalIsDisplayed(); + + couponPO.applyCoupon(testCoupons.tenDollar.name); + + expect(cartPO.getCartTotalAmount()).toEqual(testCoupons.tenDollar.whiteCoffeeMug.priceUS); + expect(cartPO.getCartDiscountAmount()).toEqual(testCoupons.tenDollar.whiteCoffeeMug.differenceUS); + + cartPO.goToCheckout(isLoggedIn); + + checkoutPO.waitForCreditCardField(); + + checkoutPO.fillNameFields(TI.selectModel, testUsers.main.name); + + browser.executeScript('window.scrollTo(0, document.body.scrollHeight)').then(function () { + checkoutPO.goToPreviewOrder(); + }); + + expect(checkoutPO.orderPreview.getTotalPrice()).toContain(testCoupons.tenDollar.whiteCoffeeMug.priceUS); + expect(checkoutPO.orderPreview.getTotalDiscount()).toContain(testCoupons.tenDollar.whiteCoffeeMug.differenceUS); + + checkoutPO.fillCreditCardFields(TI.creditCard); + checkoutPO.placeOrder(); + + checkoutPO.waitForConfirmationPage(); + + confirmationPO.verifyCustomerDetails(testUsers.couponTestUser,testCoupons.tenDollar.whiteCoffeeMug.priceUS,isMobile); + + expect(confirmationPO.getTotalDiscount()).toEqual(testCoupons.tenDollar.whiteCoffeeMug.differenceUS); + }); + }); +}); diff --git a/test/e2e/coupon/coupon.test-input.json b/test/e2e/coupon/coupon.test-input.json new file mode 100644 index 000000000..22c6282ea --- /dev/null +++ b/test/e2e/coupon/coupon.test-input.json @@ -0,0 +1,126 @@ +{ + "whiteCoffeeMug": { + "id": "55d76ce63a0eafb30e5540c8", + "one": { + "priceUS": "$20.62", + "priceDE": "€12.99" + }, + + "two": { + "priceUS": "$29.76", + "discountUS": "-$2.13" + }, + + "five": { + "priceUS": "$53.40", + "discountUS": "-$5.34" + } + }, + + "sites": { + "SushiGermany": { + "siteName": "Sushi Demo Store Germany", + "mode": "Desktop" + } + }, + + "emptyCartMessage": { + "EN": "YOUR CART IS EMPTY", + "DE": "IHR WARENKORB IST LEER" + }, + + "selectModel": "order.account.title", + + "creditCard": { + "cardNumber": 5555555555554444, + "expiryMonth": "06", + "expiryYear": 2019, + "cvcCode": "000" + }, + + "coupons": { + "signedIn": { + "name": "SIGNEDIN", + "errorMessageEN": "SIGN IN TO USE COUPON CODE" + }, + + "minimum": { + "name": "MINIMUM", + "whiteCoffeeMug": { + "priceUS": "$20.05", + "differenceUS": "-$0.53" + } + }, + + "twentyDollar": { + "name": "20DOLLAR", + "whiteCoffeeMug": { + "priceUS": "$9.20", + "differenceUS": "-$10.67" + } + }, + + "tenDollar": { + "name": "10DOLLAR", + "errorMessageDE": "WÄHRUNG FÜR COUPON UNGÜLTIG", + "whiteCoffeeMug": { + "priceUS": "$9.92", + "differenceUS": "-$10.00" + } + }, + + "tenPercent": { + "name": "10PERCENT", + "whiteCoffeeMug": { + "priceUS": "$19.47", + "differenceUS": "-$1.07" + } + }, + "specific": { + "name": "SPECIFIC", + "errorMessageEN": "COUPON NOT VALID" + }, + + "twentyMinimum": { + "name": "20MINIMUM", + "errorMessageEN": "THE ORDER VALUE IS TOO LOW FOR THIS COUPON" + }, + + "expired": { + "name": "EXPIRED", + "errorMessageEN": "THE COUPON IS NOT ACTIVE" + } + }, + + "users": { + "main": { + "name": { + "designation": "MR", + "firstName": "Mike", + "lastName": "Night" + } + }, + + "couponTestUser": { + "name": "coupontestmin2", + "email": "coupontest", + "password": "password", + "address": { + "country": "United States", + "contactName": "Coupon Test", + "street": "123 fake place", + "aptNumber": "apt 419", + "city": "Boulder", + "state": "CO", + "zipCode": "80301", + "cityStateZipCode": "BOULDER, CO 80301", + "contactPhone": "303-303-3333" + } + }, + + "couponUser": { + "username": "coupon@hybristest.com", + "password": "password" + } + } +} \ No newline at end of file diff --git a/test/e2e/login-tests.js b/test/e2e/login-tests.js deleted file mode 100644 index 170a42d92..000000000 --- a/test/e2e/login-tests.js +++ /dev/null @@ -1,275 +0,0 @@ -var fs = require('fs'); -var tu = require('./protractor-utils.js'); - -var timestamp = Number(new Date()); - -function updateNameField(id, text) { - element(by.id(id)).clear(); - browser.executeScript("document.getElementById('" + id + "').style.display='block';"); - element(by.id(id)).sendKeys(text); -} - -function waitForAccountPage() { - browser.wait(function () { - return element(by.binding('MY_ACCOUNT')).isPresent(); - }); -} - -function clickOnModalDeleteAddress() { - browser.switchTo().defaultContent(); - browser.sleep(1000); - browser.waitForAngular(); - browser.wait(function () { - return element(by.css('.modal-content')).isPresent(); - }); - tu.clickElement('id', 'confirm-delete-address-btn'); -} - - -describe("login:", function () { - - - describe("verify login functionality", function () { - - beforeEach(function () { - // ENSURE WE'RE TESTING AGAINST THE FULL SCREEN VERSION - browser.manage().deleteAllCookies(); - browser.driver.manage().window().setSize(1200, 1100); - browser.get(tu.tenant + '/#!/ct'); - browser.switchTo().alert().then( - function (alert) { - alert.dismiss(); - }, - function (err) { - } - ); - - }); - - it('should not allow user to login', function () { - tu.loginHelper('bad@bad.com', 'bad'); - expect(element(by.binding("error.message")).getText()).toEqual("You entered an invalid email or password."); - }); - - it('should allow existing user to login', function () { - tu.loginHelper('cool@cool.com', 'coolio'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - browser.sleep(1000); - expect(element(by.binding("account.firstName")).getText()).toContain('JOE'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - browser.sleep(1000); - tu.clickElement('id', 'logout-btn'); - }); - - it('should allow user to update account info', function () { - tu.loginHelper('cool@cool.com', 'coolio'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - browser.sleep(2000); - expect(element(by.binding("account.lastName")).getText()).toContain('Cool'); - tu.clickElement('id', 'edit-user-info'); - updateNameField('firstNameAccount', 'first'); - tu.sendKeys('id', 'middleNameAccount', 'middle'); - updateNameField('lastNameAccount', 'last'); - tu.clickElement('id', 'save-btn'); - expect(element(by.binding("account.lastName")).getText()).toContain('first middle last'); - tu.clickElement('id', 'edit-user-info'); - updateNameField('firstNameAccount', 'Joe'); - tu.sendKeys('id', 'middleNameAccount', 'C'); - updateNameField('lastNameAccount', 'Cool'); - tu.clickElement('id', 'save-btn'); - expect(element(by.binding("account.lastName")).getText()).toContain('Joe C Cool'); - }); - - it('should create a new user', function () { - tu.clickElement('id', 'login-btn'); - browser.wait(function () { - return element(by.binding('CREATE_ACCOUNT')).isPresent(); - }); - tu.clickElement('binding', 'CREATE_ACCOUNT'); - tu.sendKeys('id', 'emailInput', 'cool@cool' + timestamp + '.com'); - tu.sendKeys('id', 'newPasswordInput', 'pass'); - tu.clickElement('id', 'create-acct-btn'); - expect(element(by.binding("error.message")).getText()).toEqual("Password invalid - minimum of 6 characters required."); - tu.sendKeys('id', 'newPasswordInput', 'password'); - tu.clickElement('id', 'create-acct-btn'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - expect(element(by.css("h2.pull-left.ng-binding")).getText()).toEqual("Addressbook"); - }); - - it('should allow existing user to manage addresses', function () { - //dismisses pop-ups in phantomjs - browser.executeScript('window.confirm = function(){return true;}'); - tu.createAccount('addresstest'); - tu.populateAddress('United States', 'Address Test', '123 fake place', 'apt 419', 'Boulder', 'CO', '80301', '303-303-3333'); - browser.sleep(500); - // expect(element(by.binding("defaultAddress.street")).getText()).toEqual("123 fake place"); - expect(element(by.repeater('address in addresses').row(0).column('address.street')).getText()).toEqual('123 fake place, apt 419'); - expect(element(by.repeater('address in addresses').row(0).column('address.city')).getText()).toEqual('Boulder, CO 80301'); - expect(element(by.repeater('address in addresses').row(0).column('address.country')).getText()).toEqual('US'); - expect(element(by.repeater('address in addresses').row(0).column('address.contactPhone')).getText()).toEqual('303-303-3333'); - tu.populateAddress('Canada', '2nd Test', '321 phony street', 'apt 420', 'Toronto', 'ON', 'M4M 1H7', '720-555-1234'); - expect(element(by.repeater('address in addresses').row(1).column('address.contactName')).getText()).toEqual('2nd Test'); - expect(element(by.repeater('address in addresses').row(1).column('address.street')).getText()).toEqual('321 phony street, apt 420'); - expect(element(by.repeater('address in addresses').row(1).column('address.city')).getText()).toEqual('Toronto, ON M4M 1H7'); - expect(element(by.repeater('address in addresses').row(1).column('address.country')).getText()).toEqual('CA'); - expect(element(by.repeater('address in addresses').row(1).column('address.contactPhone')).getText()).toEqual('720-555-1234'); - //tu.clickElement('xpath', "(//button[@id='set-default-btn'])[2]"); - tu.clickElement('xpath', '//*[@id="set-default-btn"]/span'); - browser.sleep(1500); - expect(element(by.repeater('address in addresses').row(0).column('address.street')).getText()).toEqual('321 phony street, apt 420'); - //tu.clickElement('xpath', "( //button[@id='set-default-btn'])[2]"); - tu.clickElement('xpath', '//*[@id="set-default-btn"]/span'); - browser.sleep(1000); - expect(element(by.repeater('address in addresses').row(0).column('address.street')).getText()).toEqual('123 fake place, apt 419'); - tu.clickElement('id', 'delete-address-btn'); - // Confirm delete address - clickOnModalDeleteAddress(); - browser.wait(function () { - return element(by.id('delete-address-btn')).isPresent(); - }); - tu.clickElement('id', 'delete-address-btn'); - // Confirm delete address - clickOnModalDeleteAddress(); - expect(element(by.id('delete-address-btn')).isPresent()).toBe(false); - }); - - it('should not allow user to update their password with incorrect password', function () { - tu.loginHelper('badpassword@test.com', 'password'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - waitForAccountPage(); - tu.clickElement('id', 'update-password'); - tu.sendKeys('id', 'currentPassword', 'incorrect'); - tu.sendKeys('id', 'newPassword', 'notnew'); - tu.sendKeys('id', 'confirmNewPassword', 'notnew'); - tu.clickElement('id', 'update-password-btn'); - browser.sleep(500); - expect(element(by.binding("error.message")).getText()).toEqual("Please provide correct current password!"); - tu.clickElement('css', "a.close > span"); - }); - - it('should not allow user to update their password if it less than 6 chars', function () { - tu.loginHelper('badpassword@test.com', 'password'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - waitForAccountPage(); - tu.clickElement('id', 'update-password'); - tu.sendKeys('id', 'currentPassword', 'password'); - tu.sendKeys('id', 'newPassword', '123'); - tu.sendKeys('id', 'confirmNewPassword', '123'); - browser.sleep(500); - expect(element(by.id('update-password-btn')).isEnabled()).toBe(false); - tu.clickElement('css', "a.close > span"); - }); - - it('should not allow user to update their password if it does not match confirmation', function () { - tu.loginHelper('badpassword@test.com', 'password'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - waitForAccountPage(); - tu.clickElement('id', 'update-password'); - tu.sendKeys('id', 'currentPassword', 'password'); - tu.sendKeys('id', 'newPassword', 'incorrect1'); - tu.sendKeys('id', 'confirmNewPassword', 'incorrect2'); - browser.sleep(500); - expect(element(by.id('update-password-btn')).isEnabled()).toBe(false); - tu.clickElement('css', "a.close > span"); - }); - - it('should allow user to update their password', function () { - tu.loginHelper('password@yaastest.com', 'password'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - waitForAccountPage(); - tu.clickElement('id', 'update-password'); - tu.sendKeys('id', 'currentPassword', 'password'); - tu.sendKeys('id', 'newPassword', 'password2'); - tu.sendKeys('id', 'confirmNewPassword', 'password2'); - browser.sleep(500); - tu.clickElement('id', 'update-password-btn'); - browser.sleep(1500); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'logout-btn'); - browser.sleep(500); - browser.get(tu.tenant + '/#!/ct'); - browser.sleep(1000); - tu.loginHelper('password@yaastest.com', 'password2'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - browser.sleep(1000); - tu.clickElement('id', 'update-password'); - tu.sendKeys('id', 'currentPassword', 'password2'); - tu.sendKeys('id', 'newPassword', 'password'); - tu.sendKeys('id', 'confirmNewPassword', 'password'); - browser.sleep(500); - tu.clickElement('id', 'update-password-btn'); - browser.sleep(1500); - }); - - xit('should allow user to access order confirmation', function () { - browser.sleep(5000); - browser.get(tu.tenant + '/#!/confirmation/P0T7S1A7/'); - browser.wait(function () { - return element(by.binding('SIGN_IN')).isPresent(); - }); - tu.sendKeys('id', 'usernameInput', 'order@yaastest.com'); - tu.sendKeys('id', 'passwordInput', 'password'); - tu.clickElement('id', 'sign-in-button'); - browser.sleep(1000); - expect(element(by.binding('orderInfo.orderId')).getText()).toEqual('Order# P0T7S1A7'); - }); - - it('should allow user to update their email', function () { - tu.loginHelper('cool@yaastest.com', 'coolio'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - waitForAccountPage(); - tu.clickElement('id', 'update-email'); - tu.sendKeys('id', 'newEmail', 'cool_new@yaastest.com'); - tu.sendKeys('id', 'password', 'coolio'); - browser.sleep(500); - tu.clickElement('id', 'save-btn'); - browser.sleep(500); - - // Check for modal window - "Check your email" - browser.switchTo().defaultContent(); - browser.sleep(1000); - browser.waitForAngular(); - browser.wait(function () { - return element(by.css('.modal-content')).isPresent(); - }); - - expect(element(by.binding('CHECK_EMAIL')).isPresent()).toBe(true); - element(by.css('.modal.fade.ng-isolate-scope.in')).click(); - browser.sleep(500); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'logout-btn'); - browser.sleep(500); - browser.get(tu.tenant + '/#!/ct'); - browser.sleep(1000); - // Verify the user still can login in with the old email, as the new one was not confirmed - tu.loginHelper('cool@yaastest.com', 'coolio'); - browser.sleep(1000); - tu.clickElement('id', 'my-account-dropdown'); - tu.clickElement('id', 'my-account-link'); - waitForAccountPage(); - expect(element(by.binding('account.contactEmail')).getText()).toContain('cool@yaastest.com'); - - }); - - }); -}); - diff --git a/test/e2e/product/product-details.po.js b/test/e2e/product/product-details.po.js new file mode 100644 index 000000000..953d45b4b --- /dev/null +++ b/test/e2e/product/product-details.po.js @@ -0,0 +1,28 @@ +'use strict'; + +var utils = require('../utils/utils.js'); + +var ProductDetailsPageObject = function () { + + var buttons = { + addToCart: element(by.id('buy-button')) + }; + + var inputFields = { + quantity: element(by.id('qty')) + }; + + this.get = function (productId) { + browser.get(utils.tenant + '/#!/products/' + productId); + }; + + this.addProductToCart = function (quantity) { + inputFields.quantity.clear(); + + inputFields.quantity.sendKeys(quantity); + + buttons.addToCart.click(); + }; +}; + +module.exports = ProductDetailsPageObject; \ No newline at end of file diff --git a/test/e2e/product-tests.js b/test/e2e/product/product.spec.js similarity index 96% rename from test/e2e/product-tests.js rename to test/e2e/product/product.spec.js index 8d38429a7..09a739b16 100644 --- a/test/e2e/product-tests.js +++ b/test/e2e/product/product.spec.js @@ -1,5 +1,5 @@ var fs = require('fs'); -var tu = require('./protractor-utils.js'); +var tu = require('../utils/protractor-utils.js'); describe('product page', function () { @@ -170,11 +170,10 @@ describe('product page', function () { return element(by.css('.col-xs-6 #search')).isPresent(); }); browser.sleep(5000); - tu.sendKeys('css', '.col-xs-6 #search', 'beer'); + tu.sendKeys('css', '.col-xs-6 #search', 'beer helles'); expect(element(by.repeater('result in search.results').row(0)).getText()).toContain('Beer Mug w/Helles'); - expect(element(by.repeater('result in search.results').row(1)).getText()).toContain('Beer Mug'); - element(by.repeater('result in search.results').row(1)).click(); - expect(element(by.binding(tu.productDescriptionBind)).getText()).toEqual("Traditional bavarian beer mug with hybris logo in blue. Drink your beer in the same style as hybris employees have done since the company's first days."); + element(by.repeater('result in search.results').row(0)).click(); + expect(element(by.binding(tu.productDescriptionBind)).getText()).toEqual('Traditional bavarian beer mug with hybris logo in blue. Drink your beer in the same style as hybris employees have done since the company\'s first days. Comes with a traditional bavarian Helles from Augustiner Brau.'); }); it('not return search results', function () { @@ -200,5 +199,5 @@ describe('product page', function () { }); }); -}); +}); diff --git a/test/e2e/site/site.po.js b/test/e2e/site/site.po.js new file mode 100644 index 000000000..d5436a498 --- /dev/null +++ b/test/e2e/site/site.po.js @@ -0,0 +1,47 @@ +'use strict'; + +var utils = require('../utils/utils.js'); + +var SitePageObject = function () { + + var links = { + desktopSiteOptions: element(by.css('#siteSelectorLarge .siteSelectorIcon')), + currentLanguage: element(by.binding('language.selected.value')) + }; + + var buttons = { + desktopSiteSelector: element(by.id('siteSelectorLarge')) + }; + + this.getHomePage = function () { + browser.get(utils.tenant + '/#!/ct/'); + }; + + this.setSite = function (site) { + if(site.mode === 'Desktop') { + links.desktopSiteOptions.click(); + var siteLink = element(by.cssContainingText('#siteSelectorLarge .regionControlList li', site.siteName)); + siteLink.click(); + } + }; + + this.waitForSiteSelector = function(mode) { + browser.wait(function () { + return buttons.desktopSiteSelector.isPresent(); + }); + browser.sleep(500); //Protactor fails to click the selector sometimes even with the wait + }; + + this.setLanguage = function (language) { + links.currentLanguage.click(); + var newLanguage = element(by.repeater('lang in languages').row(1)); + browser.wait(function () { + return newLanguage.isPresent(); + }); + browser.driver.actions().mouseMove(newLanguage).perform(); + expect(element(by.repeater('lang in languages').row(1)).getText()).toEqual(language); + newLanguage.click(); + }; +}; + +module.exports = SitePageObject; \ No newline at end of file diff --git a/test/e2e/protractor-utils.js b/test/e2e/utils/protractor-utils.js similarity index 96% rename from test/e2e/protractor-utils.js rename to test/e2e/utils/protractor-utils.js index d4b827244..38a9cfccf 100644 --- a/test/e2e/protractor-utils.js +++ b/test/e2e/utils/protractor-utils.js @@ -1,5 +1,5 @@ var fs = require('fs'); -var tu = require('./protractor-utils.js'); +var tu = require('../utils/protractor-utils.js'); var _ = require('underscore'); exports.whiteCoffeeMug = "//a[contains(@href, '/products/55d76ce63a0eafb30e5540c8/')]"; @@ -178,8 +178,7 @@ exports.switchSite = function (site) { _.each(items, function (item) { if (item.currSite == site) { sites.get(item.index).click(); - } - ; + }; }) }); //element.all(by.xpath('//*[@id="siteSelectorLarge"]/div/div/div/div/div/div[1]/ul/li')).each(function (currSite) { @@ -233,7 +232,7 @@ exports.loadProductIntoCart = function (cartAmount, cartTotal, verify) { tu.verifyCartAmount(cartAmount); tu.verifyCartTotal(cartTotal); } -} +}; //country is populated from localized-addresses.js exports.populateAddress = function (country, contact, street, aptNumber, city, state, zip, phone) { @@ -299,7 +298,7 @@ exports.fillCreditCardForm = function (ccNumber, ccMonth, ccYear, cvcNumber) { }; -exports.verifyOrderConfirmation = function (account, name, number, cityStateZip, price) { +exports.verifyOrderConfirmation = function (account, name, number, cityStateZip, price, mobile) { var email = account.toLowerCase(); browser.wait(function () { return element(by.css('address > span.ng-binding')).isPresent(); @@ -309,7 +308,14 @@ exports.verifyOrderConfirmation = function (account, name, number, cityStateZip, expect(element(by.binding('confirmationDetails.shippingAddressName')).getText()).toContain(name); expect(element(by.binding('confirmationDetails.shippingAddressStreetLine1')).getText()).toContain(number); expect(element(by.binding('confirmationDetails.shippingAddressCityStateZip')).getText()).toContain(cityStateZip); - expect(element(by.binding('confirmationDetails.totalPrice')).getText()).toEqual(price); + + if (mobile) { + //expect(element(by.binding('entry.totalPrice')).getText()).toEqual(price); + expect(element(by.css('td.text-left.product-details-mobile > div:nth-child(5) > strong')).getText()).toEqual(price); + } + else { + expect(element(by.binding('confirmationDetails.totalPrice')).getText()).toEqual(price); + } }; exports.removeItemFromCart = function () { diff --git a/test/e2e/utils/utils.js b/test/e2e/utils/utils.js new file mode 100644 index 000000000..4f9d4d9f7 --- /dev/null +++ b/test/e2e/utils/utils.js @@ -0,0 +1,50 @@ +'use strict'; + +exports.tenant = 'bsdqa'; + +exports.deleteCookies = function () { + browser.manage().deleteAllCookies(); +}; + +exports.scrollTo = function(elem) { + browser.executeScript(function(elem) { + elem.scrollIntoView(); + }, elem.getWebElement()); +}; + +exports.setWindowSize = function (width, height) { + browser.driver.manage().window().setSize(width, height); +}; + +exports.dumpBrowserConsoleLogs = function() { + browser.manage().logs().get('browser').then(function(browserLog) { + console.log('log: ' + require('util').inspect(browserLog)); + }); +}; + +exports.scrollToProduct = function (prodEl) { + var deferred = protractor.promise.defer(); + var maxCount = 10; + var count = 0; + while (count < maxCount) { + browser.executeScript('window.scrollTo(0,document.body.scrollHeight)'); + browser.sleep(500); + count++; + if (element(by.xpath(prodEl)).isPresent()) { + deferred.fulfill(); + } else if (count === maxCount) { + deferred.reject(); + } + } + return deferred.promise; +}; + +exports.selectOption = function (key, value) { + var field = element(by.model(key)); + var selectField = field.element(by.css('.ui-select-search')); + field.click(); + selectField.clear(); + selectField.sendKeys(value); + element.all(by.css('.ui-select-choices-row-inner span')).first().click(); +}; + diff --git a/test/unit/account/account-svc-spec.js b/test/unit/account/account-svc-spec.js index 417f08527..3a48921d5 100644 --- a/test/unit/account/account-svc-spec.js +++ b/test/unit/account/account-svc-spec.js @@ -70,6 +70,7 @@ describe('AccountSvc Test', function () { expect(AccountSvc.saveAddress).toBeDefined(); expect(AccountSvc.removeAddress).toBeDefined(); expect(AccountSvc.getCurrentAccount).toBeDefined(); + expect(AccountSvc.isItSocialAccount).toBeDefined(); }); describe('account()', function(){ @@ -227,5 +228,18 @@ describe('AccountSvc Test', function () { }); }); + describe('isItSocialAccount', function () { + it('Should correctly decide if user is signed in via social account', function() { + var account = {accounts: [{id: 1, providerId: 'google'}]}; + expect(AccountSvc.isItSocialAccount(account)).toBeTruthy(); + account = {accounts: [{id: 2, providerId: 'test'}, {id: 1, providerId: 'facebook'}]}; + expect(AccountSvc.isItSocialAccount(account)).toBeTruthy(); + account = {accounts: [{id: 1, providerId: 'test'}]}; + expect(AccountSvc.isItSocialAccount(account)).toBeFalsy(); + account = {accounts: [{id: 1}]}; + expect(AccountSvc.isItSocialAccount(account)).toBeFalsy(); + }); + }); + }); diff --git a/test/unit/account/controllers/account-ctrl-spec.js b/test/unit/account/controllers/account-ctrl-spec.js index a70e04533..a8eaf670e 100644 --- a/test/unit/account/controllers/account-ctrl-spec.js +++ b/test/unit/account/controllers/account-ctrl-spec.js @@ -29,6 +29,11 @@ describe('AccountCtrl Test', function () { total: 0 } }, + orders: { + meta: { + total: 0 + } + }, getUserTitles: jasmine.createSpy().andReturn(['', 'MR', 'MS', 'MRS', 'DR']) }; @@ -221,11 +226,39 @@ describe('AccountCtrl Test', function () { }); it("should show all of the orders", function () { + AccountCtrl.allOrdersLoaded = false; $scope.showAllOrders(); $scope.$digest(); expect(mockedOrderListSvc.query).toHaveBeenCalled(); expect($scope.showAllOrdersButton).toEqualData(false); expect($scope.orders).toEqualData(mockedOrderList); + expect(AccountCtrl.allOrdersLoaded).toBeTruthy(); + }); + + it('should not request the order service if all orders are loaded', function() { + AccountCtrl.allOrdersLoaded = true; + $scope.showAllOrders(); + $scope.$apply(); + expect(mockedOrderListSvc.query).not.toHaveBeenCalled(); + expect(AccountCtrl.allOrdersLoaded).toBeTruthy(); + }); + + it('should show all addresses', function() { + $scope.showAllAddressButton = true; + $scope.addresses = [{id:1}, {id:2}]; + $scope.showAllAddresses(); + $scope.$apply(); + expect($scope.showAddressFilter).toEqualData($scope.addresses.length); + expect($scope.showAllAddressButton).toBeFalsy(); + }); + + it('should show amount of addresses that is specified in default paramether', function() { + $scope.showAllAddressButton = false; + $scope.addresses = [{id:1}, {id:2}]; + $scope.showAllAddresses(); + $scope.$apply(); + expect($scope.showAddressFilter).toEqualData($scope.showAddressDefault); + expect($scope.showAllAddressButton).toBeTruthy(); }); it("should close address modal", function () { diff --git a/test/unit/account/controllers/account-order-detail-ctrl-spec.js b/test/unit/account/controllers/account-order-detail-ctrl-spec.js index 9d3745e3f..d558e17ba 100644 --- a/test/unit/account/controllers/account-order-detail-ctrl-spec.js +++ b/test/unit/account/controllers/account-order-detail-ctrl-spec.js @@ -1,11 +1,13 @@ describe('AccountOrderDetailCtrl Test', function () { - var $scope, $rootScope, $controller, $q; + var $scope, $rootScope, $controller, $q, modalPromise; var orderUrl = 'http://order-service.dprod.cf.hybris.com'; var orderRoute = '/orders'; var productsUrl = 'http://product-service.dprod.cf.hybris.com'; var productsRoute = '/products'; + var mockedModal = {}; + //*********************************************************************** // Common Setup @@ -13,7 +15,9 @@ describe('AccountOrderDetailCtrl Test', function () { //*********************************************************************** // configure the target controller's module for testing - see angular.mock\ - beforeEach(angular.mock.module('ds.account'), function () {}); + beforeEach(module('ds.account', function ($provide) { + $provide.value('$modal', mockedModal); + })); beforeEach(inject(function(_$rootScope_, _$controller_, _$q_) { @@ -26,6 +30,11 @@ describe('AccountOrderDetailCtrl Test', function () { $scope = _$rootScope_.$new(); $controller = _$controller_; $q = _$q_; + modalPromise = $q.defer(); + mockedModal.close = jasmine.createSpy('close'); + mockedModal.result = modalPromise.promise; + mockedModal.open = jasmine.createSpy('open').andReturn(mockedModal); + mockedModal.opened = {then:function(){}}; })); describe('AccountOrderDetailCtrl ', function () { @@ -90,6 +99,11 @@ describe('AccountOrderDetailCtrl Test', function () { {$scope: $scope, 'order': mockedOrder, $stateParams: mockedStateParams, GlobalData: mockedGlobalData}); }); + it('should expose right interface', function() { + expect($scope.cancelOrder).toBeDefined(); + expect($scope.showCancelBtn).toBeDefined(); + }); + it('should parse the payment information', function () { expect($scope.payment.currency).toEqualData('USD'); expect($scope.payment.status).toEqualData('SUCCESS'); @@ -101,6 +115,22 @@ describe('AccountOrderDetailCtrl Test', function () { expect($scope.itemCount).toEqualData(3); }); + it("should open the order cancel dialog when calling cancelOrder method", function() { + $scope.cancelOrder(); + expect(mockedModal.open).toHaveBeenCalled(); + modalPromise.resolve({status: 'DECLINED'}); + $scope.$digest(); + expect($scope.order.status).toBe('DECLINED'); + }); + + it('should correctly decide wether or not to display cancel order button', function() { + expect($scope.showCancelBtn({status: 'CREATED'})).toBeTruthy(); + expect($scope.showCancelBtn({status: 'CONFIRMED'})).toBeTruthy(); + expect($scope.showCancelBtn({status: 'SHIPPED'})).toBeFalsy(); + expect($scope.showCancelBtn({status: 'COMPLETED'})).toBeFalsy(); + expect($scope.showCancelBtn({status: 'DECLINED'})).toBeFalsy(); + }); + }); }); diff --git a/test/unit/account/customer-details/customer-details-ctrl-spec.js b/test/unit/account/customer-details/customer-details-ctrl-spec.js index 50e013a01..676131ef9 100644 --- a/test/unit/account/customer-details/customer-details-ctrl-spec.js +++ b/test/unit/account/customer-details/customer-details-ctrl-spec.js @@ -12,7 +12,7 @@ describe('CustomerDetailsCtrl', function () { var $scope, $controller, $q, mockBackend, - account, modalPromise; + account, modalPromise, mockedAccountSvc; var mockedModal = {}; @@ -23,6 +23,10 @@ describe('CustomerDetailsCtrl', function () { }) }; + mockedAccountSvc = { + isItSocialAccount: jasmine.createSpy('isItSocialAccount') + }; + beforeEach(module('ds.account', function ($provide) { $provide.value('$modal', mockedModal); })); @@ -48,7 +52,7 @@ describe('CustomerDetailsCtrl', function () { beforeEach(function () { $controller('CustomerDetailsCtrl', { - $scope: $scope, 'AuthDialogManager': mockedAuthDialogManager, '$modal': mockedModal + $scope: $scope, 'AuthDialogManager': mockedAuthDialogManager, '$modal': mockedModal, 'AccountSvc': mockedAccountSvc }); }); @@ -56,6 +60,7 @@ describe('CustomerDetailsCtrl', function () { expect($scope.editUserName).toBeDefined(); expect($scope.editUserEmail).toBeDefined(); expect($scope.updatePassword).toBeDefined(); + expect(mockedAccountSvc.isItSocialAccount).toBeDefined(); }); it('should open modal when editUserName() is called', function () { diff --git a/test/unit/auth/auth-service-spec.js b/test/unit/auth/auth-service-spec.js index 5bf0defcb..9e31358a9 100644 --- a/test/unit/auth/auth-service-spec.js +++ b/test/unit/auth/auth-service-spec.js @@ -46,7 +46,9 @@ describe('AuthSvc Test', function () { mockedSessionSvc = { afterSocialLogin: jasmine.createSpy(), - afterLogIn: jasmine.createSpy(), + afterLogIn: jasmine.createSpy().andReturn({ + then: jasmine.createSpy() + }), afterLogOut: jasmine.createSpy(), afterLoginFromSignUp: jasmine.createSpy() }; diff --git a/test/unit/cart/cart-service-spec.js b/test/unit/cart/cart-service-spec.js index e8c6b6e31..081f9b9e0 100644 --- a/test/unit/cart/cart-service-spec.js +++ b/test/unit/cart/cart-service-spec.js @@ -39,6 +39,19 @@ describe('CartSvc Test', function () { currency: 'USD' }] }; + + var prod2Id = '2466'; + var prod2 = { + product: { + id: prod2Id, + }, + prices: [{ + effectiveAmount: 6.00, + currency: 'USD', + measurementUnit: {unitCode: 'kg', quantity: 250} + }] + }; + var itemId = '0'; var productIdFromCart = '540751ee394edbc101ff20f5'; var mockedAccountSvc = {}; @@ -131,6 +144,7 @@ describe('CartSvc Test', function () { }); describe('addProductToCart - new cart', function () { + it('should create new cart, create cart item and GET new cart', function () { mockBackend.expectPOST(cartUrl).respond({ "cartId": cartId @@ -138,8 +152,7 @@ describe('CartSvc Test', function () { mockBackend.expectPOST(cartUrl + '/' + cartId + '/items', { "product": { "id": prodId }, "price": { "effectiveAmount": 5, "currency": "USD" }, "quantity": 2 - }) - .respond(201, {}); + }).respond(201, {}); var cartPromise = cartSvc.addProductToCart(prod1.product, prod1.prices, 2, {}); var successSpy = jasmine.createSpy(); @@ -151,6 +164,15 @@ describe('CartSvc Test', function () { expect(successSpy).wasCalled(); }); + it('should return the units of measurement for a product for which measurement makes sense.', function () { + mockBackend.expectPOST(cartUrl + '/' + cartId + '/items', { + "product": {"id": "2466"},"price": {"effectiveAmount": 6,"currency": "USD","measurementUnit": {"unit": "kg","quantity": 250}},"quantity": 1 + }).respond(201, {}); + + cartSvc.addProductToCart(prod2.product, prod2.prices, 1, {}); + }); + + it('should return failing promise if cart POST fails', function () { mockBackend.expectPOST(cartUrl).respond(500, {}); diff --git a/test/unit/checkout/checkout-ctrl-spec.js b/test/unit/checkout/checkout-ctrl-spec.js index 28c48ef37..915cc341d 100644 --- a/test/unit/checkout/checkout-ctrl-spec.js +++ b/test/unit/checkout/checkout-ctrl-spec.js @@ -1,7 +1,7 @@ describe('CheckoutCtrl', function () { var $scope, $rootScope, $controller, $injector, $q, mockedCheckoutSvc, mockedShippingSvc, mockedCartSvc, checkoutCtrl, order, cart, checkoutDfd, shippingDfd, cartDfd, - $modal, mockedModal, shippingZones, shippingCountries, MockedAuthSvc, accountDef, addressDef, addressesDef, returnAddress, + $modal, mockedModal, shippingZones, MockedAuthSvc, accountDef, addressDef, addressesDef, returnAddress, returnAddresses, returnAccount, MockedAccountSvc; var isAuthenticated; var GlobalData = { @@ -67,7 +67,6 @@ describe('CheckoutCtrl', function () { order.billTo = {}; cart = {}; order.creditCard = {}; - shippingCountries = ['CA', 'US']; mockedCheckoutSvc = { ERROR_TYPES: ERROR_TYPES }; @@ -96,7 +95,6 @@ describe('CheckoutCtrl', function () { $provide.value('cart', cart); $provide.value('order', order); $provide.value('shippingZones', shippingZones); - $provide.value('shippingCountries', shippingCountries); $provide.value('$state', mockedState); $provide.value('$modal', mockedModal); })); @@ -133,6 +131,10 @@ describe('CheckoutCtrl', function () { return shippingDfd.promise; }); + mockedShippingSvc.getShipToCountries = jasmine.createSpy('getShipToCountries').andCallFake(function() { + return ['US', 'CA']; + }); + mockedShippingSvc.isShippingConfigured = jasmine.createSpy('isShippingConfigured').andReturn(true); mockedCartSvc.reformatCartItems = jasmine.createSpy(); diff --git a/test/unit/confirmation/order-detail-svc-spec.js b/test/unit/confirmation/order-detail-svc-spec.js index 90bfa65c6..a75287a0e 100644 --- a/test/unit/confirmation/order-detail-svc-spec.js +++ b/test/unit/confirmation/order-detail-svc-spec.js @@ -116,4 +116,16 @@ describe('OrderDetailSvc Test', function () { shippingAddressCityStateZip: 'Munich, Bavaria 80538', shippingAddressCountry: 'Germany', emailAddress: 'your.name@email.com', entries: [ ], currency : undefined, subTotalPrice: 15}); }); + + it('should cancel the order and return status declined', function() { + var orderId = 123; + $httpBackend.expectPOST(ordersUrl+'/'+orderId+'/transitions').respond({}); + var result = null; + orderDetailSvc.cancelOrder(orderId).then(function(response){ + result = response; + }); + $httpBackend.flush(); + expect(result).toEqualData({status: 'DECLINED'}); + }); + }); diff --git a/test/unit/orders/order-cancel-dialog-ctrl-spec.js b/test/unit/orders/order-cancel-dialog-ctrl-spec.js new file mode 100644 index 000000000..47712183f --- /dev/null +++ b/test/unit/orders/order-cancel-dialog-ctrl-spec.js @@ -0,0 +1,67 @@ +/* + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +describe('OrderCancelDialogCtrl', function () { + var $scope, $controller, $q, + order, deferredOrder; + + var OrderDetailSvc = {}; + var mockedModal = {}; + + beforeEach(module('ds.account', function ($provide) { + $provide.value('$modalInstance', mockedModal); + })); + + beforeEach(inject(function (_$rootScope_, _$controller_, _$q_) { + $q = _$q_; + order = {}; + + mockedModal.close = jasmine.createSpy('close'); + mockedModal.dismiss = jasmine.createSpy('dismiss'); + + $scope = _$rootScope_.$new(); + $controller = _$controller_; + + deferredOrder = $q.defer(); + OrderDetailSvc.cancelOrder = jasmine.createSpy('cancelOrder').andReturn(deferredOrder.promise); + })); + + describe('', function () { + + beforeEach(function () { + $controller('OrderCancelDialogCtrl', {$scope: $scope, 'OrderDetailSvc': OrderDetailSvc, 'order': order,'$modalInstance': mockedModal}); + }); + + it('should expose correct scope interface', function () { + expect($scope.cancelOrder).toBeDefined(); + expect($scope.closeCancelOrderDialog).toBeDefined(); + }); + + it('should call OrderDetailSvc.cancelOrder() when cancelOrder() is called and close modal when success', function () { + $scope.modalInstance = mockedModal; + $scope.cancelOrder(); + + expect(OrderDetailSvc.cancelOrder).toHaveBeenCalled(); + deferredOrder.resolve({}); + + $scope.$digest(); + + expect(mockedModal.close).toHaveBeenCalled(); + }); + + it('should dismiss modal when $scope.closeCancelOrderDialog() is called', function () { + $scope.closeCancelOrderDialog(); + expect(mockedModal.dismiss).toHaveBeenCalled(); + }); + + }); +}); \ No newline at end of file diff --git a/test/unit/products/product-attribute-service-spec.js b/test/unit/products/product-attribute-service-spec.js deleted file mode 100644 index c73be463d..000000000 --- a/test/unit/products/product-attribute-service-spec.js +++ /dev/null @@ -1,92 +0,0 @@ -describe("ProductAttributeSvc", function () { - - beforeEach(module('restangular')); - beforeEach(module('ds.products')); - - var $httpBackend, ProductAttributeSvc; - - beforeEach(inject(function (_$httpBackend_, _ProductAttributeSvc_) { - $httpBackend = _$httpBackend_; - ProductAttributeSvc = _ProductAttributeSvc_; - })); - - it("should get schema", function () { - var callbackSpy = jasmine.createSpy(); - - $httpBackend.expectGET('http://path.to/schema').respond(200, 'expected schema'); - ProductAttributeSvc.getSchema('http://path.to/schema').then(callbackSpy); - - $httpBackend.flush(); - expect(callbackSpy.mostRecentCall.args[0]).toEqual('expected schema'); - }); - - it("should get attribute groups from product", function () { - var product = { - metadata: { - mixins: { - attributegroup_1: "http://path.to/attributegroup_1/schema", - attributegroup_2: "http://path.to/attributegroup_2/schema", - } - }, - mixins: { - inventory: 'not a attribute group', - attributegroup_1: 'group 1 attributes', - attributegroup_2: 'group 2 attributes' - } - }; - - var groups = ProductAttributeSvc.getAttributeGroups(product); - - expect(groups.length).toBe(2); - expect(groups).toContain({ - schema: 'http://path.to/attributegroup_1/schema', - attributes: 'group 1 attributes' - }); - expect(groups).toContain({ - schema: 'http://path.to/attributegroup_2/schema', - attributes: 'group 2 attributes' - }); - }); - - it("should return positive if has any of attributes set", function () { - var product = { - metadata: { - mixins: {} - }, - mixins: { - attributegroup_1: { - attr_1: "test", - attr_2: null - }, - } - }; - - var result = ProductAttributeSvc.hasAnyOfAttributesSet(product); - - expect(result).toBe(true); - }); - - it("should return negative if has none of attributes set", function () { - var product = { - metadata: { - mixins: {} - }, - mixins: { - attributegroup_1: { - attr_1: null, - attr_2: null - }, - } - }; - - var result = ProductAttributeSvc.hasAnyOfAttributesSet(product); - - expect(result).toBe(false); - }); - - it("should define date formatting", function () { - expect(ProductAttributeSvc.dateFormatting.date).toBeDefined(); - expect(ProductAttributeSvc.dateFormatting.time).toBeDefined(); - expect(ProductAttributeSvc.dateFormatting.dateTime).toBeDefined(); - }); -}); \ No newline at end of file diff --git a/test/unit/products/product-detail-ctrl-spec.js b/test/unit/products/product-detail-ctrl-spec.js index 397ed14cf..279fef9be 100644 --- a/test/unit/products/product-detail-ctrl-spec.js +++ b/test/unit/products/product-detail-ctrl-spec.js @@ -61,6 +61,12 @@ describe('ProductDetailCtrl', function () { name: 'product1', id: 123, published: true, + mixins: { + inventory: false + }, + metadata: { + mixins: {} + } }, categories: [ { @@ -83,11 +89,6 @@ describe('ProductDetailCtrl', function () { return cartDef.promise; }) }; - - var dummyImg = 'dummy'; - var mockedSettings = { - placeholderImage: dummyImg - }; var mockedNotification = { success: jasmine.createSpy('success').andReturn('') @@ -123,23 +124,19 @@ describe('ProductDetailCtrl', function () { beforeEach(function () { $controller('ProductDetailCtrl', { $scope: $scope, $rootScope: $rootScope, - 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct), 'lastCatId': mockLastCatId, 'settings': mockedSettings, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification}); + 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct), 'lastCatId': mockLastCatId, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification, 'variants': [], 'variantPrices': []}); }); it('should set the category for the breadcrumb', function(){ expect($scope.category).toBeTruthy(); }); - - it('product without image should get default image', function () { - expect($scope.product.product.media[0].url).toEqualData(dummyImg); - }); }); describe('buy published product', function () { beforeEach(function () { $controller('ProductDetailCtrl', { $scope: $scope, $rootScope: $rootScope, - 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct), 'lastCatId': mockLastCatId, 'settings': mockedSettings, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification}); + 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct), 'lastCatId': mockLastCatId, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification, 'variants': [], 'variantPrices': []}); }); it('should add to cart from detail page', function () { @@ -174,7 +171,7 @@ describe('ProductDetailCtrl', function () { beforeEach(function () { $controller('ProductDetailCtrl', { $scope: $scope, $rootScope: $rootScope, - 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct), 'lastCatId': mockLastCatId, 'settings': mockedSettings, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification}); + 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct), 'lastCatId': mockLastCatId, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification, 'variants': [], 'variantPrices': []}); }); it('should disable buy button on invalid qty', function () { @@ -194,7 +191,7 @@ describe('ProductDetailCtrl', function () { beforeEach(function () { $controller('ProductDetailCtrl', { $scope: $scope, $rootScope: $rootScope, - 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct),'lastCatId': mockLastCatId, 'settings': mockedSettings, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification}); + 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct),'lastCatId': mockLastCatId, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification, 'variants': [], 'variantPrices': []}); $scope.addToCartFromDetailPage(); }); @@ -219,19 +216,25 @@ describe('ProductDetailCtrl', function () { { url: 'http://url1' }, { url: 'http://url2' }, { url: 'http://url3' } - ] + ], + mixins: { + inventory: false + }, + metadata: { + mixins: {} + } } }; beforeEach(function(){ $controller('ProductDetailCtrl', { $scope: $scope, $rootScope: $rootScope, - 'CartSvc': mockedCartSvc, 'product': mockProductWithMain, 'lastCatId': mockLastCatId, 'settings': mockedSettings, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification}); + 'CartSvc': mockedCartSvc, 'product': mockProductWithMain, 'lastCatId': mockLastCatId, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification, 'variants': [], 'variantPrices': []}); }); it('should list committed images as they came', function(){ - expect($scope.product.product.media[0].url).toEqualData('http://url1'); - expect($scope.product.product.media[1].url).toEqualData('http://url2'); - expect($scope.product.product.media[2].url).toEqualData('http://url3'); + expect($scope.product.media[0].url).toEqualData('http://url1'); + expect($scope.product.media[1].url).toEqualData('http://url2'); + expect($scope.product.media[2].url).toEqualData('http://url3'); }); }); @@ -244,7 +247,13 @@ describe('ProductDetailCtrl', function () { media: [ { url: 'http://url1' }, { url: 'http://url2' } - ] + ], + mixins: { + inventory: false + }, + metadata: { + mixins: {} + } }, categories: [ { @@ -260,12 +269,30 @@ describe('ProductDetailCtrl', function () { beforeEach(function(){ $controller('ProductDetailCtrl', { $scope: $scope, $rootScope: $rootScope, - 'CartSvc': mockedCartSvc, 'product': mockProductWithImages, 'lastCatId': mockLastCatId, 'settings': mockedSettings, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification}); + 'CartSvc': mockedCartSvc, 'product': mockProductWithImages, 'lastCatId': mockLastCatId, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification, 'variants': [], 'variantPrices': []}); }); it('should list first image first', function(){ - expect($scope.product.product.media[0].url).toEqualData('http://url1'); - expect($scope.product.product.media[1].url).toEqualData('http://url2'); + expect($scope.product.media[0].url).toEqualData('http://url1'); + expect($scope.product.media[1].url).toEqualData('http://url2'); + }); + }); + + describe('taxConfiguration', function () { + it ('should shorten the tax label and add a see more button if the label has more than 60 chars', function () { + + var longTaxLabel = 'Long Tax Label Long Tax Label Long Tax Label Long Tax Label Long Tax Label Long Tax Label Long Tax Label Long Tax Label Long Tax Label Long Tax Label '; + + mockedGlobalData={ + getCurrencySymbol: jasmine.createSpy('getCurrencySymbol').andReturn('USD'), + getCurrentTaxConfiguration: jasmine.createSpy('getCurrentTaxConfiguration').andReturn({ rate: '7', label: longTaxLabel, included: false }) + }; + $controller('ProductDetailCtrl', { $scope: $scope, $rootScope: $rootScope, + 'CartSvc': mockedCartSvc, 'product': angular.copy(mockProduct), 'lastCatId': mockLastCatId, 'GlobalData': mockedGlobalData, 'CategorySvc': mockCategorySvc, 'shippingZones': mockedShippingZones, 'Notification': mockedNotification, 'variants': [], 'variantPrices': []}); + + var expectedShortenedLabel = longTaxLabel.substring(0, 59); + expect($scope.taxConfiguration.shortenedLabel).toEqualData(expectedShortenedLabel); + expect($scope.taxConfiguration.seeMoreClicked).toBeDefined(); }); }); diff --git a/test/unit/products/product-extension-service-spec.js b/test/unit/products/product-extension-service-spec.js new file mode 100644 index 000000000..3b8654fde --- /dev/null +++ b/test/unit/products/product-extension-service-spec.js @@ -0,0 +1,22 @@ +describe("ProductExtensionSvc", function () { + + beforeEach(module('restangular')); + beforeEach(module('ds.products')); + + var $httpBackend, ProductExtensionSvc; + + beforeEach(inject(function (_$httpBackend_, _ProductExtensionSvc_) { + $httpBackend = _$httpBackend_; + ProductExtensionSvc = _ProductExtensionSvc_; + })); + + it("should get schema", function () { + var callbackSpy = jasmine.createSpy(); + + $httpBackend.expectGET('http://path.to/schema').respond(200, 'expected schema'); + ProductExtensionSvc.getSchema('http://path.to/schema').then(callbackSpy); + + $httpBackend.flush(); + expect(callbackSpy.mostRecentCall.args[0]).toEqual('expected schema'); + }); +}); \ No newline at end of file diff --git a/test/unit/products/product-options-helper-spac.js b/test/unit/products/product-options-helper-spac.js new file mode 100644 index 000000000..74605ea02 --- /dev/null +++ b/test/unit/products/product-options-helper-spac.js @@ -0,0 +1,150 @@ +/** + * [y] hybris Platform + * + * Copyright (c) 2000-2016 hybris AG + * All rights reserved. + * + * This software is the confidential and proprietary information of hybris + * ("Confidential Information"). You shall not disclose such Confidential + * Information and shall use it only in accordance with the terms of the + * license agreement you entered into with hybris. + */ + +describe('ProductOptionsHelper', function () { + beforeEach(angular.mock.module('ds.products')); + + describe('prepareOptions', function () { + it('should prepare options from variants', angular.mock.inject(function (ProductOptionsHelper) { + // arrange + var variants = [ + { + id: 'v1', + options: { + 'o1': { 'a': 'val1', 'b': 'val1' }, + 'o2': { 'a': 'val1' } + } + }, + { + id: 'v2', + options: { + 'o1': { 'a': 'val2', 'b': 'val1' }, + 'o2': { 'a': 'val2' } + } + } + ]; + + // act + var options = ProductOptionsHelper.prepareOptions(variants); + + // assert + expect(options).toEqual([ + { + optionKey: 'o1', + attributeKey: 'a', + attributes: [ + { value: 'val1', variantIds: ['v1'], disabled: false }, + { value: 'val2', variantIds: ['v2'], disabled: false } + ] + }, { + optionKey: 'o1', + attributeKey: 'b', + attributes: [ + { value: 'val1', variantIds: ['v1', 'v2'], disabled: false } + ] + }, { + optionKey: 'o2', + attributeKey: 'a', + attributes: [ + { value: 'val1', variantIds: ['v1'], disabled: false }, + { value: 'val2', variantIds: ['v2'], disabled: false } + ] + } + ]); + })); + + it('should omit complex attributes', angular.mock.inject(function (ProductOptionsHelper) { + // arrange + var variants = [ + { + id: 'v1', + options: { + 'o1': { 'a': 'val1', 'b': { 'complex': 'attribute' }, 'c': ['complex', 'attribute'] }, + } + } + ]; + + // act + var options = ProductOptionsHelper.prepareOptions(variants); + + // assert + expect(options).toEqual([ + { + optionKey: 'o1', + attributeKey: 'a', + attributes: [ + { value: 'val1', variantIds: ['v1'], disabled: false } + ] + } + ]); + })); + }); + + describe('getIdsOfMatchingVariants', function () { + it('should get ids of matching variants', angular.mock.inject(function (ProductOptionsHelper) { + // arrange + var attributesSelected = [ + { value: 'val1', variantIds: ['v1'], disabled: false }, + { value: 'val2', variantIds: ['v1', 'v2'], disabled: false } + ]; + + // act + var result = ProductOptionsHelper.getIdsOfMatchingVariants(attributesSelected); + + // assert + expect(result).toEqual(['v1']); + })); + }); + + describe('updateOptions', function () { + it('should update options', angular.mock.inject(function (ProductOptionsHelper) { + // arrange + var options = [ + { + optionKey: 'o1', + attributeKey: 'a', + attributes: [ + { value: 'val1', variantIds: ['v1'], disabled: false }, + { value: 'val2', variantIds: ['v2'], disabled: false } + ] + }, { + optionKey: 'o1', + attributeKey: 'b', + attributes: [ + { value: 'val1', variantIds: ['v1', 'v2'], disabled: false } + ] + } + ]; + + // act + var result = ProductOptionsHelper.updateOptions(options, ['v1']); + + // assert + expect(result).toEqual([ + { + optionKey: 'o1', + attributeKey: 'a', + attributes: [ + { value: 'val1', variantIds: ['v1'], disabled: false }, + { value: 'val2', variantIds: ['v2'], disabled: true } + ] + }, { + optionKey: 'o1', + attributeKey: 'b', + attributes: [ + { value: 'val1', variantIds: ['v1', 'v2'], disabled: false } + ] + } + ]); + })); + }); +}); \ No newline at end of file diff --git a/test/unit/products/product-svc-spec.js b/test/unit/products/product-svc-spec.js index 65db81b79..aa8ba9c12 100644 --- a/test/unit/products/product-svc-spec.js +++ b/test/unit/products/product-svc-spec.js @@ -47,34 +47,4 @@ describe('ProductSvc Test', function () { }); }); - describe('query', function(){ - - it('issues GET that returns product array', function () { - $httpBackend.expectGET(productsUrl).respond(prodList); - - var products = productSvc.query(); - - $httpBackend.flush(); - expect(products.$object.length).toBeDefined(); - expect(products.$object.length).toEqual(prodList.length); - for (var i = 0, prod; i < products.$object.length; i++) { - prod = products.$object[i]; - expect(prod.name).toEqualData(prodList[i].name); - }; - }); - - it('sets accept-language header', function(){ - - $httpBackend.expectGET(productsUrl, {"accept-language":acceptLang,"hybris-currency":"USD","Accept":"application/json, text/plain, */*"}).respond(prodList); - - productSvc.query(); - $httpBackend.flush(); - - }); - }); - - - - - }); diff --git a/test/unit/shipping/shipping-svc-spec.js b/test/unit/shipping/shipping-svc-spec.js index 8c8802eb2..0a18ff8b5 100644 --- a/test/unit/shipping/shipping-svc-spec.js +++ b/test/unit/shipping/shipping-svc-spec.js @@ -78,24 +78,12 @@ describe('ShippingSvc', function() { $httpBackend.flush(); }); - it('should issue GET shipping costs', function () { - $httpBackend.expectGET(baseUrl + '/US/zones?activeMethods=true&expand=methods').respond([]); - shippingSvc.getShipToCountries(); - $httpBackend.flush(); - }); - it('should issue POST shipping costs', function () { $httpBackend.expectPOST(baseUrl + '/US/quote').respond({}); shippingSvc.getShippingCosts(item); $httpBackend.flush(); }); - it('should issue POST shippint cost min', function () { - $httpBackend.expectPOST(baseUrl + '/US/quote/minimum').respond({}); - shippingSvc.getMinimumShippingCost(item); - $httpBackend.flush(); - }); - describe('isShippingConfigured', function () { var zones; @@ -127,6 +115,24 @@ describe('ShippingSvc', function() { }); + describe('getShipToCountries', function () { + + it('should correctly return the ship to countries', function() { + expect(shippingSvc.getShipToCountries([{shipTo: ['US', 'MX']}, {shipTo: ['CA']}])).toEqual([ 'US', 'MX', 'CA' ]); + }); + + }) + + describe('getMinimumShippingCost', function () { + + it('should correctly return minimum shipping cost', function() { + var shippingCosts = [{methods:[{fee: {amount:8.6,currency:'USD'},id:'fedex-2dayground',name:'FedEx 2Day'},{fee: {amount:8.76,currency:'USD'},id:'ups-standard',name:'UPS Standard'}], + zone: {id:'us',name:'USA'}}]; + expect(shippingSvc.getMinimumShippingCost(shippingCosts)).toEqual({fee:{ amount:8.6,currency:'USD'},id:'fedex-2dayground',name:'FedEx 2Day',zoneId:'us'}); + }); + + }) + }); }); \ No newline at end of file