Skip to content

Commit

Permalink
USF-876: tests events
Browse files Browse the repository at this point in the history
Signed-off-by: Stephen Rugh <[email protected]>
  • Loading branch information
sirugh committed Sep 13, 2024
1 parent 2d36f3d commit 8dc3e53
Show file tree
Hide file tree
Showing 9 changed files with 407 additions and 33 deletions.
71 changes: 39 additions & 32 deletions cypress/src/fixtures/index.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
export const customerShippingAddress = {
firstName: 'John',
lastName: 'Doe',
street: '11501 Domain Dr',
street1: 'Suite 110',
city: 'Austin',
postCode: '78758',
telephone: '1234567890',
email: '[email protected]',
region: '57',
regionFull: 'Texas',
countryFull: 'United States',
countryCode: 'US',
shippingMethod: 'Flat Rate - Fixed',
paymentMethod: 'Check / Money order',
};

export const customerBillingAddress = {
firstName: 'Jane',
lastName: 'Smith',
street: '5th Ave',
street1: 'Suite 20',
// Intentional string to distinguish between state and city during assertion
city: 'NewYork City',
postCode: '12345',
telephone: '0987654321',
email: '[email protected]',
region: '43',
regionFull: 'New York',
countryFull: 'United States',
countryCode: 'US',
paymentMethod: 'Check / Money order',
}
firstName: 'John',
lastName: 'Doe',
street: '11501 Domain Dr',
street1: 'Suite 110',
city: 'Austin',
postCode: '78758',
telephone: '1234567890',
email: '[email protected]',
region: '57',
regionFull: 'Texas',
countryFull: 'United States',
countryCode: 'US',
shippingMethod: 'Flat Rate - Fixed',
paymentMethod: 'Check / Money order',
};

export const customerBillingAddress = {
firstName: 'Jane',
lastName: 'Smith',
street: '5th Ave',
street1: 'Suite 20',
// Intentional string to distinguish between state and city during assertion
city: 'NewYork City',
postCode: '12345',
telephone: '0987654321',
email: '[email protected]',
region: '43',
regionFull: 'New York',
countryFull: 'United States',
countryCode: 'US',
paymentMethod: 'Check / Money order',
}

export const products = {
configurable: {
urlPath: "/products/frankie-sweatshirt/MH04",
urlPathWithOptions: "/products/frankie-sweatshirt/MH04?optionsUIDs=Y29uZmlndXJhYmxlLzE4Ni8xNzk%3D%2CY29uZmlndXJhYmxlLzkzLzY5"
},
}
3 changes: 2 additions & 1 deletion cypress/src/support/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import './deleteCustomer';
import './getUserTokenCookie';
import './getUserTokenCookie';
import './waitForResource';
66 changes: 66 additions & 0 deletions cypress/src/support/waitForResource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Adds command "cy.waitForResource(name)" that checks performance entries
* for resource that ends with the given name. Note that performance entries
* will exist for requests in flight, or not yet fully resolved/loaded.
* This command only applies to the tests in this spec file.
*
* @see https://developers.google.com/web/tools/chrome-devtools/network/understanding-resource-timing
*/
Cypress.Commands.add('waitForResource', (name, options = {}) => {
if (Cypress.browser.family === 'firefox') {
cy.log('Skip waitForResource in Firefox')

return
}

cy.log(`Waiting for resource ${name}`)

const log = false // let's not log inner commands
const timeout = options.timeout || Cypress.config('defaultCommandTimeout')

cy.window({ log }).then(
// note that ".then" method has options first, callback second
// https://on.cypress.io/then
{ log, timeout },
(win) => {
return new Cypress.Promise((resolve, reject) => {
let foundResource

// control how long we should try finding the resource
// and if it is still not found. An explicit "reject"
// allows us to show nice informative message
setTimeout(() => {
if (foundResource) {
// nothing needs to be done, successfully found the resource
return
}

clearInterval(interval)
reject(new Error(`Timed out waiting for resource ${name}`))
}, timeout)

const interval = setInterval(() => {
foundResource = win.performance
.getEntriesByType('resource')
.find((item) => item.name.endsWith(name))

if (!foundResource) {
// resource not found, will try again
return
}

clearInterval(interval)
// because cy.log changes the subject, let's resolve the returned promise
// with log + returned actual result
resolve(
cy.log('✅ success').then(() => {
// let's resolve with the found performance object
// to allow tests to inspect it
return foundResource
})
)
}, 100)
})
}
)
});
41 changes: 41 additions & 0 deletions cypress/src/tests/e2eTests/events/initialization.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const baselineContexts = (adobeDataLayer) => {
const pageContextIndex = adobeDataLayer.findIndex(event => !!event?.pageContext);
const storefrontInstanceContextIndex = adobeDataLayer.findIndex(event => !!event?.storefrontInstanceContext);
const eventForwardingContextIndex = adobeDataLayer.findIndex(event => !!event?.eventForwardingContext);

expect(pageContextIndex).to.be.greaterThan(-1);
expect(storefrontInstanceContextIndex).to.be.greaterThan(-1);
expect(eventForwardingContextIndex).to.be.greaterThan(-1);
};

it('has baseline contexts on homepage', () => {
cy.visit('/');
cy.waitForResource('commerce-events-collector.js')
.then(() => {
cy.window().its('adobeDataLayer').then(baselineContexts);
});
});

it('has baseline contexts on PDP', () => {
cy.visit('/products/frankie-sweatshirt/MH04');
cy.waitForResource('commerce-events-collector.js')
.then(() => {
cy.window().its('adobeDataLayer').then(baselineContexts);
});
});

it('has baseline contexts on cart', () => {
cy.visit('/cart');
cy.waitForResource('commerce-events-collector.js')
.then(() => {
cy.window().its('adobeDataLayer').then(baselineContexts);
});
});

it('has baseline contexts on checkout', () => {
cy.visit('/checkout');
cy.waitForResource('commerce-events-collector.js')
.then(() => {
cy.window().its('adobeDataLayer').then(baselineContexts);
});
});
104 changes: 104 additions & 0 deletions cypress/src/tests/e2eTests/events/initiate-checkout.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { products } from '../../../fixtures';
/**
* https://github.com/adobe/commerce-events/blob/main/examples/events/initiate-checkout.md
*
* Required Contexts: page, storefront, shoppingCart
*/
it("is sent on mini cart Checkout button click", () => {
cy.visit(
products.configurable.urlPathWithOptions
);
cy.waitForResource("commerce-events-collector.js").then(() => {
cy.window()
.its("adobeDataLayer")
.then((adobeDataLayer) => {
const pageContextIndex = adobeDataLayer.findIndex(
(event) => !!event?.pageContext
);
const storefrontInstanceContextIndex = adobeDataLayer.findIndex(
(event) => !!event?.storefrontInstanceContext
);
// page and storefront pushed before spy
expect(pageContextIndex).to.be.greaterThan(-1);
expect(storefrontInstanceContextIndex).to.be.greaterThan(-1);
});
});
cy.waitForResource("commerce-events-collector.js").then(() => {
cy.window().then((win) => {
cy.spy(win.adobeDataLayer, "push").as("adl");
// add to cart
cy.get("span:contains('Add to Cart')").should("be.visible").click();
// click the minicart toggle
cy.get('button[data-count="1"]').should("be.visible").click();
// click the checkout button
cy.get('#nav div.cart-mini-cart a[href="/checkout"]')
.should("be.visible")
.click()
.then(() => {
cy.get("@adl", { timeout: 1000 }).should((adobeDataLayerPush) => {
const targetEventIndex = adobeDataLayerPush.args.findIndex(
(event) => event[0]?.event === "initiate-checkout"
);
const shoppingCartContextIndex = adobeDataLayerPush.args.findIndex(
(event) => !!event[0]?.shoppingCartContext
);
// TODO: USF-1498
expect(targetEventIndex).to.be.greaterThan(-1);
expect(shoppingCartContextIndex).to.be.greaterThan(-1);
});
});
});
});
});

