Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue #358]: Add e2e tests against PR preview env #85

Open
wants to merge 51 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
11e75b7
initial commit
rylew1 Jul 8, 2024
e4f4aa6
upgrade github actions versions in e2e-tests
rylew1 Jul 8, 2024
c96c22a
try sed command
rylew1 Jul 8, 2024
14e5f4d
comment out home page element test
rylew1 Jul 11, 2024
4e3ff7b
remove console.log
rylew1 Jul 11, 2024
77385b0
expect response status to be 200
rylew1 Jul 11, 2024
3df74cf
timeout comment
rylew1 Jul 11, 2024
eb56ca1
use .env and BASE_URL
rylew1 Jul 11, 2024
cea66b0
install dotenv
rylew1 Jul 11, 2024
30a748f
Update .github/workflows/pr-environment-update.yml
rylew1 Jul 11, 2024
e8bd7e0
add response const
rylew1 Jul 11, 2024
5e02221
set base url env in workflow (remove jq/sed)
rylew1 Jul 11, 2024
1a6cabe
install browsers and cat config file
rylew1 Jul 11, 2024
c39ac5e
fix output reference
rylew1 Jul 11, 2024
da7a026
.js for playwright config
rylew1 Jul 11, 2024
975eab7
update scripts
rylew1 Jul 11, 2024
7bce8ac
add root makefile commands
rylew1 Jul 11, 2024
9df7fe4
install required deps in workflow
rylew1 Jul 11, 2024
03406ce
update comment to //
rylew1 Jul 11, 2024
e1b4fda
revert makefile
rylew1 Jul 11, 2024
09a058d
update install deps
rylew1 Jul 11, 2024
75e1dca
libx-dev
rylew1 Jul 11, 2024
3e00968
fix running test to proper script
rylew1 Jul 11, 2024
f457e9d
add APP_NAME in .env.example
rylew1 Jul 11, 2024
071c778
use just desktop and mobile chrome as default config
rylew1 Jul 11, 2024
4eb68c3
try to run from e2e/app folder
rylew1 Jul 11, 2024
35e4a81
ts to js for app config
rylew1 Jul 11, 2024
06ad3cc
update to run package.json script with env var
rylew1 Jul 11, 2024
ffe9c32
add working directory and app_name to ci
rylew1 Jul 11, 2024
e04fc49
e2e-tests plural
rylew1 Jul 11, 2024
74d5e16
remove testDir in derived
rylew1 Jul 11, 2024
6cb5f9c
try ci specific run script
rylew1 Jul 11, 2024
c47eebf
add a11y test
rylew1 Jul 11, 2024
9e080ee
add comment to playwright a11y testing
rylew1 Jul 11, 2024
7317e7e
add make commands
rylew1 Jul 11, 2024
be56e36
test title
rylew1 Jul 11, 2024
88927d6
e2e-test singular
rylew1 Jul 12, 2024
68df307
remove cross-var
rylew1 Jul 12, 2024
e2ed683
remove e2e-test-ci and use make command
rylew1 Jul 12, 2024
53be1c4
add docs
rylew1 Jul 12, 2024
3a79901
fix dead markdown link
rylew1 Jul 12, 2024
e98edc7
Update makefile e2e header
rylew1 Jul 12, 2024
7d93b28
fix name for PR view
rylew1 Jul 12, 2024
21e70df
update upload-artifact v4
rylew1 Jul 12, 2024
de497d5
Merge branch 'rylew/358-e2e-tests-preview-env' of https://github.com/…
rylew1 Jul 12, 2024
ea717ae
fix typo in docs
rylew1 Jul 12, 2024
47c394d
add make target
rylew1 Jul 12, 2024
fce035a
have ci use new make e2e-setup-ci target
rylew1 Jul 12, 2024
cc250e7
add default base url in derived config
rylew1 Jul 12, 2024
75cd1f1
rename workflow title and filename
rylew1 Jul 16, 2024
1c00c00
update docs
rylew1 Jul 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI App PR Environment Update
name: CI App PR Environment Checks
on:
workflow_dispatch:
inputs:
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/e2e-tests.yml
rylew1 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: E2E Tests

on:
workflow_call:
inputs:
service_endpoint:
required: true
type: string
app_name:
required: false
type: string

jobs:
e2e:
name: " " # GitHub UI is noisy when calling reusable workflows, so use whitespace for name to reduce noise
runs-on: ubuntu-latest

