fix(ui): show the saved team in read mode before the model query refetches

Read mode built the Team display from the react-query snapshot while save only wrote localModelData, so the old team flashed until the parent's invalidation refetched. Read the team from localModelData like the neighbouring fields and look up its alias from the local team id. The regression test also waits for the Select trigger to report expanded before clicking an option, because Base UI opens the popup asynchronously and keeps the closed popup mounted, which made back-to-back option clicks flaky.
This commit is contained in:
ryan-crabbe-berri 2026-09-17 17:04:14 -07:00
parent 790c3ab71b
commit 5156dbc67f
3 changed files with 41 additions and 7 deletions

View file

@ -818,8 +818,8 @@ const ModelInfoEditForm: React.FC<ModelInfoEditFormProps> = ({
) : (
<Display>
{teamAlias
? `${teamAlias} (${modelData.model_info.team_id})`
: modelData.model_info.team_id || "Not Set"}
? `${teamAlias} (${localModelData.model_info?.team_id})`
: localModelData.model_info?.team_id || "Not Set"}
</Display>
)}
</div>

View file

@ -1509,6 +1509,11 @@ describe("ModelInfoView", () => {
expect(await screen.findByRole("button", { name: /save changes/i })).toBeInTheDocument();
};
const openSelect = async (user: ReturnType<typeof userEvent.setup>, triggerText: string) => {
await user.click(await screen.findByText(triggerText));
await screen.findByRole("combobox", { expanded: true });
};
const save = async (user: ReturnType<typeof userEvent.setup>) => {
await user.click(screen.getByRole("button", { name: /save changes/i }));
await waitFor(() => expect(mockModelPatchUpdateCall).toHaveBeenCalled());
@ -1660,7 +1665,7 @@ describe("ModelInfoView", () => {
const user = userEvent.setup();
await enterEditMode(user);
await user.click(screen.getByText("alpha (team-1)"));
await openSelect(user, "alpha (team-1)");
await user.click(await screen.findByText("beta (team-2)"));
const payload = await save(user);
@ -1668,6 +1673,33 @@ describe("ModelInfoView", () => {
expect(payload.model_info.team_id).toBe("team-2");
});
it("shows the picked team in read mode right after saving", async () => {
mockUseTeams.mockReturnValue({
data: [
{ team_id: "team-1", team_alias: "alpha" },
{ team_id: "team-2", team_alias: "beta" },
],
isLoading: false,
error: null,
});
const teamModel = {
...defaultModelData,
model_info: { ...defaultModelData.model_info, team_id: "team-1" },
};
mockUseModelsInfo.mockReturnValue({ data: { data: [teamModel] }, isLoading: false, error: null });
mockModelInfoV1Call.mockResolvedValue({ data: [teamModel] });
const user = userEvent.setup();
await enterEditMode(user);
await openSelect(user, "alpha (team-1)");
await user.click(await screen.findByText("beta (team-2)"));
await save(user);
expect(await screen.findByRole("button", { name: /edit settings/i })).toBeInTheDocument();
expect(screen.getByText("beta (team-2)")).toBeInTheDocument();
expect(screen.queryByText("alpha (team-1)")).not.toBeInTheDocument();
});
it("shows the Team ID placeholder for a model with no team", async () => {
mockUseTeams.mockReturnValue({
data: [{ team_id: "team-1", team_alias: "alpha" }],
@ -1734,7 +1766,7 @@ describe("ModelInfoView", () => {
const user = userEvent.setup();
await enterEditMode(user);
await user.click(await screen.findByText("selected-credential"));
await openSelect(user, "selected-credential");
await user.click(await screen.findByText("other-credential"));
const payload = await save(user);
@ -1770,7 +1802,7 @@ describe("ModelInfoView", () => {
const user = userEvent.setup();
await enterEditMode(user);
await user.click(screen.getByText("Select existing health check model"));
await openSelect(user, "Select existing health check model");
await user.click(await screen.findByText("openai/gpt-4o"));
const payload = await save(user);

View file

@ -115,7 +115,9 @@ export default function ModelInfoView({
// Keep modelData variable name for backwards compatibility
const modelData = transformedModelData;
const teamAlias = teams?.find((team) => team.team_id === modelData?.model_info?.team_id)?.team_alias || null;
const aliasForTeam = (teamId: string | null | undefined): string | null =>
teams?.find((team) => team.team_id === teamId)?.team_alias || null;
const teamAlias = aliasForTeam(modelData?.model_info?.team_id);
const rawModelInfoEntries = Object.entries(modelData?.model_info ?? {}).flatMap((entry) =>
entry[0] === "team_id" && teamAlias ? [entry, ["team_alias", teamAlias]] : [entry],
);
@ -724,7 +726,7 @@ export default function ModelInfoView({
<ModelInfoEditForm
localModelData={localModelData}
modelData={modelData}
teamAlias={teamAlias}
teamAlias={aliasForTeam(localModelData.model_info?.team_id)}
accessToken={accessToken}
isEditing={isEditing}
isSaving={isSaving}