[Test] UI - Cover proxy_admin_viewer access to /api-keys

vitest: assert UserDashboard renders the keys table for both Admin Viewer and proxy_admin (no Access Denied).
e2e: viewer sees seeded keys (admin scope), Create button is hidden, key detail view loads without Regenerate / Delete / Edit.
This commit is contained in:
kimsehwan96 2026-04-29 07:44:09 +09:00
parent 167f1b6342
commit e232c9ec4c
2 changed files with 67 additions and 1 deletions

View file

@ -0,0 +1,45 @@
import { test, expect } from "@playwright/test";
import {
ADMIN_VIEWER_STORAGE_PATH,
E2E_INTERNAL_USER_KEY_ALIAS,
} from "../../constants";
import { Page } from "../../fixtures/pages";
import { navigateToPage } from "../../helpers/navigation";
test.describe("Proxy Admin Viewer - Keys (read-only)", () => {
test.use({ storageState: ADMIN_VIEWER_STORAGE_PATH });
test("Sees the keys table without an Access Denied gate", async ({ page }) => {
await navigateToPage(page, Page.ApiKeys);
// Hard entry-level gate is gone.
await expect(page.getByText("Access Denied")).toHaveCount(0);
await expect(
page.getByText("Ask your proxy admin for access to create keys"),
).toHaveCount(0);
// Admin viewer has the same all-keys view as proxy admin
// (backend use_substring_matching path).
await expect(page.getByText(E2E_INTERNAL_USER_KEY_ALIAS)).toBeVisible({ timeout: 10_000 });
// rolesWithWriteAccess guard hides the create affordance.
await expect(page.getByRole("button", { name: /Create New Key/i })).toHaveCount(0);
});
test("Can open a key detail view but cannot regenerate / delete / edit", async ({ page }) => {
await navigateToPage(page, Page.ApiKeys);
// Open the detail view of one of the seeded keys.
const keyRow = page.locator("tr", { hasText: E2E_INTERNAL_USER_KEY_ALIAS });
await expect(keyRow).toBeVisible({ timeout: 10_000 });
await keyRow.locator("button").first().click();
// Detail view loaded.
await expect(page.getByText("Back to Keys")).toBeVisible({ timeout: 10_000 });
// No write affordances on the detail view.
await expect(page.getByRole("button", { name: "Regenerate Key" })).toHaveCount(0);
await expect(page.getByRole("button", { name: "Delete Key" })).toHaveCount(0);
await expect(page.getByRole("button", { name: "Edit Settings" })).toHaveCount(0);
});
});

View file

@ -1,5 +1,5 @@
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
import { cleanup } from "@testing-library/react";
import { cleanup, screen } from "@testing-library/react";
import React from "react";
import { renderWithProviders } from "../../tests/test-utils";
@ -138,3 +138,24 @@ describe("UserDashboard beforeunload listener", () => {
expect(removeCalls).toHaveLength(1);
});
});
describe("UserDashboard role-based rendering", () => {
afterEach(() => {
cleanup();
});
it("renders the keys page (no Access Denied screen) for proxy_admin_viewer", () => {
renderDashboard({ userRole: "Admin Viewer" });
expect(screen.queryByText("Access Denied")).toBeNull();
expect(screen.queryByText("Ask your proxy admin for access to create keys")).toBeNull();
expect(screen.getByTestId("virtual-keys-table-mock")).toBeInTheDocument();
});
it("renders the keys page for proxy_admin", () => {
renderDashboard({ userRole: "Admin" });
expect(screen.queryByText("Access Denied")).toBeNull();
expect(screen.getByTestId("virtual-keys-table-mock")).toBeInTheDocument();
});
});