ghostguild-org/e2e/updates.spec.js
Jennie Robinson Faber 1e30ba23cd
Some checks are pending
Test / vitest (push) Waiting to run
Test / playwright (push) Blocked by required conditions
Test / visual (push) Blocked by required conditions
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.
2026-04-04 16:07:21 +01:00

123 lines
4.1 KiB
JavaScript

import { test, expect } from './helpers/fixtures.js'
test.describe('My Updates page', () => {
test('authenticated user sees the my-updates page', async ({ adminPage }) => {
await adminPage.goto('/member/my-updates')
await expect(adminPage.locator('h1', { hasText: 'My Updates' })).toBeVisible({
timeout: 10000,
})
})
test('authenticated user sees the new update link', async ({ adminPage }) => {
await adminPage.goto('/member/my-updates')
// Wait for ClientOnly content to hydrate
await expect(adminPage.locator('h1', { hasText: 'My Updates' })).toBeVisible({
timeout: 10000,
})
// The page shows either the "+ New Update" button (stats row) or
// the "+ Post Your First Update" link (empty state) — both go to /updates/new
const newUpdateLink = adminPage.locator('a[href="/updates/new"]')
await expect(newUpdateLink.first()).toBeVisible({ timeout: 10000 })
})
test('unauthenticated user sees sign-in prompt', async ({ browser }) => {
const context = await browser.newContext()
const page = await context.newPage()
await page.goto('/member/my-updates')
await expect(
page
.getByText('Sign in required')
.or(page.getByText('Sign in to view your updates'))
).toBeVisible({ timeout: 10000 })
await context.close()
})
})
test.describe('New Update page', () => {
test('loads the new update form', async ({ adminPage }) => {
await adminPage.goto('/updates/new')
await expect(adminPage.locator('h1', { hasText: 'New Update' })).toBeVisible({
timeout: 10000,
})
// Form elements are present
await expect(adminPage.locator('textarea')).toBeVisible()
await expect(adminPage.locator('select')).toBeVisible()
// Submit button exists and starts disabled (empty textarea)
const submitBtn = adminPage.locator('button[type="submit"]')
await expect(submitBtn).toBeVisible()
await expect(submitBtn).toBeDisabled()
})
test('submit button enables when content is entered', async ({ adminPage }) => {
await adminPage.goto('/updates/new')
await expect(adminPage.locator('h1', { hasText: 'New Update' })).toBeVisible({
timeout: 10000,
})
const textarea = adminPage.locator('textarea')
const submitBtn = adminPage.locator('button[type="submit"]')
await expect(submitBtn).toBeDisabled()
await textarea.fill('Test update content')
await expect(submitBtn).toBeEnabled()
})
test('privacy selector defaults to members and has all options', async ({ adminPage }) => {
await adminPage.goto('/updates/new')
await expect(adminPage.locator('h1', { hasText: 'New Update' })).toBeVisible({
timeout: 10000,
})
const select = adminPage.locator('select')
await expect(select).toHaveValue('members')
// Verify all three privacy options exist
await expect(select.locator('option[value="members"]')).toBeAttached()
await expect(select.locator('option[value="public"]')).toBeAttached()
await expect(select.locator('option[value="private"]')).toBeAttached()
})
test('cancel link navigates back to my-updates', async ({ adminPage }) => {
await adminPage.goto('/updates/new')
await expect(adminPage.locator('h1', { hasText: 'New Update' })).toBeVisible({
timeout: 10000,
})
const cancelLink = adminPage.locator('a', { hasText: 'Cancel' })
await expect(cancelLink).toHaveAttribute('href', '/member/my-updates')
})
test('back link points to my-updates', async ({ adminPage }) => {
await adminPage.goto('/updates/new')
const backLink = adminPage.locator('.back-link a')
await expect(backLink).toBeVisible({ timeout: 10000 })
await expect(backLink).toHaveAttribute('href', '/member/my-updates')
})
})
test.describe('Updates API (public access)', () => {
test('public updates endpoint returns data', async ({ page }) => {
const response = await page.request.get('/api/updates')
expect(response.ok()).toBe(true)
const data = await response.json()
expect(data).toHaveProperty('updates')
expect(data).toHaveProperty('total')
expect(data).toHaveProperty('hasMore')
expect(Array.isArray(data.updates)).toBe(true)
})
})