it("is sent on cart page Checkout button click", () => {
// add item to cart
cy.visit(
products.configurable.urlPathWithOptions
);
// add to cart
cy.get("span:contains('Add to Cart')").should("be.visible").click();
// after mini cart count updates, go to /cart page
cy.get('button[data-count="1"]').should("be.visible");
cy.visit("/cart");

cy.waitForResource("commerce-events-collector.js").then(() => {
cy.window()
.its("adobeDataLayer")
.then((adobeDataLayer) => {
const pageContextIndex = adobeDataLayer.findIndex(
(event) => !!event?.pageContext
);
const storefrontInstanceContextIndex = adobeDataLayer.findIndex(
(event) => !!event?.storefrontInstanceContext
);
// page and storefront pushed before spy
expect(pageContextIndex).to.be.greaterThan(-1);
expect(storefrontInstanceContextIndex).to.be.greaterThan(-1);
});
});
cy.waitForResource("commerce-events-collector.js").then(() => {
cy.window().then((win) => {
cy.spy(win.adobeDataLayer, "push").as("adl");
// click the checkout button
cy.get(
"body > main:nth-child(2) > div.section.commerce-cart-order-summary-container > div > div > div > div.cart-order-summary__content > div.cart-order-summary__entry.cart-order-summary__primaryAction > a"
)
.should("be.visible")
.click()
.then(() => {
cy.get("@adl", { timeout: 1000 }).should((adobeDataLayerPush) => {
const targetEventIndex = adobeDataLayerPush.args.findIndex(
(event) => event[0]?.event === "initiate-checkout"
);
const shoppingCartContextIndex = adobeDataLayerPush.args.findIndex(
(event) => !!event[0]?.shoppingCartContext
);
// TODO: USF-1498
expect(targetEventIndex).to.be.greaterThan(-1);
expect(shoppingCartContextIndex).to.be.greaterThan(-1);
});
});
});
});
});
27 changes: 27 additions & 0 deletions cypress/src/tests/e2eTests/events/product-page-view.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { products } from '../../../fixtures';
/**
* https://github.com/adobe/commerce-events/blob/main/examples/events/product-page-view.md
*
* Required Contexts: page, storefront, product, shoppingCart
*/
it('is sent on product page view/render', () => {
cy.visit(products.configurable.urlPath);
cy.waitForResource('commerce-events-collector.js')
.then(() => {
cy.window().its('adobeDataLayer').then((adobeDataLayer) => {
const targetEventIndex = adobeDataLayer.findIndex(event => event?.event === 'product-page-view');
const pageContextIndex = adobeDataLayer.findIndex(event => !!event?.pageContext);
const storefrontInstanceContextIndex = adobeDataLayer.findIndex(event => !!event?.storefrontInstanceContext);
const productContextIndex = adobeDataLayer.findIndex(event => !!event?.productContext);
const shoppingCartContextIndex = adobeDataLayer.findIndex(event => !!event?.shoppingCartContext);

// expected contexts and event are in ACDL
expect(targetEventIndex).to.be.greaterThan(-1);
expect(pageContextIndex).to.be.greaterThan(-1);
expect(storefrontInstanceContextIndex).to.be.greaterThan(-1);
expect(productContextIndex).to.be.greaterThan(-1);
// TODO: this context is not pushed because it is "owned" by the cart dropin. See DINT-1656.
expect(shoppingCartContextIndex).to.be.greaterThan(-1);
});
});
});
40 changes: 40 additions & 0 deletions cypress/src/tests/e2eTests/events/search-product-click.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* https://github.com/adobe/commerce-events/blob/main/examples/events/search-product-click.md
*
* Required contexts: page, storefront, searchResult
*/
it("is sent on search bar product click", () => {
cy.visit("/");
cy.waitForResource('commerce-events-collector.js').then(() => {
cy.window().its('adobeDataLayer').then((adobeDataLayer) => {
const pageContextIndex = adobeDataLayer.findIndex(event => !!event?.pageContext);
const storefrontInstanceContextIndex = adobeDataLayer.findIndex(event => !!event?.storefrontInstanceContext);
// page and storefront pushed before spy
expect(pageContextIndex).to.be.greaterThan(-1);
expect(storefrontInstanceContextIndex).to.be.greaterThan(-1);
});
});
cy.waitForResource("commerce-events-collector.js").then(() => {
cy.window().then((win) => {
cy.spy(win.adobeDataLayer, "push").as("adl");
cy.get(".nav-search-button").should("be.visible").click();
cy.wait(2000);
cy.get("#search").type("shirt");
cy.get(".livesearch.product-link", { timeout: 10000 })
.first()
.click()
.then(() => {
cy.get("@adl", { timeout: 1000 }).should((adobeDataLayerPush) => {
const targetEventIndex = adobeDataLayerPush.args.findIndex(
(event) => event[0]?.event === "search-product-click"
);
const searchResultsContextIndex = adobeDataLayerPush.args.findIndex(
(event) => !!event[0]?.searchResultsContext
);
expect(targetEventIndex).to.be.greaterThan(-1);
expect(searchResultsContextIndex).to.be.greaterThan(-1);
});
});
});
});
});
Loading

0 comments on commit 8dc3e53

Please sign in to comment.