-
Notifications
You must be signed in to change notification settings - Fork 663
Playwright Browser Server #5424
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
Merged
+2,792
−2
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
c582891
playwright browser server
bmiddha 07c28ed
redo the vscode extension icon
TheLarkInn 5e379bd
always deny launch options and prompt for adding each time
TheLarkInn 5b2dcb0
Refactor launch options prompt handling to always auto-approve browse…
TheLarkInn 5d2efd5
Add configure allowlist from modal and remove dupe cancel
TheLarkInn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| { | ||
| "servers": { | ||
| "playwright": { | ||
| "type": "stdio", | ||
| "command": "node", | ||
| "args": [ | ||
| "${workspaceFolder}/apps/playwright-browser-tunnel/lib/PlaywrightMcpBrowserTunnelClientCommandLine.js" | ||
| ] | ||
| } | ||
| }, | ||
| "inputs": [] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
|
|
||
| # @rushstack/playwright-browser-tunnel | ||
|
|
||
| Run a Playwright browser server in one environment and drive it from another environment by forwarding Playwright’s WebSocket traffic through a tunnel. | ||
|
|
||
| This package is intended for remote development / CI scenarios (for example: Codespaces, devcontainers, or a separate “browser host” machine) where you want tests to run “here” but the actual browser process to run “there”. | ||
|
|
||
| ## Relationship to the Playwright on Codespaces VS Code extension | ||
|
|
||
| This package is the core tunneling/runtime layer used by the **Playwright on Codespaces** VS Code extension (located at [vscode-extensions/playwright-on-codespaces-vscode-extension](../../vscode-extensions/playwright-on-codespaces-vscode-extension)). | ||
|
|
||
| In a typical Codespaces workflow: | ||
|
|
||
| - Your **tests** run inside the Codespace and call `tunneledBrowserConnection()`. | ||
| - `tunneledBrowserConnection()` starts a WebSocket server (by default on port `3000`) that a browser host can attach to. | ||
| - The VS Code extension runs on the **UI side** and starts a `PlaywrightTunnel` which connects to `ws://127.0.0.1:3000`. | ||
| - In Codespaces, this works when port `3000` is forwarded to your local machine (VS Code port forwarding makes the remote port reachable as `localhost:3000`). | ||
| - Once connected, the extension hosts the actual Playwright browser process locally, while your tests continue to run remotely. | ||
|
|
||
| The extension provides a UI wrapper around this library (start/stop commands, status bar state, and logs), while `@rushstack/playwright-browser-tunnel` provides the underlying protocol forwarding and browser lifecycle management. | ||
|
|
||
| ### Detecting whether the VS Code extension is present | ||
|
|
||
| Some remote test fixtures want to detect whether the **Playwright on Codespaces** extension is installed/active (for example, to skip local-browser-only scenarios when the extension isn’t available). | ||
|
|
||
| The extension writes a marker file named `.playwright-codespaces-extension-installed.txt` into the remote environment’s `os.tmpdir()` using VS Code’s remote filesystem APIs. | ||
|
|
||
| On the remote side, `isExtensionInstalledAsync()` checks for that marker file and returns `true` if it exists: | ||
|
|
||
| ```ts | ||
| import { isExtensionInstalledAsync } from '@rushstack/playwright-browser-tunnel'; | ||
|
|
||
| if (!(await isExtensionInstalledAsync())) { | ||
| throw new Error('Playwright on Codespaces extension is not installed/active in this environment'); | ||
| } | ||
| ``` | ||
|
|
||
|
|
||
| ## Requirements | ||
|
|
||
| - Node.js `>= 20` (see `engines` in `package.json`) | ||
| - A compatible Playwright version (this package is built/tested with Playwright `1.56.x`) | ||
|
|
||
| ## Exports | ||
|
|
||
| From [src/index.ts](src/index.ts): | ||
|
|
||
| - `PlaywrightTunnel` (class) | ||
| - `IPlaywrightTunnelOptions` (type) | ||
| - `TunnelStatus` (type) | ||
| - `BrowserNames` (type) | ||
| - `tunneledBrowserConnection()` (function) | ||
| - `tunneledBrowser()` (function) | ||
| - `IDisposableTunneledBrowserConnection` (type) | ||
| - `isExtensionInstalledAsync()` (function) | ||
|
|
||
| ## Usage | ||
|
|
||
| There are two pieces: | ||
|
|
||
| 1) **Browser host**: run a `PlaywrightTunnel` to launch the real browser server and forward messages. | ||
| 2) **Test runner**: create a local endpoint via `tunneledBrowserConnection()` that your Playwright client can connect to (it forwards to the browser host). | ||
|
|
||
| ### 1) Browser host: run the tunnel | ||
|
|
||
| Use `PlaywrightTunnel` in the environment where you want the browser process to run. | ||
|
|
||
| ```ts | ||
| import { ConsoleTerminalProvider, Terminal, TerminalProviderSeverity } from '@rushstack/terminal'; | ||
| import { PlaywrightTunnel } from '@rushstack/playwright-browser-tunnel'; | ||
| import path from 'node:path'; | ||
| import os from 'node:os'; | ||
|
|
||
| const terminalProvider = new ConsoleTerminalProvider(); | ||
| const terminal = new Terminal(terminalProvider); | ||
|
|
||
| const tunnel = new PlaywrightTunnel({ | ||
| mode: 'wait-for-incoming-connection', | ||
| listenPort: 3000, | ||
| tmpPath: path.join(os.tmpdir(), 'playwright-browser-tunnel'), | ||
| terminal, | ||
| onStatusChange: (status) => terminal.writeLine(`status: ${status}`) | ||
| }); | ||
|
|
||
| await tunnel.startAsync({ keepRunning: true }); | ||
| ``` | ||
|
|
||
| Notes: | ||
|
|
||
| - `mode: 'wait-for-incoming-connection'` starts a WebSocket server and waits for the other side to connect. | ||
| - `mode: 'poll-connection'` repeatedly attempts to connect to a WebSocket endpoint you provide (`wsEndpoint`). | ||
| - `tmpPath` is used as a working directory to install the requested `playwright-core` version and run its CLI. | ||
|
|
||
| ### 2) Test runner: create a local endpoint to connect() | ||
|
|
||
| Use `tunneledBrowserConnection()` in the environment where your tests run. | ||
|
|
||
| It starts: | ||
|
|
||
| - a **remote** WebSocket server (port `3000`) that the browser host connects to | ||
| - a **local** WebSocket endpoint (random port) that your Playwright client connects to | ||
|
|
||
| ```ts | ||
| import { tunneledBrowserConnection } from '@rushstack/playwright-browser-tunnel'; | ||
| import playwright from 'playwright-core'; | ||
|
|
||
| using connection = await tunneledBrowserConnection(); | ||
|
|
||
| // Build the connect URL with query parameters consumed by the local proxy. | ||
| const url = new URL(connection.remoteEndpoint); | ||
| url.searchParams.set('browser', 'chromium'); | ||
| url.searchParams.set('launchOptions', JSON.stringify({ headless: true })); | ||
|
|
||
| const browser = await playwright.chromium.connect(url.toString()); | ||
| // ...run tests... | ||
| await browser.close(); | ||
| ``` | ||
|
|
||
| ## Development | ||
|
|
||
| - Build: `rush build --to playwright-browser-tunnel` | ||
| - Demo script (if configured): `rushx demo` | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| - If the tunnel is stuck in `waiting-for-connection`, ensure the counterpart process is reachable and ports are forwarded correctly. | ||
| - If browser installation is slow/repeated, ensure `tmpPath` is stable and writable for the host environment. | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { | ||
| "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", | ||
|
|
||
| "mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts", | ||
|
|
||
| "apiReport": { | ||
| "enabled": true, | ||
| "reportFolder": "../../../common/reviews/api" | ||
| }, | ||
|
|
||
| "docModel": { | ||
| "enabled": true, | ||
| "apiJsonFilePath": "../../../common/temp/api/<unscopedPackageName>.api.json" | ||
| }, | ||
|
|
||
| "dtsRollup": { | ||
| "enabled": true | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| // The "rig.json" file directs tools to look for their config files in an external package. | ||
| // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package | ||
| "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", | ||
|
|
||
| "rigPackageName": "local-node-rig" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. | ||
| // See LICENSE in the project root for license information. | ||
|
|
||
| const nodeTrustedToolProfile = require('local-node-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); | ||
| const friendlyLocalsMixin = require('local-node-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); | ||
|
|
||
| module.exports = [ | ||
| ...nodeTrustedToolProfile, | ||
| ...friendlyLocalsMixin, | ||
| { | ||
| files: ['**/*.ts', '**/*.tsx'], | ||
| languageOptions: { | ||
| parserOptions: { | ||
| tsconfigRootDir: __dirname | ||
| } | ||
| } | ||
| } | ||
| ]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| { | ||
| "name": "@rushstack/playwright-browser-tunnel", | ||
| "version": "0.0.1", | ||
| "description": "Run a remote Playwright Browser Tunnel. Useful in remote development environments.", | ||
| "license": "MIT", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/microsoft/rushstack.git", | ||
| "directory": "apps/playwright-browser-tunnel" | ||
| }, | ||
| "main": "lib/index.js", | ||
| "engines": { | ||
| "node": ">=20.0.0" | ||
| }, | ||
| "engineStrict": true, | ||
| "homepage": "https://rushstack.io", | ||
| "scripts": { | ||
| "build": "heft build --clean", | ||
| "_phase:build": "heft run --only build -- --clean", | ||
| "demo": "playwright test --config=playwright.config.ts" | ||
| }, | ||
| "dependencies": { | ||
| "@rushstack/node-core-library": "workspace:*", | ||
| "@rushstack/terminal": "workspace:*", | ||
| "@rushstack/ts-command-line": "workspace:*", | ||
| "string-argv": "~0.3.1", | ||
| "semver": "~7.5.4", | ||
| "ws": "~8.14.1", | ||
| "playwright": "1.56.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@rushstack/heft": "workspace:*", | ||
| "eslint": "~9.37.0", | ||
| "local-node-rig": "workspace:*", | ||
| "@types/semver": "7.5.0", | ||
| "@types/ws": "8.5.5", | ||
| "playwright-core": "~1.56.1", | ||
| "@playwright/test": "~1.56.1", | ||
| "@types/node": "20.17.19" | ||
| }, | ||
| "peerDependencies": { | ||
| "playwright-core": "~1.56.1" | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { defineConfig, devices } from '@playwright/test'; | ||
|
|
||
| export default defineConfig({ | ||
| testDir: './tests', | ||
| /* Run tests in files in parallel */ | ||
| fullyParallel: true, | ||
| /* Retry on CI only */ | ||
| retries: 0, | ||
| /* Opt out of parallel tests on CI. */ | ||
| workers: 1, | ||
| /* 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://localhost:3000', | ||
|
|
||
| /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ | ||
| trace: 'on' | ||
| }, | ||
|
|
||
| /* Configure projects for major browsers */ | ||
| projects: [ | ||
| { | ||
| name: 'chromium', | ||
| use: { ...devices['Desktop Chrome'] } | ||
| }, | ||
| { | ||
| name: 'firefox', | ||
| use: { ...devices['Desktop Firefox'] } | ||
| }, | ||
| { | ||
| name: 'webkit', | ||
| use: { ...devices['Desktop Safari'] } | ||
| }, | ||
| { | ||
| name: 'Google Chrome', | ||
| use: { ...devices['Desktop Chrome'], channel: 'chrome' } // or 'chrome-beta' | ||
| }, | ||
| { | ||
| name: 'Microsoft Edge', | ||
| use: { ...devices['Desktop Edge'], channel: 'msedge' } // or "msedge-beta" or 'msedge-dev' | ||
| } | ||
| ] | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.