fix(FN-2419): preserve three-state bulk model selection

- Add optional noChangeValue/noChangeLabel support to CustomModelDropdown so No change can coexist with Use default
- Update ListView bulk model controls to pass through a dedicated __no_change__ sentinel and avoid conflating untouched with clear-to-default
- Keep batch update payloads explicit by sending null provider/model only for Use default while leaving untouched lanes undefined
- Add dashboard tests covering No change vs explicit model vs Use default behavior and update README bulk-edit documentation
This commit is contained in:
Fusion
2026-04-24 04:50:26 -07:00
committed by gsxdsm
parent 8ffe005ba1
commit 0ebe20e487
5 changed files with 149 additions and 35 deletions

View File

@@ -54,6 +54,35 @@ describe("CustomModelDropdown", () => {
expect(hostSurface.contains(portal)).toBe(false);
});
it("supports an explicit No change sentinel while keeping Use default available", async () => {
const user = userEvent.setup();
const onChange = vi.fn();
render(
<CustomModelDropdown
label="Executor Model"
value="__no_change__"
onChange={onChange}
models={MOCK_MODELS}
noChangeValue="__no_change__"
noChangeLabel="No change"
/>,
);
await user.click(screen.getByRole("button", { name: "Executor Model" }));
const portal = await screen.findByTestId("model-combobox-portal");
await user.click(within(portal).getByText("Use default"));
expect(onChange).toHaveBeenCalledWith("");
onChange.mockClear();
await user.click(screen.getByRole("button", { name: "Executor Model" }));
const reopenedPortal = await screen.findByTestId("model-combobox-portal");
await user.click(within(reopenedPortal).getByText("No change"));
expect(onChange).toHaveBeenCalledWith("__no_change__");
});
it("keeps the portaled list interactive for selecting a model and clearing back to default", async () => {
const user = userEvent.setup();
const onChange = vi.fn();