Fix add product dialog opening and duplicate validation tests

This commit is contained in:
beatz174-bit
2025-12-01 16:30:28 +10:00
parent e4c51d69b6
commit f6498c1bbc
2 changed files with 26 additions and 7 deletions
+23 -7
View File
@@ -15,6 +15,7 @@ import {
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { useDatabase } from '../context/DBProvider'; import { useDatabase } from '../context/DBProvider';
import { useProducts } from '../hooks/dataHooks';
import { BarcodeScannerView } from './BarcodeScannerView'; import { BarcodeScannerView } from './BarcodeScannerView';
import { ExternalProductInfo, fetchProductFromOFF } from '../modules/openFoodFacts'; import { ExternalProductInfo, fetchProductFromOFF } from '../modules/openFoodFacts';
import { DEFAULT_BULK_NAME, DEFAULT_UNIT_TYPE, Product } from '../models/Product'; import { DEFAULT_BULK_NAME, DEFAULT_UNIT_TYPE, Product } from '../models/Product';
@@ -35,6 +36,7 @@ export const AddProductDialog = ({
initialBarcode, initialBarcode,
}: AddProductDialogProps) => { }: AddProductDialogProps) => {
const db = useDatabase(); const db = useDatabase();
const products = useProducts();
const [name, setName] = useState(''); const [name, setName] = useState('');
const [category, setCategory] = useState(''); const [category, setCategory] = useState('');
const [barcode, setBarcode] = useState(''); const [barcode, setBarcode] = useState('');
@@ -83,20 +85,26 @@ export const AddProductDialog = ({
const findBarcodeConflict = useCallback( const findBarcodeConflict = useCallback(
async (value?: string) => { async (value?: string) => {
if (!value) return undefined; if (!value) return undefined;
const conflict = await db.products.where('barcode').equals(value).first(); const conflict = products.find((product) => product.barcode === value);
return conflict ?? undefined; if (conflict) return conflict;
const dbConflict = await db.products.where('barcode').equals(value).first();
return dbConflict ?? undefined;
}, },
[db.products], [db.products, products],
); );
const findNameConflict = useCallback( const findNameConflict = useCallback(
async (value?: string) => { async (value?: string) => {
if (!value) return undefined; if (!value) return undefined;
const normalizedValue = value.trim().toLowerCase(); const normalizedValue = value.trim().toLowerCase();
const conflict = await db.products.filter((product) => product.name.trim().toLowerCase() === normalizedValue).first(); const conflict = products.find((product) => product.name.trim().toLowerCase() === normalizedValue);
return conflict ?? undefined; if (conflict) return conflict;
const dbConflict = await db.products
.filter((product) => product.name.trim().toLowerCase() === normalizedValue)
.first();
return dbConflict ?? undefined;
}, },
[db.products], [db.products, products],
); );
const assertUniqueBarcode = useCallback( const assertUniqueBarcode = useCallback(
@@ -254,7 +262,14 @@ export const AddProductDialog = ({
}; };
return ( return (
<Dialog open={open} onClose={handleDialogClose} aria-label="Add product dialog" fullWidth maxWidth="sm"> <Dialog
open={open}
onClose={handleDialogClose}
aria-label="Add product dialog"
fullWidth
maxWidth="sm"
PaperProps={{ role: 'form' }}
>
<DialogTitle sx={{ pr: 6 }}> <DialogTitle sx={{ pr: 6 }}>
Add product Add product
<IconButton <IconButton
@@ -294,6 +309,7 @@ export const AddProductDialog = ({
inputProps={{ 'data-testid': 'product-barcode-input' }} inputProps={{ 'data-testid': 'product-barcode-input' }}
error={!!barcodeError} error={!!barcodeError}
helperText={barcodeError || ' '} helperText={barcodeError || ' '}
FormHelperTextProps={{ 'data-testid': 'barcode-error' }}
fullWidth fullWidth
/> />
<Button onClick={() => setScannerOpen(true)}>Scan barcode</Button> <Button onClick={() => setScannerOpen(true)}>Scan barcode</Button>
@@ -58,6 +58,7 @@ describe('ManageProductsScreen add and update flows', () => {
</MemoryRouter>, </MemoryRouter>,
); );
await user.click(screen.getByRole('button', { name: /add product/i }));
await user.type(screen.getByLabelText(/name/i), 'New Product'); await user.type(screen.getByLabelText(/name/i), 'New Product');
await selectCategory(user, 'Snacks'); await selectCategory(user, 'Snacks');
await user.type(screen.getByLabelText(/barcode/i), '111'); await user.type(screen.getByLabelText(/barcode/i), '111');
@@ -91,6 +92,7 @@ describe('ManageProductsScreen add and update flows', () => {
</MemoryRouter>, </MemoryRouter>,
); );
await user.click(screen.getByRole('button', { name: /add product/i }));
await user.type(screen.getByLabelText(/name/i), 'Another'); await user.type(screen.getByLabelText(/name/i), 'Another');
await selectCategory(user, 'Snacks'); await selectCategory(user, 'Snacks');
await user.click(screen.getByText(/scan barcode/i)); await user.click(screen.getByText(/scan barcode/i));
@@ -139,6 +141,7 @@ describe('ManageProductsScreen add and update flows', () => {
</MemoryRouter>, </MemoryRouter>,
); );
await user.click(screen.getByRole('button', { name: /add product/i }));
await user.type(screen.getByLabelText(/name/i), 'Lettuce'); await user.type(screen.getByLabelText(/name/i), 'Lettuce');
await selectCategory(user, 'Fresh'); await selectCategory(user, 'Fresh');
await clickSaveButton(user); await clickSaveButton(user);