From e9fdce57722c341264e1dadba314ecd56576c5ed Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Sun, 23 Nov 2025 16:58:36 +1000 Subject: [PATCH 1/2] Expand unit and e2e coverage --- e2e/picklist.spec.ts | 21 ++++++++++++++++++ src/modules/openFoodFacts.test.ts | 23 +++++++++++++++++++ src/screens/ManageProductsScreen.test.tsx | 27 +++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/e2e/picklist.spec.ts b/e2e/picklist.spec.ts index 945c423..c390052 100644 --- a/e2e/picklist.spec.ts +++ b/e2e/picklist.spec.ts @@ -32,4 +32,25 @@ test.describe('Active pick list', () => { await expect(page.getByText(additionalProduct).first()).toBeVisible(); await expect(page.getByRole('button', { name: 'Save and Return' })).toBeEnabled(); }); + + test('allows adding and editing products from the manage products screen', async ({ page }) => { + await page.goto('/'); + + await page.getByRole('link', { name: 'Manage Products' }).click(); + + await page.getByLabel('Name').click(); + await page.getByLabel('Name').fill('Playwright Cola'); + await page.getByLabel('Category').click(); + await page.getByRole('option', { name: 'Drinks' }).click(); + await page.getByRole('button', { name: 'Save Product' }).click(); + + await expect(page.getByText('Product added.')).toBeVisible(); + await expect(page.getByText('Playwright Cola')).toBeVisible(); + + await page.getByRole('button', { name: 'Edit Playwright Cola' }).click(); + await page.getByLabel('Name').nth(1).fill('Playwright Cola Zero'); + await page.getByRole('button', { name: 'Save product' }).click(); + + await expect(page.getByText('Playwright Cola Zero')).toBeVisible(); + }); }); diff --git a/src/modules/openFoodFacts.test.ts b/src/modules/openFoodFacts.test.ts index af5d92e..33adb49 100644 --- a/src/modules/openFoodFacts.test.ts +++ b/src/modules/openFoodFacts.test.ts @@ -76,5 +76,28 @@ describe('fetchProductFromOFF', () => { expect(result).toBeNull(); }); + + it('returns null immediately when the barcode is empty', async () => { + const result = await fetchProductFromOFF(''); + + expect(result).toBeNull(); + }); + + it('returns null when the browser is offline', async () => { + const originalNavigator = navigator; + Object.defineProperty(globalThis, 'navigator', { + value: { onLine: false }, + configurable: true, + }); + + const result = await fetchProductFromOFF('123456'); + + expect(result).toBeNull(); + + Object.defineProperty(globalThis, 'navigator', { + value: originalNavigator, + configurable: true, + }); + }); }); diff --git a/src/screens/ManageProductsScreen.test.tsx b/src/screens/ManageProductsScreen.test.tsx index fa3554c..575dde9 100644 --- a/src/screens/ManageProductsScreen.test.tsx +++ b/src/screens/ManageProductsScreen.test.tsx @@ -165,6 +165,33 @@ describe('ManageProductsScreen barcode lookup', () => { expect(mockDb.products.add).not.toHaveBeenCalled(); }); + it('informs the user when barcode lookup happens offline', async () => { + const originalNavigator = navigator; + Object.defineProperty(globalThis, 'navigator', { + value: { onLine: false }, + configurable: true, + }); + + try { + const user = userEvent.setup(); + render( + + + , + ); + + await user.click(screen.getByRole('button', { name: /scan barcode/i })); + await user.click(screen.getByRole('button', { name: /mock scan/i })); + + expect(await screen.findByText(/you are offline\. enter details manually\./i)).toBeVisible(); + } finally { + Object.defineProperty(globalThis, 'navigator', { + value: originalNavigator, + configurable: true, + }); + } + }); + it('prevents updating a product to use an existing barcode', async () => { mockUseProducts.mockReturnValue([ { From 09cd4a2548606ea037fd18b298f1f622f628fdb2 Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Sun, 23 Nov 2025 17:06:01 +1000 Subject: [PATCH 2/2] Fix ActivePickListScreen test mocks typing --- src/screens/ActivePickListScreen.test.tsx | 40 ++--------------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/src/screens/ActivePickListScreen.test.tsx b/src/screens/ActivePickListScreen.test.tsx index 8f8b235..21eb51b 100644 --- a/src/screens/ActivePickListScreen.test.tsx +++ b/src/screens/ActivePickListScreen.test.tsx @@ -8,8 +8,8 @@ import { Product } from '../models/Product'; const addMock = vi.fn(); const updateMock = vi.fn(); -const pickItemsMock = vi.fn(); -const productsMock = vi.fn(); +const pickItemsMock = vi.fn<() => PickItem[]>(); +const productsMock = vi.fn<() => Product[]>(); const pickListMock = vi.fn(); const defaultProducts: Product[] = [ @@ -50,41 +50,7 @@ const defaultProducts: Product[] = [ vi.mock('../hooks/dataHooks', () => ({ usePickItems: () => pickItemsMock(), - useProducts: () => [ - { - id: 'prod-1', - name: 'Cola', - category: 'Drinks', - unit_type: 'unit', - bulk_name: 'box', - barcode: '111', - archived: false, - created_at: 0, - updated_at: 0, - }, - { - id: 'prod-2', - name: 'Chips', - category: 'Snacks', - unit_type: 'unit', - bulk_name: 'box', - barcode: '222', - archived: false, - created_at: 0, - updated_at: 0, - }, - { - id: 'prod-3', - name: 'Apple Juice', - category: 'Drinks', - unit_type: 'unit', - bulk_name: 'box', - barcode: '333', - archived: false, - created_at: 0, - updated_at: 0, - }, - ], + useProducts: () => productsMock(), usePickList: () => pickListMock(), useAreas: () => [{ id: 'area-1', name: 'Front Counter', created_at: 0, updated_at: 0 }], }));