fix(ui): fall back to key name and server id in row labels

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
jesus 2026-10-13 22:49:52 +00:00
parent ed788c99fa
commit d137b81fc5
4 changed files with 37 additions and 9 deletions

View file

@ -24,7 +24,6 @@ const defaultProps = {
function makeKey(overrides: Partial<KeyResponse> = {}): KeyResponse {
return {
token: "tok-abc123",
token_id: "tid-abc123",
key_name: "sk-...abc",
key_alias: "Test Key",
spend: 0,
@ -115,15 +114,26 @@ describe("ProjectKeysTable", () => {
expect(within(row).queryByRole("link", { name: "My API Key" })).not.toBeInTheDocument();
});
it("falls back to the token ID in the accessible row name when the alias is empty", () => {
it("falls back to the key name in the accessible row name when the alias is empty", () => {
renderWithProviders(
<ProjectKeysTable
{...defaultProps}
keys={[makeKey({ token: "tok-empty-alias", token_id: "tid-empty-alias", key_alias: "" })]}
keys={[makeKey({ token: "tok-empty-alias", key_name: "name-empty-alias", key_alias: "" })]}
/>,
);
expect(screen.getByRole("row", { name: "Open key tid-empty-alias" })).toBeInTheDocument();
expect(screen.getByRole("row", { name: "Open key name-empty-alias" })).toBeInTheDocument();
});
it("falls back to the token when the alias and key name are empty", () => {
renderWithProviders(
<ProjectKeysTable
{...defaultProps}
keys={[makeKey({ token: "tok-empty-name", key_name: "", key_alias: "" })]}
/>,
);
expect(screen.getByRole("row", { name: "Open key tok-empty-name" })).toBeInTheDocument();
});
it("navigates to key details when plain row content is clicked", async () => {
@ -136,18 +146,18 @@ describe("ProjectKeysTable", () => {
expect(push).toHaveBeenCalledWith("/ui/api-keys?key=tok-abc123");
});
it("opens a focused row with Enter and labels an alias-less key with its ID", async () => {
it("opens a focused row with Enter and labels an alias-less key with its key name", async () => {
const user = userEvent.setup();
push.mockClear();
const aliasLessKeyInput = {
token: "tok-no-alias",
token_id: "tid-no-alias",
key_name: "name-no-alias",
key_alias: null as any,
user_id: "owner-1",
};
const aliasLessKey = makeKey(aliasLessKeyInput);
renderWithProviders(<ProjectKeysTable {...defaultProps} keys={[aliasLessKey]} />);
const row = screen.getByRole("row", { name: "Open key tid-no-alias" });
const row = screen.getByRole("row", { name: "Open key name-no-alias" });
row.focus();
expect(row).toHaveFocus();
await user.keyboard("{Enter}");

View file

@ -62,7 +62,7 @@ export function ProjectKeysTable({
onRowClick={(key) => {
if (key.token) router.push(keyDetailHref(key.token));
}}
getRowLabel={(key) => `Open key ${key.key_alias || key.token_id}`}
getRowLabel={(key) => `Open key ${key.key_alias || key.key_name || key.token}`}
/>
);
}

View file

@ -521,6 +521,24 @@ describe("publicMCPHubColumns", () => {
});
describe("public hub MCP details modal", () => {
it("uses the alias in the accessible label when the server name is empty", async () => {
const networkingModule = await import("./networking");
const serverWithoutName = {
...mockMcpServer,
server_id: "server-fallback-id",
server_name: "",
alias: "server-fallback-alias",
};
vi.mocked(networkingModule.mcpHubPublicServersCall).mockResolvedValueOnce([serverWithoutName]);
renderHub();
await userEvent.click(await screen.findByRole("tab", { name: /MCP Hub/i }));
expect(
await screen.findByRole("row", { name: "Open MCP server server-fallback-alias" }),
).toBeInTheDocument();
});
it("does not show the upstream url when a server is opened", async () => {
const user = userEvent.setup();
const networkingModule = await import("./networking");

View file

@ -629,7 +629,7 @@ const PublicModelHub: React.FC<PublicModelHubProps> = ({ accessToken, isEmbedded
columns={mcpColumns}
getRowId={(server, index) => server.server_id || String(index)}
onRowClick={showMcpModal}
getRowLabel={(server) => `Open MCP server ${server.server_name}`}
getRowLabel={(server) => `Open MCP server ${server.server_name || server.alias || server.server_id}`}
sortingMode="client"
sorting={mcpSorting}
onSortingChange={setMcpSorting}