From 00d99f65fa3ebaa882fc787e82eb716112d2ea7f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 22:25:12 +1000 Subject: [PATCH] [Bug] Fix for build forms (#12081) (#12083) * Bug fix for build forms - Memoize outputs to prevent re-rendering reset issues * Add playwright test (cherry picked from commit 3dfd03fa89aa42d7d43bb00b2cd3f6d3428237ae) Co-authored-by: Oliver --- 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 2fc4b447eb..80e6634dca 100644 --- a/src/frontend/src/forms/BuildForms.tsx +++ b/src/frontend/src/forms/BuildForms.tsx @@ -344,16 +344,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 ( @@ -421,16 +426,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 ( @@ -487,15 +497,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 7f4e8fde81..e426345040 100644 --- a/src/frontend/tests/pages/pui_build.spec.ts +++ b/src/frontend/tests/pages/pui_build.spec.ts @@ -327,6 +327,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(); });