Skip to main content
Skip table of contents

Writing an end-to-end test

Frontend engineers use end-to-end tests in vets-website to validate multipage applications with client-side routing. They are primarily used to assert that:

  • Client applications render their inputs.

  • Client-side navigation occurs when the required fields are populated.

End-to-end testing overview

vets-website uses Cypress to write end-to-end tests.

  • Some older end-to-end tests were written in Nightwatch before Cypress. All new tests should be written using Cypress. Nightwatch tests are being deprecated/migrated to Cypress.

  • End-to-end tests are collocated in the application folder with the application they test.

  • Cypress tests can be run using the command yarn cy:run (after yarn watch to yarn build).

See Cypress Best Practices on the VA.gov Platform and Cypress Resources Reference Guide for detailed use cases and documented helpers/mocks.

End-to-end tests conventions

  • Use the name of the test spec to indicate the page under test.

  • Disable scrolling on the page.

  • Assert navigating the page is successful.

  • Use functions from the helper file to perform all actions on the page.

These are recommendations, not requirements, except when labeled as required.

  • Separate page navigation from form field input.

    • Use a main test file for navigation, assertions, and calls helpers.

    • Use a helper file for filling out forms.

  • Create separate, numbered, main test files to organize tests by their focus:

    • 00-all-fields.cypress.spec.js - required and optional fields.

    • 01-required.cypress.spec.js - only required fields.

    • 02-accessibility.cypress.spec.js - validates accessibility.

    • 03-auth.cypress.spec.js - validates authentication.

    • 04-cross-cutting-feature.cypress.spec.js - validates one feature used across several pages (Example: save in progress).

  • Group tests by pages and use a comment to indicate what page is being tested.

  • Mock all API responses before starting the test. See Mocking API responses below.

  • Use waitForElementVisible before interacting with any element on the page.

  • Use timeouts constant for setting timeouts (platform/testing/e2e/timeouts.js).

  • Use helpers for filling in data and performing actions on the page.

  • Required: Perform axeCheckon the main body of the application on each page - see axeCheck.

  • Assert that each navigation is successful.

  • Cypress uses chai to handle assertions.

Test dependencies

You generally don’t need to import any modules for helpers, timeouts, etc.

Test structure

Cypress uses Mocha's behavior-driven development (BDD) syntax, which is what we use for our unit tests.

Each spec file starts a new browser instance and runs the suite of tests according to the describe() and it() blocks.

  • Note that it() blocks are individual tests, so each it() block should be independent of others in the same test suite.

  • Everything executed in the browser must be inside an it() block.

Visit the Cypress docs for more context.

Form tests

Applications that are built with the VA Forms Library should be tested with the Cypress form tester.

Visiting a page

When visiting a page, you don't need to specify the baseUrl. The Cypress configuration file takes care of this. You can visit the page with a relative path:

CODE
cy.visit("health-care/apply/application");

Interacting with page elements

The most common interactions you'll probably use are clicking, selecting elements from dropdowns, and entering text inputs.

Below are examples of these interactions in Cypress:

Clicking
CODE
cy.get(".form-panel .usa-button-primary").click()
Selecting from dropdown
CODE
cy.findByLabelText(/country/i).select(testData.veteranAddress.country);
Entering data
CODE
cy.findByLabelText(/first name/i).type(testData.veteranFullName.first);

For more information about how Cypress interactions behave, visit the Cypress guide for interacting with elements.

For additional ways to interact with the DOM, we've also included the Cypress Testing Library as a dependency.

Active element

Checks if the given element is focused on the page.

CODE
// BDD assertion
cy.findByLabelText("First name").should("have.focus");
Disabled element

Checks if the given element is disabled on the page.

CODE
// BDD assertion
cy.findByRole("button", { name: "Submit" }).should("be.disabled");

Examples

Cypress test for VAOS

Cypress test for the 21-526EZ form using the form tester

Mocking API responses

A mock server runs with the end-to-end tests to allow tests to make production-like calls.

See the Mocks section of Cypress Resources Reference Guide for detailed mock API examples currently used.

Below are some of the commonly used Cypress mocks (accessible from the link above).

  • mockFeatureToggles

  • mockConstants

  • createTestHistory

  • renderWithStoreAndRouter

  • mockAppointmentsGetApi

  • mockFacilityApi

Custom Cypress commands

Custom Cypress commands can be found in src/platform/testing/e2e/cypress/support/commands.

Cypress supports extending its client API with custom commands.

Below are some of the commonly used custom Cypress commands.

  • axeCheck - Callback from accessibility check that logs axe violations to console output.

  • expandAccordions - Expands all accordions and AdditionalInfo components.

  • injectAxeThenAxeCheck - Combines two common, sequentially called functions.

  • login - Simulates a logged-in session.

  • upload - Workaround to support file upload functionality in tests, which is currently not officially implemented.

  • viewportPreset - Sets the viewport by preset name.

Helpers

The Cypress Resources Reference Guide contains a list of currently utilized Cypress & VAOS Helpers and Appointment Helpers.


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.