Skip to content

Commit af9dd8f

Browse files
authored
ci: add e2e test verifying the deployed version of the runtime (#76)
* ci: add e2e test verifying the deployed version of the runtime * chore: update secret name * chore: update name * chore: update auth details * chore: use different token * chore: update * chore: fix cleanup * chore: don't run e2e tests with vitest * chore: update
1 parent fe68c74 commit af9dd8f

9 files changed

+384
-11
lines changed

.github/workflows/run-tests.yml

+43-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,51 @@
11
name: 'Run tests'
22
on:
33
pull_request:
4+
branches: [main]
45

56
jobs:
7+
e2e:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v3
11+
- name: 'Install Node'
12+
uses: actions/setup-node@v3
13+
with:
14+
node-version: '18.x'
15+
cache: 'npm'
16+
cache-dependency-path: '**/package-lock.json'
17+
- name: 'Install dependencies'
18+
run: npm ci
19+
- name: 'Netlify Login'
20+
env:
21+
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
22+
run: |
23+
npm i -g netlify-cli
24+
netlify login
25+
- name: Get installed Playwright version
26+
id: playwright-version
27+
run: echo "::set-output name=version::$(npm view @playwright/test version)"
28+
- uses: actions/cache@v3
29+
id: playwright-cache
30+
with:
31+
path: '~/.cache/ms-playwright'
32+
key: '${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}'
33+
restore-keys: |
34+
${{ runner.os }}-playwright-
35+
- name: Install Playwright Browsers
36+
if: steps.playwright-cache.outputs.cache-hit != 'true'
37+
run: npx playwright install --with-deps
38+
- name: Run Playwright tests
39+
run: npm run e2e:ci
40+
env:
41+
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
42+
- uses: actions/upload-artifact@v3
43+
if: always()
44+
with:
45+
name: playwright-report
46+
path: playwright-report/
47+
retention-days: 30
48+
649
test:
750
runs-on: ubuntu-latest
851
strategy:
@@ -16,7 +59,6 @@ jobs:
1659
node-version: '18.x'
1760
cache: 'npm'
1861
cache-dependency-path: '**/package-lock.json'
19-
2062
- name: 'Install dependencies'
2163
run: npm ci
2264
- name: 'Build'

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ dist/
44

55
# Local Netlify folder
66
.netlify
7+
/test-results/
8+
/playwright-report/
9+
/blob-report/
10+
/playwright/.cache/

package-lock.json

+103-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"build:debug": "tsc --sourceMap",
1919
"build:watch": "tsc --watch",
2020
"test": "vitest",
21-
"test:ci": "vitest run --reporter=default --retry=3"
21+
"test:ci": "vitest run --reporter=default --retry=3",
22+
"e2e": "playwright test",
23+
"e2e:ci": "playwright test"
2224
},
2325
"repository": {
2426
"type": "git",
@@ -41,8 +43,8 @@
4143
"@netlify/build": "^29.20.6",
4244
"@netlify/functions": "^2.0.1",
4345
"@vercel/nft": "^0.24.3",
44-
"fs-monkey": "^1.0.5",
4546
"fast-glob": "^3.3.2",
47+
"fs-monkey": "^1.0.5",
4648
"os": "^0.1.2",
4749
"outdent": "^0.8.0",
4850
"p-limit": "^4.0.0"
@@ -51,6 +53,8 @@
5153
"@netlify/eslint-config-node": "^7.0.1",
5254
"@netlify/serverless-functions-api": "^1.10.1",
5355
"@netlify/zip-it-and-ship-it": "^9.25.5",
56+
"@playwright/test": "^1.40.0",
57+
"@types/node": "^20.9.2",
5458
"@types/uuid": "^9.0.6",
5559
"cheerio": "^1.0.0-rc.12",
5660
"execa": "^8.0.1",

playwright.config.ts

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { defineConfig, devices } from '@playwright/test'
2+
3+
/**
4+
* See https://playwright.dev/docs/test-configuration.
5+
*/
6+
export default defineConfig({
7+
testDir: './tests/e2e',
8+
/* Run tests in files in parallel */
9+
fullyParallel: true,
10+
/* Fail the build on CI if you accidentally left test.only in the source code. */
11+
forbidOnly: !!process.env.CI,
12+
/* Retry on CI only */
13+
retries: process.env.CI ? 2 : 0,
14+
/* Opt out of parallel tests on CI. */
15+
workers: process.env.CI ? 1 : undefined,
16+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
17+
reporter: 'html',
18+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
19+
use: {
20+
/* Base URL to use in actions like `await page.goto('/')`. */
21+
baseURL: process.env.URL,
22+
23+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
24+
trace: 'on-first-retry',
25+
},
26+
27+
timeout: 10 * 60 * 1000,
28+
29+
/* Configure projects for major browsers */
30+
projects: [
31+
// {
32+
// name: 'setup',
33+
// testMatch: /global\.setup\.ts/,
34+
// },
35+
{
36+
name: 'chromium',
37+
// dependencies: ['setup'],
38+
use: { ...devices['Desktop Chrome'] },
39+
},
40+
],
41+
42+
/* Run your local dev server before starting the tests */
43+
// webServer: {
44+
// command: 'npm run start',
45+
// url: 'http://127.0.0.1:3000',
46+
// reuseExistingServer: !process.env.CI,
47+
// },
48+
})

tests/e2e/page-router.test.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { test, expect } from '@playwright/test'
2+
import { createE2EFixture } from '../utils/create-e2e-fixture.js'
3+
4+
let ctx: Awaited<ReturnType<typeof createE2EFixture>>
5+
6+
test.describe('page-router', () => {
7+
test.beforeAll(async () => {
8+
ctx = await createE2EFixture('page-router')
9+
})
10+
11+
test.afterAll(async () => {
12+
await ctx?.cleanup?.()
13+
})
14+
15+
// NOT working yet as blob storage upload ins not working with the CLI
16+
test.skip('Static revalidate works correctly', async ({ page }) => {
17+
const response1 = await page.goto(new URL('static/revalidate', ctx.url).href)
18+
const headers1 = response1?.headers() || {}
19+
expect(response1?.status()).toBe(200)
20+
expect(headers1['x-nextjs-cache']).toBe('HIT')
21+
expect(headers1['netlify-cdn-cache-control']).toBe('s-maxage=3, stale-while-revalidate')
22+
23+
const h1 = await page.textContent('h1')
24+
expect(h1).toBe('Show #71')
25+
26+
const date1 = await page.textContent('[data-testid="date-now"]')
27+
28+
// wait to have a stale page
29+
page.waitForTimeout(3_000)
30+
31+
const response2 = await page.goto(new URL('static/revalidate', ctx.url).href)
32+
const headers2 = response1?.headers() || {}
33+
expect(response2?.status()).toBe(200)
34+
expect(response1?.status()).toBe(200)
35+
expect(headers2['x-nextjs-cache']).toBe('MISS')
36+
37+
const date2 = await page.textContent('[data-testid="date-now"]')
38+
39+
expect(date1).not.toBe(date2)
40+
})
41+
})

tests/e2e/simple-app.test.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { test, expect } from '@playwright/test'
2+
import { createE2EFixture } from '../utils/create-e2e-fixture.js'
3+
4+
let ctx: Awaited<ReturnType<typeof createE2EFixture>>
5+
6+
test.describe('simple-next-app', () => {
7+
test.beforeAll(async () => {
8+
ctx = await createE2EFixture('simple-next-app')
9+
})
10+
11+
test.afterAll(async () => {
12+
await ctx?.cleanup?.()
13+
})
14+
15+
test('Renders the Home page correctly', async ({ page }) => {
16+
await page.goto(ctx.url)
17+
18+
await expect(page).toHaveTitle('Simple Next App')
19+
20+
const h1 = await page.locator('h1')
21+
await expect(h1).toHaveText('Home')
22+
})
23+
})

0 commit comments

Comments
 (0)