All checks were successful
build-and-release / build (push) Successful in 2m25s
The e2e suite only ever worked against a local docker-compose stack: - Hardcoded http://localhost:3000 / :9100 everywhere, ignoring TEST_ENV=production and playwright.config.ts's own baseURL logic. - /api/auth/login and /api/auth/register now require solving a math captcha first; none of these tests sent captcha_id/captcha_answer, so every login/register call 422'd against the live API. - OTP retrieval shelled out to a local, unauthenticated redis-cli, which can't reach the real (kubectl-exec + password-protected) Redis. - Several files launched their own chromium.launch({headless: false}), which crashes immediately on a server with no X display. - One file had a hardcoded macOS absolute path for screenshots. Added tests/e2e/helpers/{env,captcha,otp,auth-flow}.ts as shared, reusable fixes for all of the above, and updated every affected spec file to use them. Verified via a full run against test111.nxtgauge.com: 971 schemathesis-adjacent smoke assertions aside, the actual signal here is 0 of the 130 prior failures came from real product bugs - all were this environment mismatch. See docs/LIVE_SERVER_RUNBOOK.md step 5. Also fixes .gitignore: it excluded 'playwright-report' (singular) but playwright.config.ts's actual outputFolder is 'playwright-reports' (plural) - generated HTML report artifacts had been getting committed by accident. Untracked the existing ones; left tests/e2e/visual/*-snapshots/ (newly-generated visual regression baselines from this run) untracked for now since establishing baselines needs a human look, not a blind commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
113 lines
No EOL
4.3 KiB
TypeScript
113 lines
No EOL
4.3 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
import AxeBuilder from "@axe-core/playwright";
|
|
import { apiLogin } from "./helpers/auth-flow";
|
|
|
|
async function setupAuth(page: any): Promise<boolean> {
|
|
const loginData = await apiLogin("testcompany@example.com", "TestPassword123!");
|
|
if (!loginData) return false;
|
|
const token = loginData.access_token;
|
|
await page.goto("/dashboard");
|
|
await page.evaluate((t: string) => {
|
|
window.sessionStorage.setItem("nxtgauge_access_token", t);
|
|
window.sessionStorage.setItem("nxtgauge_frontend_access_token", t);
|
|
}, token);
|
|
await page.reload();
|
|
await page.waitForLoadState("networkidle");
|
|
return !page.url().includes("/login");
|
|
}
|
|
|
|
test.describe("Company Jobs Page - Authenticated", () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
const loggedIn = await setupAuth(page);
|
|
if (!loggedIn) test.skip();
|
|
});
|
|
|
|
test("page loads and shows jobs section", async ({ page }) => {
|
|
const jobsHeader = page.locator("text=Jobs").first();
|
|
await expect(jobsHeader).toBeVisible({ timeout: 10000 });
|
|
});
|
|
|
|
test("create job form opens and has AI buttons", async ({ page }) => {
|
|
const createBtn = page.locator("text=+ Create Job").first();
|
|
await expect(createBtn).toBeVisible({ timeout: 10000 });
|
|
await createBtn.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
const titleInput = page.locator('input[placeholder="Frontend Developer"]').first();
|
|
await expect(titleInput).toBeVisible();
|
|
|
|
const aiButtons = page.locator('button[title="Generate with AI"]');
|
|
const count = await aiButtons.count();
|
|
expect(count).toBeGreaterThanOrEqual(3);
|
|
});
|
|
|
|
test("create job shows error when title is empty", async ({ page }) => {
|
|
const createBtn = page.locator("text=+ Create Job").first();
|
|
await createBtn.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
await page.fill('input[placeholder="Bengaluru (Hybrid)"]', "Some location");
|
|
await page.fill('textarea[placeholder*="Role overview"]', "Some description");
|
|
|
|
await page.locator("text=Create Draft").first().click();
|
|
await page.waitForTimeout(500);
|
|
|
|
const error = page.locator('text="Title, description, and location are required."');
|
|
await expect(error).toBeVisible({ timeout: 3000 });
|
|
});
|
|
|
|
test("create job shows error when description is empty", async ({ page }) => {
|
|
const createBtn = page.locator("text=+ Create Job").first();
|
|
await createBtn.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
await page.fill('input[placeholder="Frontend Developer"]', "Test Title");
|
|
await page.fill('input[placeholder="Bengaluru (Hybrid)"]', "Some location");
|
|
|
|
await page.locator("text=Create Draft").first().click();
|
|
await page.waitForTimeout(500);
|
|
|
|
const error = page.locator('text="Title, description, and location are required."');
|
|
await expect(error).toBeVisible({ timeout: 3000 });
|
|
});
|
|
|
|
test("create job shows error when location is empty", async ({ page }) => {
|
|
const createBtn = page.locator("text=+ Create Job").first();
|
|
await createBtn.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
await page.fill('input[placeholder="Frontend Developer"]', "Test Title");
|
|
await page.fill('textarea[placeholder*="Role overview"]', "Some description");
|
|
|
|
await page.locator("text=Create Draft").first().click();
|
|
await page.waitForTimeout(500);
|
|
|
|
const error = page.locator('text="Title, description, and location are required."');
|
|
await expect(error).toBeVisible({ timeout: 3000 });
|
|
});
|
|
|
|
test("form clears error when user starts typing required field", async ({ page }) => {
|
|
const createBtn = page.locator("text=+ Create Job").first();
|
|
await createBtn.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
await page.locator("text=Create Draft").first().click();
|
|
await page.waitForTimeout(500);
|
|
|
|
const error = page.locator('text="Title, description, and location are required."');
|
|
await expect(error).toBeVisible({ timeout: 3000 });
|
|
|
|
await page.fill('input[placeholder="Frontend Developer"]', "T");
|
|
await page.waitForTimeout(200);
|
|
await expect(error).not.toBeVisible();
|
|
});
|
|
|
|
test("create job form has no accessibility violations", async ({ page }) => {
|
|
const createBtn = page.locator("text=+ Create Job").first();
|
|
await createBtn.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
const results = await new AxeBuilder({ page }).analyze();
|
|
expect(results.violations).toEqual([]);
|
|
});
|
|
}); |