fix(web): make the Connection Info extension sections say something

Three things the Skills work got wrong in that modal, all found by review
of the PR screenshots.

- The "Skills Extension" section repeated `io.modelcontextprotocol/skills`
  as its value — the identifier the "Server Extensions" section two rows
  above already lists, so the section added nothing. What a flat key list
  *cannot* show is the extension's sub-options, which is the fact a server
  author opens this modal to check. Renamed "Skills Extension Options" and
  rendered as a ✓/✗ row for `directoryRead`, in the same vocabulary as the
  capability columns, so it reads as the same kind of claim.
- The extension sections' contents were bold (`ValueText`, the value half
  of a label/value pair) while sitting directly beneath the capability
  checklists, which are plain. They are lists of items, not values, so
  they now use the same `Text` the checklist rows do.
- Those lists were comma-joined into one line, which wraps mid-identifier
  in a half-width column. One row per identifier.

The `skills-directory-read` tests now assert `data-supported` rather than
the copy: "Not supported" contains "Supported", so a text assertion passed
for either answer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018kfrH3uRNUM4JAk1reKtyY
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-04 22:57:51 -04:00
commit 27fafe6acb

View file

@ -427,11 +427,12 @@ describe("ConnectionInfoContent", () => {
expect(
screen.getByText("Client Advertised Extensions"),
).toBeInTheDocument();
// One row per identifier, not a comma-joined string: two ~30-character
// ids wrap mid-name in a half-width column.
expect(
screen.getByText(
"io.modelcontextprotocol/tasks, io.modelcontextprotocol/ui",
),
screen.getByText("io.modelcontextprotocol/tasks"),
).toBeInTheDocument();
expect(screen.getByText("io.modelcontextprotocol/ui")).toBeInTheDocument();
});
it("renders em-dashes for the extensions sections when neither side advertises any (#1740)", () => {
@ -461,7 +462,9 @@ describe("ConnectionInfoContent", () => {
protocolEra="legacy"
/>,
);
expect(screen.queryByText("Skills Extension")).not.toBeInTheDocument();
expect(
screen.queryByText("Skills Extension Options"),
).not.toBeInTheDocument();
});
it("shows the Skills extension and its directoryRead sub-flag (#2234)", () => {
@ -484,10 +487,16 @@ describe("ConnectionInfoContent", () => {
protocolEra="legacy"
/>,
);
expect(screen.getByText("Skills Extension")).toBeInTheDocument();
expect(screen.getByTestId("skills-directory-read")).toHaveTextContent(
"Supported",
expect(screen.getByText("Skills Extension Options")).toBeInTheDocument();
// Asserted on the attribute, not the copy: "Not supported" contains
// "Supported", so a text check would pass for either answer.
expect(screen.getByTestId("skills-directory-read")).toHaveAttribute(
"data-supported",
"true",
);
// The section states the sub-option, not the identifier — that is already
// in "Server Extensions" and repeating it would add nothing.
expect(screen.getByText("resources/directory/read")).toBeInTheDocument();
});
it("reports directory read as unsupported for a bare skills declaration (#2234)", () => {
@ -505,8 +514,9 @@ describe("ConnectionInfoContent", () => {
protocolEra="legacy"
/>,
);
expect(screen.getByTestId("skills-directory-read")).toHaveTextContent(
"Not supported",
expect(screen.getByTestId("skills-directory-read")).toHaveAttribute(
"data-supported",
"false",
);
});