env:
BASE_URL: ${{ inputs.service_endpoint }}
APP_NAME: ${{ inputs.app_name }}

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

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libwoff1 libopus0 libvpx7 libevent-2.1-7 libopus0 libgstreamer1.0-0 \
libgstreamer-plugins-base1.0-0 libgstreamer-plugins-good1.0-0 libharfbuzz-icu0 libhyphen0 \
libenchant-2-2 libflite1 libgles2 libx264-dev
Comment on lines +33 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these for? Does it merit a comment or link to documentation that explains the need for these packages and/or what they do?

Copy link
Author

@rylew1 rylew1 Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it helps, you can see the initial deps failure here: https://github.com/navapbc/platform-test-nextjs/actions/runs/9885358319/job/27303354260


rylew1 marked this conversation as resolved.
Show resolved Hide resolved
- name: Install Node.js dependencies
run: npm ci
working-directory: ./e2e

- name: Install Playwright browsers
run: make e2e-setup-ci

- name: Run e2e tests
run: make e2e-test APP_NAME=${{ inputs.app_name }} BASE_URL=${{ inputs.service_endpoint }}
env:
BASE_URL: ${{ inputs.service_endpoint }}
APP_NAME: ${{ inputs.app_name }}

- name: Upload Playwright report
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: ./e2e/playwright-report
18 changes: 17 additions & 1 deletion .github/workflows/pr-environment-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ jobs:

concurrency: pr-environment-${{ inputs.pr_number }}

outputs:
service_endpoint: ${{ steps.update-environment.outputs.service_endpoint }}

steps:
- uses: actions/checkout@v4

Expand All @@ -51,6 +54,19 @@ jobs:
environment: ${{ inputs.environment }}

- name: Update environment
run: ./bin/update-pr-environment "${{ inputs.app_name }}" "${{ inputs.environment }}" "${{ inputs.pr_number }}" "${{ inputs.commit_hash }}"
id: update-environment
run: |
./bin/update-pr-environment "${{ inputs.app_name }}" "${{ inputs.environment }}" "${{ inputs.pr_number }}" "${{ inputs.commit_hash }}"
service_endpoint=$(terraform -chdir="infra/${{ inputs.app_name }}/service" output -raw service_endpoint)
echo "service_endpoint=${service_endpoint}"
echo "service_endpoint=${service_endpoint}" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ github.token }}

e2e-tests:
name: Run E2E Tests
needs: [update]
uses: ./.github/workflows/e2e-tests.yml
with:
service_endpoint: ${{ needs.update.outputs.service_endpoint }}
app_name: ${{ inputs.app_name }}
23 changes: 20 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ __check_defined = \
release-image-name \
release-image-tag \
release-publish \
release-run-database-migrations


release-run-database-migrations \
e2e-setup \
e2e-test

infra-set-up-account: ## Configure and create resources for current AWS profile and save tfbackend file to infra/accounts/$ACCOUNT_NAME.ACCOUNT_ID.s3.tfbackend
@:$(call check_defined, ACCOUNT_NAME, human readable name for account e.g. "prod" or the AWS account alias)
Expand Down Expand Up @@ -217,6 +217,23 @@ release-image-name: ## Prints the image name of the release image
release-image-tag: ## Prints the image tag of the release image
@echo $(IMAGE_TAG)

##############################
## End-to-end (E2E) Testing ##
##############################

e2e-setup: ## Setup end-to-end tests
@cd e2e && npm install
@cd e2e && npx playwright install --with-deps

e2e-setup-ci: ## Install dependencies and Playwright browsers
cd e2e && npx playwright install --with-deps

e2e-test: ## Run end-to-end tests
# make e2e-test APP_NAME=app BASE_URL=http://localhost:3000
@:$(call check_defined, APP_NAME, ...)
@:$(call check_defined, BASE_URL, ...)
@cd e2e && cd $(APP_NAME) && APP_NAME=$(APP_NAME) BASE_URL=$(BASE_URL) npx playwright test $(E2E_ARGS)

rylew1 marked this conversation as resolved.
Show resolved Hide resolved
########################
## Scripts and Helper ##
########################
Expand Down
76 changes: 76 additions & 0 deletions docs/e2e/e2e-checks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# End-to-End (E2E) Tests

## Overview

