diff --git a/lib/fixtures/productPageRoute.ts b/lib/fixtures/productPageRoute.ts new file mode 100644 index 0000000..5763d7f --- /dev/null +++ b/lib/fixtures/productPageRoute.ts @@ -0,0 +1,48 @@ +import { HomePage } from "@pages"; + +/** + * Sets up a route to retrieve the product ID from the API response. + * @param page - The Playwright page object. + * @param name - Optional name of the string to get the ID for. + * @returns The product ID. + * @example + * const page = await browser.newPage(); + * const productId = await productIdRoute(page); // Gets the second product ID + * + * const productId = await productIdRoute(page, "Pliers") // Gets the ID for the product named "Pliers" + */ +export async function productIdRoute(page: any, name?: string) { + let productId; + + await page.route( + "https://api.practicesoftwaretesting.com/products?between=price,1,100&page=1", + async (route) => { + let body; + const response = await route.fetch(); + body = await response.json(); + if (name) { + productId = findIdByName(body, name); + console.log("pid: " + productId); + } else { + // Get the second product in the list + productId = body.data[1].id; + } + route.continue(); + } + ); + + const homePage = new HomePage(page); + await homePage.goto(); + + return productId; +} + +function findIdByName(json: any, name: string): string | undefined { + const data = json.data; + for (let i = 0; i < data.length; i++) { + if (data[i].name === name) { + return data[i].id; + } + } + return undefined; +} diff --git a/lib/pages/homePage.ts b/lib/pages/homePage.ts index e11099f..230d312 100644 --- a/lib/pages/homePage.ts +++ b/lib/pages/homePage.ts @@ -1,10 +1,12 @@ +import { productIdRoute } from "@fixtures/productPageRoute"; import { Page } from "@playwright/test"; export class HomePage { - readonly product1 = this.page.locator('[data-test="product-1"]'); - readonly product2 = this.page.locator('[data-test="product-2"]'); - readonly product3 = this.page.locator('[data-test="product-3"]'); - readonly product4 = this.page.locator('[data-test="product-4"]'); + readonly productId = (id: string) => + this.page.locator(`[data-test="product-${id}"]`); + readonly product2 = this.page.locator( + '[data-test="product-01H88E5BMA2F3PX6VYX2NS3KX4"]' + ); readonly addToCart = this.page.locator('[data-test="add-to-cart"]'); readonly navCart = this.page.locator('[data-test="nav-cart"]'); @@ -13,5 +15,10 @@ export class HomePage { await this.page.goto("/#/"); } + async clickProductIdFor(name: string) { + const productId = await productIdRoute(this.page, name); + await this.productId(productId).click(); + } + constructor(private readonly page: Page) {} } diff --git a/package-lock.json b/package-lock.json index 1491c42..f5cdeb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,18 +12,18 @@ "dotenv": "^16.3.0" }, "devDependencies": { - "@playwright/test": "^1.35.1", + "@playwright/test": "^1.37.1", "typescript": "^5.1.6" } }, "node_modules/@playwright/test": { - "version": "1.35.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.35.1.tgz", - "integrity": "sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==", + "version": "1.37.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.37.1.tgz", + "integrity": "sha512-bq9zTli3vWJo8S3LwB91U0qDNQDpEXnw7knhxLM0nwDvexQAwx9tO8iKDZSqqneVq+URd/WIoz+BALMqUTgdSg==", "dev": true, "dependencies": { "@types/node": "*", - "playwright-core": "1.35.1" + "playwright-core": "1.37.1" }, "bin": { "playwright": "cli.js" @@ -67,9 +67,9 @@ } }, "node_modules/playwright-core": { - "version": "1.35.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz", - "integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==", + "version": "1.37.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.37.1.tgz", + "integrity": "sha512-17EuQxlSIYCmEMwzMqusJ2ztDgJePjrbttaefgdsiqeLWidjYz9BxXaTaZWxH1J95SHGk6tjE+dwgWILJoUZfA==", "dev": true, "bin": { "playwright-core": "cli.js" diff --git a/package.json b/package.json index 5f8c247..b62b932 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "author": "", "license": "ISC", "devDependencies": { - "@playwright/test": "^1.35.1", + "@playwright/test": "^1.37.1", "typescript": "^5.1.6" }, "dependencies": { diff --git a/playwright.config.ts b/playwright.config.ts index 41c6e44..d93be7b 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -25,5 +25,7 @@ export default defineConfig({ apiURL: process.env.API_URL, apiBaseURL: process.env.API_URL, trace: "on", + screenshot: "only-on-failure", + video: "retain-on-failure", }, }); diff --git a/tests/checkout/checkout.spec.ts b/tests/checkout/checkout.spec.ts index b1e84fe..840d871 100644 --- a/tests/checkout/checkout.spec.ts +++ b/tests/checkout/checkout.spec.ts @@ -1,10 +1,12 @@ import { expect } from "@playwright/test"; import { test, CheckoutPage, HomePage } from "@pages"; import { getLoginToken } from "@datafactory/login"; +import { productIdRoute } from "@fixtures/productPageRoute"; test.describe("Basic UI Checks", () => { const username = process.env.CUSTOMER_01_USERNAME || ""; const password = process.env.CUSTOMER_01_PASSWORD || ""; + let productId; test.beforeEach(async ({ page }) => { // Gets Login Token via API call @@ -14,6 +16,8 @@ test.describe("Basic UI Checks", () => { await page.addInitScript((value) => { window.localStorage.setItem("auth-token", value); }, token); + + productId = await productIdRoute(page); }); test("Add to Cart and Checkout", async ({ page }) => { @@ -21,8 +25,7 @@ test.describe("Basic UI Checks", () => { const checkoutPage = new CheckoutPage(page); await homePage.goto(); - - await homePage.product2.click(); + await homePage.productId(productId).click(); await homePage.addToCart.click(); await homePage.navCart.click(); diff --git a/tests/checkout/checkoutWithApiFixture.spec.ts b/tests/checkout/checkoutWithApiFixture.spec.ts index a003547..b2d624c 100644 --- a/tests/checkout/checkoutWithApiFixture.spec.ts +++ b/tests/checkout/checkoutWithApiFixture.spec.ts @@ -1,6 +1,7 @@ import { expect } from "@playwright/test"; import { test } from "@fixtures/apiRequest"; import { CheckoutPage, HomePage } from "@pages"; +import { productIdRoute } from "@fixtures/productPageRoute"; test.describe("Basic UI Checks With API Fixture", () => { const username = process.env.CUSTOMER_01_USERNAME || ""; @@ -32,7 +33,7 @@ test.describe("Basic UI Checks With API Fixture", () => { await homePage.goto(); - await homePage.product2.click(); + await homePage.clickProductIdFor("Pliers"); await homePage.addToCart.click(); await homePage.navCart.click(); diff --git a/tests/checkout/checkoutWithPageFixture.spec.ts b/tests/checkout/checkoutWithPageFixture.spec.ts index 33e80f5..23b136a 100644 --- a/tests/checkout/checkoutWithPageFixture.spec.ts +++ b/tests/checkout/checkoutWithPageFixture.spec.ts @@ -4,6 +4,7 @@ import { test, CheckoutPage, HomePage } from "@pages"; test.describe("Basic UI Checks With Page Fixture", () => { const username = process.env.CUSTOMER_01_USERNAME || ""; const password = process.env.CUSTOMER_01_PASSWORD || ""; + let productId; test.beforeEach(async ({ page, request, apiURL }) => { // Gets Login Token via API call using apiBaseURL from fixture @@ -23,6 +24,16 @@ test.describe("Basic UI Checks With Page Fixture", () => { await page.addInitScript((value) => { window.localStorage.setItem("auth-token", value); }, token); + + await page.route( + "**/products?between=price,1,100&page=1", + async (route) => { + const response = await route.fetch(); + let body = await response.json(); + productId = body.data[1].id; + route.continue(); + } + ); }); test("Add to Cart and Checkout", async ({ page }) => { @@ -31,7 +42,7 @@ test.describe("Basic UI Checks With Page Fixture", () => { await homePage.goto(); - await homePage.product2.click(); + await homePage.productId(productId).click(); await homePage.addToCart.click(); await homePage.navCart.click();