import { expect, test, type Page } from "@playwright/test"; import { mockConfig, seedAuthStorage } from "./helpers/e2e"; const household = { id: 1, name: "Selector House", role: "owner", invite_code: "ABCD1234" }; const user = { id: 1, username: "selector-user", role: "owner" }; async function mockGroceryShell(page: Page, stores: Array>) { await seedAuthStorage(page, { username: "selector-user", role: "owner" }); await mockConfig(page); await page.route("**/households", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify([household]), }); }); await page.route("**/households/1/stores", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(stores), }); }); await page.route("**/households/1/members", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify([user]), }); }); await page.route("**/households/1/locations/*/zones", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ zones: [] }), }); }); await page.route("**/households/1/locations/*/map", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ location: stores.find((store) => String(store.id) === route.request().url().match(/locations\/(\d+)\/map/)?.[1]) || stores[0], map: null, draft_map: null, published_map: null, objects: [], draft_objects: [], published_objects: [], zones: [], items: [], unmapped_count: 0, can_manage: true, }), }); }); await page.route("**/households/1/locations/*/list/recent", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify([]), }); }); await page.route("**/households/1/locations/*/list/suggestions**", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify([]), }); }); await page.route("**/households/1/locations/*/list/item**", async (route) => { await route.fulfill({ status: 404, contentType: "application/json", body: JSON.stringify({ message: "Item not found" }), }); }); await page.route("**/households/1/locations/*/list", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ items: [] }), }); }); } test("grocery store selector shows one selected store and picks from a modal", async ({ page }) => { await page.setViewportSize({ width: 473, height: 1000 }); await mockGroceryShell(page, [ { id: 10, household_store_id: 100, name: "Costco", location_name: "Eastvale", display_name: "Costco - Eastvale", is_default: true, }, { id: 13, household_store_id: 100, name: "Costco", location_name: "Fontana", display_name: "Costco - Fontana", is_default: false, }, { id: 11, household_store_id: 200, name: "99 Ranch", location_name: "Eastvale", display_name: "99 Ranch - Eastvale", is_default: false, }, { id: 12, household_store_id: 300, name: "Stater Bros", location_name: "Ontario Ranch", display_name: "Stater Bros - Ontario Ranch", is_default: false, }, ]); await page.goto("/"); const storeSelector = page.locator(".store-selector-trigger").first(); const locationSelector = page.locator(".location-selector-trigger"); await expect(storeSelector).toBeVisible(); await expect(storeSelector).toContainText("Costco"); await expect(locationSelector).toBeVisible(); await expect(locationSelector).toContainText("Eastvale"); await expect(page.getByRole("button", { name: "Manage Map" })).toBeVisible(); await expect(page.locator(".store-tabs")).not.toContainText("Costco - Eastvale"); await expect(page.locator(".store-tabs")).not.toContainText("99 Ranch"); await expect(page.locator(".store-tabs")).not.toContainText("Stater Bros"); await storeSelector.click(); const modal = page.getByRole("dialog", { name: "Select store" }); await expect(modal).toBeVisible(); await expect(modal.getByRole("button", { name: "Costco" })).toBeVisible(); await expect(modal.getByRole("button", { name: "99 Ranch" })).toBeVisible(); await expect(modal.getByRole("button", { name: "Stater Bros" })).toBeVisible(); await expect(modal).not.toContainText("Eastvale"); await expect(modal).not.toContainText("Ontario Ranch"); await modal.getByRole("button", { name: "99 Ranch" }).click(); await expect(modal).toHaveCount(0); await expect(storeSelector).toContainText("99 Ranch"); await expect(locationSelector).toContainText("Eastvale"); await expect.poll(() => page.evaluate(() => localStorage.getItem("activeHouseholdStoreId_1"))).toBe("200"); await expect.poll(() => page.evaluate(() => localStorage.getItem("activeStoreLocationId_1_200"))).toBe("11"); await storeSelector.click(); await expect(modal).toBeVisible(); await page.locator(".store-selector-modal-overlay").click({ position: { x: 4, y: 4 } }); await expect(modal).toHaveCount(0); await storeSelector.click(); await modal.getByRole("button", { name: "Costco" }).click(); await locationSelector.click(); const locationModal = page.getByRole("dialog", { name: "Select location" }); await expect(locationModal).toBeVisible(); await expect(locationModal.getByRole("button", { name: "Eastvale" })).toBeVisible(); await expect(locationModal.getByRole("button", { name: "Fontana" })).toBeVisible(); await expect(locationModal).not.toContainText("Costco - Eastvale"); await locationModal.getByRole("button", { name: "Fontana" }).click(); await expect(locationModal).toHaveCount(0); await expect(storeSelector).toContainText("Costco"); await expect(locationSelector).toContainText("Fontana"); await expect.poll(() => page.evaluate(() => localStorage.getItem("activeHouseholdStoreId_1"))).toBe("100"); await expect.poll(() => page.evaluate(() => localStorage.getItem("activeStoreLocationId_1_100"))).toBe("13"); await page.getByRole("button", { name: "Manage Map" }).click(); await expect(page).toHaveURL(/\/stores\/100\/locations\/13\/map$/); }); test("single grocery store selector click does not open picker modal", async ({ page }) => { await mockGroceryShell(page, [ { id: 10, household_store_id: 100, name: "Costco", location_name: "Default Location", display_name: "Costco", is_default: true, }, ]); await page.goto("/"); const storeSelector = page.locator(".store-selector-trigger").first(); const locationSelector = page.locator(".location-selector-trigger"); await expect(storeSelector).toBeVisible(); await expect(storeSelector).toContainText("Costco"); await expect(locationSelector).toBeVisible(); await expect(locationSelector).toContainText("Default"); await storeSelector.click(); await expect(page.getByRole("dialog", { name: "Select store" })).toHaveCount(0); await locationSelector.click(); await expect(page.getByRole("dialog", { name: "Select location" })).toHaveCount(0); });