Skip to content

Commit b45f583

Browse files
authored
Merge pull request #5 from topheman/feat/add-playwright
Add Playwright E2E Testing Infrastructure
2 parents 41c2b6a + 4b4dcfc commit b45f583

File tree

18 files changed

+572
-71
lines changed

18 files changed

+572
-71
lines changed

.github/workflows/web-host.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ jobs:
2222
run: npm ci
2323
- name: Build
2424
run: npm run web-host:build
25+
- name: Install Playwright
26+
run: npx playwright install --with-deps
27+
working-directory: ./packages/web-host
28+
- name: e2e tests (playwright)
29+
run: WAIT_FOR_SERVER_AT_URL=http://localhost:4173/webassembly-component-model-experiments/ npm run test:e2e:all:preview
30+
- uses: actions/upload-artifact@v4
31+
if: ${{ !cancelled() }}
32+
with:
33+
name: playwright-report
34+
path: ./packages/web-host/playwright-report/
35+
retention-days: 30
2536
- name: Cache build artifacts
2637
id: cache-build-www-host
2738
uses: actions/cache@v4

.vscode/extensions.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"bytecodealliance.wit-idl",
55
"skellock.just",
66
"biomejs.biome",
7-
"bradlc.vscode-tailwindcss"
7+
"bradlc.vscode-tailwindcss",
8+
"ms-playwright.playwright"
89
]
910
}

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ rustup target add wasm32-unknown-unknown wasm32-wasip1
163163
```
164164

165165
```bash
166+
# Install project dependencies (web part)
166167
npm install
168+
# Install Playwright browsers (e2e tests for web-host)
169+
npx playwright install
167170
```
168171

169172
### pluginlab (rust)
@@ -277,6 +280,27 @@ Will do the same as the dev command, small changes:
277280

278281
You can then run `npm run web-host:preview` to preview the build.
279282

283+
#### Test
284+
285+
The project is configured to run e2e tests on the `web-host` using [playwright](./packages/web-host/playwright.config.ts), the test files are in [`packages/web-host/tests`](./packages/web-host/tests).
286+
287+
To run the tests against your local dev server (launched with `npm run dev`)
288+
289+
- `npm run test:e2e:all`: will run all the tests in headless mode
290+
- `npm run test:e2e:ui`: will open the playwright ui to run the tests
291+
292+
To run the tests against a preview server (build with `npm run build` and launched with `npm run preview`):
293+
294+
- `npm run test:e2e:all:preview`: will run all the tests in headless mode
295+
- `npm run test:e2e:ui:preview`: will open the playwright ui to run the tests
296+
297+
Specific to github actions:
298+
299+
In [`.github/workflows/web-host.yml`](./.github/workflows/web-host.yml), after the build step, the tests are run against the preview server.
300+
301+
To be sure that the preview server is up and running before running the tests, we use the [`webServer.command` option](https://playwright.dev/docs/test-webserver) of [playwright.config.ts](./packages/web-host/playwright.config.ts) to run `WAIT_FOR_SERVER_AT_URL=http://localhost:4173/webassembly-component-model-experiments/ npm run test:e2e:all:preview`
302+
303+
280304
### plugins (TypeScript)
281305

