first commit
This commit is contained in:
91
tests/cypress/e2e/buyProduct_Balikovna.cy.ts
Normal file
91
tests/cypress/e2e/buyProduct_Balikovna.cy.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import * as wpj from '../support/wpj';
|
||||
import * as gtm from '../support/gtm';
|
||||
|
||||
describe('Průchod košíkem s vybráním dopravy Balíkovny', () => {
|
||||
afterEach(() => {
|
||||
gtm.checkUserInfoPosition();
|
||||
});
|
||||
|
||||
it('Přidej produkt do košíku', () => {
|
||||
wpj.addProductToCart();
|
||||
});
|
||||
|
||||
it('Přejdi do košíku', () => {
|
||||
wpj.stepIntoCart();
|
||||
gtm.dataLayerContainsEvent('begin_checkout');
|
||||
|
||||
cy.matchImageSnapshot('Košík');
|
||||
});
|
||||
|
||||
it('Výběr Balikovny', () => {
|
||||
cy.get('.delivery-item-balikovna .custom-control-input').then(($radio) => {
|
||||
if (!$radio.is(':checked')) {
|
||||
cy.get('.delivery-item-balikovna > .custom-radio').click();
|
||||
} else {
|
||||
cy.get('[data-btn="open-balikovna-widget"]').click();
|
||||
}
|
||||
});
|
||||
cy.getIframeBody('iframe[data-src*="BALIKOVNY"]')
|
||||
.find('.Suggest-input')
|
||||
.should('exist')
|
||||
.type('54301{enter}');
|
||||
cy.wait(5000);
|
||||
cy.getIframeBody('iframe[data-src*="BALIKOVNY"]')
|
||||
.find('.Suggest-resultButton')
|
||||
.first()
|
||||
.click();
|
||||
cy.wait(5000);
|
||||
cy.getIframeBody('iframe[data-src*="BALIKOVNY"]')
|
||||
.find('.PointRow', { timeout: 10000 })
|
||||
.contains('Krkonošská 164', { timeout: 10000 })
|
||||
.click();
|
||||
cy.getIframeBody('iframe[data-src*="BALIKOVNY"]').find('.PointDetail-btnPrimary').click();
|
||||
});
|
||||
|
||||
it('Doprava se vybrala správně', () => {
|
||||
cy.get('.delivery-item-balikovna').should('have.class', 'selected');
|
||||
cy.get('.delivery-class-info').contains('Vrchlabí SAZKA Tabák Krkonošská 164');
|
||||
cy.get('.delivery-class-info').contains('Krkonošská 164, 54301, Vrchlabí');
|
||||
cy.wait(1000);
|
||||
gtm.dataLayerContainsEvent('add_shipping_info');
|
||||
|
||||
cy.matchImageSnapshot('Košík s vybranou dopravou Balikovna');
|
||||
});
|
||||
|
||||
it('Výběr dobírky', () => {
|
||||
cy.get('.payment-item-dobirka').first().click().should('have.class', 'selected');
|
||||
gtm.dataLayerContainsEvent('add_payment_info');
|
||||
|
||||
cy.matchImageSnapshot('Košík s dobírkou');
|
||||
});
|
||||
|
||||
it('Kontrola ceny', () => {
|
||||
cy.get('.price-box .price-box-row:first-child > :nth-child(2)').contains('149 Kč');
|
||||
cy.get('.price-box .price-box-row:nth-child(2) > :nth-child(2)').contains('134 Kč');
|
||||
cy.get('.price-box .price-box-row:nth-child(3) > :nth-child(2)').contains('233,88 Kč');
|
||||
cy.get('.price-box .total-price > :nth-child(2)').contains('283 Kč');
|
||||
});
|
||||
|
||||
it('Proklik na vyplnění údajů', () => {
|
||||
cy.get('.cart-nextstep-wrapper > .btn').click({ force: true });
|
||||
cy.wait(1500);
|
||||
wpj.fillCustomerDeliveryInfo();
|
||||
gtm.dataLayerContainsEvent('add_contact_details');
|
||||
|
||||
cy.matchImageSnapshot('Košík s vyplněnými údaji pro doručení');
|
||||
});
|
||||
|
||||
it('Dokončení nákupního procesu', () => {
|
||||
cy.get('.cart-nextstep-wrapper > .btn').click();
|
||||
cy.get('.page-ordersuccess').contains('úspěšně přijali');
|
||||
gtm.dataLayerContainsEvent('purchase');
|
||||
gtm.dataLayerEventEcommerceContainsKey('purchase', 'transaction_id');
|
||||
gtm.dataLayerEventContainsEcommerceItem('purchase', {
|
||||
...gtm.getCelenkaEcommerceItem(),
|
||||
category_current: [],
|
||||
quantity: 1,
|
||||
});
|
||||
|
||||
cy.matchImageSnapshot('Odeslaná objednávka');
|
||||
});
|
||||
});
|
||||
39
tests/cypress/e2e/buyProduct_OsobniOdber.cy.ts
Normal file
39
tests/cypress/e2e/buyProduct_OsobniOdber.cy.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as wpj from '../support/wpj';
|
||||
|
||||
describe('Průchod košíkem Osobní odběr', () => {
|
||||
it('Vejdi do detailu produktu', () => {
|
||||
wpj.visitProductDetail();
|
||||
});
|
||||
|
||||
it('Zobrazení dostupnosti - kdy zboží dostanu', () => {
|
||||
cy.get('.c-product-deliverytime button').first().click({ force: true }).wait(1000);
|
||||
cy.get('.c-modal .close').first().click({ force: true });
|
||||
});
|
||||
it('Zvýšit počet na 2 kusy', () => {
|
||||
cy.get('.c-product-buycount .plus_unit').first().click();
|
||||
cy.get('.c-product-buycount .form-control').should('have.value', '2');
|
||||
});
|
||||
it('Přidat do košíku a kontrola že se zvětšila cena na 298', () => {
|
||||
cy.get('.btn.c-product-addtocartbutton').first().click();
|
||||
cy.get('.price-total strong').contains('298');
|
||||
});
|
||||
it('Přejít do košíku', () => {
|
||||
wpj.stepIntoCart();
|
||||
});
|
||||
it('Výběr Osobní odběr a platba hotovosti', () => {
|
||||
cy.get('.delivery-item-osobniodber > .custom-radio').click();
|
||||
cy.get('.payment-item-hotovost').first().click();
|
||||
});
|
||||
it('Pokračovat na vyplnění údajů', () => {
|
||||
cy.get('.cart-nextstep-wrapper > .btn').click({ force: true });
|
||||
wpj.fillCustomerInfo();
|
||||
});
|
||||
it('Dokončit objednávku', () => {
|
||||
cy.get('.cart-nextstep-wrapper > .btn').click();
|
||||
cy.get('.page-ordersuccess').contains('úspěšně přijali');
|
||||
});
|
||||
it('Kontrola funkčnosti odkazu na detail objednávky', () => {
|
||||
cy.get('.page-ordersuccess').contains('Detail objednávky').click({ force: true });
|
||||
cy.url().should('include', '/objednavka/');
|
||||
});
|
||||
});
|
||||
33
tests/cypress/e2e/buyProduct_Zasilkovna.cy.ts
Normal file
33
tests/cypress/e2e/buyProduct_Zasilkovna.cy.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as wpj from '../support/wpj';
|
||||
|
||||
describe('Průchod košíkem s vybráním dopravy Zasilkovna', () => {
|
||||
// it('Přidej produkt do košíku a vyber Zasilkovna dopravu', () => {
|
||||
// wpj.addProductToCart();
|
||||
// wpj.stepIntoCart();
|
||||
// cy.get('.delivery-item-zasilkovna > .custom-radio').click();
|
||||
// cy.get('.deliveries-box', {
|
||||
// timeout: 2000,
|
||||
// }).should('be.visible');
|
||||
// cy.url().should('include', 'doprava-platba');
|
||||
// });
|
||||
// it('Vyber Zasilkovny', () => {
|
||||
// cy.get('.delivery-item-zasilkovna> .custom-radio').click({ force: true });
|
||||
// cy.getIframeBody('#packeta-widget')
|
||||
// .find('.custom-autocomplete input')
|
||||
// .type('Vrchlabí{enter}');
|
||||
// cy.getIframeBody('#packeta-widget')
|
||||
// .find('custom-autocomplete__list li.point', { timeout: 3000 })
|
||||
// .first()
|
||||
// .click();
|
||||
// cy.getIframeBody('#packeta-widget').find('#btn_select_branch').click();
|
||||
// });
|
||||
// it('Proklik na vyplnění údajů', () => {
|
||||
// cy.get('.cart-nextstep-wrapper > .btn', { timeout: 10000 }).click({ force: true });
|
||||
// cy.url().should('include', '/kosik/udaje/');
|
||||
// wpj.fillCustomerDeliveryInfo();
|
||||
// });
|
||||
// it('Dokončení nákupního procesu', () => {
|
||||
// cy.get('.cart-nextstep-wrapper > .btn').click();
|
||||
// cy.get('.cart-success-message').contains('úspěšně přijata');
|
||||
// });
|
||||
});
|
||||
68
tests/cypress/e2e/filters.cy.ts
Normal file
68
tests/cypress/e2e/filters.cy.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import * as wpj from '../support/wpj';
|
||||
|
||||
describe('Výběr filtrů', () => {
|
||||
it('Přechod do filtrovatelné sekce', () => {
|
||||
cy.visit('/');
|
||||
cy.get('.c-header-sections ul li a').contains('Káva').click();
|
||||
cy.url().should('contain', '/kava_k451/');
|
||||
|
||||
cy.matchImageSnapshot('Sekce Káva{id=451}');
|
||||
});
|
||||
|
||||
it('Kontrola výchozího počtu produktů', () => {
|
||||
cy.get('.filter-total').should('contain', 6);
|
||||
});
|
||||
|
||||
it('Kliknuti na filtr vyrobci', () => {
|
||||
cy.get('.filter-top-horizontal > .filter-item:not(.filter-item-more)').last().click();
|
||||
});
|
||||
|
||||
it('Vybrani vyrobce Beansmith\'s', () => {
|
||||
cy.get('[for="mc-beansmith\'s-124"]').click();
|
||||
cy.get('.reset-item').contains('Beansmith\'s');
|
||||
cy.url().should('include', 'dynamic_filter%5BproducerIds%5D%5B0%5D=124');
|
||||
cy.get('.filter-total').should('contain', 2);
|
||||
|
||||
cy.matchImageSnapshot('Sekce Káva filtrováno podle výrobce Beansmith\'s');
|
||||
});
|
||||
|
||||
it('Vyber dalsiho filtru vyrobce Nordbeans', () => {
|
||||
cy.get('[for="mc-nordbeans-125"]').click();
|
||||
cy.get('.reset-item').contains('Nordbeans');
|
||||
cy.url().should('include', 'dynamic_filter%5BproducerIds%5D%5B1%5D=125');
|
||||
cy.get('.filter-total').should('contain', 6);
|
||||
|
||||
cy.matchImageSnapshot('Sekce Káva filtrováno podle výrobců Rafiki a wpj');
|
||||
});
|
||||
|
||||
it('Reset filtru', () => {
|
||||
cy.get('.reset-all').click();
|
||||
cy.url().should('not.include', 'producerIds');
|
||||
});
|
||||
|
||||
it('Výběr řazení "Nejlevnější"', () => {
|
||||
cy.get('[name="order"]').select('Nejlevnější');
|
||||
cy.url().should('include', 'order=price');
|
||||
|
||||
cy.matchImageSnapshot('Sekce Káva řazeno podle nejlevnějších produktů');
|
||||
});
|
||||
|
||||
it('Výběr prvního produktu v aktivním filtru', () => {
|
||||
wpj.getNthProduct(0).find('.product-link').first().click();
|
||||
cy.get('.c-breadcrumbs .active').contains('Hacienda Sonora, 250g');
|
||||
});
|
||||
|
||||
it('Výběr filtru "Nejdražší"', () => {
|
||||
cy.get('.c-breadcrumbs li:nth-child(2) > a').click();
|
||||
cy.get('.c-breadcrumbs .active').contains('Káva');
|
||||
cy.get('[name="order"]').select('Nejdražší');
|
||||
cy.url().should('include', 'order');
|
||||
|
||||
cy.matchImageSnapshot('Sekce Káva řazeno podle nejdražších produktů');
|
||||
});
|
||||
|
||||
it('Výběr prvního produktu v aktivním filtru', () => {
|
||||
wpj.getNthProduct(0).find('.product-link').first().click();
|
||||
cy.get('.c-breadcrumbs .active').contains('Předplatné Espresso 1000g');
|
||||
});
|
||||
});
|
||||
16
tests/cypress/e2e/firstProductDetail.cy.ts
Normal file
16
tests/cypress/e2e/firstProductDetail.cy.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import * as wpj from '../support/wpj';
|
||||
|
||||
describe('Výběr prvního produktu', () => {
|
||||
it('Proklik na první sekci - Capsle', () => {
|
||||
cy.visit('/');
|
||||
cy.get('.c-header-sections ul li a').first().click();
|
||||
cy.get('.c-breadcrumbs .active').contains('Capsle');
|
||||
cy.url().should('contain', '/capsle_k436/');
|
||||
});
|
||||
|
||||
it('Výběr prvního produktu', () => {
|
||||
cy.get('.c-section-products > div .product-link').first().click();
|
||||
cy.url().should('contain', '/darkovy-poukaz-capsle-1000-kc_z6263/');
|
||||
cy.get('.c-breadcrumbs .active').first().contains('Dárkový poukaz Capsle 1000 Kč');
|
||||
});
|
||||
});
|
||||
27
tests/cypress/e2e/image.cy.ts
Normal file
27
tests/cypress/e2e/image.cy.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as wpj from '../support/wpj';
|
||||
|
||||
describe('Zobrazení obrázku v produktu', () => {
|
||||
it('Proklik na detail produktu + Kliknuti na obrazek', () => {
|
||||
cy.visit('/');
|
||||
cy.get('.c-header-sections [href*="typy-produktu"]').click();
|
||||
wpj.getNthProduct(0).find('.product-link').first().click();
|
||||
cy.get('.main-photo a').click();
|
||||
cy.wait(3000);
|
||||
});
|
||||
|
||||
it('Zavreni obrazku', () => {
|
||||
cy.get('.pswp__button--close').click();
|
||||
});
|
||||
|
||||
it('Proklik mezi obrazku u produktu', () => {
|
||||
cy.visit('/');
|
||||
cy.get('.c-header-sections [href*="typy-produktu"]').click();
|
||||
wpj.getNthProduct(1).find('.product-link').first().click();
|
||||
cy.get('.c-breadcrumbs .active').contains('Kolekce');
|
||||
cy.get('.main-photo a').click();
|
||||
cy.wait(3000);
|
||||
cy.get('.pswp__button--arrow--next').click();
|
||||
cy.get('.pswp').type('{esc}');
|
||||
cy.wait(1000);
|
||||
});
|
||||
});
|
||||
44
tests/cypress/e2e/multiset.cy.ts
Normal file
44
tests/cypress/e2e/multiset.cy.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import * as wpj from '../support/wpj';
|
||||
|
||||
describe('Konfigurace multisetu a přidání do košíku', () => {
|
||||
it('Vejdi na detail multiset produktu', () => {
|
||||
cy.visit('multiset-konfigurator_z6163/');
|
||||
});
|
||||
|
||||
it('Otevři výběr první části multisetu', () => {
|
||||
wpj.clickMultisetSelectionButton(1);
|
||||
});
|
||||
|
||||
it('Vyber druhý produkt a variantu M', () => {
|
||||
wpj.selectMultisetItem(2);
|
||||
wpj.selectMultisetVariation('M');
|
||||
});
|
||||
|
||||
it('Otevři popisek a galerii', () => {
|
||||
cy.get('.jsmultisets-opener-title-wrapper').click({ multiple: true });
|
||||
cy.wait(1000);
|
||||
// TODO(havlicek): Vymyslet, jak udělat dobrý screenshot bez duplikace multisetu nebo použití viewportu, který je hodně malý
|
||||
cy.matchImageSnapshot('Multiset s otevřeným popiskem a galerií', { capture: 'viewport' });
|
||||
});
|
||||
|
||||
it('Vlož výběr do setu', () => {
|
||||
wpj.clickAddToSetButton();
|
||||
});
|
||||
|
||||
it('Otevři výběr druhé části multisetu, vyber variantu XL a vlož do setu', () => {
|
||||
wpj.clickMultisetSelectionButton(2);
|
||||
wpj.selectMultisetVariation('M');
|
||||
wpj.clickAddToSetButton();
|
||||
});
|
||||
|
||||
it('Otevři výběr třetí části multisetu a vlož do setu', () => {
|
||||
wpj.clickMultisetSelectionButton(3);
|
||||
wpj.clickAddToSetButton();
|
||||
});
|
||||
|
||||
it('Přidej multiset do košíku', () => {
|
||||
cy.get('.product-right-side .c-product-addtocartbutton').click();
|
||||
cy.wait(1000);
|
||||
cy.get('.cartbox-product').contains('Multiset');
|
||||
});
|
||||
});
|
||||
48
tests/cypress/e2e/navigation.cy.ts
Normal file
48
tests/cypress/e2e/navigation.cy.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import * as gtm from '../support/gtm';
|
||||
|
||||
describe('Pruchod sekcemi pres navigaci', () => {
|
||||
it('Kontrola, ze existuje sekce Typy produktů', () => {
|
||||
cy.visit('/');
|
||||
cy.get('.c-header-sections > .container').contains('Typy produktů');
|
||||
});
|
||||
|
||||
it('Proklik do sekce Typy produktů', () => {
|
||||
cy.get('.c-header-sections [href*="typy-produktu"]').click();
|
||||
cy.get('.c-breadcrumbs .active').should('contain', 'Typy produktů');
|
||||
});
|
||||
|
||||
it('Proklik do prvniho produktu', () => {
|
||||
cy.get('.c-section-products .c-productlist-squareitem').contains('Dárkový poukaz 1000 Kč').click();
|
||||
cy.get('.c-breadcrumbs .active').contains('Dárkový poukaz 1000 Kč');
|
||||
});
|
||||
|
||||
it('Navrat pres navigaci do predchozi sekce', () => {
|
||||
cy.get('.c-breadcrumbs li:nth-child(2) > a').click();
|
||||
cy.get(' .c-breadcrumbs .active').should('contain', 'Typy produktů');
|
||||
});
|
||||
|
||||
it('Zopakovat proklik do produktu s produktem Kolekce', () => {
|
||||
cy.get('.c-section-products .c-productlist-squareitem').contains('Kolekce').click();
|
||||
cy.get('.c-breadcrumbs .active').should('contain', 'Kolekce');
|
||||
// cy.matchImageSnapshot();
|
||||
});
|
||||
|
||||
it('Kliknuti na produkt tag, ktery neni stejny jako sekce, ze ktere prijdu', () => {
|
||||
cy.get('.c-product-sections [href*="wpj_v90"]').click();
|
||||
cy.get('.c-breadcrumbs .active').should('contain', 'Výrobce wpj');
|
||||
});
|
||||
|
||||
it('Navigace skrz recommender na homepage', () => {
|
||||
cy.visit('/');
|
||||
cy.get('.c-editablecontent-recommender').eq(0).scrollIntoView();
|
||||
cy.wait(1500);
|
||||
gtm.dataLayerContainsEvent('view_item_list');
|
||||
gtm.dataLayerEventEcommerceContainsKeyAndValue('view_item_list', 'item_list_name', 'recommender');
|
||||
gtm.checkDataLayerEventHasCorrectPositionsForEcommerceItems('view_item_list');
|
||||
cy.get('.c-editablecontent-recommender .c-productlist-squareitem').eq(1).find('.product-link').eq(0).then($link => {
|
||||
$link.removeAttr('href');
|
||||
});
|
||||
cy.get('.c-editablecontent-recommender .c-productlist-squareitem').eq(1).find('.product-link').eq(0).click();
|
||||
gtm.checkDataLayerEcommerceItemHasCorrectPosition('select_item', 0, 2);
|
||||
});
|
||||
});
|
||||
17
tests/cypress/e2e/registration.cy.ts
Normal file
17
tests/cypress/e2e/registration.cy.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import * as wpj from '../support/wpj';
|
||||
|
||||
describe('Registrace a prihlaseni uzivatele', () => {
|
||||
it('Registrace uzivatele', () => {
|
||||
wpj.register();
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
it('Odhlaseni uzivatele', () => {
|
||||
wpj.logout();
|
||||
});
|
||||
|
||||
it('Prihlaseni uzivatele', () => {
|
||||
wpj.login();
|
||||
// cy.matchImageSnapshot();
|
||||
});
|
||||
});
|
||||
5
tests/cypress/fixtures/example.json
Normal file
5
tests/cypress/fixtures/example.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
22
tests/cypress/plugins/index.ts
Normal file
22
tests/cypress/plugins/index.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
49
tests/cypress/support/commands.ts
Normal file
49
tests/cypress/support/commands.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
getIframeBody(selector: string): Chainable<JQuery>;
|
||||
inIframe(selector: string, callback: (chainable: Chainable<JQuery>) => unknown): void;
|
||||
}
|
||||
}
|
||||
}
|
||||
Cypress.Commands.add('getIframeBody', (selector) => {
|
||||
return cy
|
||||
.get(selector, { timeout: 30000 })
|
||||
.should('be.visible')
|
||||
.its('0.contentDocument.body', { timeout: 30000 })
|
||||
.should('not.be.empty');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('inIframe', (selector, callback) => {
|
||||
return cy.getIframeBody(selector).then(($body) => {
|
||||
callback(cy.wrap($body));
|
||||
});
|
||||
});
|
||||
|
||||
export {};
|
||||
29
tests/cypress/support/e2e.ts
Normal file
29
tests/cypress/support/e2e.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { addMatchImageSnapshotCommand } from '@simonsmith/cypress-image-snapshot/command';
|
||||
import installLogsCollector from 'cypress-terminal-report/src/installLogsCollector';
|
||||
|
||||
import 'cypress-fail-fast';
|
||||
import './commands';
|
||||
import { acceptAllCookies } from './wpj';
|
||||
|
||||
addMatchImageSnapshotCommand({
|
||||
failureThresholdType: 'percent',
|
||||
failureThreshold: 0.01,
|
||||
customDiffDir: 'cypress/snapshot_diffs',
|
||||
});
|
||||
|
||||
Cypress.env('useDetailedLogging') && installLogsCollector();
|
||||
|
||||
before(() => {
|
||||
// preventivně nastavit zemi na CZ, kvůli dopravě
|
||||
cy.visit('/zeme/CZ');
|
||||
cy.wait(5000);
|
||||
acceptAllCookies();
|
||||
});
|
||||
// Cypress.on('uncaught:exception', e => {
|
||||
// // TODO(hauschwitz): asi není nejlepší řešení, ale prozatim dobrý
|
||||
// if (e.message.toLowerCase().match(/(sentry)|(\$)|(wpj\.onready)/).length > 1) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// throw e;
|
||||
// });
|
||||
148
tests/cypress/support/gtm.ts
Normal file
148
tests/cypress/support/gtm.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
declare global {
|
||||
interface Window {
|
||||
dataLayer: Record<string, any>[];
|
||||
}
|
||||
}
|
||||
|
||||
function getArrayOfEventsFromDataLayer(dataLayer: Record<string, any>[]) {
|
||||
return Cypress._.map(dataLayer, (o) => Cypress._.pick(o, 'event'));
|
||||
}
|
||||
|
||||
function getEventFromDataLayer(dataLayer: Record<string, any>[], event: string) {
|
||||
return Cypress._.find(dataLayer, (o) => o.event === event);
|
||||
}
|
||||
|
||||
export function getCelenkaEcommerceItem() {
|
||||
return {
|
||||
item_id: 104,
|
||||
product_id: 104,
|
||||
ean: '',
|
||||
item_code: 'XY264',
|
||||
product_code: 'XY264',
|
||||
has_variations: false,
|
||||
variation_ids: [],
|
||||
variation_id: null,
|
||||
variation_code: null,
|
||||
item_variant: null,
|
||||
sold_out: null,
|
||||
variation_codes: [],
|
||||
category_main: [
|
||||
{ id: 386, name: 'Oblečení' },
|
||||
{ id: 388, name: 'Doplňky' },
|
||||
{ id: 393, name: 'Čepice' },
|
||||
],
|
||||
item_brand: 'wpj',
|
||||
campaigns: [],
|
||||
item_name: 'Čelenka Mountains black&white',
|
||||
tax: 21,
|
||||
price: 149,
|
||||
price_with_tax: 149,
|
||||
price_without_tax: 123.14,
|
||||
price_tax: 25.86,
|
||||
price_without_discount: 149,
|
||||
discount: 0,
|
||||
has_discount: false,
|
||||
availability: 'skladem',
|
||||
url: '',
|
||||
image_url: '',
|
||||
category_current: [
|
||||
{ id: 386, name: 'Oblečení' },
|
||||
{ id: 388, name: 'Doplňky' },
|
||||
{ id: 393, name: 'Čepice' },
|
||||
],
|
||||
quantity: null,
|
||||
};
|
||||
}
|
||||
|
||||
export function dataLayerContains(target: Record<string, any>) {
|
||||
expect(window.dataLayer).to.contain(target);
|
||||
}
|
||||
|
||||
export function dataLayerContainsEvent(event: string) {
|
||||
cy.window()
|
||||
.then((win) => {
|
||||
return getArrayOfEventsFromDataLayer(win.dataLayer);
|
||||
})
|
||||
.should('deep.include', { event });
|
||||
}
|
||||
|
||||
export function dataLayerContainsEcommerceItem(ecommerceItem: Record<string, any>) {
|
||||
cy.window().then((win) => {
|
||||
const itemFound = win.dataLayer.some((layerItem) =>
|
||||
layerItem.ecommerce?.items.some((item: Record<string, any>) =>
|
||||
Cypress._.isEqual({
|
||||
...item,
|
||||
url: '',
|
||||
image_url: '',
|
||||
}, ecommerceItem),
|
||||
),
|
||||
);
|
||||
expect(itemFound, `Item ${JSON.stringify(ecommerceItem)} not found in any ecommerce items array \ndataLayer: ${JSON.stringify(win.dataLayer)}`).to.be.true;
|
||||
});
|
||||
}
|
||||
|
||||
export function dataLayerEventContainsEcommerceItem(
|
||||
event: string,
|
||||
ecommerceItem: Record<string, any>,
|
||||
) {
|
||||
cy.window().then((win) => {
|
||||
const eventObject = getEventFromDataLayer(win.dataLayer, event);
|
||||
const itemFound = eventObject.ecommerce?.items.some((item: Record<string, any>) => {
|
||||
return Cypress._.isEqual({
|
||||
...item,
|
||||
url: '',
|
||||
image_url: '',
|
||||
}, ecommerceItem);
|
||||
});
|
||||
expect(itemFound, `Item ${JSON.stringify(ecommerceItem)} not found in ecommerce of ${event} event. \neventObject: ${JSON.stringify(eventObject)}`).to.be.true;
|
||||
});
|
||||
}
|
||||
|
||||
export function dataLayerEventEcommerceContainsKey(event: string, key: string) {
|
||||
cy.window().then((win) => {
|
||||
const eventObject = getEventFromDataLayer(win.dataLayer, event);
|
||||
expect(Object.prototype.hasOwnProperty.call(eventObject.ecommerce, key), `Event ${event} doesn't have ${key} key. \neventObject: ${JSON.stringify(eventObject)}`).to.be.true;
|
||||
});
|
||||
}
|
||||
|
||||
export function checkUserInfoPosition() {
|
||||
cy.window().then((win) => {
|
||||
const events = Cypress._.filter(
|
||||
getArrayOfEventsFromDataLayer(win.dataLayer),
|
||||
(event) => {
|
||||
return Object.prototype.hasOwnProperty.call(event, 'event') && !event.event.includes('gtm');
|
||||
},
|
||||
);
|
||||
const consentIndex = Cypress._.findIndex(events, { event: 'consent_default' });
|
||||
const userInfoIndex = Cypress._.findIndex(events, { event: 'user_info' });
|
||||
|
||||
// user info je hned po consentu
|
||||
expect(userInfoIndex).to.be.eq(consentIndex + 1, `User info is in wrong position, \nall events: ${JSON.stringify(events)}`);
|
||||
});
|
||||
}
|
||||
|
||||
export function dataLayerEventEcommerceContainsKeyAndValue(event: string, key: string, value: string) {
|
||||
cy.window().then((win) => {
|
||||
const eventObject = getEventFromDataLayer(win.dataLayer, event);
|
||||
|
||||
expect(Object.prototype.hasOwnProperty.call(eventObject.ecommerce, key), `${event} is missing the ${key} property, \neventObject: ${JSON.stringify(eventObject)}`).to.be.true;
|
||||
expect(eventObject.ecommerce[key]).to.be.eq(value, `${key} in event ${event} does not have expected value ${value}`);
|
||||
});
|
||||
}
|
||||
|
||||
export function checkDataLayerEventHasCorrectPositionsForEcommerceItems(event: string) {
|
||||
cy.window().then((win) => {
|
||||
const eventObject = getEventFromDataLayer(win.dataLayer, event);
|
||||
|
||||
expect(eventObject.ecommerce.items[0].position).to.be.eq(1, `Item at position 0 has wrong position value, \neventObject: ${JSON.stringify(eventObject)}`);
|
||||
expect(eventObject.ecommerce.items[1].position).to.be.eq(2, `Item at position 1 has wrong position value, \neventObject: ${JSON.stringify(eventObject)}`);
|
||||
});
|
||||
}
|
||||
|
||||
export function checkDataLayerEcommerceItemHasCorrectPosition(event: string, index: number, position: number) {
|
||||
cy.window().then((win) => {
|
||||
const eventObject = getEventFromDataLayer(win.dataLayer, event);
|
||||
|
||||
expect(eventObject.ecommerce.items[index].position).to.be.eq(position, `Item at index ${index} in event ${event} has wrong position, \neventObject: ${JSON.stringify(eventObject)}`);
|
||||
});
|
||||
}
|
||||
204
tests/cypress/support/wpj.ts
Normal file
204
tests/cypress/support/wpj.ts
Normal file
@@ -0,0 +1,204 @@
|
||||
import { syncFetch } from '../util';
|
||||
import * as gtm from './gtm';
|
||||
import Selector = JQuery.Selector;
|
||||
import Chainable = Cypress.Chainable;
|
||||
|
||||
function withPreviousUrl(callback: (url: string) => unknown): void {
|
||||
cy.url().then((url) => {
|
||||
callback(url);
|
||||
|
||||
if (url.startsWith('about:')) {
|
||||
url = '/';
|
||||
}
|
||||
|
||||
cy.visit(url);
|
||||
});
|
||||
}
|
||||
|
||||
export const testUser = {
|
||||
email: 'cuchac@email.cz',
|
||||
password: 'wpjwpj123',
|
||||
name: 'Wpj',
|
||||
surname: 'Wpj',
|
||||
phone: '+420728123219',
|
||||
street: 'Fügnerova 1288',
|
||||
city: 'Vrchlabí',
|
||||
zip: '54301',
|
||||
country: 'CZ',
|
||||
} as const;
|
||||
|
||||
export type LoginOptions = {
|
||||
[key in keyof typeof testUser]?: (typeof testUser)[key];
|
||||
};
|
||||
|
||||
export function register(): LoginOptions;
|
||||
export function register(login: LoginOptions): LoginOptions;
|
||||
export function register(login?: LoginOptions): LoginOptions {
|
||||
withPreviousUrl(() => {
|
||||
login = {
|
||||
...testUser,
|
||||
...(login ?? {}),
|
||||
};
|
||||
|
||||
cy.visit('/');
|
||||
acceptAllCookies();
|
||||
cy.get('.cart-signin').click();
|
||||
cy.get('.c-userlogin-form [href*=registrace]').first().click();
|
||||
cy.wait(100); // hack - $ is not defined
|
||||
|
||||
for (const [id, value] of Object.entries(login)) {
|
||||
if (id === 'country') {
|
||||
continue;
|
||||
}
|
||||
|
||||
cy.get(`#${id}`).type(value, { force: true });
|
||||
}
|
||||
cy.get('#country').select(login.country);
|
||||
|
||||
cy.get('.registration-submit > .btn').click();
|
||||
});
|
||||
|
||||
return login;
|
||||
}
|
||||
|
||||
export function login(): void;
|
||||
export function login(email: string, password: string): void;
|
||||
export function login(email?: string, password?: string): void {
|
||||
withPreviousUrl(() => {
|
||||
email ??= testUser.email;
|
||||
password ??= testUser.password;
|
||||
|
||||
cy.visit('/');
|
||||
cy.get('.cart-signin').click();
|
||||
cy.get('#type_login').type(email);
|
||||
cy.get('#type_password').type(password);
|
||||
cy.get('#type_Submit').click();
|
||||
});
|
||||
}
|
||||
|
||||
export function logout(): void {
|
||||
withPreviousUrl(() => {
|
||||
//Zakomentovat login() z duvodu registration.cy.ts, jelikoz nejprve probehne registrace a uzivatel je jiz prihlasen
|
||||
// tudiz problem s visit('/prihlaseni')
|
||||
// login();
|
||||
|
||||
cy.visit('/ucet');
|
||||
cy.get('.item-logout > a').click();
|
||||
});
|
||||
}
|
||||
|
||||
export function resetSoft() {
|
||||
cy.clearAllCookies();
|
||||
cy.clearAllLocalStorage();
|
||||
cy.clearAllSessionStorage();
|
||||
}
|
||||
|
||||
export function resetHard(opts?: { baseUrl: string }) {
|
||||
let baseUrl: string;
|
||||
if (opts) {
|
||||
baseUrl = opts.baseUrl;
|
||||
} else {
|
||||
baseUrl = Cypress.config('baseUrl');
|
||||
}
|
||||
|
||||
const url = new URL('/_cypress/resetHard', baseUrl);
|
||||
const response = syncFetch(url.href);
|
||||
|
||||
// prime web server
|
||||
syncFetch(baseUrl);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export function getNthProduct(idx: number = 0) {
|
||||
return cy.get('.c-section-products .c-productlist-squareitem').eq(idx);
|
||||
}
|
||||
|
||||
export function fillCustomerInfo() {
|
||||
cy.get('.cart-nextstep-wrapper > .btn').click();
|
||||
cy.get('#iemail ').type(testUser.email);
|
||||
cy.get('#iname').type(testUser.name);
|
||||
cy.get('#isurname').type(testUser.surname);
|
||||
cy.get('#iphone').type(testUser.phone);
|
||||
}
|
||||
|
||||
export function fillCustomerDeliveryInfo() {
|
||||
cy.get('.cart-nextstep-wrapper > .btn').click();
|
||||
cy.get('#iemail ').type(testUser.email);
|
||||
cy.get('#iname').type(testUser.name);
|
||||
cy.get('#isurname').type(testUser.surname);
|
||||
cy.get('#iphone').type(testUser.phone);
|
||||
cy.get('#istreet').type(testUser.street);
|
||||
cy.get('#icity').type(testUser.city);
|
||||
cy.get('#izip').type(testUser.zip);
|
||||
}
|
||||
|
||||
export function priceEquals<Subject extends JQuery>(price: number): (fn: Subject) => void {
|
||||
return function (subject) {
|
||||
const actualPrice = +subject.text().replace(/\D/, '');
|
||||
cy.wrap(actualPrice).should('eq', price);
|
||||
};
|
||||
}
|
||||
|
||||
export function getIframeDocument(selector: Selector): Chainable<JQuery> {
|
||||
return cy.get(selector).its('0.contentDocument').should('exist');
|
||||
}
|
||||
|
||||
export function getIframeBody(selector: Selector): Chainable<JQuery> {
|
||||
return getIframeDocument(selector)
|
||||
.its('body')
|
||||
.should('not.be.undefined')
|
||||
.then((body: JQuery) => cy.wrap(body));
|
||||
}
|
||||
|
||||
export function acceptAllCookies() {
|
||||
cy.get('.cookiebar-btns-simple .btn', { timeout: 10000 }).last().then(
|
||||
($btn) => {
|
||||
if ($btn.is(':visible')) {
|
||||
cy.wrap($btn).click();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function visitProductDetail() {
|
||||
cy.wait(100);
|
||||
cy.visit('/celenka-mountains-black-white_z104/');
|
||||
gtm.dataLayerContainsEvent('page_view');
|
||||
gtm.dataLayerContainsEvent('view_item');
|
||||
gtm.dataLayerContainsEcommerceItem(gtm.getCelenkaEcommerceItem());
|
||||
}
|
||||
|
||||
export function addProductToCart() {
|
||||
visitProductDetail();
|
||||
cy.get('.c-product-submitblock > .btn.c-product-addtocartbutton').first().click();
|
||||
gtm.dataLayerContainsEvent('add_to_cart');
|
||||
gtm.dataLayerEventContainsEcommerceItem('add_to_cart', {
|
||||
...gtm.getCelenkaEcommerceItem(),
|
||||
quantity: 1,
|
||||
});
|
||||
}
|
||||
|
||||
export function stepIntoCart() {
|
||||
cy.get('.cartbox-footer > .btn', { timeout: 30_000 }).first().click();
|
||||
cy.url().should('include', 'kosik');
|
||||
gtm.dataLayerContainsEvent('view_cart');
|
||||
cy.get('.cart-nextstep-wrapper > .btn', { timeout: 30_000 }).click();
|
||||
}
|
||||
|
||||
export function clickMultisetSelectionButton(index: number) {
|
||||
cy.get('.jsmultisets-selected .item').eq(index - 1).find('a').click();
|
||||
cy.wait(500);
|
||||
}
|
||||
|
||||
export function selectMultisetItem(index: number) {
|
||||
cy.get('.jsmultisets-selection-item-navigation .item').eq(index - 1).find('a').click();
|
||||
}
|
||||
|
||||
export function selectMultisetVariation(text: string) {
|
||||
cy.get('.jsmultisets-product-variation').contains(text).click();
|
||||
}
|
||||
|
||||
export function clickAddToSetButton() {
|
||||
cy.get('.jsmultisets-sidebar-submit button').click();
|
||||
}
|
||||
24
tests/cypress/util.ts
Normal file
24
tests/cypress/util.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export function syncFetch(
|
||||
url: string,
|
||||
init?: RequestInit & { body?: XMLHttpRequestBodyInit | Document },
|
||||
) {
|
||||
// Running under node.js
|
||||
if (typeof window === 'undefined') {
|
||||
return require('sync-fetch')(url, init);
|
||||
}
|
||||
|
||||
const request = new XMLHttpRequest();
|
||||
if (init?.headers) {
|
||||
for (const [key, value] of Object.entries(init.headers)) {
|
||||
request.setRequestHeader(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
request.open(init?.method ?? 'GET', url, false);
|
||||
request.send(init?.body ?? null);
|
||||
|
||||
return {
|
||||
...request,
|
||||
json: () => JSON.parse(request.responseText),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user