feat: add public account overview visibility
This commit is contained in:
@@ -23,6 +23,7 @@ const responses: Record<string, unknown> = {
|
||||
email: "test@example.com",
|
||||
planType: "plus",
|
||||
expectedKind: "personal",
|
||||
publicVisible: false,
|
||||
actualKind: "personal",
|
||||
validationStatus: "matched",
|
||||
possibleDuplicate: false,
|
||||
@@ -180,6 +181,54 @@ test("shows every account as a collapsible summary on the overview", async ({
|
||||
await expect(page.locator(".account-detail")).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("shows a read-only overview before login", async ({ page }) => {
|
||||
await page.route("**/api/v1/**", async (route) => {
|
||||
const key = new URL(route.request().url()).pathname.replace("/api/v1/", "");
|
||||
if (key === "system/status")
|
||||
return route.fulfill({
|
||||
json: { initialized: true, appServer: true, version: "test" },
|
||||
});
|
||||
if (key === "auth/me")
|
||||
return route.fulfill({ status: 401, json: { error: "未登录" } });
|
||||
if (key === "accounts") return route.fulfill({ json: responses.accounts });
|
||||
if (key === "dashboard")
|
||||
return route.fulfill({
|
||||
json: {
|
||||
accountId: 1,
|
||||
displayName: "默认账号",
|
||||
account: {
|
||||
email: null,
|
||||
planType: "plus",
|
||||
connected: true,
|
||||
},
|
||||
limits: [],
|
||||
summary: {},
|
||||
usage: [],
|
||||
fetchedAt: 1_900_000_000,
|
||||
stale: false,
|
||||
},
|
||||
});
|
||||
return route.fulfill({ json: responses[key] ?? {} });
|
||||
});
|
||||
|
||||
await page.goto("/");
|
||||
await expect(page.getByRole("button", { name: "登录后配置" })).toBeVisible();
|
||||
await expect(page.locator(".account-overview")).toHaveCount(1);
|
||||
await expect(page.getByRole("button", { name: "刷新全部" })).toHaveCount(0);
|
||||
await expect(page.getByRole("button", { name: "设置中心" })).toHaveCount(0);
|
||||
|
||||
const account = page.locator('[data-account-id="1"]');
|
||||
await account.getByRole("button", { name: "展开默认账号详情" }).click();
|
||||
await expect(account.getByText("登录后查看")).toBeVisible();
|
||||
await expect(account.locator(".account-detail .refresh")).toHaveCount(0);
|
||||
|
||||
await page.goto("/settings");
|
||||
await expect(page).toHaveURL(/\/$/);
|
||||
await page.getByRole("button", { name: "登录后配置" }).click();
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(page.getByRole("heading", { name: "欢迎回来" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("shows the build version in the authenticated brand", async ({ page }) => {
|
||||
await openSettings(page);
|
||||
const mobile = (page.viewportSize()?.width ?? 0) <= 800;
|
||||
@@ -260,7 +309,7 @@ test("shows the build version on login", async ({ page }) => {
|
||||
await page.route("**/api/v1/auth/me", (route) =>
|
||||
route.fulfill({ status: 401, json: { error: "unauthorized" } }),
|
||||
);
|
||||
await page.goto("/");
|
||||
await page.goto("/login");
|
||||
const badge = page.locator(".login .version-badge");
|
||||
await expect(badge).toBeVisible();
|
||||
await expect(badge).toHaveText("vtest");
|
||||
@@ -570,6 +619,71 @@ test("deleting a newly added account clears its device authorization", async ({
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("sets public visibility when adding and editing an account", async ({
|
||||
page,
|
||||
}) => {
|
||||
let accounts: Array<(typeof responses.accounts)[number]> = [];
|
||||
let createdBody: { publicVisible?: boolean } | undefined;
|
||||
let updatedBody: { publicVisible?: boolean } | undefined;
|
||||
await page.route("**/api/v1/**", async (route) => {
|
||||
const request = route.request();
|
||||
const key = new URL(request.url()).pathname.replace("/api/v1/", "");
|
||||
if (key === "accounts" && request.method() === "GET")
|
||||
return route.fulfill({ json: accounts });
|
||||
if (key === "accounts" && request.method() === "POST") {
|
||||
createdBody = request.postDataJSON() as { publicVisible?: boolean };
|
||||
const account = {
|
||||
...responses.accounts[0],
|
||||
id: 2,
|
||||
displayName: "账号 1",
|
||||
email: "",
|
||||
connected: false,
|
||||
validationStatus: "pending" as const,
|
||||
publicVisible: createdBody.publicVisible === true,
|
||||
};
|
||||
accounts = [account];
|
||||
return route.fulfill({ json: account });
|
||||
}
|
||||
if (key === "accounts/2/login/device")
|
||||
return route.fulfill({
|
||||
json: {
|
||||
verificationUrl: "https://auth.openai.com/codex/device",
|
||||
userCode: "PLTJ-7M6I6",
|
||||
},
|
||||
});
|
||||
if (key === "accounts/2" && request.method() === "PUT") {
|
||||
updatedBody = request.postDataJSON() as { publicVisible?: boolean };
|
||||
accounts = [
|
||||
{
|
||||
...accounts[0],
|
||||
publicVisible: updatedBody.publicVisible === true,
|
||||
},
|
||||
];
|
||||
return route.fulfill({ json: { ok: true } });
|
||||
}
|
||||
return route.fulfill({ json: responses[key] ?? {} });
|
||||
});
|
||||
|
||||
await page.goto("/settings");
|
||||
await page.getByRole("tab", { name: "Codex" }).click();
|
||||
const addVisibility = page.locator(
|
||||
".add-account-controls input[type=checkbox]",
|
||||
);
|
||||
await expect(addVisibility).not.toBeChecked();
|
||||
await addVisibility.check();
|
||||
await page.getByRole("button", { name: "添加账号" }).click();
|
||||
await expect.poll(() => createdBody?.publicVisible).toBe(true);
|
||||
|
||||
const accountCard = page.locator(".account-card");
|
||||
const accountVisibility = accountCard.locator('input[type="checkbox"]');
|
||||
await expect(accountVisibility).toBeChecked();
|
||||
await accountVisibility.evaluate((checkbox) =>
|
||||
(checkbox as HTMLInputElement).click(),
|
||||
);
|
||||
await expect.poll(() => updatedBody?.publicVisible).toBe(false);
|
||||
await expect(accountVisibility).not.toBeChecked();
|
||||
});
|
||||
|
||||
test("Codex account cards fit within the viewport", async ({ page }) => {
|
||||
await openSettings(page);
|
||||
await page.getByRole("tab", { name: "Codex" }).click();
|
||||
@@ -645,12 +759,12 @@ test("Codex account emails are masked everywhere they are displayed", async ({
|
||||
await expect(page.locator("body")).not.toContainText("test@example.com");
|
||||
});
|
||||
|
||||
test("returns to login when an authenticated request receives 401", async ({
|
||||
test("shows the public overview when the session is unavailable", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.route("**/api/v1/**", async (route) => {
|
||||
const key = new URL(route.request().url()).pathname.replace("/api/v1/", "");
|
||||
if (key === "accounts/1/sync")
|
||||
if (key === "auth/me")
|
||||
return route.fulfill({ status: 401, json: { error: "未登录" } });
|
||||
if (key === "dashboard")
|
||||
return route.fulfill({
|
||||
@@ -669,8 +783,7 @@ test("returns to login when an authenticated request receives 401", async ({
|
||||
});
|
||||
await page.goto("/");
|
||||
await expect(page.locator(".account-overview")).toBeVisible();
|
||||
await page.getByRole("button", { name: "刷新全部" }).click();
|
||||
await expect(page.getByRole("heading", { name: "欢迎回来" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "登录后配置" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("keeps each account dashboard in its own card when responses finish out of order", async ({
|
||||
|
||||
Reference in New Issue
Block a user