282306
You can write plugins in rust in [`crates/plugin-*`](./crates), you can also write plugins in TypeScript in [`packages/plugin-*`](./packages), thanks to `jco componentize` (based on [componentize-js](https://github.com/bytecodealliance/componentize-js)).

package-lock.json

Lines changed: 64 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
"lint": "biome check .",
3030
"lint:fix": "biome check --write .",
3131
"format": "biome format --write .",
32+
"test:e2e:all": "npm run test:e2e:all --workspace=packages/web-host",
33+
"test:e2e:ui": "npm run test:e2e:ui --workspace=packages/web-host",
34+
"test:e2e:all:preview": "npm run test:e2e:all:preview --workspace=packages/web-host",
35+
"test:e2e:ui:preview": "npm run test:e2e:ui:preview --workspace=packages/web-host",
36+
"test:e2e:report": "npm run test:e2e:report --workspace=packages/web-host",
3237
"typecheck": "npm run typecheck --workspace=*",
3338
"web-host:typecheck": "npm run typecheck --workspace=packages/web-host",
3439
"web-host:build": "npm run build --workspace=packages/web-host",

packages/web-host/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,9 @@ dist-ssr
2626
# Project specific
2727
public/plugins/*.wasm
2828
src/wasm/generated
29+
30+
# Playwright
31+
/test-results/
32+
/playwright-report/
33+
/blob-report/
34+
/playwright/.cache/

packages/web-host/package.json

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,62 @@
11
{
2-
"name": "web-host",
3-
"private": true,
4-
"version": "0.0.0",
5-
"type": "module",
6-
"description": "Web host for Terminal REPL with plugin system (using WebAssembly Component Model)",
7-
"scripts": {
8-
"predev": "npm run prebuild",
9-
"predev:debug": "npm run wit-types && just build-plugins && just build-repl-logic-guest && npm run prepareWasmFiles:debug && npm run wasm:transpile",
10-
"dev": "vite --host",
11-
"dev:debug": "vite --host",
12-
"prebuild": "npm run wit-types && just build-plugins-release && just build-repl-logic-guest-release && npm run prepareWasmFiles:release && npm run wasm:transpile && npm run prepareVirtualFs",
13-
"build": "tsc -b && vite build",
14-
"preview": "vite preview --host",
15-
"lint": "biome check .",
16-
"lint:fix": "biome check --write .",
17-
"typecheck": "tsc --noEmit -p tsconfig.app.json",
18-
"prepareWasmFiles:release": "node --experimental-strip-types --no-warnings ./clis/prepareWasmFiles.ts --mode release",
19-
"prepareWasmFiles:debug": "node --experimental-strip-types --no-warnings ./clis/prepareWasmFiles.ts --mode debug",
20-
"prepareVirtualFs": "node --experimental-strip-types --no-warnings ./clis/prepareFilesystem.ts --path fixtures/filesystem --format ts > src/wasm/virtualFs.ts; biome format --write ./src/wasm/virtualFs.ts",
21-
"wasm:transpile:plugin-echo": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_echo.wasm -o ./src/wasm/generated/plugin_echo/transpiled",
22-
"wasm:transpile:plugin-weather": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_weather.wasm -o ./src/wasm/generated/plugin_weather/transpiled",
23-
"wasm:transpile:plugin-greet": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_greet.wasm -o ./src/wasm/generated/plugin_greet/transpiled",
24-
"wasm:transpile:plugin-ls": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_ls.wasm -o ./src/wasm/generated/plugin_ls/transpiled",
25-
"wasm:transpile:plugin-cat": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_cat.wasm -o ./src/wasm/generated/plugin_cat/transpiled",
26-
"wasm:transpile:repl-logic-guest": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/repl_logic_guest.wasm -o ./src/wasm/generated/repl_logic_guest/transpiled",
27-
"wasm:transpile": "npm run wasm:transpile:plugin-echo && npm run wasm:transpile:plugin-weather && npm run wasm:transpile:plugin-greet && npm run wasm:transpile:plugin-ls && npm run wasm:transpile:plugin-cat && npm run wasm:transpile:repl-logic-guest",
28-
"wit-types:host-api": "jco types --world-name host-api --out-dir ./src/types/generated ../../crates/pluginlab/wit",
29-
"wit-types:plugin-api": "jco types --world-name plugin-api --out-dir ./src/types/generated ../../crates/pluginlab/wit",
30-
"wit-types": "npm run wit-types:clean && npm run wit-types:host-api && npm run wit-types:plugin-api && biome format --write ./src/types/generated",
31-
"wit-types:clean": "rm -rf ./src/types/generated"
32-
},
33-
"dependencies": {
34-
"clsx": "^2.1.1",
35-
"lucide-react": "^0.525.0",
36-
"qrcode.react": "^4.2.0",
37-
"react": "^19.1.0",
38-
"react-dom": "^19.1.0",
39-
"tailwind-merge": "^3.3.1",
40-
"zustand": "^5.0.6"
41-
},
42-
"devDependencies": {
43-
"@bytecodealliance/jco": "^1.11.2",
44-
"@tailwindcss/vite": "^4.1.11",
45-
"@types/node": "^24.0.4",
46-
"@types/react": "^19.1.8",
47-
"@types/react-dom": "^19.1.6",
48-
"@vitejs/plugin-react": "^4.5.2",
49-
"commander": "^12.1.0",
50-
"globals": "^16.2.0",
51-
"tailwindcss": "^4.1.11",
52-
"typescript": "~5.8.3",
53-
"typescript-eslint": "^8.34.1",
54-
"vite": "^7.0.0"
55-
}
2+
"name": "web-host",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"description": "Web host for Terminal REPL with plugin system (using WebAssembly Component Model)",
7+
"scripts": {
8+
"predev": "npm run prebuild",
9+
"predev:debug": "npm run wit-types && just build-plugins && just build-repl-logic-guest && npm run prepareWasmFiles:debug && npm run wasm:transpile",
10+
"dev": "vite --host",
11+
"dev:debug": "vite --host",
12+
"prebuild": "npm run wit-types && just build-plugins-release && just build-repl-logic-guest-release && npm run prepareWasmFiles:release && npm run wasm:transpile && npm run prepareVirtualFs",
13+
"build": "tsc -b && vite build",
14+
"preview": "vite preview --host",
15+
"lint": "biome check .",
16+
"lint:fix": "biome check --write .",
17+
"typecheck": "tsc --noEmit -p tsconfig.app.json",
18+
"prepareWasmFiles:release": "node --experimental-strip-types --no-warnings ./clis/prepareWasmFiles.ts --mode release",
19+
"prepareWasmFiles:debug": "node --experimental-strip-types --no-warnings ./clis/prepareWasmFiles.ts --mode debug",
20+
"prepareVirtualFs": "node --experimental-strip-types --no-warnings ./clis/prepareFilesystem.ts --path fixtures/filesystem --format ts > src/wasm/virtualFs.ts; biome format --write ./src/wasm/virtualFs.ts",
21+
"test:e2e:all": "playwright test",
22+
"test:e2e:ui": "playwright test --ui",
23+
"test:e2e:all:preview": "BASE_URL=http://localhost:4173/webassembly-component-model-experiments npm run test:e2e:all",
24+
"test:e2e:ui:preview": "BASE_URL=http://localhost:4173/webassembly-component-model-experiments npm run test:e2e:ui",
25+
"test:e2e:report": "playwright show-report",
26+
"wasm:transpile:plugin-echo": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_echo.wasm -o ./src/wasm/generated/plugin_echo/transpiled",
27+
"wasm:transpile:plugin-weather": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_weather.wasm -o ./src/wasm/generated/plugin_weather/transpiled",
28+
"wasm:transpile:plugin-greet": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_greet.wasm -o ./src/wasm/generated/plugin_greet/transpiled",
29+
"wasm:transpile:plugin-ls": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_ls.wasm -o ./src/wasm/generated/plugin_ls/transpiled",
30+
"wasm:transpile:plugin-cat": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/plugin_cat.wasm -o ./src/wasm/generated/plugin_cat/transpiled",
31+
"wasm:transpile:repl-logic-guest": "jco transpile --no-nodejs-compat --no-namespaced-exports public/plugins/repl_logic_guest.wasm -o ./src/wasm/generated/repl_logic_guest/transpiled",
32+
"wasm:transpile": "npm run wasm:transpile:plugin-echo && npm run wasm:transpile:plugin-weather && npm run wasm:transpile:plugin-greet && npm run wasm:transpile:plugin-ls && npm run wasm:transpile:plugin-cat && npm run wasm:transpile:repl-logic-guest",
33+
"wit-types:host-api": "jco types --world-name host-api --out-dir ./src/types/generated ../../crates/pluginlab/wit",
34+
"wit-types:plugin-api": "jco types --world-name plugin-api --out-dir ./src/types/generated ../../crates/pluginlab/wit",
35+
"wit-types": "npm run wit-types:clean && npm run wit-types:host-api && npm run wit-types:plugin-api && biome format --write ./src/types/generated",
36+
"wit-types:clean": "rm -rf ./src/types/generated"
37+
},
38+
"dependencies": {
39+
"clsx": "^2.1.1",
40+
"lucide-react": "^0.525.0",
41+
"qrcode.react": "^4.2.0",
42+
"react": "^19.1.0",
43+
"react-dom": "^19.1.0",
44+
"tailwind-merge": "^3.3.1",
45+
"zustand": "^5.0.6"
46+
},
47+
"devDependencies": {
48+
"@bytecodealliance/jco": "^1.11.2",
49+
"@playwright/test": "^1.54.1",
50+
"@tailwindcss/vite": "^4.1.11",
51+
"@types/node": "^24.0.4",
52+
"@types/react": "^19.1.8",
53+
"@types/react-dom": "^19.1.6",
54+
"@vitejs/plugin-react": "^4.5.2",
55+
"commander": "^12.1.0",
56+
"globals": "^16.2.0",
57+
"tailwindcss": "^4.1.11",
58+
"typescript": "~5.8.3",
59+
"typescript-eslint": "^8.34.1",
60+
"vite": "^7.0.0"
61+
}
5662
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { defineConfig, devices } from "@playwright/test";
2+
3+
/**
4+
* Read environment variables from file.
5+
* https://github.com/motdotla/dotenv
6+
*/
7+
// import dotenv from 'dotenv';
8+
// import path from 'path';
9+
// dotenv.config({ path: path.resolve(__dirname, '.env') });
10+
11+
/**
12+
* See https://playwright.dev/docs/test-configuration.
13+
*/
14+
export default defineConfig({
15+
testDir: "./tests",
16+
/* Run tests in files in parallel */
17+
fullyParallel: true,
18+
/* Fail the build on CI if you accidentally left test.only in the source code. */
19+
forbidOnly: !!process.env.CI,
20+
/* Retry on CI only */
21+
retries: process.env.CI ? 2 : 0,
22+
/* Opt out of parallel tests on CI. */
23+
workers: process.env.CI ? 1 : undefined,
24+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
25+
reporter: "html",
26+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
27+
use: {
28+
/* Base URL to use in actions like `await page.goto('/')`. */
29+
baseURL:
30+
process.env.BASE_URL ||
31+
"http://localhost:5173/webassembly-component-model-experiments/",
32+
33+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
34+
trace: "on-first-retry",
35+
},
36+
...(process.env.WAIT_FOR_SERVER_AT_URL
37+
? {
38+
webServer: {
39+
command: "npm run preview -- --strictPort",
40+
url: process.env.WAIT_FOR_SERVER_AT_URL,
41+
reuseExistingServer: !process.env.CI,
42+
},
43+
}
44+
: {}),
45+
46+
/* Configure projects for major browsers */
47+
projects: [
48+
{
49+
name: "chromium",
50+
use: { ...devices["Desktop Chrome"] },
51+
},
52+
{
53+
name: "Mobile Chrome",
54+
use: { ...devices["Pixel 5"] },
55+
},
56+
57+
{
58+
name: "firefox",
59+
use: { ...devices["Desktop Firefox"] },
60+
},
61+
62+
{
63+
name: "webkit",
64+
use: { ...devices["Desktop Safari"] },
65+
},
66+
67+
/* Test against mobile viewports. */
68+
// {
69+
// name: 'Mobile Chrome',
70+
// use: { ...devices['Pixel 5'] },
71+
// },
72+
// {
73+
// name: 'Mobile Safari',
74+
// use: { ...devices['iPhone 12'] },
75+
// },
76+
77+
/* Test against branded browsers. */
78+
// {
79+
// name: 'Microsoft Edge',
80+
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
81+
// },
82+
// {
83+
// name: 'Google Chrome',
84+
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
85+
// },
86+
],
87+
88+
/* Run your local dev server before starting the tests */
89+
// webServer: {
90+
// command: 'npm run start',
91+
// url: 'http://localhost:3000',
92+
// reuseExistingServer: !process.env.CI,
93+
// },
94+
});

packages/web-host/src/components/Repl.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export function Repl({
9292
className="border border-gray-300 rounded-md p-2 w-full pr-10"
9393
onFocus={() => setInputFocus(true)}
9494
onBlur={() => setInputFocus(false)}
95+
placeholder="Type a command..."
9596
/>
9697
</div>
9798
<button

0 commit comments

Comments
 (0)