From 3dfd03fa89aa42d7d43bb00b2cd3f6d3428237ae Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 4 Jun 2026 22:12:29 +1000 Subject: [PATCH] [Bug] Fix for build forms (#12081) * Bug fix for build forms - Memoize outputs to prevent re-rendering reset issues * Add playwright test --- src/frontend/src/forms/BuildForms.tsx | 49 ++++++++++++++-------- src/frontend/tests/pages/pui_build.spec.ts | 18 ++++++++ 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/frontend/src/forms/BuildForms.tsx b/src/frontend/src/forms/BuildForms.tsx index c1ad970684..3fd3acbc41 100644 --- a/src/frontend/src/forms/BuildForms.tsx +++ b/src/frontend/src/forms/BuildForms.tsx @@ -343,16 +343,21 @@ export function useCompleteBuildOutputsForm({ ); }, [location, build.destination, build.part_detail]); + // Memoize the outputs once to avoid re-rendering issues + const buildOutputs = useMemo(() => { + return outputs.map((output: any) => { + return { + output: output.pk, + quantity: output.quantity + }; + }); + }, [outputs]); + const buildOutputCompleteFields: ApiFormFieldSet = useMemo(() => { return { outputs: { field_type: 'table', - value: outputs.map((output: any) => { - return { - output: output.pk, - quantity: output.quantity - }; - }), + value: buildOutputs, modelRenderer: (row: TableFieldRowProps) => { const record = outputs.find((output) => output.pk == row.item.output); return ( @@ -420,16 +425,21 @@ export function useScrapBuildOutputsForm({ ); }, [location, build.destination, build.part_detail]); + // Memoize the outputs once to avoid re-rendering issues + const buildOutputs = useMemo(() => { + return outputs.map((output: any) => { + return { + output: output.pk, + quantity: output.quantity + }; + }); + }, [outputs]); + const buildOutputScrapFields: ApiFormFieldSet = useMemo(() => { return { outputs: { field_type: 'table', - value: outputs.map((output: any) => { - return { - output: output.pk, - quantity: output.quantity - }; - }), + value: buildOutputs, modelRenderer: (row: TableFieldRowProps) => { const record = outputs.find((output) => output.pk == row.item.output); return ( @@ -486,15 +496,20 @@ export function useCancelBuildOutputsForm({ outputs: any[]; onFormSuccess: (response: any) => void; }) { + // Memoize the outputs once to avoid re-rendering issues + const buildOutputs = useMemo(() => { + return outputs.map((output: any) => { + return { + output: output.pk + }; + }); + }, [outputs]); + const buildOutputCancelFields: ApiFormFieldSet = useMemo(() => { return { outputs: { field_type: 'table', - value: outputs.map((output: any) => { - return { - output: output.pk - }; - }), + value: buildOutputs, modelRenderer: (row: TableFieldRowProps) => { const record = outputs.find((output) => output.pk == row.item.output); return ( diff --git a/src/frontend/tests/pages/pui_build.spec.ts b/src/frontend/tests/pages/pui_build.spec.ts index 0979f7cf07..7243dd7994 100644 --- a/src/frontend/tests/pages/pui_build.spec.ts +++ b/src/frontend/tests/pages/pui_build.spec.ts @@ -379,6 +379,24 @@ test('Build Order - Build Outputs', async ({ browser }) => { ) .waitFor(); await page.getByRole('cell', { name: 'Quantity: 16' }).waitFor(); + + // Adjust the quantity field - we will only 'partially' scrap this output + await page.getByRole('textbox', { name: 'number-field-quantity' }).fill('10'); + + // Next, adjust the "location" field - and check that the "quantity" field does not change + // Ref: https://github.com/inventree/InvenTree/pull/12081 + await page + .getByRole('combobox', { name: 'related-field-location' }) + .fill('factory'); + await page.getByTitle('Factory/Mechanical Lab').click(); + await page.waitForTimeout(250); + + // Check the 'quantity' value again - it should not have changed + const quantityValue = await page + .getByRole('textbox', { name: 'number-field-quantity' }) + .inputValue(); + expect(quantityValue).toBe('10'); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); });