grocery-app/frontend/tests/available-items-catalog.spec.ts
Nico a2c08aff45
All checks were successful
Build & Deploy Costco Grocery List / build (push) Successful in 1m36s
Build & Deploy Costco Grocery List / verify-images (push) Successful in 2s
Build & Deploy Costco Grocery List / deploy (push) Successful in 8s
Build & Deploy Costco Grocery List / notify (push) Successful in 0s
chore: harden reliability checks
2026-05-25 16:20:35 -07:00

196 lines
6.5 KiB
TypeScript

import { expect, test } from "@playwright/test";
import {
confirmSlide,
mockConfig,
mockHouseholdAndStoreShell,
seedAuthStorage,
} from "./helpers/e2e";
test("manage stores opens a modal to edit and delete household store items", async ({ page }) => {
await seedAuthStorage(page, { username: "catalog-user" });
await mockConfig(page);
await mockHouseholdAndStoreShell(page, {
household: { name: "Catalog House" },
});
let availableItems = [
{
item_id: 501,
item_name: "milk",
item_image: null,
image_mime_type: null,
item_type: "dairy",
item_group: "Milk",
zone: "Dairy & Refrigerated",
has_managed_settings: true,
},
{
item_id: 777,
item_name: "apples",
item_image: null,
image_mime_type: null,
item_type: null,
item_group: null,
zone: null,
has_managed_settings: false,
},
];
await page.route("**/stores", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify([{ id: 10, name: "Costco" }]),
});
});
await page.route("**/households/1/stores/10/available-items*", async (route) => {
const request = route.request();
const url = new URL(request.url());
const query = (url.searchParams.get("query") || "").toLowerCase();
if (request.method() === "GET") {
const filteredItems = availableItems.filter((item) => item.item_name.includes(query));
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ items: filteredItems, catalog_ready: true }),
});
return;
}
await route.fulfill({ status: 500 });
});
await page.route("**/households/1/stores/10/available-items/777", async (route) => {
if (route.request().method() === "PATCH") {
availableItems = availableItems.map((item) =>
item.item_id === 777
? {
...item,
item_type: "produce",
item_group: "Fruits",
zone: "Produce & Fresh Vegetables",
has_managed_settings: true,
}
: item
);
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
message: "Available item updated",
item: availableItems.find((item) => item.item_id === 777),
}),
});
return;
}
await route.fulfill({ status: 500 });
});
await page.route("**/households/1/stores/10/available-items/501", async (route) => {
if (route.request().method() === "DELETE") {
availableItems = availableItems.filter((item) => item.item_id !== 501);
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ message: "Store item deleted" }),
});
return;
}
await route.fulfill({ status: 500 });
});
await page.goto("/manage?tab=stores");
const storeCard = page.locator(".store-card").filter({ hasText: "Costco" });
await expect(storeCard).toBeVisible();
await expect(storeCard.getByRole("button", { name: "Manage Items" })).toBeVisible();
await storeCard.getByRole("button", { name: "Manage Items" }).click();
const managerModal = page.locator(".store-items-modal");
await expect(managerModal).toBeVisible();
await expect(managerModal.getByText("milk", { exact: true })).toBeVisible();
await expect(managerModal.getByText("apples", { exact: true })).toBeVisible();
await managerModal.locator(".store-items-table-row").filter({ hasText: "apples" }).getByRole("button", { name: "Edit Settings" }).click();
const editorModal = page.locator(".available-item-editor-modal");
await expect(editorModal).toBeVisible();
await expect(editorModal.getByLabel("Item Name")).toBeDisabled();
await editorModal.locator(".available-item-editor-select").nth(0).selectOption("produce");
await editorModal.locator(".available-item-editor-select").nth(1).selectOption("Fruits");
await editorModal.locator(".available-item-editor-select").nth(2).selectOption("Produce & Fresh Vegetables");
await editorModal.getByRole("button", { name: "Save Changes" }).click();
await expect(page.locator(".action-toast.action-toast-success")).toContainText("Updated store item");
await expect(managerModal.getByText("produce | Fruits | Produce & Fresh Vegetables")).toBeVisible();
await managerModal.locator(".store-items-table-row").filter({ hasText: "milk" }).getByRole("button", { name: "Delete Item" }).click();
const confirmModal = page.locator(".confirm-slide-modal");
await expect(confirmModal).toBeVisible();
await expect(confirmModal.getByText("Delete milk?")).toBeVisible();
await confirmSlide(page);
await expect(
page.locator(".action-toast.action-toast-success").filter({ hasText: "Deleted store item" })
).toContainText("Deleted store item");
await expect(managerModal.locator(".store-items-table-row").filter({ hasText: "milk" })).toHaveCount(0);
});
test("grocery page remains unchanged and does not show a store items picker", async ({ page }) => {
await seedAuthStorage(page);
await mockConfig(page);
await mockHouseholdAndStoreShell(page);
await page.route("**/households/1/members", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify([
{ id: 1, username: "owner", name: "Owner User", display_name: "Owner User", role: "owner" },
]),
});
});
await page.route("**/households/1/stores/10/list/recent", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify([]),
});
});
await page.route("**/households/1/stores/10/list/suggestions**", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify([]),
});
});
await page.route("**/households/1/stores/10/list/item**", async (route) => {
await route.fulfill({
status: 404,
contentType: "application/json",
body: JSON.stringify({ message: "Item not found" }),
});
});
await page.route("**/households/1/stores/10/list", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ items: [] }),
});
});
await page.goto("/");
await expect(page.getByRole("button", { name: "Store Items" })).toHaveCount(0);
await expect(page.locator(".available-items-picker-modal")).toHaveCount(0);
});