@ricsam/quickjs-playwright
v0.2.20
Published
Playwright browser automation bridge for QuickJS
Maintainers
Readme
@ricsam/quickjs-playwright
Playwright browser automation bridge for QuickJS. Provides page object, locators, and expect matchers for browser testing from within the sandbox.
Note: This is a low-level package. For most use cases, use
@ricsam/quickjs-runtimewithcreateRuntime({ playwright: { page } })instead.
Installation
bun add @ricsam/quickjs-playwrightSetup
import { chromium } from "playwright";
import { setupPlaywright } from "@ricsam/quickjs-playwright";
const browser = await chromium.launch();
const page = await browser.newPage();
const handle = setupPlaywright(context, {
page,
baseUrl: "https://example.com",
timeout: 30000,
console: true, // Route browser console logs through console handler
onEvent: (event) => {
if (event.type === "browserConsoleLog") {
console.log(`[browser:${event.level}]`, ...event.args);
}
},
});
// Collected data
const data = handle.getBrowserConsoleLogs();
const requests = handle.getNetworkRequests();
const responses = handle.getNetworkResponses();
handle.clearCollected();
handle.dispose();
await browser.close();Injected Globals
page- Page object with navigation and locator methodsLocator- Element locator class with actions
Usage in QuickJS
// Navigation
await page.goto("/dashboard");
await page.reload();
const url = await page.url();
const title = await page.title();
// Waiting
await page.waitForSelector(".loaded");
await page.waitForTimeout(1000);
await page.waitForLoadState("networkidle");
// Locators
const button = page.locator("button.submit");
const heading = page.getByRole("heading", { name: "Welcome" });
const input = page.getByLabel("Email");
const link = page.getByText("Sign in");
const field = page.getByPlaceholder("Enter email");
const item = page.getByTestId("user-card");
// Locator actions
await button.click();
await input.fill("[email protected]");
await input.clear();
await button.hover();
await input.focus();
// Locator queries
const text = await heading.textContent();
const value = await input.inputValue();
const visible = await button.isVisible();
const enabled = await button.isEnabled();
const count = await page.locator("li").count();
// Chaining
await page.locator("ul").locator("li").nth(2).click();
// Request API
const response = await page.request.get("/api/users");
const data = await response.json();
await page.request.post("/api/users", {
data: { name: "John" },
headers: { "Content-Type": "application/json" },
});Playwright + Test Environment
When both test environment and playwright are set up, expect() is extended with locator matchers:
describe("Homepage", () => {
it("displays welcome message", async () => {
await page.goto("/");
await expect(page.getByRole("heading")).toBeVisible();
await expect(page.getByRole("heading")).toContainText("Welcome");
});
it("login form works", async () => {
await page.goto("/login");
await page.getByLabel("Email").fill("[email protected]");
await expect(page.getByLabel("Email")).toHaveValue("[email protected]");
await expect(page.getByRole("button", { name: "Submit" })).toBeEnabled();
});
});Locator Matchers
| Matcher | Description |
|---------|-------------|
| toBeVisible() | Assert element is visible |
| toContainText(text) | Assert element contains text |
| toHaveValue(value) | Assert input has value |
| toBeEnabled() | Assert element is enabled |
| toBeChecked() | Assert checkbox is checked |
All matchers support .not for negation: expect(locator).not.toBeVisible()
PlaywrightEvent Types
| Event Type | Description |
|------------|-------------|
| browserConsoleLog | Browser console message (level, args, timestamp) |
| networkRequest | Network request made (url, method, headers, timestamp) |
| networkResponse | Network response received (url, status, headers, timestamp) |
