From d1c6eab474838fb98f7bdbfbca69dee4c861d85a Mon Sep 17 00:00:00 2001 From: Ynda Jas Date: Wed, 6 Nov 2024 14:47:27 +0000 Subject: [PATCH 1/2] Set up Playwright Breaking changes were merged to the app that caused it to be unable to boot up. We didn't notice this until someone tried to load up the deployed site. Non-major Renovate dependency PRs are merged automatically on this repo, which is risky without at least minimal automated testing. We had a CI workflow to test that the app built but this evidently wasn't sufficient. This adds Playwright so that we can do a basic 'homepage loads' kind of end-to-end test, and run this on CI for pull requests and pushes to main --- .github/workflows/ci.yml | 18 ------------ .github/workflows/e2e.yml | 26 +++++++++++++++++ .gitignore | 4 +++ package-lock.json | 60 ++++++++++++++++++++++++++++++++++++--- package.json | 4 +++ playwright.config.js | 48 +++++++++++++++++++++++++++++++ 6 files changed, 138 insertions(+), 22 deletions(-) delete mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/e2e.yml create mode 100644 playwright.config.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index ef823f9d..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: CI - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Use Node.js - uses: actions/setup-node@v4 - with: - cache: 'npm' - - run: npm ci diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 00000000..7d2addd8 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,26 @@ +name: End-to-end tests +on: + pull_request: + push: + branches: [ main ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 1c0876b2..2bca8c01 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,7 @@ node_modules/ /cypress/temp tmp/ package-lock.json +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/package-lock.json b/package-lock.json index d08adef5..769ac4aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,10 @@ "hmrc-frontend": "^6.0.0", "jquery": "3.7.1", "notifications-node-client": "5.2.3" + }, + "devDependencies": { + "@playwright/test": "^1.48.2", + "@types/node": "^22.9.0" } }, "node_modules/@govuk-prototype-kit/step-by-step": { @@ -343,6 +347,22 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@playwright/test": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", + "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -378,12 +398,12 @@ } }, "node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/qs": { @@ -2876,6 +2896,38 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/portscanner": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", diff --git a/package.json b/package.json index e06fa7bd..fa9977c8 100644 --- a/package.json +++ b/package.json @@ -13,5 +13,9 @@ "hmrc-frontend": "^6.0.0", "jquery": "3.7.1", "notifications-node-client": "5.2.3" + }, + "devDependencies": { + "@playwright/test": "^1.48.2", + "@types/node": "^22.9.0" } } diff --git a/playwright.config.js b/playwright.config.js new file mode 100644 index 00000000..e955ce44 --- /dev/null +++ b/playwright.config.js @@ -0,0 +1,48 @@ +// @ts-check +const { defineConfig, devices } = require('@playwright/test'); + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config({ path: path.resolve(__dirname, '.env') }); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +module.exports = defineConfig({ + testDir: './e2e', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run dev', + url: 'http://127.0.0.1:3000', + reuseExistingServer: !process.env.CI, + }, +}); From e7b4ec20204ed60d04b7771767248fd8a4ac4a2e Mon Sep 17 00:00:00 2001 From: Ynda Jas Date: Wed, 6 Nov 2024 14:48:29 +0000 Subject: [PATCH 2/2] Add basic end-to-end test Per the last commit, this is to ensure automated dependency PRs don't get merged and silently bring the app down --- e2e/app.spec.js | 10 ++++++++++ package.json | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 e2e/app.spec.js diff --git a/e2e/app.spec.js b/e2e/app.spec.js new file mode 100644 index 00000000..4050d4f7 --- /dev/null +++ b/e2e/app.spec.js @@ -0,0 +1,10 @@ +// @ts-check +const { test, expect } = require('@playwright/test'); + +test('homepage loads', async ({ page }) => { + await page.goto('/'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle("Home – dxw Prototype Library"); + await expect(page.getByRole('heading', { name: "dxw Prototype Gallery" })).toBeVisible(); +}); diff --git a/package.json b/package.json index fa9977c8..5d6a206e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "scripts": { "dev": "govuk-prototype-kit dev", "serve": "govuk-prototype-kit serve", - "start": "govuk-prototype-kit start" + "start": "govuk-prototype-kit start", + "test": "npx playwright test" }, "name": "govuk-prototype-kit", "dependencies": {