From ee8b0df0544ceac97f5bd2683ad8a4ca03c940ba Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Mon, 24 Nov 2025 14:42:58 +1000 Subject: [PATCH] Fix packaging filter enablement and coverage --- e2e/picklist.spec.ts | 31 +++++++ src/screens/ActivePickListScreen.test.tsx | 105 ++++++++++++++++++++-- src/screens/ActivePickListScreen.tsx | 36 +++++--- 3 files changed, 151 insertions(+), 21 deletions(-) diff --git a/e2e/picklist.spec.ts b/e2e/picklist.spec.ts index 001c119..7e232c0 100644 --- a/e2e/picklist.spec.ts +++ b/e2e/picklist.spec.ts @@ -264,6 +264,37 @@ test.describe('Active pick list', () => { await expect(showPickedToggle).toBeChecked(); }); + test('enables packaging filters when mixed pick statuses are visible and keeps the selection', async ({ page }) => { + await navigateToNewPickList(page); + + await addProductToPickList(page, additionalProduct); + await addProductToPickList(page, secondaryProduct); + + await page.getByRole('button', { name: /Switch to carton packaging/i }).first().click(); + + const statusToggles = page.getByLabel('Toggle picked status'); + await statusToggles.first().check(); + + const cartonsRadio = page.getByRole('radio', { name: 'Cartons' }); + const unitsRadio = page.getByRole('radio', { name: 'Units' }); + + await expect(cartonsRadio).toBeEnabled(); + await expect(unitsRadio).toBeEnabled(); + + await unitsRadio.click(); + await expect(unitsRadio).toBeChecked(); + await expect(cartonsRadio).not.toBeChecked(); + await expect(page.getByText(secondaryProduct)).toBeVisible(); + await expect(page.getByText(additionalProduct)).toHaveCount(0); + + const showPickedToggle = page.getByRole('checkbox', { name: 'Show picked' }); + await showPickedToggle.click(); + + await expect(cartonsRadio).toBeDisabled(); + await expect(unitsRadio).toBeDisabled(); + await expect(page.getByRole('radio', { name: 'All' })).toBeChecked(); + }); + test('toggles packaging type and persists the selection', async ({ page }) => { await navigateToNewPickList(page); await addProductToPickList(page, additionalProduct); diff --git a/src/screens/ActivePickListScreen.test.tsx b/src/screens/ActivePickListScreen.test.tsx index 8d70205..f959f9c 100644 --- a/src/screens/ActivePickListScreen.test.tsx +++ b/src/screens/ActivePickListScreen.test.tsx @@ -442,7 +442,7 @@ describe('ActivePickListScreen product search', () => { expect(screen.getByRole('radio', { name: /units/i })).toBeDisabled(); }); - it('evaluates packaging filters based on visible (unpicketed) items when hiding picked', async () => { + it('enables and disables packaging filters based on the visible item statuses', async () => { pickItemsMock.mockReturnValue([ { id: 'item-1', @@ -476,15 +476,20 @@ describe('ActivePickListScreen product search', () => { , ); - expect(screen.getByRole('radio', { name: /cartons/i })).toBeEnabled(); - expect(screen.getByRole('radio', { name: /units/i })).toBeEnabled(); + const cartonsRadio = screen.getByRole('radio', { name: /cartons/i }); + const unitsRadio = screen.getByRole('radio', { name: /units/i }); + expect(cartonsRadio).toBeEnabled(); + expect(unitsRadio).toBeEnabled(); - await user.click(screen.getByLabelText(/show picked/i)); + const togglePicked = screen.getByLabelText(/show picked/i); + await user.click(togglePicked); - await waitFor(() => expect(screen.getByRole('radio', { name: /cartons/i })).toBeDisabled()); + expect(cartonsRadio).toBeDisabled(); + expect(unitsRadio).toBeDisabled(); - expect(screen.getByRole('radio', { name: /all/i })).toBeChecked(); - expect(screen.getByRole('radio', { name: /units/i })).toBeDisabled(); + await user.click(togglePicked); + expect(cartonsRadio).toBeEnabled(); + expect(unitsRadio).toBeEnabled(); }); it('resets the filter when the selected packaging type is unavailable', async () => { @@ -497,7 +502,7 @@ describe('ActivePickListScreen product search', () => { product_id: 'prod-1', quantity: 1, is_carton: true, - status: 'pending', + status: 'picked', created_at: 0, updated_at: 0, }, @@ -597,6 +602,90 @@ describe('ActivePickListScreen product search', () => { expect(screen.getByText('Cola')).toBeVisible(); }); + it('filters the visible list by packaging type and keeps the selection active', async () => { + pickItemsMock.mockReturnValue([ + { + id: 'item-1', + pick_list_id: 'list-1', + product_id: 'prod-1', + quantity: 1, + is_carton: true, + status: 'picked', + created_at: 0, + updated_at: 0, + }, + { + id: 'item-2', + pick_list_id: 'list-1', + product_id: 'prod-2', + quantity: 1, + is_carton: false, + status: 'pending', + created_at: 0, + updated_at: 0, + }, + ]); + + const user = userEvent.setup(); + + render( + + + } /> + + , + ); + + const cartonsRadio = screen.getByRole('radio', { name: /cartons/i }); + const unitsRadio = screen.getByRole('radio', { name: /units/i }); + + await user.click(unitsRadio); + expect(unitsRadio).toBeChecked(); + expect(screen.getByText('Chips')).toBeVisible(); + expect(screen.queryByText('Cola')).not.toBeInTheDocument(); + + await user.click(cartonsRadio); + expect(cartonsRadio).toBeChecked(); + expect(screen.getByText('Cola')).toBeVisible(); + expect(screen.queryByText('Chips')).not.toBeInTheDocument(); + }); + + it('disables packaging filters when all items share the same status', () => { + pickItemsMock.mockReturnValue([ + { + id: 'item-1', + pick_list_id: 'list-1', + product_id: 'prod-1', + quantity: 1, + is_carton: true, + status: 'pending', + created_at: 0, + updated_at: 0, + }, + { + id: 'item-2', + pick_list_id: 'list-1', + product_id: 'prod-2', + quantity: 1, + is_carton: false, + status: 'pending', + created_at: 0, + updated_at: 0, + }, + ]); + + render( + + + } /> + + , + ); + + expect(screen.getByRole('radio', { name: /cartons/i })).toBeDisabled(); + expect(screen.getByRole('radio', { name: /units/i })).toBeDisabled(); + }); + it('disables show picked toggle when all items are picked', async () => { pickItemsMock.mockReturnValue([ { diff --git a/src/screens/ActivePickListScreen.tsx b/src/screens/ActivePickListScreen.tsx index 5f1d9d3..f5ffe3c 100644 --- a/src/screens/ActivePickListScreen.tsx +++ b/src/screens/ActivePickListScreen.tsx @@ -43,10 +43,24 @@ export const ActivePickListScreen = () => { setItemState(items); }, [items]); + const itemsVisibleByStatus = useMemo( + () => (showPicked ? itemState : itemState.filter((item) => item.status !== 'picked')), + [itemState, showPicked], + ); + const allItemsPicked = useMemo( () => itemState.length > 0 && itemState.every((item) => item.status === 'picked'), [itemState], ); + const hasUnpickedItems = useMemo( + () => itemsVisibleByStatus.some((item) => item.status !== 'picked'), + [itemsVisibleByStatus], + ); + const hasPickedItems = useMemo( + () => itemsVisibleByStatus.some((item) => item.status === 'picked'), + [itemsVisibleByStatus], + ); + const hasMixedPickStatuses = hasPickedItems && hasUnpickedItems; const productMap = useMemo(() => { const map = new Map(); @@ -62,13 +76,8 @@ export const ActivePickListScreen = () => { [areas, pickList?.area_id], ); - const visibleItemsByStatus = useMemo( - () => (showPicked ? itemState : itemState.filter((item) => item.status !== 'picked')), - [itemState, showPicked], - ); - const sortedItems = useMemo(() => { - return [...visibleItemsByStatus].sort((a, b) => { + return [...itemsVisibleByStatus].sort((a, b) => { const productA = productMap.get(a.product_id); const productB = productMap.get(b.product_id); @@ -89,7 +98,7 @@ export const ActivePickListScreen = () => { return timeA - timeB; }); - }, [visibleItemsByStatus, productMap]); + }, [itemsVisibleByStatus, productMap]); const sortedProducts = useMemo(() => { const dedupedById = new Map(); @@ -132,15 +141,16 @@ export const ActivePickListScreen = () => { }, [pickList?.categories, sortedProducts]); const hasCartonItems = useMemo( - () => visibleItemsByStatus.some((item) => item.is_carton), - [visibleItemsByStatus], + () => itemsVisibleByStatus.some((item) => item.is_carton), + [itemsVisibleByStatus], ); const hasUnitItems = useMemo( - () => visibleItemsByStatus.some((item) => !item.is_carton), - [visibleItemsByStatus], + () => itemsVisibleByStatus.some((item) => !item.is_carton), + [itemsVisibleByStatus], ); const packagingTypeCount = Number(hasCartonItems) + Number(hasUnitItems); const singlePackagingType = packagingTypeCount === 1; + const packagingFiltersDisabled = !hasMixedPickStatuses; const productIdsInList = useMemo( () => new Set(itemState.map((item) => item.product_id)), @@ -424,13 +434,13 @@ export const ActivePickListScreen = () => { value="cartons" control={} label="Cartons" - disabled={singlePackagingType || !hasCartonItems} + disabled={packagingFiltersDisabled || !hasCartonItems} /> } label="Units" - disabled={singlePackagingType || !hasUnitItems} + disabled={packagingFiltersDisabled || !hasUnitItems} />