169 lines
6.0 KiB
TypeScript
169 lines
6.0 KiB
TypeScript
import { expect } from "@playwright/test";
|
|
import { test } from "../fixtures";
|
|
import { registerAndLogin } from "../helpers";
|
|
|
|
/** Navigates to the rewards cards page. */
|
|
async function gotoRewards(page: import("@playwright/test").Page) {
|
|
await page.goto("/rewards");
|
|
await expect(page.locator("h1")).toContainText("Rewards cards");
|
|
}
|
|
|
|
/**
|
|
* Adds a rewards card and lands back on the /rewards page with it rendered.
|
|
*/
|
|
async function addCard(
|
|
page: import("@playwright/test").Page,
|
|
storeName: string,
|
|
number: string,
|
|
symbology?: string,
|
|
) {
|
|
await page.fill("#store-name", storeName);
|
|
await page.fill("#card-number", number);
|
|
if (symbology) {
|
|
await page.selectOption("#symbology", symbology);
|
|
}
|
|
await page.click('button:has-text("Add card")');
|
|
await expect(page).toHaveURL(/\/rewards$/);
|
|
const card = page.locator(".rewards-card").filter({ hasText: storeName });
|
|
await expect(card).toBeVisible();
|
|
return card;
|
|
}
|
|
|
|
test("the rewards page shows an empty state before any cards are added", async ({
|
|
page,
|
|
}) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
await gotoRewards(page);
|
|
await expect(page.locator(".empty-state")).toContainText("No rewards cards yet");
|
|
await expect(page.locator(".rewards-card")).toHaveCount(0);
|
|
});
|
|
|
|
test("the Rewards link is available in the site navigation", async ({ page }) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
const nav = page.locator(".site-nav");
|
|
await expect(nav.locator('a[href="/rewards"]')).toHaveText("Rewards");
|
|
});
|
|
|
|
test("a user can add a rewards card and see its barcode", async ({ page }) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
await gotoRewards(page);
|
|
|
|
const card = await addCard(page, "Kroger", "606171584511340224537");
|
|
|
|
// The card renders an inline SVG barcode and the store's card number.
|
|
await expect(card.locator(".rewards-barcode svg")).toBeVisible();
|
|
await expect(card.locator(".rewards-number")).toHaveText("606171584511340224537");
|
|
|
|
// The barcode should be included via the embedded SVG (Code 128 set B→C mix),
|
|
// not rendered client-side from scratch by an image.
|
|
const svg = card.locator(".rewards-barcode svg");
|
|
await expect(svg).toHaveAttribute("viewBox", /\d+ \d+/);
|
|
});
|
|
|
|
test("a user can add a card as Code 39 and see its barcode", async ({ page }) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
await gotoRewards(page);
|
|
|
|
const card = await addCard(page, "Safeway", "ABC123", "code39");
|
|
await expect(card.locator(".rewards-barcode svg")).toBeVisible();
|
|
});
|
|
|
|
test("multiple rewards cards are each rendered with their own barcode", async ({
|
|
page,
|
|
}) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
await gotoRewards(page);
|
|
|
|
await addCard(page, "Kroger", "606171584511340224537");
|
|
await addCard(page, "Safeway", "012345678901");
|
|
|
|
await expect(page.locator(".rewards-card")).toHaveCount(2);
|
|
await expect(page.locator(".rewards-card").filter({ hasText: "Kroger" })).toBeVisible();
|
|
await expect(page.locator(".rewards-card").filter({ hasText: "Safeway" })).toBeVisible();
|
|
});
|
|
|
|
test("removing a rewards card prompts for confirmation and deletes on accept", async ({
|
|
page,
|
|
}) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
await gotoRewards(page);
|
|
await addCard(page, "Kroger", "606171584511340224537");
|
|
|
|
await expect(page).toHaveURL(/\/rewards$/);
|
|
await expect(page.locator(".rewards-card")).toHaveCount(1);
|
|
|
|
page.on("dialog", (dialog) => dialog.accept());
|
|
await page.click('button:has-text("Remove")');
|
|
|
|
// The card is deleted and the empty state returns.
|
|
await expect(page.locator(".rewards-card")).toHaveCount(0);
|
|
await expect(page.locator(".empty-state")).toContainText("No rewards cards yet");
|
|
});
|
|
|
|
test("cancelling the remove confirmation keeps the rewards card", async ({
|
|
page,
|
|
}) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
await gotoRewards(page);
|
|
await addCard(page, "Kroger", "606171584511340224537");
|
|
|
|
await expect(page.locator(".rewards-card")).toHaveCount(1);
|
|
|
|
page.on("dialog", (dialog) => dialog.dismiss());
|
|
await page.click('button:has-text("Remove")');
|
|
|
|
// The card must remain after cancelling.
|
|
await expect(page.locator(".rewards-card")).toHaveCount(1);
|
|
await expect(page.locator(".rewards-card").filter({ hasText: "Kroger" })).toBeVisible();
|
|
});
|
|
|
|
test("a user can open a single-card scan view with only one barcode", async ({
|
|
page,
|
|
}) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
await gotoRewards(page);
|
|
await addCard(page, "Kroger", "606171584511340224537");
|
|
await addCard(page, "Safeway", "012345678901");
|
|
|
|
// Click the Kroger card's barcode to open its focused scan view.
|
|
await page
|
|
.locator(".rewards-card")
|
|
.filter({ hasText: "Kroger" })
|
|
.locator(".rewards-card-link")
|
|
.click();
|
|
|
|
await expect(page).toHaveURL(/\/rewards\/\d+/);
|
|
// Only one barcode is rendered on the scan page.
|
|
await expect(page.locator(".scan-barcode svg")).toHaveCount(1);
|
|
await expect(page.locator(".scan-store")).toHaveText("Kroger");
|
|
await expect(page.locator(".scan-card .rewards-number")).toHaveText(
|
|
"606171584511340224537",
|
|
);
|
|
// The wake-lock script is loaded on the scan page.
|
|
await expect(page.locator('script[src*="rewards.js"]')).toHaveCount(1);
|
|
|
|
// Back link returns to the list.
|
|
await page.click('.scan-back');
|
|
await expect(page).toHaveURL(/\/rewards$/);
|
|
});
|
|
|
|
test("a scan view for another user's card is not accessible", async ({ page }) => {
|
|
await registerAndLogin(page, "alice@example.com");
|
|
await gotoRewards(page);
|
|
await addCard(page, "Kroger", "606171584511340224537");
|
|
|
|
// Grab the card id from the URL of the scan view.
|
|
await page
|
|
.locator(".rewards-card-link")
|
|
.click();
|
|
const url = page.url();
|
|
const cardId = url.split("/").pop();
|
|
|
|
// Sign out and sign in as a different user.
|
|
await page.click('button:has-text("Sign out")');
|
|
await registerAndLogin(page, "bob@example.com");
|
|
|
|
// Bob cannot view Alice's card.
|
|
await page.goto(`/rewards/${cardId}`);
|
|
await expect(page.locator(".scan-barcode svg")).toHaveCount(0);
|
|
}); |