feat: add testing infrastructure — Vitest, Playwright, CI, git hooks
Add comprehensive testing covering 420 unit/handler tests across 24 Vitest files, 9 Playwright E2E specs, accessibility scans, and visual regression. Includes GitHub Actions CI, Husky pre-push hook, and TESTING.md docs.
This commit is contained in:
parent
036af95e00
commit
1e30ba23cd
35 changed files with 3637 additions and 5 deletions
73
e2e/visual/pages.spec.js
Normal file
73
e2e/visual/pages.spec.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import { test, expect } from '@playwright/test'
|
||||
import { loginAsAdmin } from '../helpers/auth.js'
|
||||
|
||||
const viewports = {
|
||||
desktop: { width: 1280, height: 720 },
|
||||
mobile: { width: 375, height: 667 },
|
||||
}
|
||||
|
||||
const publicPages = [
|
||||
{ name: 'home', path: '/' },
|
||||
{ name: 'join', path: '/join' },
|
||||
{ name: 'events', path: '/events' },
|
||||
{ name: 'coming-soon', path: '/coming-soon' },
|
||||
]
|
||||
|
||||
const authenticatedPages = [
|
||||
{ name: 'member-dashboard', path: '/member/dashboard' },
|
||||
{ name: 'member-profile', path: '/member/profile' },
|
||||
{ name: 'admin-members', path: '/admin/members' },
|
||||
{ name: 'admin-events-create', path: '/admin/events/create' },
|
||||
]
|
||||
|
||||
// Wait for fonts and images to load before taking screenshots
|
||||
async function waitForStable(page) {
|
||||
await page.waitForLoadState('networkidle')
|
||||
// Wait for web fonts to load
|
||||
await page.evaluate(() => document.fonts.ready)
|
||||
}
|
||||
|
||||
test.describe('visual regression — public pages', () => {
|
||||
for (const { name, path } of publicPages) {
|
||||
for (const [viewportName, viewport] of Object.entries(viewports)) {
|
||||
test(`${name} — ${viewportName}`, async ({ page }) => {
|
||||
await page.setViewportSize(viewport)
|
||||
await page.goto(path)
|
||||
await waitForStable(page)
|
||||
|
||||
await expect(page).toHaveScreenshot(`${name}-${viewportName}.png`, {
|
||||
maxDiffPixelRatio: 0.01,
|
||||
mask: [
|
||||
// Mask dynamic content like dates and counts
|
||||
page.locator('.event-date'),
|
||||
page.locator('.event-count'),
|
||||
page.locator('time'),
|
||||
],
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test.describe('visual regression — authenticated pages', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await loginAsAdmin(page)
|
||||
})
|
||||
|
||||
for (const { name, path } of authenticatedPages) {
|
||||
test(`${name} — desktop`, async ({ page }) => {
|
||||
await page.setViewportSize(viewports.desktop)
|
||||
await page.goto(path)
|
||||
await waitForStable(page)
|
||||
|
||||
await expect(page).toHaveScreenshot(`${name}-desktop.png`, {
|
||||
maxDiffPixelRatio: 0.01,
|
||||
mask: [
|
||||
page.locator('.event-date'),
|
||||
page.locator('time'),
|
||||
page.locator('.member-since'),
|
||||
],
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue