# Testing Guide — Nxtgauge Frontend

## Test Stack

| Type | Tool | Config |
|------|------|--------|
| Unit | Vitest | `vitest.config.ts` |
| E2E | Playwright | `playwright.config.ts` |
| Accessibility | Playwright + axe-core | `playwright.a11y.config.ts` |
| Visual | Playwright screenshot diff | `playwright.visual.config.ts` |

## Running Tests

### Local (before push)

```bash
# Unit tests
npm run test

# Unit tests (watch mode)
npm run test:watch

# Unit tests with coverage
npm run test:coverage

# All E2E tests
npm run test:e2e

# Accessibility tests only
npm run test:accessibility

# Visual tests only
npm run test:visual
```

### Dev server must be running for E2E/a11y/visual tests

```bash
npm run dev &
npx wait-on http://localhost:3000
# Then run tests in another terminal
```

## Test Directories

```
tests/
├── e2e/
│   ├── ai-chat-widget.spec.ts      # AI Chat Widget E2E
│   ├── company-jobs.spec.ts        # Company Jobs Page E2E
│   ├── company-verification-flow.spec.ts
│   ├── signup-verification-submission.spec.ts
│   ├── accessibility.spec.ts
│   └── visual/
│       └── *.png                  # Visual baseline screenshots
├── vitest/
│   └── components/
│       ├── AiChatWidget.test.tsx
│       └── PublicFooter.test.tsx
```

## Writing E2E Tests

```typescript
import { test, expect } from "@playwright/test";

test("description of test", async ({ page }) => {
  await page.goto("/route");
  await page.waitForLoadState("networkidle");

  // Assertions
  await expect(page.locator("text=Expected")).toBeVisible();

  // Interactions
  await page.click("button[type='submit']");
  await page.fill("input[name='email']", "test@example.com");
});
```

## Writing Vitest Unit Tests

```typescript
import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@solidjs/testing-library";
import { MyComponent } from "../src/components/MyComponent";

global.fetch = vi.fn();

describe("MyComponent", () => {
  it("renders correctly", () => {
    render(() => <MyComponent />);
    expect(screen.getByText("Hello")).toBeTruthy();
  });
});
```

## Visual Tests

Visual tests compare screenshots against baselines in `tests/e2e/visual/`.
- Update baselines: `npx playwright test --config=playwright.visual.config.ts --update-snapshots`
- Review diffs in `test-results/visual/`

## CI / Nightly Runs

GitHub Actions runs tests nightly via `.forgejo/workflows/test.yaml`:
- **2:30 AM daily** — all test suites
- **On-demand** — use `workflow_dispatch` trigger in Forgejo

Artifacts are uploaded:
- `vitest-coverage/` — coverage reports
- `playwright-report/` — HTML test report
- `playwright-videos/` — recordings of failed tests
- `playwright-a11y-report/` — accessibility results
- `playwright-visual-diffs/` — screenshot diffs

## Coverage Requirements

- Minimum coverage target: **70%**
- Run `npm run test:coverage` to generate coverage report
- Coverage report location: `test-results/vitest-coverage/`

## Adding New Tests

1. **E2E tests**: Add `.spec.ts` to `tests/e2e/`
2. **Unit tests**: Add `.test.tsx` to `tests/vitest/components/`
3. **Visual tests**: Add page screenshots to `tests/e2e/visual/` as baselines

## Troubleshooting

**Playwright timeout**: Increase `timeout` in config or use `test.setTimeout()`

**Flaky tests**: Use `await page.waitForLoadState("networkidle")` instead of arbitrary waits

**MSW not intercepting**: Ensure `setup.ts` is imported in `vitest.config.ts` via `setupFiles`