modified: .gitignore

modified:   src/components/PickItemRow.test.tsx
	modified:   src/components/ProductAutocomplete.tsx
	modified:   src/screens/ActivePickListScreen.test.tsx
	modified:   src/screens/ActivePickListScreen.tsx
	modified:   src/screens/ManageCategoriesScreen.test.tsx
	modified:   src/screens/ManageProductsScreen.test.tsx
	modified:   src/screens/ManageProductsScreen.tsx
	modified:   src/screens/StartPickListScreen.test.tsx
This commit is contained in:
beatzaplenty committed 2025-11-26 12:01:52 +10:00
1 parent d6b784ad11
commit 59be57a5e4
9 files changed
+479 -445

No files matched your search

+9 -8
View File
@@ -59,19 +59,18 @@ describe('PickItemRow', () => {
/>,
);
const productName = screen.getByText(baseProduct.name);
const quantityLabel = screen.getByText('Qty: 1 unit');
// The component now renders the quantity together with the product name
// (e.g. "1 x Test Product"). Match the combined text.
const productName = screen.getByText(new RegExp(`${baseItem.quantity} x ${baseProduct.name}`));
const titleRow = screen.getByTestId('pick-item-title-row');
const rowStyle = getComputedStyle(titleRow);
expect(rowStyle.display).toBe('flex');
expect(rowStyle.flexDirection).toBe('row');
// Ensure the title typography exists and has the expected fontWeight set by the component
const productStyle = getComputedStyle(productName);
const quantityStyle = getComputedStyle(quantityLabel);
expect(productStyle.fontSize).toBe(quantityStyle.fontSize);
expect(productStyle.fontWeight).toBe(quantityStyle.fontWeight);
expect(productStyle.fontWeight).toBe('600');
});
it('asks for confirmation before deleting a product from the pick list', async () => {
@@ -143,7 +142,8 @@ describe('PickItemRow', () => {
await user.click(screen.getByRole('button', { name: /open item controls/i }));
expect(screen.getByRole('dialog', { name: baseProduct.name })).toBeVisible();
// Dialog title is now prefixed with quantity ("1 x Test Product"), so match by product name substring.
expect(screen.getByRole('dialog', { name: new RegExp(baseProduct.name) })).toBeVisible();
});
it('uses inline controls on wide screens', async () => {
@@ -193,6 +193,7 @@ describe('PickItemRow', () => {
row.focus();
await user.keyboard('{Enter}');
expect(screen.getByRole('dialog', { name: baseProduct.name })).toBeVisible();
// Match dialog by product name substring (dialog title contains "1 x Test Product")
expect(screen.getByRole('dialog', { name: new RegExp(baseProduct.name) })).toBeVisible();
});
});
+20 -4
View File
@@ -1,3 +1,4 @@
// src/components/ProductAutocomplete.tsx
import {
Autocomplete,
IconButton,
@@ -16,12 +17,14 @@ interface ProductAutocompleteProps {
availableProducts: Product[];
onSelect: (product: Product) => void;
placeholder?: string;
onQueryChange?: (q: string) => void;
}
export const ProductAutocomplete = ({
availableProducts,
onSelect,
placeholder = 'Search products',
onQueryChange,
}: ProductAutocompleteProps) => {
const categories = useCategories();
const categoriesById = useMemo(() => new Map(categories.map((c) => [c.id, c.name])), [categories]);
@@ -35,6 +38,7 @@ export const ProductAutocomplete = ({
onSelect(selectedProduct);
setSelectedProduct(null);
setQuery('');
if (onQueryChange) onQueryChange('');
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedProduct]);
@@ -57,8 +61,14 @@ export const ProductAutocomplete = ({
onChange={(_, value) => setSelectedProduct(value ?? null)}
inputValue={query}
onInputChange={(_, value, reason) => {
if (reason === 'input') setQuery(value);
if (reason === 'clear') setQuery('');
if (reason === 'input') {
setQuery(value);
if (onQueryChange) onQueryChange(value);
}
if (reason === 'clear') {
setQuery('');
if (onQueryChange) onQueryChange('');
}
}}
filterOptions={(options) => options}
noOptionsText="No available products"
@@ -67,6 +77,12 @@ export const ProductAutocomplete = ({
<TextField
{...params}
placeholder={placeholder}
/* Add accessible name and stable test id */
inputProps={{
...params.inputProps,
'aria-label': placeholder,
'data-testid': 'product-search-input',
}}
InputProps={{
...params.InputProps,
startAdornment: (
@@ -74,12 +90,12 @@ export const ProductAutocomplete = ({
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
{params.InputProps.startAdornment}
{params.InputProps?.startAdornment}
</>
),
endAdornment: (
<>
{params.InputProps.endAdornment}
{params.InputProps?.endAdornment}
<InputAdornment position="end">
<Tooltip title="Add a new product">
<IconButton aria-label="Add product" component={RouterLink} to="/products" size="small">