Merge branch 'v2/main' into v2/feat/1915-manual-server-headers

This commit is contained in:
Cliff Hall 2026-08-16 23:21:17 -04:00 • committed by GitHub
commit 4d7405bea0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 2747 additions and 136 deletions

View file

@ -451,6 +451,52 @@ describe("ServerSettingsModal", () => {
});
});
// #1906 — a typed endpoint override lands on the settings; clearing it
// persists `undefined` rather than an empty string, so "cleared" and "never
// set" are the same state on disk.
it("persists a typed endpoint override, and clears it back to undefined", async () => {
const user = userEvent.setup();
const onSettingsChange = vi.fn();
const { rerender } = renderWithMantine(
<ServerSettingsModal
opened
settings={emptySettings}
serverType="streamable-http"
isStdio={false}
onClose={vi.fn()}
onSettingsChange={onSettingsChange}
/>,
);
await user.click(screen.getByRole("button", { name: "OAuth Settings" }));
await user.type(
screen.getByRole("textbox", { name: /Token URL override/i }),
"h",
);
expect(onSettingsChange).toHaveBeenCalledWith(
expect.objectContaining({ oauthTokenUrl: "h" }),
);
onSettingsChange.mockClear();
rerender(
<ServerSettingsModal
opened
settings={{
...emptySettings,
oauthTokenUrl: "https://staging.test/token",
}}
serverType="streamable-http"
isStdio={false}
onClose={vi.fn()}
onSettingsChange={onSettingsChange}
/>,
);
const clearButtons = screen.getAllByRole("button", { name: /clear/i });
await user.click(clearButtons[clearButtons.length - 1]);
expect(onSettingsChange).toHaveBeenCalledWith(
expect.objectContaining({ oauthTokenUrl: undefined }),
);
});
// #2018 — the authorization-parameter rows ride the same onOAuthChange
// callback, so the modal folds them onto the settings object.
it("persists an added authorization-parameter row onto the settings", async () => {

View file

@ -183,6 +183,11 @@ export function ServerSettingsModal({
// survives a re-render; the drop-blank/omit-empty filtering happens on the
// way to disk. An emptied list persists as `[]`, which writes nothing.
oauthAuthorizationParams: oauth.authorizationParams,
// #1906: an emptied field persists as undefined rather than `""` — the
// read side treats a blank override as "not configured", and keeping the
// two in step means clearing the input really clears the setting.
oauthAuthorizationUrl: oauth.authorizationUrl || undefined,
oauthTokenUrl: oauth.tokenUrl || undefined,
enterpriseManaged: oauth.enterpriseManaged ? true : undefined,
// SEP-2350: persist only the non-default ('throw') so unset servers keep
// the SDK's `reauthorize` behavior without writing a spurious field.