domain project / government

Government & Public Sector

Test strategies for citizen portals, permit applications, benefit claims, public information services, and accessibility-first government websites.

Citizen authenticationForm submission & trackingDocument uploadBenefit & permit applicationsWCAG 2.1 AA complianceMulti-language support

Domain Overview

Government portals serve all citizens — including those with disabilities, limited digital literacy, and slow connections. WCAG 2.1 AA compliance is legally mandated in most jurisdictions, not optional. Forms are complex: multi-step wizards with conditional fields, document uploads, government ID verification, and processing times measured in days or weeks. A form bug can mean a citizen misses a benefit deadline or permit expiry.

Typical stack: Government-approved CMS or bespoke Java/.NET backend, GOV.UK Notify / AWS SES for notifications, S3/Azure Blob for document storage, identity providers (GOV.UK Verify, Login.gov, FranceConnect), strict Content Security Policies.

The high E2E percentage (25%) reflects the complexity of multi-step wizard flows where state management, conditional logic, and session handling all interact — bugs only surface across the full journey.

Key Test Areas

AreaWhat to testRisk
AuthenticationGovernment ID / GOV.UK Verify / Login.gov SSO, MFA, session expiryUnauthorised access, citizen locked out
FormsMulti-step wizard, conditional field logic, save-and-resume, server validationLost data, invalid submission accepted
Document uploadPDF and image types, file size limits, virus scan, confirmation referenceMissing evidence, failed applications
Application trackingStatus updates, reference number display, email/SMS notificationsCitizens unaware of decisions
Accessibilityaxe-core on every page, keyboard-only navigation, screen reader landmarksLegal non-compliance, citizen exclusion
InternationalisationWelsh/French/Spanish language switch, translated content completeness, RTLCitizens cannot complete forms in native language

Test Pyramid for Government & Public Sector

Unit (40%):        Form validation rules, conditional field logic, date calculations, eligibility rules
Integration (35%): SSO flows, document upload API, notification triggers, audit log writes
E2E (25%):         Full application submission, accessibility checks per wizard step, session timeout handling

Critical E2E tests (must pass before every deploy):

  1. Citizen completes full multi-step application form and receives reference number
  2. Keyboard-only user can navigate and submit the form without mouse
  3. axe-core reports zero critical violations on every wizard step
  4. Document upload succeeds and reference appears in application record
  5. Session timeout mid-form prompts save warning, not silent data loss

Common Failure Scenarios

1. Form loses data on browser back navigation (no history state management)
   Test: fill step 2, click browser back, click forward, assert step 2 data preserved

2. Conditional field required validation fires even when field is hidden
   Test: choose option that hides field, submit form, assert no validation error for hidden field

3. Document upload succeeds (200 OK) but reference not saved in application (race condition)
   Test: intercept upload response, delay DB write via page.route(), complete submission, assert reference in record

4. Session timeout mid-form loses all data (no auto-save implemented)
   Test: fill form fields, advance step, expire session token via page.evaluate(), attempt continue, assert save prompt shown

5. Language switch mid-form resets form state (router remounts component)
   Test: fill step 1 in English, switch to Welsh, assert form field values unchanged

Playwright Patterns for Government Portals

// Test form autosave by intercepting the save API
test('form data is autosaved on step advance', async ({ page }) => {
  let savedPayload: unknown;
  await page.route('**/api/application/save', async route => {
    const body = await route.request().postDataJSON();
    savedPayload = body;
    await route.fulfill({ json: { saved: true } });
  });

  await page.goto('/apply/step-1');
  await page.getByLabel('Full name').fill('Jane Doe');
  await page.getByRole('button', { name: 'Continue' }).click();

  expect((savedPayload as any)?.fullName).toBe('Jane Doe');
});

// Run axe-core on every wizard step
import AxeBuilder from '@axe-core/playwright';

test('wizard step 2 has no critical accessibility violations', async ({ page }) => {
  await page.goto('/apply/step-2');
  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa'])
    .analyze();
  expect(results.violations).toEqual([]);
});

// Test keyboard-only form completion
test('form is completable with keyboard only', async ({ page }) => {
  await page.goto('/apply/step-1');
  await page.keyboard.press('Tab'); // focus first field
  await page.keyboard.type('Jane Doe');
  await page.keyboard.press('Tab');
  await page.keyboard.type('01/01/1980');
  await page.keyboard.press('Tab');
  await page.keyboard.press('Enter'); // submit
  await expect(page).toHaveURL(/step-2/);
});