nxtgauge-frontend-solid/tests/e2e/company-jobs.spec.ts
Tracewebstudio Dev 0d63bb304e Add comprehensive test infrastructure and AI guardrails
- Add Vitest unit tests for AiChatWidget component
- Add Playwright E2E tests: ai-chat-widget, api, security, guardrails
- Add AI guardrails tests validating no phone/email leaks from Ollama
- Add security tests: auth, rate limiting, input validation, token handling
- Add API tests for AI endpoints and authentication
- Fix playwright.config.ts reporter path conflict
- Update CompanyJobsPage with AI generate buttons (orange icon, loading state)
- Fix AiChatWidget accessibility (role=dialog, aria-label, aria-modal)
- Add app.css spin animation for AI loading spinner
- Add Gitea Actions workflow for nightly CI tests
- Add TESTING.md documentation
2026-05-01 02:54:25 +02:00

118 lines
No EOL
4.4 KiB
TypeScript

import { test, expect } from "@playwright/test";
import AxeBuilder from "@axe-core/playwright";
async function setupAuth(page: any): Promise<boolean> {
const res = await page.request.post("http://localhost:3000/api/auth/login", {
data: {
email: "testcompany@example.com",
password: "TestPassword123!",
},
});
if (!res.ok()) return false;
const data = await res.json();
const token = data.access_token;
await page.goto("http://localhost:3000/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([]);
});
});