Archive note: This guide was originally published on July 6, 2023 and uses Cypress 12, Node.js 19, and older GitHub Actions releases. The overall workflow is still useful, but check the current documentation and update the dependency and Action versions before using it in a new project.

Okay, now we’ve created an online portfolio and published it.

Let’s make sure our next changes don’t break what we already have.

What will you need?

We’re going to use Cypress to write automated end-to-end tests and GitHub Actions to execute them.

Configure Cypress

Install Cypress as a development dependency:

npm install --save-dev cypress

Add commands for opening Cypress interactively and running its end-to-end suite to package.json:

{
  "scripts": {
    "cypress:open": "cypress open",
    "cypress:e2e": "cypress run --e2e"
  }
}

Open Cypress:

npm run cypress:open

Select E2E Testing to begin the setup.

The Cypress welcome screen showing E2E Testing and Component Testing setup options.
Selecting E2E Testing in Cypress 12.

Continue through the setup so Cypress can create its configuration and support files.

Cypress confirming the configuration and support files added for end-to-end testing.
The files generated by the Cypress 12 setup flow.

Once Cypress is configured, you can close its windows and create your first end-to-end test:

mkdir -p cypress/e2e
touch cypress/e2e/home.cy.js

Add a small smoke test to home.cy.js:

describe("Home Page", () => {
  beforeEach(() => {
    cy.visit("/")
  })

  it("renders successfully", () => {
    cy.get("h1").should("contain", "Headline")
  })
})

Run the suite:

npm run cypress:e2e

Configure GitHub Actions

First, add a baseUrl to cypress.config.js:

const { defineConfig } = require("cypress")

module.exports = defineConfig({
  e2e: {
    baseUrl: "http://localhost:3001",
    setupNodeEvents(on, config) {
      // Implement Node event listeners here.
    },
  },
})

To run the end-to-end test in continuous integration, we need a utility that starts the website, waits for it to become available, and then runs Cypress:

npm install --save-dev start-server-and-test

Add a new package.json script. This assumes the existing start command serves the site on port 3001.

{
  "scripts": {
    "test:e2e": "start-server-and-test start 3001 cypress:e2e"
  }
}

Verify the setup locally:

npm run test:e2e

Now create the GitHub Actions workflow:

mkdir -p .github/workflows
touch .github/workflows/e2e-test.yml

Add the following to .github/workflows/e2e-test.yml:

name: E2E Test

on:
  pull_request:
    branches:
      - main
  push:
    branches:
      - main

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: 19

      - name: Install dependencies
        run: npm install

      - name: Run E2E tests
        run: npm run test:e2e

That’s it. Push the changes to your repository to run the workflow.

Cover photograph by Ferenc Almasi.