parallel tests

This commit is contained in:
counterweight 2025-12-25 00:48:22 +01:00
parent 73a45b81cc
commit 139a5fbef3
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
5 changed files with 61 additions and 228 deletions

View file

@ -82,11 +82,18 @@ test.describe("Admin Invites Page", () => {
// Create an invite first
const godfatherSelect = page.locator("select").first();
await godfatherSelect.selectOption({ label: REGULAR_USER_EMAIL });
// Wait for create invite response
const createPromise = page.waitForResponse(
(resp) => resp.url().includes("/api/admin/invites") && resp.request().method() === "POST"
);
await page.click('button:has-text("Create Invite")');
await createPromise;
// Wait for table to update with new invite
await expect(page.locator("table")).toContainText("ready");
// Wait for the new invite to appear and capture its code
// The new invite should be the first row with godfather = REGULAR_USER_EMAIL and status = ready
const newInviteRow = page
.locator("tr")
.filter({ hasText: REGULAR_USER_EMAIL })
@ -97,23 +104,33 @@ test.describe("Admin Invites Page", () => {
// Get the invite code from this row (first cell)
const inviteCode = await newInviteRow.locator("td").first().textContent();
// Click revoke on this specific row
// Click revoke and wait for the response
// The revoke endpoint is POST /api/admin/invites/{invite_id}/revoke
const revokePromise = page.waitForResponse(
(resp) =>
resp.url().includes("/api/admin/invites") &&
resp.url().includes("/revoke") &&
resp.request().method() === "POST"
);
await newInviteRow.locator('button:has-text("Revoke")').click();
await revokePromise;
// Verify this specific invite now shows "revoked"
// Wait for table to refresh and verify this specific invite now shows "revoked"
const revokedRow = page.locator("tr").filter({ hasText: inviteCode! });
await expect(revokedRow).toContainText("revoked");
await expect(revokedRow).toContainText("revoked", { timeout: 5000 });
// Test status filter - filter by "revoked" status
const statusFilter = page.locator("select").nth(1); // Second select is the status filter
await statusFilter.selectOption("revoked");
// Wait for the filter to apply
// Wait for the filter to apply and verify revoked invite is visible
await page.waitForResponse((resp) => resp.url().includes("status=revoked"));
await expect(revokedRow).toBeVisible({ timeout: 5000 });
// Filter by "ready" status - should show our invite (if we create another one)
// Filter by "ready" status - should not show our revoked invite
await statusFilter.selectOption("ready");
await page.waitForResponse((resp) => resp.url().includes("status=ready"));
await expect(revokedRow).not.toBeVisible({ timeout: 5000 });
});
});

View file

@ -15,7 +15,7 @@ const ADMIN_EMAIL = "admin@example.com";
const ADMIN_PASSWORD = "admin123";
// Helper to create an invite via the API
const API_BASE = "http://localhost:8000";
const API_BASE = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000";
async function createInvite(request: APIRequestContext): Promise<string> {
// Login as admin