From 527eb6e73f5b07b71996e8260852f77513b6e832 Mon Sep 17 00:00:00 2001 From: "O.Bilenko" Date: Wed, 13 Feb 2019 13:26:21 +0100 Subject: [PATCH 1/2] PWA-1687 Check issues of Browser Connector with Cypress Tests --- .eslintignore | 1 + Makefile | 26 +++++++--- themes/theme-gmd/e2e/cypress.json | 11 ++-- themes/theme-gmd/e2e/helper/cart.js | 22 ++++---- .../e2e/integration/consistency/CartPage.js | 28 +++++----- .../integration/consistency/CartPageCoupon.js | 8 ++- .../e2e/integration/functional/CartPage.js | 37 +++++++------ .../integration/functional/CartPageCoupon.js | 8 ++- .../integration/functional/CartPageOptions.js | 8 ++- .../integration/functional/FavoritesPage.js | 52 ++++++++++--------- .../e2e/integration/functional/ProductPage.js | 8 ++- .../functional/ProductPageOptions.js | 8 ++- utils/e2e/plugins/index.js | 10 ++-- utils/e2e/support/commands.js | 4 ++ utils/e2e/support/index.js | 40 ++++++++------ 15 files changed, 148 insertions(+), 123 deletions(-) diff --git a/.eslintignore b/.eslintignore index b93ef23e1b..55f2a469aa 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,6 +4,7 @@ coverage /pipelines/ /trustedPipelines/ /themes/*/extensions/ +/themes/*/e2e/ !/extensions/@shopgate-product-reviews !/extensions/@shopgate-tracking-native !/extensions/@shopgate-user-privacy diff --git a/Makefile b/Makefile index e7520c2789..b09c8d9761 100644 --- a/Makefile +++ b/Makefile @@ -146,11 +146,21 @@ setup-frontend-with-current-ip: echo '{\n "ip": "$(shell ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | awk '{print $1}')",\n "port": 8080,\n "apiPort": 9666,\n "hmrPort": 3000,\n "remotePort": 8000,\n "sourceMapsType": "cheap-module-eval-source-map"\n}\n' > ./.sgcloud/frontend.json; +# Open cypress UI for GMD theme e2e-gmd: - cd themes/theme-gmd && yarn run e2e; + cd themes/theme-gmd && yarn run e2e; +# Open cypress UI for IOS theme e2e-ios11: - cd themes/theme-ios11 && yarn run e2e; + cd themes/theme-ios11 && yarn run e2e; + +# Run GMD legacy tests +e2e-gmd-legacy: + npx cypress run -P ./themes/theme-gmd/e2e -s 'themes/theme-gmd/e2e/integration/specFiles/functional/legacy.js' + +# Run IOS legacy tests +e2e-ios11-legacy: + npx cypress run -P ./themes/theme-ios11/e2e -s 'themes/theme-ios11/e2e/integration/specFiles/consistency/legacy.js,themes/theme-ios11/e2e/integration/specFiles/functional/legacy.js' e2e-checkout: cd themes/theme-gmd && yarn run e2e:checkout; @@ -159,10 +169,14 @@ e2e-user: cd themes/theme-gmd && yarn run e2e:user; e2e-install: - npm i --no-save --no-package-lock cypress@3.1.1; - - - + npm i --no-save --no-package-lock cypress symlink-dir + # Symlinking support, plugins, fixtures + npx symlink-dir ./utils/e2e/support ./themes/theme-gmd/e2e/cypress/support + npx symlink-dir ./utils/e2e/fixtures ./themes/theme-gmd/e2e/cypress/fixtures + npx symlink-dir ./utils/e2e/plugins ./themes/theme-gmd/e2e/cypress/plugins + npx symlink-dir ./utils/e2e/support ./themes/theme-ios11/e2e/cypress/support + npx symlink-dir ./utils/e2e/fixtures ./themes/theme-ios11/e2e/cypress/fixtures + npx symlink-dir ./utils/e2e/plugins ./themes/theme-ios11/e2e/cypress/plugins #################################################################################################### # MAKE HELPER WHICH USES THE CORRECT MAKEFILE TO RUN (local or another one predefined by Jenkins) diff --git a/themes/theme-gmd/e2e/cypress.json b/themes/theme-gmd/e2e/cypress.json index 3aa6f052eb..123592be2c 100755 --- a/themes/theme-gmd/e2e/cypress.json +++ b/themes/theme-gmd/e2e/cypress.json @@ -1,6 +1,7 @@ { - "integrationFolder": "./integration", - "fixturesFolder": "../../../node_modules/@shopgate/pwa-e2e-test/fixtures", - "pluginsFile": "../../../node_modules/@shopgate/pwa-e2e-test/plugins/", - "supportFile": "../../../node_modules/@shopgate/pwa-e2e-test/support/" -} \ No newline at end of file + "integrationFolder": "./integration", + "fixturesFolder": "./cypress/fixtures", + "pluginsFile": "./cypress/plugins", + "supportFile": "./cypress/support", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G892A Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Mobile Safari/537.36" +} diff --git a/themes/theme-gmd/e2e/helper/cart.js b/themes/theme-gmd/e2e/helper/cart.js index 6c72f7c629..545df2099d 100755 --- a/themes/theme-gmd/e2e/helper/cart.js +++ b/themes/theme-gmd/e2e/helper/cart.js @@ -3,21 +3,19 @@ import els from '../elements/de'; /** * Helper function that clears the Cart */ -export function clearProductFromCart() { +export function clearProductsFromCart() { try { // Delete single product from cart - cy.visit('Cart'); - cy.wait(500); - cy.get(els.contextMenu).each(() => { - cy.get(els.contextMenu) - .should('be.visible') - .first() - .click(); - cy.get(els.contextMenuButton) - .contains('Entfernen') - .click(); - cy.wait(1000); + cy.visit('cart'); + cy.get(els.contextMenu).each(($el) => { + cy.window().spyAction('RECEIVE_CART', () => { + cy.wrap($el).should('be.visible').click(); + cy.get(els.contextMenuButton) + .contains('Entfernen') + .click(); + }); }); + // Check for empty cart cy.get(els.emptyCartPlaceHolderString) .scrollIntoView() diff --git a/themes/theme-gmd/e2e/integration/consistency/CartPage.js b/themes/theme-gmd/e2e/integration/consistency/CartPage.js index d5285da17d..d87730a087 100755 --- a/themes/theme-gmd/e2e/integration/consistency/CartPage.js +++ b/themes/theme-gmd/e2e/integration/consistency/CartPage.js @@ -1,15 +1,14 @@ -import { clearProductFromCart } from '../../helper/cart'; +import { clearProductsFromCart } from '../../helper/cart'; import els from '../../elements/de'; describe('AndroidGMDTest CartPage', () => { + after(clearProductsFromCart); + it('it should check for empty cart', () => { cy.visit(''); - cy.get(els.navigatorButton) - .click(); - cy.get(els.navDrawerCartButton) - .click(); - cy.get(els.emptyCartPlaceHolderString) - .should('be.visible'); + cy.get(els.navigatorButton).click(); + cy.get(els.navDrawerCartButton).click(); + cy.get(els.emptyCartPlaceHolderString).should('be.visible'); }); it('it should check for product in cart', () => { @@ -21,11 +20,12 @@ describe('AndroidGMDTest CartPage', () => { cy.get(els.productWithManyProps4GridViewName) .last() .click(); - cy.get(els.addToCartButton) - .click(); - cy.get(els.cartButton) - .last() - .click(); + cy.window().spyAction('RECEIVE_CART', () => { + cy.get(els.addToCartButton).click(); + }); + cy.window().spyAction('ROUTE_DID_ENTER', () => { + cy.get(els.cartButton).last().click(); + }); cy.get(els.cartItem) .contains('Product with many Properties - 4 -') .should('be.visible'); @@ -53,8 +53,4 @@ describe('AndroidGMDTest CartPage', () => { .contains('* Alle Preise inkl. MwSt. evtl. zzgl. Versand') .should('be.visible'); }); - - it('should clear Cart', () => { - clearProductFromCart(); - }); }); diff --git a/themes/theme-gmd/e2e/integration/consistency/CartPageCoupon.js b/themes/theme-gmd/e2e/integration/consistency/CartPageCoupon.js index bac25aa097..915c35d4be 100644 --- a/themes/theme-gmd/e2e/integration/consistency/CartPageCoupon.js +++ b/themes/theme-gmd/e2e/integration/consistency/CartPageCoupon.js @@ -1,7 +1,9 @@ -import { clearProductFromCart } from '../../helper/cart'; +import { clearProductsFromCart } from '../../helper/cart'; import els from '../../elements/de'; describe('AndroidGMDTest CartPageCoupons', () => { + after(clearProductsFromCart); + it('should add second product to cart', () => { cy.visit(''); cy.get(els.basicCategory) @@ -37,8 +39,4 @@ describe('AndroidGMDTest CartPageCoupons', () => { cy.get(els.couponSubmitButton) .should('be.visible'); }); - - it('should clear Cart', () => { - clearProductFromCart(); - }); }); diff --git a/themes/theme-gmd/e2e/integration/functional/CartPage.js b/themes/theme-gmd/e2e/integration/functional/CartPage.js index 312afec109..0dfff02c2f 100755 --- a/themes/theme-gmd/e2e/integration/functional/CartPage.js +++ b/themes/theme-gmd/e2e/integration/functional/CartPage.js @@ -1,8 +1,10 @@ import els from '../../elements/de'; -import { clearProductFromCart } from '../../helper/cart'; +import { clearProductsFromCart } from '../../helper/cart'; describe('functional tests cart page', () => { - it.skip('check for increase / decrease quanitity', () => { + after(clearProductsFromCart); + + it('check for increase / decrease quanitity', () => { cy.visit(''); cy.get(els.allProductCategory) @@ -21,7 +23,7 @@ describe('functional tests cart page', () => { cy.get(els.quantityPicker) .should('be.visible') .click() - .type(2) + .type('2') .wait(100) .focus() .blur(); @@ -29,7 +31,7 @@ describe('functional tests cart page', () => { .should('be.visible'); cy.get(els.quantityPicker) .clear() - .type(1) + .type('1') .wait(100) .focus() .blur(); @@ -94,14 +96,21 @@ describe('functional tests cart page', () => { .should('be.visible') .click() .wait(2000); - cy.get(els.size5ShoeSizeVariant) - .should('be.visible') - .last() - .click() - .wait(2000); - cy.get(els.addToCartButton) - .should('be.visible') - .click(); + + // Wait until variant selection and data received + cy.window().spyAction('RECEIVE_PRODUCT', () => { + cy.get(els.size5ShoeSizeVariant) + .should('be.visible') + .last() + .click(); + }); + + cy.window().spyAction('RECEIVE_CART', () => { + cy.get(els.addToCartButton) + .should('be.visible') + .click(); + }); + cy.get(els.cartButtonProductPage) .last() .should('be.visible') @@ -110,8 +119,4 @@ describe('functional tests cart page', () => { cy.get(els.productWithChild1ColorBlackSize5CartItem) .should('be.visible'); }); - - it('should check for delete product from cart', () => { - clearProductFromCart(); - }); }); diff --git a/themes/theme-gmd/e2e/integration/functional/CartPageCoupon.js b/themes/theme-gmd/e2e/integration/functional/CartPageCoupon.js index e8ad9f2c51..6378cd337c 100644 --- a/themes/theme-gmd/e2e/integration/functional/CartPageCoupon.js +++ b/themes/theme-gmd/e2e/integration/functional/CartPageCoupon.js @@ -1,8 +1,10 @@ import els from '../../elements/de'; -import { clearProductFromCart } from '../../helper/cart'; +import { clearProductsFromCart } from '../../helper/cart'; import { checkForWrongCoupon } from '../../helper/coupon'; describe('functional tests cart page', () => { + after(clearProductsFromCart); + it('should add second product to cart', () => { cy.visit(''); cy.get(els.basicCategory) @@ -51,8 +53,4 @@ describe('functional tests cart page', () => { cy.get(els.deleteCouponButton) .should('not.exist'); }); - - it('should check for delete product from cart', () => { - clearProductFromCart(); - }); }); diff --git a/themes/theme-gmd/e2e/integration/functional/CartPageOptions.js b/themes/theme-gmd/e2e/integration/functional/CartPageOptions.js index d348f0867a..441c9438c4 100755 --- a/themes/theme-gmd/e2e/integration/functional/CartPageOptions.js +++ b/themes/theme-gmd/e2e/integration/functional/CartPageOptions.js @@ -1,8 +1,10 @@ import els from '../../elements/de'; -import { clearProductFromCart } from '../../helper/cart'; +import { clearProductsFromCart } from '../../helper/cart'; describe('functional test cart page options', () => { + after(clearProductsFromCart); + it('should check for product with options', () => { cy.visit(''); @@ -34,8 +36,4 @@ describe('functional test cart page options', () => { .contains('bright') .should('be.visible'); }); - - it('should clear cart', () => { - clearProductFromCart(); - }); }); diff --git a/themes/theme-gmd/e2e/integration/functional/FavoritesPage.js b/themes/theme-gmd/e2e/integration/functional/FavoritesPage.js index 0d9330d099..7db9d3d3aa 100755 --- a/themes/theme-gmd/e2e/integration/functional/FavoritesPage.js +++ b/themes/theme-gmd/e2e/integration/functional/FavoritesPage.js @@ -15,21 +15,23 @@ describe('e2e functional test favoritePage', () => { .should('be.visible') .last() .click(); - cy.get(els.favoriteButtonProductPage) - .should('be.visible') - .last() - .click(); - cy.go('back'); - cy.go('back'); - cy.go('back'); + cy.window().spyAction('RECEIVE_FAVORITES', () => { + cy.get(els.favoriteButtonProductPage) + .should('be.visible') + .last() + .click(); + }); cy.get(els.navigatorButton) .first() .should('be.visible') .click() - .wait(1000); - cy.get(els.navDrawerFavoritesButton) - .should('be.visible') - .click(); + .wait(200); + + cy.window().spyAction('ROUTE_DID_ENTER', () => { + cy.get(els.navDrawerFavoritesButton) + .should('be.visible') + .click(); + }); cy.get(els.addToCartButton) .should('be.visible') .click(); @@ -40,31 +42,33 @@ describe('e2e functional test favoritePage', () => { .contains('Abbrechen') .should('be.visible') .click(); - cy.wait(3000); - cy.get(els.addToCartButton) - .click(); + + cy.wait(500); + + cy.get(els.addToCartButton).click(); cy.get(els.basicDialogText) .contains('Um dieses Produkt zum Warenkorb hinzuzufügen, wählen Sie bitte die Varianten.') .should('be.visible'); - cy.get(els.basicDialogOkButton) - .contains('Varianten wählen') - .click(); + + cy.window().spyAction('ROUTE_DID_ENTER', () => { + cy.get(els.basicDialogOkButton) + .contains('Varianten wählen') + .click(); + }); cy.get(els.variantPickerColor) .contains('Color auswählen') .should('be.visible'); cy.get(els.variantPickerShoeSize) .contains('Shoe size auswählen') .should('be.visible'); - cy.reload() - .wait(3000); - cy.get(els.favoriteButtonProductPage) - .click() - .wait(1000); + + cy.window().spyAction('RECEIVE_FAVORITES', () => { + cy.get(els.favoriteButtonProductPage).click(); + }); }); it('should check for empty fav list', () => { cy.visit('/favourite_list'); - cy.get(els.favoritesPageEmptyFavComponent) - .should('be.visible'); + cy.get(els.favoritesPageEmptyFavComponent).should('be.visible'); }); }); diff --git a/themes/theme-gmd/e2e/integration/functional/ProductPage.js b/themes/theme-gmd/e2e/integration/functional/ProductPage.js index e379bcc12b..996b2dc7da 100755 --- a/themes/theme-gmd/e2e/integration/functional/ProductPage.js +++ b/themes/theme-gmd/e2e/integration/functional/ProductPage.js @@ -1,7 +1,9 @@ import els from '../../elements/de'; -import { clearProductFromCart } from '../../helper/cart'; +import { clearProductsFromCart } from '../../helper/cart'; describe('functional test product page', () => { + after(clearProductsFromCart); + it('should check for correct error message if no variant are selected', () => { cy.visit(''); @@ -69,8 +71,4 @@ describe('functional test product page', () => { .should('be.visible') .contains('1'); }); - - it('should clear cart', () => { - clearProductFromCart(); - }); }); diff --git a/themes/theme-gmd/e2e/integration/functional/ProductPageOptions.js b/themes/theme-gmd/e2e/integration/functional/ProductPageOptions.js index 60f7c57f51..67412730fe 100755 --- a/themes/theme-gmd/e2e/integration/functional/ProductPageOptions.js +++ b/themes/theme-gmd/e2e/integration/functional/ProductPageOptions.js @@ -1,7 +1,9 @@ import els from '../../elements/de'; -import { clearProductFromCart } from '../../helper/cart'; +import { clearProductsFromCart } from '../../helper/cart'; describe('functional test product page', () => { + after(clearProductsFromCart); + it('should check for options select', () => { cy.visit(''); @@ -39,8 +41,4 @@ describe('functional test product page', () => { cy.get(els.cartButton) .contains('1'); }); - - it('should clear cart', () => { - clearProductFromCart(); - }); }); diff --git a/utils/e2e/plugins/index.js b/utils/e2e/plugins/index.js index 93dc0a7ed5..164a64cb03 100644 --- a/utils/e2e/plugins/index.js +++ b/utils/e2e/plugins/index.js @@ -7,13 +7,13 @@ module.exports = (on, config) => { if (process.env.IP && process.env.PORT) { ip = process.env.IP; port = process.env.PORT; - } else { + } else if (!process.env.BC) { const sdkConfig = require('../../../.sgcloud/frontend.json'); ip = sdkConfig.ip || '127.0.0.1'; port = sdkConfig.port || 8080; - } - console.warn(ip, port); + console.warn(ip, port); + } // Build a new config object. const newConfig = Object.assign({}, config, { @@ -31,6 +31,10 @@ module.exports = (on, config) => { // Set the viewport height. newConfig.viewportHeight = 731; + if (process.env.BC) { + newConfig.baseUrl = process.env.BC; + } + return newConfig; }; diff --git a/utils/e2e/support/commands.js b/utils/e2e/support/commands.js index eb06e3e2bf..bbe1db20ca 100644 --- a/utils/e2e/support/commands.js +++ b/utils/e2e/support/commands.js @@ -25,6 +25,10 @@ // -- This is will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) +/** + * @typedef (Function) Window.spyAction + */ + /** * Spy console log for PWA actions. * When action is logged, assign it as cypress resource diff --git a/utils/e2e/support/index.js b/utils/e2e/support/index.js index 460bbf16cf..36033e0e13 100644 --- a/utils/e2e/support/index.js +++ b/utils/e2e/support/index.js @@ -1,3 +1,4 @@ +/* eslint-disable global-require */ // *********************************************************** // This example support/index.js is processed and // Loaded automatically before your test files. @@ -16,31 +17,38 @@ // Import commands.js using ES2015 syntax: import './commands'; -const istanbul = require('istanbul-lib-coverage'); - -const map = istanbul.createCoverageMap({}); - beforeEach(() => { cy.fixture('userCredentials.json').as('user'); }); -Cypress.on('window:before:unload', (e) => { - const coverage = e.currentTarget.__coverage__; // eslint-disable-line no-underscore-dangle - - if (coverage) { - map.merge(coverage); - } +Cypress.Cookies.defaults({ + whitelist: 'SGCONNECT', }); -after(() => { - cy.window().then((win) => { - const coverage = win.__coverage__; // eslint-disable-line no-underscore-dangle +if (process.env.COVERAGE_REPORT) { + const istanbul = require('istanbul-lib-coverage'); + const map = istanbul.createCoverageMap({}); + + Cypress.on('window:before:unload', (e) => { + const coverage = e.currentTarget.__coverage__; // eslint-disable-line no-underscore-dangle if (coverage) { map.merge(coverage); } + }); - cy.writeFile('.nyc_output/out.json', JSON.stringify(map)); - cy.exec('nyc report --temp-directory e2e/.nyc_output --reporter=html --reporter=lcov'); + after(() => { + cy.window().then((win) => { + const coverage = win.__coverage__; // eslint-disable-line no-underscore-dangle + + if (coverage) { + map.merge(coverage); + } + + cy.writeFile('.nyc_output/out.json', JSON.stringify(map)); + cy.exec('nyc report --temp-directory e2e/.nyc_output --reporter=html --reporter=lcov'); + }); }); -}); +} + +/* eslint-enable global-require */ From faca9468b62116947eda74e444b7cecbdca5a7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frithjof=20Klo=CC=88s?= Date: Fri, 15 Feb 2019 11:23:47 +0100 Subject: [PATCH 2/2] PWA-1687: Adjusted tests --- .../e2e/integration/functional/CategoryPage.js | 5 +---- .../integration/functional/FavoritesPageOptions.js | 14 +++++++------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/themes/theme-gmd/e2e/integration/functional/CategoryPage.js b/themes/theme-gmd/e2e/integration/functional/CategoryPage.js index 5c62df8a14..b27e85d395 100755 --- a/themes/theme-gmd/e2e/integration/functional/CategoryPage.js +++ b/themes/theme-gmd/e2e/integration/functional/CategoryPage.js @@ -39,10 +39,7 @@ describe('functional tests category page', () => { it('check for sorting reset', () => { cy.go('back'); - cy.get(els.allProductCategory).first() - .should('be.visible') - .click(); - cy.get("[data-test-id='sorting'] [data-test-id='filter.sort.most_popular']") + cy.get(els.shopLogo) .should('be.visible'); }); }); diff --git a/themes/theme-gmd/e2e/integration/functional/FavoritesPageOptions.js b/themes/theme-gmd/e2e/integration/functional/FavoritesPageOptions.js index 462ed7121d..cfe8171deb 100755 --- a/themes/theme-gmd/e2e/integration/functional/FavoritesPageOptions.js +++ b/themes/theme-gmd/e2e/integration/functional/FavoritesPageOptions.js @@ -15,8 +15,6 @@ describe('e2e functional test favoritePage', () => { .should('be.visible') .last() .click(); - cy.go('back'); - cy.go('back'); cy.get(els.navigatorButton) .should('be.visible') .click() @@ -24,11 +22,13 @@ describe('e2e functional test favoritePage', () => { cy.get(els.navDrawerFavoritesButton) .should('be.visible') .click(); - cy.get(els.favoriteButtonFavList) - .should('be.visible') - .last() - .click() - .wait(4000); + + cy.window().spyAction('RECEIVE_FAVORITES', () => { + cy.get(els.favoriteButtonFavList) + .should('be.visible') + .last() + .click(); + }); }); it('should check for empty fav list', () => {