fix: group Connection Info's full-width OAuth fields above the token rows

Client ID sat third in OAuth Details, between Status and Client registration,
so its label-over-value block interrupted the run of inline two-column rows and
broke the scan down the label column for everything after it. Access Token and
ID Token already used that layout, at the bottom.

Moved Client ID and Auth URL down to sit with them: the inline rows now run
Protocol, Status, Client registration, IdP session, Scopes, and the full-width
fields follow as one group — Auth URL, Client ID, Access Token, ID Token — so
Client ID is directly above the only other field a reader sees laid out the
same way.

A test asserts the order off the DOM rather than each field's presence, since
order is the property; putting Client ID back in its old slot fails it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GfHQ8vMm5NBgzbUJ6UwxmB
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-11 09:56:33 -04:00
commit 664c9f8800
2 changed files with 68 additions and 11 deletions

View file

@ -625,6 +625,57 @@ describe("ConnectionInfoContent", () => {
}
});
it("groups the full-width fields at the end, Client ID directly above Access Token", () => {
renderWithMantine(
<ConnectionInfoContent
initializeResult={fullResult}
clientCapabilities={fullClientCaps}
transport="streamable-http"
oauth={{
protocol: "standard",
authorized: true,
clientId: "http://127.0.0.1:8093/client-metadata.json",
clientRegistrationKind: "cimd",
authUrl: "https://auth.example.com/authorize",
scopes: ["mcp"],
accessToken: "token-123",
}}
/>,
);
// Order is the assertion, so read the labels off the DOM rather than
// checking each is merely present: the inline two-column rows come first,
// then every label-over-value field together. Interleaving them is what
// this guards against — it broke the scan down the label column, and the
// tokens already used the full-width layout at the bottom.
const order = [
"Client registration",
"Scopes",
"Auth URL",
"Client ID",
"Access Token",
];
const positions = order.map((label) => {
const node = screen.getAllByText(label)[0];
expect(node).toBeInTheDocument();
return (
node.compareDocumentPosition(screen.getAllByText("Protocol")[0]) &
Node.DOCUMENT_POSITION_PRECEDING
);
});
expect(positions.every(Boolean)).toBe(true);
const labelNode = (label: string) => screen.getAllByText(label)[0];
for (let i = 0; i < order.length - 1; i++) {
const earlier = labelNode(order[i]);
const later = labelNode(order[i + 1]);
expect(
earlier.compareDocumentPosition(later) &
Node.DOCUMENT_POSITION_FOLLOWING,
).toBeTruthy();
}
});
it("renders EMA idp session when provided", () => {
renderWithMantine(
<ConnectionInfoContent

View file

@ -459,12 +459,6 @@ export function ConnectionInfoContent({
{oauth.authorized ? "Authorized" : "Not authorized"}
</Badge>
</SimpleGrid>
{oauth.clientId && (
<FullWidthField>
<FieldLabel>Client ID</FieldLabel>
<ValueCode>{oauth.clientId}</ValueCode>
</FullWidthField>
)}
{oauth.clientRegistrationKind && (
<SimpleGrid cols={2}>
<FieldLabel>Client registration</FieldLabel>
@ -479,17 +473,29 @@ export function ConnectionInfoContent({
<ValueText>{formatIdpSession(oauth.idpSession)}</ValueText>
</SimpleGrid>
)}
{oauth.scopes && oauth.scopes.length > 0 && (
<SimpleGrid cols={2}>
<FieldLabel>Scopes</FieldLabel>
<ValueText>{formatScopes(oauth.scopes)}</ValueText>
</SimpleGrid>
)}
{/* The full-width fields are kept together at the end of the
section, directly above the token rows, which use the same
label-over-value layout. Interleaved with the inline two-column
rows they broke the scan down the label column for every row
after them, and Client ID — the one most likely to be long —
was the worst offender (#2328). */}
{oauth.authUrl && (
<FullWidthField>
<FieldLabel>Auth URL</FieldLabel>
<ValueCode>{oauth.authUrl}</ValueCode>
</FullWidthField>
)}
{oauth.scopes && oauth.scopes.length > 0 && (
<SimpleGrid cols={2}>
<FieldLabel>Scopes</FieldLabel>
<ValueText>{formatScopes(oauth.scopes)}</ValueText>
</SimpleGrid>
{oauth.clientId && (
<FullWidthField>
<FieldLabel>Client ID</FieldLabel>
<ValueCode>{oauth.clientId}</ValueCode>
</FullWidthField>
)}
{oauth.accessToken && (
<OAuthTokenField