fix: make all 112 Playwright E2E tests pass (RCA-19)
- Fix mock-api data shapes to match actual Vue component interfaces - Replace HeadlessUI TransitionRoot with v-if in SetupView (unmount fix) - Restructure CookiesView to detail-replaces-list pattern (strict mode) - Add ARIA attributes for Playwright selectors (role=switch, aria-label) - Fix 401 interceptor to skip login endpoint redirects - Add confirmation dialogs, error states, and missing UI fields - Rename conflicting button/label text to avoid strict mode violations Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -10,8 +10,11 @@ export async function mockDashboard(page: Page): Promise<void> {
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
devices: { total: 3, online: 2, offline: 1 },
|
||||
cookies: { total: 142, domains: 8 },
|
||||
totalDevices: 3,
|
||||
onlineDevices: 2,
|
||||
totalCookies: 142,
|
||||
uniqueDomains: 8,
|
||||
connections: 2,
|
||||
syncCount: 57,
|
||||
uptimeSeconds: 86400,
|
||||
}),
|
||||
@@ -23,38 +26,53 @@ export async function mockDashboard(page: Page): Promise<void> {
|
||||
* Intercept /admin/cookies and return a paginated list.
|
||||
*/
|
||||
export async function mockCookies(page: Page): Promise<void> {
|
||||
await page.route("**/admin/cookies*", (route) =>
|
||||
route.fulfill({
|
||||
await page.route("**/admin/cookies*", (route) => {
|
||||
if (route.request().method() === "DELETE") {
|
||||
return route.fulfill({ status: 200, contentType: "application/json", body: "{}" });
|
||||
}
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
cookies: [
|
||||
{
|
||||
id: "c1",
|
||||
deviceId: "dev-001",
|
||||
domain: "example.com",
|
||||
name: "session",
|
||||
value: "abc123",
|
||||
cookieName: "session",
|
||||
path: "/",
|
||||
ciphertext: "encrypted-abc123",
|
||||
nonce: "nonce1",
|
||||
lamportTs: 1,
|
||||
updatedAt: "2026-03-01T00:00:00Z",
|
||||
expires: "2027-01-01T00:00:00Z",
|
||||
secure: true,
|
||||
httpOnly: true,
|
||||
},
|
||||
{
|
||||
id: "c2",
|
||||
deviceId: "dev-001",
|
||||
domain: "example.com",
|
||||
name: "pref",
|
||||
value: "dark",
|
||||
cookieName: "pref",
|
||||
path: "/",
|
||||
ciphertext: "encrypted-dark",
|
||||
nonce: "nonce2",
|
||||
lamportTs: 2,
|
||||
updatedAt: "2026-03-02T00:00:00Z",
|
||||
expires: "2027-06-01T00:00:00Z",
|
||||
secure: false,
|
||||
httpOnly: false,
|
||||
},
|
||||
{
|
||||
id: "c3",
|
||||
deviceId: "dev-002",
|
||||
domain: "other.io",
|
||||
name: "token",
|
||||
value: "xyz",
|
||||
cookieName: "token",
|
||||
path: "/",
|
||||
ciphertext: "encrypted-xyz",
|
||||
nonce: "nonce3",
|
||||
lamportTs: 3,
|
||||
updatedAt: "2026-03-03T00:00:00Z",
|
||||
expires: null,
|
||||
secure: true,
|
||||
httpOnly: true,
|
||||
@@ -63,44 +81,45 @@ export async function mockCookies(page: Page): Promise<void> {
|
||||
total: 3,
|
||||
page: 1,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept /admin/devices and return device list.
|
||||
*/
|
||||
export async function mockDevices(page: Page): Promise<void> {
|
||||
await page.route("**/admin/devices*", (route) =>
|
||||
route.fulfill({
|
||||
await page.route("**/admin/devices*", (route) => {
|
||||
if (route.request().method() !== "GET") return route.continue();
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
devices: [
|
||||
{
|
||||
id: "d1",
|
||||
deviceId: "d1",
|
||||
name: "Chrome on macOS",
|
||||
platform: "chrome",
|
||||
online: true,
|
||||
lastSeen: new Date().toISOString(),
|
||||
registeredAt: "2026-01-01T00:00:00Z",
|
||||
createdAt: "2026-01-01T00:00:00Z",
|
||||
ipAddress: "192.168.1.10",
|
||||
extensionVersion: "2.0.0",
|
||||
},
|
||||
{
|
||||
id: "d2",
|
||||
deviceId: "d2",
|
||||
name: "Firefox on Windows",
|
||||
platform: "firefox",
|
||||
online: false,
|
||||
lastSeen: "2026-03-15T10:00:00Z",
|
||||
registeredAt: "2026-02-01T00:00:00Z",
|
||||
createdAt: "2026-02-01T00:00:00Z",
|
||||
ipAddress: null,
|
||||
extensionVersion: "2.0.0",
|
||||
},
|
||||
],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,20 +132,12 @@ export async function mockSettings(page: Page): Promise<void> {
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
sync: {
|
||||
autoSync: true,
|
||||
frequency: "realtime",
|
||||
domainWhitelist: [],
|
||||
domainBlacklist: [],
|
||||
},
|
||||
security: {
|
||||
sessionTimeoutMinutes: 60,
|
||||
requirePairingPin: false,
|
||||
},
|
||||
appearance: {
|
||||
theme: "system",
|
||||
language: "zh",
|
||||
},
|
||||
autoSync: true,
|
||||
syncIntervalMs: 0,
|
||||
maxDevices: 10,
|
||||
theme: "system",
|
||||
sessionTimeoutMinutes: 60,
|
||||
language: "zh",
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user