.agents/skills/playwright-e2e/SKILL.md
Deploy a Playwright sandbox (chromium or firefox) on Blaxel and run e2e tests against it. Use to validate that playwright hub images work end-to-end (browser connection, page navigation, DOM interaction) after changes.
npx skillsauth add blaxel-ai/sandbox playwright-e2eInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Deploy a Playwright sandbox to Blaxel dev, wait for it to be ready, connect via Playwright, and run browser tests.
Supported sandbox templates:
playwright-chromium -- Chromium browser, connect via chromium.connect()playwright-firefox -- Firefox browser, connect via firefox.connect()Both expose the same Playwright server on port 8081 with the same protocol. The only difference is the browser type used to connect.
bl CLI authenticated on the target workspace (bl login)node available locallyplaywright npm package installed locally (matching the server version)Determine which browser to test. Use SANDBOX_NAME=playwright-chromium or SANDBOX_NAME=playwright-firefox. If the user doesn't specify, default to playwright-chromium. If both need testing, run the steps below once per browser.
Use bl push to build and push the image without creating the sandbox resource:
bl push -y -t sandbox -d hub/$SANDBOX_NAME -n $SANDBOX_NAME
This builds the image from hub/$SANDBOX_NAME/Dockerfile and pushes it to the Blaxel registry.
Note: The CLI may report build timed out after 15 minutes for large images (~1.9 GB). If the logs show ✅ Build completed successfully before the timeout, the image was pushed successfully and you can proceed. The timeout is a CLI-side log monitoring limit, not a server-side failure.
Use bl apply to create the sandbox resource with the correct port declarations. Port 8081 (Playwright server) must be declared, otherwise only port 8080 (sandbox-api) is exposed and Playwright connections fail with 502.
bl apply -f - <<EOF
apiVersion: blaxel.ai/v1alpha1
kind: Sandbox
metadata:
name: $SANDBOX_NAME
spec:
runtime:
image: sandbox/$SANDBOX_NAME:latest
memory: 4096
ports:
- name: sandbox-api
target: 8080
protocol: HTTP
- name: playwright
target: 8081
protocol: HTTP
EOF
Poll until the sandbox status is DEPLOYED. Note: bl get sbx returns a JSON array, so access [0].
while true; do
STATUS=$(bl get sbx $SANDBOX_NAME -ojson 2>/dev/null | jq -r '.[0].status')
echo "Sandbox status: $STATUS"
if [ "$STATUS" = "DEPLOYED" ]; then
break
fi
sleep 5
done
SANDBOX_URL=$(bl get sbx $SANDBOX_NAME -ojson | jq -r '.[0].metadata.url')
The DEPLOYED status means the image is pushed, but the VM may still be cold-starting. Poll the Playwright server until it responds:
TOKEN=$(bl token)
while true; do
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $TOKEN" "$SANDBOX_URL/port/8081/json" 2>/dev/null)
echo "Playwright server HTTP status: $HTTP_STATUS"
if [ "$HTTP_STATUS" = "200" ]; then
break
fi
sleep 10
done
Connect with the token as a ?token= query parameter on the WebSocket URL.
Use the browser type matching the sandbox:
playwright-chromium --> chromium.connect()playwright-firefox --> firefox.connect()Write a Node.js script that:
wss://{SANDBOX_HOST}/port/8081/?token={TOKEN} using the appropriate browser typehttps://example.com)const { chromium } = require('playwright');
const browser = await chromium.connect(
`wss://${SANDBOX_HOST}/port/8081/?token=${TOKEN}`,
{ timeout: 15000 }
);
const page = await browser.newPage();
await page.goto('https://example.com');
const title = await page.title();
assert(title.includes('Example Domain'));
await page.close();
await browser.close();
const { firefox } = require('playwright');
const browser = await firefox.connect(
`wss://${SANDBOX_HOST}/port/8081/?token=${TOKEN}`,
{ timeout: 15000 }
);
const page = await browser.newPage();
await page.goto('https://example.com');
const title = await page.title();
assert(title.includes('Example Domain'));
await page.close();
await browser.close();
playwright package version MUST match the server version. The sandbox runs Playwright v1.58. If you get a 428 Precondition Required with a version mismatch error, install the correct version: npm install [email protected].browserType.connect(), NOT connectOverCDP(). The sandbox runs a Playwright server, not a raw CDP endpoint.chromium.connect() for playwright-chromium, firefox.connect() for playwright-firefox. Using the wrong browser type will fail.?token= query parameter on the WebSocket URL.bl apply spec.After tests pass, optionally delete the sandbox:
bl delete sbx $SANDBOX_NAME
bl token to refresh.bl apply spec. Check with bl get sbx $SANDBOX_NAME -ojson | jq '.[0].spec.runtime.ports'.bl logs sbx $SANDBOX_NAME for build errors.development
Regenerate the OpenAPI reference documentation after adding, modifying, or removing API endpoints in sandbox-api. Run this whenever handler signatures, route paths, or swag annotations change.
development
Run the sandbox-api integration tests against a live API instance. Use after making changes to sandbox-api to verify all endpoints still work correctly.
development
Run the full end-to-end test suite against a custom sandbox image deployed locally or on Blaxel. Use before merging significant changes to validate the complete sandbox-api binary, not just unit/integration tests.
development
Start the local sandbox-api development environment with hot-reload. Use when developing or testing changes to the sandbox-api Go code locally.