Cypress E2E Tests for Applications hosted on Vercel
• 4min readIntroduction
Personally, I am a big fan of having any sort of (well-written) tests in all of my programming projects. They give me the confidence to push changes to my production build while knowing that all my core features are still functioning properly. Especially if they are fully integrated into your work pipeline. I recently switched to Vercel as my personal choice as a deployment platform and I was looking for a way to automate my E2E test runs whenever I added new features to my codebase. There are a couple tutorials already out there which explain in great detail on how to do that [1][2]. But unlike explained there, I did not want to run my E2E tests on every commit but rather on every pull request since I have a protected main branch and only allow changes coming in through a PR. Setting it up this way would also save some bandwidth since the number of PRs is smaller or equal to the number of incoming commits. So here is a walkthrough on how I manage to do that using GitHub actions:
Implementation
Let’s start by initializing a new Next.js project and add cypress
as a devdependency:
npx create-next-app cypress-vercel-github --use-npm npm install -D cypress
Add two new npm scripts for running cypress (UI and headless mode):
// package.json { "name": "cypress-vercel-github", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "e2e": "cypress open", "e2e:headless": "cypress run" }, "dependencies": { "next": "12.1.5", "react": "18.0.0", "react-dom": "18.0.0" }, "devDependencies": { "cypress": "^9.5.4", "eslint": "8.13.0", "eslint-config-next": "12.1.5" } }
After running npm run e2e
for the first time, we should end up with a cypress
folder in our root directory. Let’s add a very basic E2E test:
// cypress/integration/example.spec.js describe("Example", () => { it("should have correct title", () => { cy.visit("/"); cy.get("h1").contains("Welcome to Next.js!"); }); });
Don’t forget to set/adjust the baseUrl
in your cypress configuration file:
// cypress.json { "baseUrl": "http://localhost:3000" }
We should now have a first passing test. Feel free to add as many tests as you need. If we want, we can also execute a headless run with npm run e2e:headless
to simulate the test run on our CI/CD pipeline.
Successful Cypress E2E test run
Having our local code in place, we push our code to our GitHub repository and connect it with a new project on Vercel. This should automatically trigger a deployment and create a production build hosted at <project-name>.vercel.app
. Similarly, Vercel also automatically creates a preview build for every Git branch other than our production branch (hosted at project-name>-<unique-hash>-<scope-slug>.vercel.app
). We can take advantage of this feature by having our E2E tests run against these preview builds before merging our changes to main
. If our tests turn green, we then have the confidence that our new changes do not impede our current production build. To do so, we add a new GitHub workflow file so our tests run automatically whenever we create a new pull request against our main
branch:
// .github/workflows/pull_request.yaml name: Pull request on: pull_request: branches: - main jobs: e2e-cypress: name: E2E Cypress runs-on: ubuntu-latest steps: - name: Wait for Vercel Preview uses: patrickedqvist/wait-for-vercel-preview@v1.2.0 id: waitForVercelPreview with: token: ${{ secrets.GITHUB_TOKEN }} max_timeout: 60 - name: Checkout uses: actions/checkout@v3 - name: Run Cypress Tests uses: cypress-io/github-action@v2 env: CYPRESS_BASE_URL: ${{ steps.waitForVercelPreview.outputs.url }}
Here is a short description of each step:
- Since we need the URL of our preview build we have to wait until the deployment on Vercel is finished. Fortunately, there exists a GitHub Action that not only waits until the deployment is successful but also provides the resulting URL as an output for later steps.
- Checkout the code on the local runner.
- Use the official Cypress GitHub Action to run our E2E tests. By providing a URL through the respective environment variable, our tests automatically run against our preview build.
And that’s it! If we now create a new branch to add a new feature and eventually create a pull request against our main
branch, the GitHub action should automatically trigger and report its result as an additional check:
Pull request with integrated E2E test run check
If we click on Details
we can see the logs generated by Cypress:
E2E test run logs
Bonus point: If you have a GitHub Pro membership, you can additionally setup branch protection rules so pull requests can only be merged if our E2E test run is successful.
For more details, check my example repository on GitHub: https://github.com/dangpg/cypress-vercel-github