- Refresh AI guide docs (api, svelte-patterns, testing-patterns) - Add API updates notes, drop the outdated portal_api_v2_schema.md - Format package.json
242 lines
2.7 KiB
Markdown
242 lines
2.7 KiB
Markdown
# Testing Patterns
|
|
|
|
Only read this file when creating or modifying tests.
|
|
|
|
This project uses:
|
|
|
|
- Vitest
|
|
- Playwright browser testing
|
|
- Svelte Testing Library patterns through vitest/browser
|
|
|
|
---
|
|
|
|
# Test Philosophy
|
|
|
|
Tests should prove behavior.
|
|
|
|
Do not write tests that only confirm implementation details.
|
|
|
|
Every test must contain meaningful assertions.
|
|
|
|
A test without assertions fails because:
|
|
|
|
expect.requireAssertions is enabled.
|
|
|
|
---
|
|
|
|
# Test Locations
|
|
|
|
Tests are colocated with source files.
|
|
|
|
Client tests:
|
|
|
|
_.svelte.test.ts
|
|
_.svelte.spec.ts
|
|
|
|
Server tests:
|
|
|
|
_.test.ts
|
|
_.spec.ts
|
|
|
|
---
|
|
|
|
# Vitest Projects
|
|
|
|
There are two test environments.
|
|
|
|
## Client
|
|
|
|
Used for Svelte components.
|
|
|
|
Environment:
|
|
|
|
Playwright Chromium browser.
|
|
|
|
Used for:
|
|
|
|
- rendering
|
|
- user interaction
|
|
- form behavior
|
|
|
|
---
|
|
|
|
## Server
|
|
|
|
Used for:
|
|
|
|
- load functions
|
|
- actions
|
|
- server utilities
|
|
|
|
Environment:
|
|
|
|
Node.
|
|
|
|
---
|
|
|
|
# Before Each Test
|
|
|
|
Always reset mocks:
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
---
|
|
|
|
# Server Tests
|
|
|
|
Server route tests should cover:
|
|
|
|
- authenticated behavior
|
|
- unauthenticated behavior
|
|
- authorization rules
|
|
- successful operations
|
|
- failed operations
|
|
|
|
Mock:
|
|
|
|
- $lib/db
|
|
- authentication helpers
|
|
- external services
|
|
|
|
---
|
|
|
|
# Prisma Mocking
|
|
|
|
Mock only the methods used.
|
|
|
|
Example:
|
|
|
|
vi.mock('$lib/db', () => ({
|
|
prisma: {
|
|
proclamation: {
|
|
findMany: vi.fn(),
|
|
findUnique: vi.fn(),
|
|
create: vi.fn(),
|
|
update: vi.fn(),
|
|
delete: vi.fn()
|
|
}
|
|
}
|
|
}));
|
|
|
|
Do not create massive unused mocks.
|
|
|
|
---
|
|
|
|
# Authentication Testing
|
|
|
|
Use:
|
|
|
|
createLocals()
|
|
|
|
Examples:
|
|
|
|
Unauthenticated:
|
|
|
|
createLocals()
|
|
|
|
Authenticated:
|
|
|
|
createLocals(mockUser() as any)
|
|
|
|
Specific roles:
|
|
|
|
createLocals(
|
|
mockUser({ roleId: 4 }) as any
|
|
)
|
|
|
|
---
|
|
|
|
# Client Test Locators
|
|
|
|
Available:
|
|
|
|
getByRole
|
|
getByText
|
|
getByPlaceholder
|
|
getByAltText
|
|
getByTestId
|
|
|
|
Unavailable:
|
|
|
|
getByLabel
|
|
getByDisplayValue
|
|
|
|
---
|
|
|
|
# Role Queries
|
|
|
|
Always use exact regex names.
|
|
|
|
Preferred:
|
|
|
|
page.getByRole(
|
|
'textbox',
|
|
{ name: /^Name$/ }
|
|
)
|
|
|
|
Avoid:
|
|
|
|
page.getByRole(
|
|
'textbox',
|
|
{ name: 'Name' }
|
|
)
|
|
|
|
because substring matching can create strict-mode failures.
|
|
|
|
---
|
|
|
|
# Select Testing
|
|
|
|
Because selects use selected options instead of bind:value:
|
|
|
|
const element =
|
|
await page
|
|
.getByRole(
|
|
'combobox',
|
|
{ name: /^Frequency$/ }
|
|
)
|
|
.element();
|
|
|
|
expect(
|
|
(element as HTMLSelectElement).value
|
|
).toBe('2');
|
|
|
|
---
|
|
|
|
# Svelte Component Mocking
|
|
|
|
When mocking Svelte 5 components:
|
|
|
|
Use:
|
|
|
|
vi.mock('$lib/components/example.svelte', () => ({
|
|
default: ($anchor: Element) => {
|
|
const div = document.createElement('div');
|
|
$anchor.replaceWith(div);
|
|
}
|
|
}));
|
|
|
|
Imports using mocked modules must come after vi.mock().
|
|
|
|
If variables are needed inside mocks:
|
|
|
|
Use vi.hoisted().
|
|
|
|
---
|
|
|
|
# Test Completion Rule
|
|
|
|
After writing tests:
|
|
|
|
Run:
|
|
|
|
npm run test
|
|
|
|
If failures occur:
|
|
|
|
Fix them.
|
|
|
|
Do not report "tests added" without verifying they pass.
|