From 05039f511dfdd8e209b662a703b3bfee9d0749f5 Mon Sep 17 00:00:00 2001 From: Stephan Boyer Date: Mon, 27 Jul 2026 20:49:55 -0700 Subject: [PATCH] Run web integration tests in CI --- .gitignore | 1 + MAINTAINERS.md | 7 +- .../typescript_web/package-lock.json | 64 +++++++++++++++++++ integration_tests/typescript_web/package.json | 3 + .../typescript_web/playwright.config.ts | 13 ++++ .../typescript_web/tests/integration.spec.ts | 18 ++++++ toast.yml | 34 ++++++++++ 7 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 integration_tests/typescript_web/playwright.config.ts create mode 100644 integration_tests/typescript_web/tests/integration.spec.ts diff --git a/.gitignore b/.gitignore index 59ea0654..afaa70b1 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ /integration_tests/typescript_web/dist/ /integration_tests/typescript_web/generated/ /integration_tests/typescript_web/node_modules/ +/integration_tests/typescript_web/test-results/ /target/ diff --git a/MAINTAINERS.md b/MAINTAINERS.md index de845ee8..868adf00 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -30,8 +30,7 @@ The GitHub workflow will fail initially because the jobs which test the installe ### Release instructions -Releasing a new version is a three-step process: +Releasing a new version is a two-step process: -1. Run `(cd integration_tests/typescript_web && npm ci && npm run serve)` and open [http://localhost:5173/](http://localhost:5173/) in a browser to run the browser-based integration tests. This is the only test suite that doesn't run in the GitHub workflow. -2. Bump the version in `[file:Cargo.toml]`, run `cargo build` to update `[file:Cargo.lock]`, and update `[file:CHANGELOG.md]` with information about the new version. Ship those changes as a single commit. Once the GitHub workflow publishes the release, the installation script will begin installing it by default. -3. Create a pull request in the `Homebrew/homebrew-core` repository on GitHub to bump the version in [this file](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/t/typical.rb). +1. Bump the version in `[file:Cargo.toml]`, run `cargo build` to update `[file:Cargo.lock]`, and update `[file:CHANGELOG.md]` with information about the new version. Ship those changes as a single commit. Once the GitHub workflow publishes the release, the installation script will begin installing it by default. +2. Create a pull request in the `Homebrew/homebrew-core` repository on GitHub to bump the version in [this file](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/t/typical.rb). diff --git a/integration_tests/typescript_web/package-lock.json b/integration_tests/typescript_web/package-lock.json index 3806782d..428db8ae 100644 --- a/integration_tests/typescript_web/package-lock.json +++ b/integration_tests/typescript_web/package-lock.json @@ -12,6 +12,7 @@ "lodash": "4.18.1" }, "devDependencies": { + "@playwright/test": "^1.62.0", "@types/lodash": "4.17.24", "typescript": "^7.0.2", "vite-plus": "^0.2.6" @@ -877,6 +878,22 @@ "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@playwright/test": { + "version": "1.62.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.0.tgz", + "integrity": "sha512-9zOJ6ZQRAena31MpOH9VSzIz8Ou3YJ/wtY/eQm5T2uhfhG7/U3COrMS8xOtUrZrp9OgdmzEnIYODye3nY1VqzA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.62.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", @@ -2676,6 +2693,53 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.62.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.0.tgz", + "integrity": "sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.62.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.62.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.0.tgz", + "integrity": "sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/pngjs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", diff --git a/integration_tests/typescript_web/package.json b/integration_tests/typescript_web/package.json index 5953b62c..2b476872 100644 --- a/integration_tests/typescript_web/package.json +++ b/integration_tests/typescript_web/package.json @@ -6,6 +6,8 @@ "main": "npm run typical && tsc --project tsconfig.json && vp build", "lint": "npm run typical && vp check", "format": "vp fmt && typical format ../types/types.t", + "preview": "vp preview", + "test": "playwright test", "typical": "(cd ../.. && cargo run -- generate integration_tests/types/types.t --typescript-dir integration_tests/typescript_web/generated)", "serve": "npm run typical && tsc --project tsconfig.json && vp dev" }, @@ -14,6 +16,7 @@ "lodash": "4.18.1" }, "devDependencies": { + "@playwright/test": "^1.62.0", "@types/lodash": "4.17.24", "typescript": "^7.0.2", "vite-plus": "^0.2.6" diff --git a/integration_tests/typescript_web/playwright.config.ts b/integration_tests/typescript_web/playwright.config.ts new file mode 100644 index 00000000..722b8c7b --- /dev/null +++ b/integration_tests/typescript_web/playwright.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from '@playwright/test'; + +// Run the production build in the same way locally and in continuous integration. +export default defineConfig({ + use: { + baseURL: 'http://127.0.0.1:5173', + }, + webServer: { + command: 'npm run preview -- --host 127.0.0.1 --port 5173', + reuseExistingServer: false, + url: 'http://127.0.0.1:5173', + }, +}); diff --git a/integration_tests/typescript_web/tests/integration.spec.ts b/integration_tests/typescript_web/tests/integration.spec.ts new file mode 100644 index 00000000..40a7732e --- /dev/null +++ b/integration_tests/typescript_web/tests/integration.spec.ts @@ -0,0 +1,18 @@ +import { expect, test } from '@playwright/test'; + +// Verify that all integration scenarios finish successfully in a browser. +test('runs the browser integration tests', async ({ page }) => { + const pageErrors: Error[] = []; + + // Preserve uncaught browser errors so the test reports them after the page finishes. + page.on('pageerror', (error) => { + pageErrors.push(error); + }); + + // Load the test harness and wait for its success status. + await page.goto('/'); + await expect(page.locator('#app')).toHaveText('Integration tests passed.'); + + // Ensure no uncaught error was hidden by an otherwise successful status update. + expect(pageErrors).toEqual([]); +}); diff --git a/toast.yml b/toast.yml index 0d2f8158..d9460df3 100644 --- a/toast.yml +++ b/toast.yml @@ -160,6 +160,7 @@ tasks: - integration_tests/typescript_web/dist - integration_tests/typescript_web/generated - integration_tests/typescript_web/node_modules + - integration_tests/typescript_web/test-results - target/ build: @@ -170,6 +171,32 @@ tasks: # Build the project with Cargo. cargo-offline build + install_playwright_dependencies: + description: Install the system dependencies needed by Playwright. + dependencies: + - repository + user: root + command: | + # Load the Node.js installation belonging to the unprivileged build user. + set +x + export NVM_DIR=/home/user/.nvm + . "$NVM_DIR/nvm.sh" + set -x + + # Read the locked Playwright version and install Chromium's system dependencies. + PLAYWRIGHT_VERSION="$(node --print "require('./integration_tests/typescript_web/package-lock.json').packages['node_modules/@playwright/test'].version")" + npx --yes "playwright@$PLAYWRIGHT_VERSION" install-deps chromium + + install_playwright: + description: Install the browser used by the web integration tests. + dependencies: + - install_playwright_dependencies + command: | + # Install the locked JavaScript packages and Chromium browser binary. + cd integration_tests/typescript_web + npm ci + npx playwright install chromium + test_units: description: Run the unit test suite. dependencies: @@ -206,6 +233,7 @@ tasks: description: Run integration tests for the TypeScript code generator. dependencies: - build + - install_playwright command: | # Add Typical to `$PATH`. export PATH="$PWD/target/debug:$PATH" @@ -226,6 +254,12 @@ tasks: ) done + # Run the web integration test in a headless browser. + ( + cd integration_tests/typescript_web + npm test + ) + # Validate the data from the integration test. cmp test_data/omnifile /tmp/omnifile-typescript