# Website testing guidelines

This guide is the required local minimum for the public website and participant portal. It applies the shared [PFR testing guidelines](https://github.com/people-for-research/pfr-core/blob/main/docs/testing-guidelines.md) when that canonical link is accessible. If it is temporarily unavailable, apply this local guide, record the missing source and residual risk, and do not invent rules. Select evidence from risk: use deterministic scripts for logic and integrations they cover, environment-backed verification for a named deployed-like dependency, and a concise manual/exploratory charter for journeys that are not automated.

## Current deterministic checks

The repository has focused TypeScript scripts for Ghost/PDF behaviour, Ghost-backed page loaders, sitemap and JSON-LD safety, privacy-policy fallback, participant-list utilities, participant-list session-visibility server actions, and participant questionnaire compatibility. Run the smallest relevant script while working; `npm run test:ghost` is the aggregate Ghost/PDF suite.

```bash
npm run test:ghost
npm run test:participant-list-utils
npm run test:portal-actions-session-visibility
npm run test:questionnaire-compatibility
npm run test:portal-proxy-signature
npm run lint
npm run format:check
```

`prebuild` currently runs `test:ghost`, `test:participant-list-utils`,
`test:portal-actions-session-visibility`, and
`test:questionnaire-compatibility`. It does not run
`test:portal-proxy-signature`; run that script for signed portal changes.
Adding it to the aggregate/prebuild path is a follow-up, not an assumption this
guide makes.

### Environment-backed client-preview verification

`npm run verify:client-preview-exchange` is side-effecting environment-backed
verification, not a normal deterministic test. It may create exchange/audit state
and exercise rate limiting. Run it only against an approved non-production
environment with synthetic account and job data; never run it against production.
Record its side effects, cleanup, environment, and result when a client-preview
exchange, its configuration, or its contract changes.

Normal deterministic tests must not call production services or rely on production
data. Use controlled fetchers, fixtures, clocks, and inputs. Do not place secrets,
participant data, signed URLs, or tokens in source, assertion output, screenshots,
or release notes.

## Choose the right evidence

- For Ghost-backed pages, follow the specialised [Ghost integration guidelines](ghost-integration-guidelines.md). They define the fetch, cache, parsing, fallback, security, focused-test, and editor-documentation rules; do not duplicate those mechanics here.
- For public or portal code with focused deterministic coverage, test the user-visible outcome, error path, boundary input, and meaningful post-state. A missing prerequisite must fail the test or be explicitly arranged; conditional assertions that can pass without proving the scenario are not evidence.
- For changes to signup, login, profile, opportunities, campaign, or Turnstile-protected flows, create a risk-based browser/manual charter until suitable automation exists. State the role and safe data, start/end state and cleanup, expected and rejected paths, environment, accessibility/visual checks, third-party hand-off or recovery, and evidence captured.
- For Core API, authentication, campaign, webhook, or shared-domain changes, identify producer and consumer evidence. Verify the request/response and error shapes, roles, time/format assumptions, and the website's interpretation. Keep compatible changes additive until known consumers are ready where practical.

Component or unit-like checks cannot prove browser rendering, access control, a deployed environment, or an external hand-off. Conversely, manual completion of a happy path does not replace a repeatable regression check. Use the lowest reliable layer first, then add the missing boundary evidence.

## Non-functional and release evidence

Treat participant data, authentication, permissions, privacy, security, error handling, accessibility, and third-party resilience as explicit risks. Performance or reliability work needs a representative journey, data shape, environment, and an agreed product or operational target; do not invent an SLO or threshold in a test plan.

Before review, record the commit, commands, environment/data assumptions, result, and any intentional gap. A merged change is not deployed evidence: for a critical release also identify the deployed artifact/environment and record the relevant smoke or exploratory result. Classify failures before retrying (product defect, test defect, contract drift, environment/infrastructure, or suspected flake); preserve the exact failure and only call a test flaky after controlled repeats demonstrate non-determinism.

If a defect escapes, capture the missed assumption, the smallest prevention that would have caught it, an owner, and a completion condition. Avoid turning an incident into an unsupported coverage claim.

## Current debt and follow-ups

- The repository has no checked-in browser test runner or workflow. This does not make claims about external CI; it means critical browser evidence must currently be planned and recorded per change.
- Most signup, login, profile, opportunity, campaign, and Turnstile journeys lack committed automated coverage.
- `test:portal-proxy-signature` is not part of the current aggregate/prebuild gate.

These are known gaps, not reasons to bypass risk-based verification.
