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
83
e2e/join-flow.spec.js
Normal file
83
e2e/join-flow.spec.js
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Join page — member signup flow', () => {
|
||||
test('join form loads with all fields', async ({ page }) => {
|
||||
await page.goto('/join')
|
||||
|
||||
await expect(page.locator('#join-name')).toBeVisible()
|
||||
await expect(page.locator('#join-email')).toBeVisible()
|
||||
await expect(page.locator('#circle-community')).toBeAttached()
|
||||
await expect(page.locator('#circle-founder')).toBeAttached()
|
||||
await expect(page.locator('#circle-practitioner')).toBeAttached()
|
||||
await expect(page.locator('#join-contribution')).toBeVisible()
|
||||
await expect(page.locator('.form-submit')).toBeVisible()
|
||||
})
|
||||
|
||||
test('submit button disabled when form incomplete', async ({ page }) => {
|
||||
await page.goto('/join')
|
||||
|
||||
// Clear name and email — circle defaults to community, contribution defaults to $15
|
||||
await page.locator('#join-name').fill('')
|
||||
await page.locator('#join-email').fill('')
|
||||
|
||||
// Button should be disabled with empty required fields
|
||||
await expect(page.locator('.form-submit')).toBeDisabled()
|
||||
|
||||
// Fill only name — still incomplete
|
||||
await page.locator('#join-name').fill('Test User')
|
||||
await expect(page.locator('.form-submit')).toBeDisabled()
|
||||
|
||||
// Fill email too — now all fields are populated and button should be enabled
|
||||
await page.locator('#join-email').fill('incomplete-test@example.com')
|
||||
await expect(page.locator('.form-submit')).toBeEnabled()
|
||||
})
|
||||
|
||||
test('fill and submit free tier', async ({ page }) => {
|
||||
const uniqueEmail = `test-e2e-${Date.now()}@example.com`
|
||||
|
||||
await page.goto('/join')
|
||||
|
||||
await page.locator('#join-name').fill('E2E Test User')
|
||||
await page.locator('#join-email').fill(uniqueEmail)
|
||||
await page.locator('#circle-community').check({ force: true })
|
||||
await page.locator('#join-contribution').selectOption('0')
|
||||
|
||||
await expect(page.locator('.form-submit')).toBeEnabled()
|
||||
await page.locator('.form-submit').click()
|
||||
|
||||
// Free tier skips payment (step 2) and goes to confirmation (step 3)
|
||||
// or redirects to /welcome. Wait for either outcome.
|
||||
await expect(
|
||||
page.getByText('Welcome to Ghost Guild!').or(page.locator('.success-box'))
|
||||
).toBeVisible({ timeout: 15000 })
|
||||
})
|
||||
|
||||
test('duplicate email shows error', async ({ page }) => {
|
||||
// First submission — create a member
|
||||
const duplicateEmail = `test-e2e-dup-${Date.now()}@example.com`
|
||||
|
||||
await page.goto('/join')
|
||||
await page.locator('#join-name').fill('Dup Test User')
|
||||
await page.locator('#join-email').fill(duplicateEmail)
|
||||
await page.locator('#circle-community').check({ force: true })
|
||||
await page.locator('#join-contribution').selectOption('0')
|
||||
await page.locator('.form-submit').click()
|
||||
|
||||
// Wait for first submission to succeed
|
||||
await expect(
|
||||
page.getByText('Welcome to Ghost Guild!').or(page.locator('.success-box'))
|
||||
).toBeVisible({ timeout: 15000 })
|
||||
|
||||
// Navigate back and try to register the same email again
|
||||
await page.goto('/join')
|
||||
await page.locator('#join-name').fill('Dup Test User Again')
|
||||
await page.locator('#join-email').fill(duplicateEmail)
|
||||
await page.locator('#circle-community').check({ force: true })
|
||||
await page.locator('#join-contribution').selectOption('0')
|
||||
await page.locator('.form-submit').click()
|
||||
|
||||
// Should show an error about the email already existing
|
||||
await expect(page.locator('.error-box')).toBeVisible({ timeout: 10000 })
|
||||
await expect(page.locator('.error-box')).toContainText(/already/i)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue