Mirror the Hyperping browser-check runtime on your laptop. Same Playwright version, same package set, same timeout cap, so a script that passes locally runs the same way in production. Pick the runtime that matches your monitor and follow the install for that version.
Open the monitor in Hyperping and check the runtime card. Install Playwright at the version that matches it, otherwise locator behavior, fixture syntax, and reporter output can drift between local and production.
Node 24 with Playwright 1.59.1. Web Vitals are collected by the runtime, so they only appear once the check runs in Hyperping.
mkdir hyperping-browser-checks
cd hyperping-browser-checks
npm init -y
# Playwright versions used by the 2026.05 runtime
npm install playwright@1.59.1 @playwright/test@1.59.1
# Same package set as the runtime
npm install typescript@^5.6 expect@^29 uuid@^9.0.1 \
lodash@4.17.21 moment@^2.30.1 axios@^1.13.2 \
btoa@1.2.1 jsonwebtoken@^9.0.2 date-fns@^2.30.0 crypto-js@^4.2.0
# Download Chromium
npx playwright install chromiumNode 16 with Playwright 1.33. Use this only if the monitor is still on the 2023.04 runtime.
mkdir hyperping-browser-checks
cd hyperping-browser-checks
npm init -y
# Playwright versions used by the 2023.04 runtime
npm install playwright@1.33.0 @playwright/test@1.33.0
# Same package set as the runtime
npm install typescript@^5.0.4 expect@^27.5.1 uuid@^9.0.0 \
lodash@4.17.21 moment@^2.29.4 axios@^1.4.0 \
btoa@1.2.1 jsonwebtoken@^9.0.0 date-fns@^2.30.0 crypto-js@^4.1.1
# Download Chromium
npx playwright install chromiumMatch the run cap and the workers count Hyperping uses. The 2-minute global timeout is the most common gotcha, scripts that pass locally with no cap will fail in production when they sneak past 120 seconds.
// playwright.config.js
const config = {
globalTimeout: 120 * 1000, // match Hyperping's 2-minute run cap
workers: 1,
expect: { timeout: 30 * 1000 },
projects: [
{
name: 'chromium',
use: {
viewport: { width: 1280, height: 720 },
deviceScaleFactor: 1,
defaultBrowserType: 'chromium',
},
},
],
};
export default config;Drop a script under tests/ and run it. Playwright auto-detects .spec.ts and .spec.js files in that directory.
// tests/example.spec.ts
import { test, expect } from '@playwright/test';
test('homepage renders', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example Domain/);
await expect(page.locator('h1')).toContainText('Example Domain');
});Hyperping runs scripts headless. Locally you'll usually want a visible browser while you're authoring, so you can see exactly what the script does.
npx playwright test --headedFor step-by-step debugging, open the Playwright Inspector:
npx playwright test --debugAfter a run, the HTML report shows traces, screenshots, and the step tree:
npx playwright show-reportHyperping injects environment variables at run time and exposes them as process.env.NAME. Mirror that locally with a .env file or shell exports so the same script works in both places.
# .env
EMAIL=test@example.com
PASSWORD=changeme
API_TOKEN=...
BASE_URL=https://staging.your-app.comLodash, moment, axios, date-fns, and the other libraries that ship with the runtime are all available in your script. Importing them locally with the same versions keeps the behavior identical.
import { test, expect } from '@playwright/test';
import axios from 'axios';
test('cart roundtrip', async ({ page }) => {
test.setTimeout(120_000);
await page.goto(process.env.BASE_URL);
await page.click('[data-testid="add-to-cart"]');
await expect(page.locator('.cart-count')).toHaveText('1');
// Cross-check via the API
const { data } = await axios.get(`${process.env.BASE_URL}/api/cart`, {
headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
});
expect(data.items).toHaveLength(1);
});playwright1.59.1@playwright/test1.59.1typescript^5.6expect^29uuid^9.0.1lodash4.17.21moment^2.30.1axios^1.13.2btoa1.2.1jsonwebtoken^9.0.2date-fns^2.30.0crypto-js^4.2.0playwright^1.33.0@playwright/test1.33typescript^5.0.4expect^27.5.1uuid^9.0.0lodash4.17.21moment^2.29.4axios^1.4.0btoa1.2.1jsonwebtoken^9.0.0date-fns^2.30.0crypto-js^4.1.1process.env.NAME reference under Environment variables in the settings panel.Stable selectorsrole / data-testidgetByRole and getByTestId instead of CSS classes. Stylesheet rewrites won't break them.Auto-waiting assertionsexpect()await expect(locator).toBeVisible() retries on its own. Most waitForTimeout calls are unnecessary and add flake.Stay under 2 minutesrun capSecrets in env varsprocess.envLog the values you watchconsole.logconsole.log for latency, counts, or IDs lands in the run logs and makes post-mortem analysis easier.