From e17b55fe22ba3441003f81e6cf2c19f6afc4291e Mon Sep 17 00:00:00 2001 From: Matteo Parenti Date: Tue, 17 Feb 2026 16:23:06 +0100 Subject: [PATCH] Add tests for core_weight_catalog_id handling --- .../components/SpoolFormModal.test.tsx | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/frontend/src/__tests__/components/SpoolFormModal.test.tsx b/frontend/src/__tests__/components/SpoolFormModal.test.tsx index a13e49b64..f357fc121 100644 --- a/frontend/src/__tests__/components/SpoolFormModal.test.tsx +++ b/frontend/src/__tests__/components/SpoolFormModal.test.tsx @@ -62,6 +62,7 @@ const existingSpool: InventorySpool = { rgba: 'FF0000FF', label_weight: 1000, core_weight: 250, + core_weight_catalog_id: null, weight_used: 300, slicer_filament: 'GFL99', slicer_filament_name: 'Generic PLA', @@ -183,4 +184,140 @@ describe('SpoolFormModal weightTouched', () => { // weight_used MUST be included for new spools (default value 0) expect(payload).toHaveProperty('weight_used', 0); }); + + it('preserves core_weight_catalog_id when editing other fields', async () => { + const spoolWithCatalogId: InventorySpool = { + ...existingSpool, + core_weight_catalog_id: 5, + }; + + render( + + ); + + await waitFor(() => { + expect(screen.getByText('Edit Spool')).toBeInTheDocument(); + }); + + // Change the note field (unrelated to catalog ID) + const noteInputs = screen.getAllByPlaceholderText(/note/i); + expect(noteInputs.length).toBeGreaterThan(0); + fireEvent.change(noteInputs[0], { target: { value: 'Updated note' } }); + + // Click Save + const saveButton = screen.getByRole('button', { name: /save/i }); + fireEvent.click(saveButton); + + await waitFor(() => { + expect(api.updateSpool).toHaveBeenCalledTimes(1); + }); + + const [spoolId, payload] = vi.mocked(api.updateSpool).mock.calls[0]; + expect(spoolId).toBe(1); + // core_weight_catalog_id MUST be preserved when editing other fields + expect(payload).toHaveProperty('core_weight_catalog_id', 5); + // Other changes should also be present + expect(payload).toHaveProperty('note', 'Updated note'); + }); + + it('includes core_weight_catalog_id when selecting from catalog', async () => { + const mockCatalog = [ + { id: 1, name: 'Generic 250g', weight: 250 }, + { id: 2, name: 'Bambu Lab 250g', weight: 250 }, + { id: 3, name: 'Standard 300g', weight: 300 }, + ]; + + vi.mocked(api.getSpoolCatalog).mockResolvedValue(mockCatalog); + + render( + + ); + + await waitFor(() => { + expect(screen.getByRole('heading', { name: 'Add Spool' })).toBeInTheDocument(); + }); + + // Wait for catalog to load + await waitFor(() => { + expect(api.getSpoolCatalog).toHaveBeenCalled(); + }); + + // Click on the empty spool weight field to open dropdown + const weightInputs = screen.getAllByPlaceholderText(/search/i); + const weightPicker = weightInputs.find(input => + input.getAttribute('placeholder')?.toLowerCase().includes('spool') + ); + expect(weightPicker).toBeTruthy(); + fireEvent.focus(weightPicker!); + + // Click on "Bambu Lab 250g" option + await waitFor(() => { + const bambuOption = screen.queryByText('Bambu Lab 250g'); + if (bambuOption) fireEvent.click(bambuOption); + }); + + // Click the add spool button + const addButtons = screen.getAllByRole('button', { name: /add spool/i }); + const submitButton = addButtons.find(btn => btn.tagName === 'BUTTON' && btn.querySelector('svg.lucide-save')); + expect(submitButton).toBeTruthy(); + fireEvent.click(submitButton!); + + await waitFor(() => { + expect(api.createSpool).toHaveBeenCalledTimes(1); + }); + + const [payload] = vi.mocked(api.createSpool).mock.calls[0]; + // Both weight AND catalog ID should be sent + expect(payload).toHaveProperty('core_weight', 250); + expect(payload).toHaveProperty('core_weight_catalog_id', 2); // ID of "Bambu Lab 250g" + }); + + it('displays correct catalog name when duplicates exist', async () => { + const spoolWithCatalogId: InventorySpool = { + ...existingSpool, + core_weight: 250, + core_weight_catalog_id: 2, // "Bambu Lab 250g", not the first match + }; + + const mockCatalog = [ + { id: 1, name: 'Generic 250g', weight: 250 }, + { id: 2, name: 'Bambu Lab 250g', weight: 250 }, + { id: 3, name: 'Standard 300g', weight: 300 }, + ]; + + vi.mocked(api.getSpoolCatalog).mockResolvedValue(mockCatalog); + + render( + + ); + + await waitFor(() => { + expect(screen.getByText('Edit Spool')).toBeInTheDocument(); + }); + + // Wait for catalog to load + await waitFor(() => { + expect(api.getSpoolCatalog).toHaveBeenCalled(); + }); + + // Should display "Bambu Lab 250g" (by ID), not "Generic 250g" (first match by weight) + await waitFor(() => { + const weightInputs = screen.getAllByDisplayValue(/250|Bambu/i); + const bambuFound = weightInputs.some(input => + input.value === 'Bambu Lab 250g' || input.getAttribute('value') === 'Bambu Lab 250g' + ); + expect(bambuFound || screen.queryByText('Bambu Lab 250g')).toBeTruthy(); + }); + }); });