NJ Municipality Lookup
CodebaseTestsE2e

Helpers

Utility functions for accessible, realistic form interactions in E2E tests.

E2E Test Helpers

Utility functions for accessible, realistic form interactions in E2E tests.

What This Directory Contains

Helper functions that simulate real user interactions with forms. These helpers ensure tests validate the actual user experience, including keyboard navigation and assistive technology compatibility.

Why These Helpers Exist

Standard Playwright methods like fill() bypass important behaviors:

  1. Keyboard events: Real users trigger keydown, keypress, keyup events
  2. Incremental state updates: React state updates with each keystroke
  3. Debounced handlers: Autocomplete triggers after typing pauses
  4. Accessibility: Screen reader users interact differently than mouse users

These helpers simulate how real users (including those using assistive technology) interact with the application.

Files

form-interaction.ts

Accessible form interaction utilities.

How to Use

Fill Form Accessibly

import {
  fillAddressFormAccessibly,
  submitAddressForm,
} from "./helpers/form-interaction";

test("should lookup address", async ({ page }) => {
  await page.goto("/lookup");

  // Fill form like a real user would
  await fillAddressFormAccessibly(page, {
    streetAddress: "323 Dr Martin Luther King Jr Blvd",
    city: "Newark",
    zipCode: "07102",
  });

  // Submit using accessible button interaction
  await submitAddressForm(page);

  // Verify results
  await expect(page.getByText(/newark/i)).toBeVisible();
});

Keyboard Navigation

import {
  fillAccessibly,
  navigateSuggestionsWithKeyboard,
  selectSuggestionWithKeyboard,
} from "./helpers/form-interaction";

test("should navigate suggestions with keyboard", async ({ page }) => {
  await page.goto("/lookup");

  const streetInput = page.getByRole("combobox", { name: /street/i });

  // Type to trigger autocomplete
  await fillAccessibly(streetInput, "323");

  // Navigate suggestions with arrow keys
  await navigateSuggestionsWithKeyboard(page, 0); // First suggestion

  // Select with Enter
  await selectSuggestionWithKeyboard(page);

  // Verify selection was applied
  await expect(streetInput).toHaveValue(/323/);
});

Wait for Form Validation

import {
  fillAddressFormAccessibly,
  waitForSubmitEnabled,
} from "./helpers/form-interaction";

test("should enable submit after valid input", async ({ page }) => {
  await page.goto("/lookup");

  await fillAddressFormAccessibly(page, {
    streetAddress: "323 Dr Martin Luther King Jr Blvd",
    city: "Newark",
  });

  // Wait for form validation to complete
  await waitForSubmitEnabled(page);

  // Now safe to click submit
});

API Reference

fillAccessibly(locator, value, options?)

Types text character-by-character like a real user.

OptionTypeDefaultDescription
delaynumber10Milliseconds between keystrokes
clearbooleantrueClear input before typing
waitAfternumber300Wait for debounced handlers

fillAddressFormAccessibly(page, address)

Fills the structured address form fields.

FieldRequiredDescription
streetAddressYesStreet address (fills combobox)
cityYesCity name
zipCodeNoZIP code

waitForSubmitEnabled(page, timeout?)

Waits for submit button to become enabled (form validation passed).

submitAddressForm(page)

Clicks the submit button using accessible role.

Navigates autocomplete suggestions using arrow keys.

selectSuggestionWithKeyboard(page)

Selects current suggestion using Enter key.

Best Practices

  1. Use accessible selectors: getByRole() over getByTestId()
  2. Simulate real typing: Use fillAccessibly() instead of fill()
  3. Wait for debounce: Allow time for autocomplete to respond
  4. Test keyboard navigation: Many users navigate with keyboard only

On this page