This repository uses [Playwright](https://playwright.dev/) to perform end-to-end (E2E) tests. The tests can be run locally, but also run on [Pull Request preview environments](../infra/pull-request-environments.md). This ensures that any new code changes are validated through E2E tests before being merged.

## Folder Structure
In order to support e2e for multiple apps, the folder structure will include a base playwright config (`./e2e/playwright.config.js`), and app-specific derived playwright config that override the base config. See the example folder structure below:
```
- e2e
- playwright.config.js
- app/
- playwright.config.js
- tests/
- index.spec.js
- app2/
- playwright.config.js
- tests/
- index.spec.js
```

Some highlights:
- By default, the base config is defined to run on a minimal browser-set (desktop and mobile chrome)
- Snapshots will be output locally or in the artifacts of the CI job
- HTML reports are output to the `playwright-report` folder
- Parallelism limited on CI to ensure stable execution
- Accessibility testing can be performed using the `@axe-core/playwright` package (https://playwright.dev/docs/accessibility-testing)


## Running Locally

### Running Locally From the Root Directory

Make targets are setup to easily pass in a particular app name and URL to run tests against

```
make e2e-setup # install playwright deps
make e2e-test APP_NAME=app BASE_URL=http://localhost:3000 # run tests on a particular app
```

### Running Locally From the `./e2e` Directory

If you prefer to run package.json run scripts, you can do so by creating a `./e2e/.env` file with an `APP_NAME` and `BASE_URL`

```
cd e2e

# Create .env file with BASE_URL and APP_NAME
echo "BASE_URL=http://127.0.0.1:3000" > .env
echo "APP_NAME=your-app-name" >> .env

npm install
npm run e2e-test
```

### PR Environments

The E2E tests are triggered in PR preview environments on each PR update. For more information on how PR environments work, please refer to [PR Environments Documentation](../infra/pull-request-environments.md).

### Workflows

The following workflows trigger E2E tests:
- [PR Environment Update](../../.github/workflows/pr-environment-update.yml)
- [E2E Tests Workflow](../../.github/workflows/e2e-tests.yml)

The [E2E Tests Workflow](../../.github/workflows/e2e-tests.yml) takes a `service_endpoint` URL and an `app_name` to run the tests against specific configurations for your app.

## Configuration

The E2E tests are configured using the following files:
- [Base Configuration](../../e2e/playwright.config.js)
- [App-specific Configuration](../../e2e/app/playwright.config.js)

The app-specific configuration files extend the common base configuration.

By default when running `make e2e-test APP_NAME=app BASE_URL=http://localhost:3000 ` - you don't necessarily need to pass an `BASE_URL` since the default is defined in the app-specific playwright config (`./e2e/app/playwright.config.js`).
2 changes: 2 additions & 0 deletions e2e/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BASE_URL=http://127.0.0.1:3000
APP_NAME=app
6 changes: 6 additions & 0 deletions e2e/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
*.png*
19 changes: 19 additions & 0 deletions e2e/app/playwright.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineConfig, devices } from '@playwright/test';

import baseConfig from '../playwright.config';

export default defineConfig({
...baseConfig,
rylew1 marked this conversation as resolved.
Show resolved Hide resolved
use: {
...baseConfig.use,
baseUrl: baseConfig.use.baseUrl || "localhost:3000"
},
projects: [
...baseConfig.projects,
// add Safari for derived app config
{
name: "webkit",
use: { ...devices["Desktop Safari"] },
},
],
});
31 changes: 31 additions & 0 deletions e2e/app/tests/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const { test, expect } = require('@playwright/test');

import AxeBuilder from '@axe-core/playwright';

test.describe('Generic Webpage Tests', () => {
test('should load the webpage successfully', async ({ page }) => {
const response = await page.goto('/');
const title = await page.title();
await expect(response.status()).toBe(200);
});

test('should take a screenshot of the webpage', async ({ page }) => {
await page.goto('/');
await page.screenshot({ path: 'example-screenshot.png', fullPage: true });
});

// https://playwright.dev/docs/accessibility-testing
test('should not have any automatically detectable accessibility issues', async ({ page }) => {
await page.goto('/');
const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
expect(accessibilityScanResults.violations).toEqual([]);
});

// Example test of finding a an html element on the index/home page
// test('should check for an element to be visible', async ({ page }) => {
// await page.goto('/');
// const element = page.locator('h1');
// await expect(element).toBeVisible();
// });

});
123 changes: 123 additions & 0 deletions e2e/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading