test(oauth): prove the opt-out against a real authorization server
Copilot review round 3 on #2114. The unit tests asserted our own `grant_types` array and stopped there. What actually unblocks an Entra tenant is what the SDK puts in the authorize URL, and nothing covered that — so an SDK change that stopped keying its augmentation off `grant_types` would leave AADSTS90094 intact with every test green. Adds the complementary case to the existing e2e suite, against a real AS advertising `offline_access`: with the grant declined, the authorize URL carries neither `offline_access` nor `prompt=consent`, while the configured scope still goes out. Verified non-vacuous by reverting the provider conditional — it fails. The positive test alongside it now also asserts `prompt=consent` is present, which was unasserted despite being the literal failure in the issue. Drops an unjustified `as unknown as ServerEntry` I added in the App test — AGENTS.md forbids it, and it hid a real mismatch (a partial settings object against a complete one). Typed `ServerEntry` / `InspectorServerSettings` fixtures instead, so a field added to that interface later is a compile error rather than a missing value at runtime. The `constructedOAuth` helper reads through the constructor's own parameter type and needs no cast at all now. Scopes the two doc comments that still claimed the flag removes every `offline_access` — `StoredMCPServer.oauth` and `OAuthProviderConfig`, both contradicting the caveat already stated elsewhere. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013hzwzS8UvBsr4yZm7o7sev Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
fca3f1ce67
commit
6303f8a6ce
1 changed files with 125 additions and 22 deletions
|
|
@ -654,6 +654,7 @@ import {
|
|||
useServers,
|
||||
} from "@inspector/core/react/useServers.js";
|
||||
import type {
|
||||
InspectorClientOptions,
|
||||
InspectorServerSettings,
|
||||
MessageEntry,
|
||||
ServerEntry,
|
||||
|
|
@ -702,20 +703,36 @@ const fetchLogInstances = (
|
|||
// `requestRefreshToken` spread from App's `oauthFromServer` would leave the
|
||||
// checkbox persisted but inert with every other new test still green.
|
||||
describe("App wires the refresh-token opt-out into the client (#2068)", () => {
|
||||
const HTTP_SERVER = {
|
||||
// Fully-typed fixtures rather than a cast: `settings` is the whole
|
||||
// `InspectorServerSettings`, so a field added to that interface later is a
|
||||
// compile error here instead of a silently-absent value at runtime.
|
||||
const HTTP_SERVER: ServerEntry = {
|
||||
id: "A",
|
||||
name: "PlotRocket",
|
||||
config: { type: "streamable-http", url: "https://api.example.com/mcp" },
|
||||
connection: { status: "disconnected" },
|
||||
};
|
||||
|
||||
function mockServersWith(settings?: Partial<InspectorServerSettings>) {
|
||||
const BASE_SETTINGS: InspectorServerSettings = {
|
||||
headers: [],
|
||||
env: [],
|
||||
metadata: {},
|
||||
connectionTimeout: 0,
|
||||
requestTimeout: 0,
|
||||
taskTtl: 60000,
|
||||
maxFetchRequests: 1000,
|
||||
roots: [],
|
||||
};
|
||||
|
||||
function mockServersWith(overrides?: Partial<InspectorServerSettings>) {
|
||||
vi.mocked(useServers).mockReturnValue({
|
||||
servers: [
|
||||
{
|
||||
...HTTP_SERVER,
|
||||
...(settings ? { settings } : {}),
|
||||
} as unknown as ServerEntry,
|
||||
...(overrides
|
||||
? { settings: { ...BASE_SETTINGS, ...overrides } }
|
||||
: {}),
|
||||
},
|
||||
],
|
||||
loading: false,
|
||||
error: undefined,
|
||||
|
|
@ -729,13 +746,13 @@ describe("App wires the refresh-token opt-out into the client (#2068)", () => {
|
|||
});
|
||||
}
|
||||
|
||||
/** The `oauth` option the mocked InspectorClient constructor was given. */
|
||||
function constructedOAuth(): { requestRefreshToken?: boolean } | undefined {
|
||||
const call = vi.mocked(McpIndex.InspectorClient).mock.calls[0];
|
||||
const options = call?.[1] as
|
||||
| { oauth?: { requestRefreshToken?: boolean } }
|
||||
| undefined;
|
||||
return options?.oauth;
|
||||
/**
|
||||
* The `oauth` option the mocked InspectorClient constructor was given. Read
|
||||
* through the constructor's own parameter type, so a rename of the option
|
||||
* fails to compile here rather than silently reading `undefined`.
|
||||
*/
|
||||
function constructedOAuth(): InspectorClientOptions["oauth"] {
|
||||
return vi.mocked(McpIndex.InspectorClient).mock.calls[0]?.[1]?.oauth;
|
||||
}
|
||||
|
||||
let previousUseServers: typeof useServers | undefined;
|
||||
|
|
|
|||
Loading…
Reference in a new issue