@aphrody/bxc-test
v0.1.1
Published
Playwright-compatible browser/site test runner for Bun, backed by bxc's native in-process CDP layer. Zero-spawn, no Chromium bundling.
Downloads
189
Maintainers
Readme
@aphrody/bxc-test
Playwright-compatible browser/site test runner for Bun, backed by bxc's
native in-process CDP layer (src/cdp/**) and the bun:test runner. No
Chromium bundling, no Playwright dependency — zero-spawn in the static profile.
import { test, expect } from "@aphrody/bxc-test";
test("homepage renders", async ({ page }) => {
await page.goto("http://localhost:3000/");
await expect(page.getByRole("heading")).toHaveText("Welcome");
await expect(page.getByTestId("cart")).toHaveCount(1);
await expect(page.locator("#submit")).toBeEnabled();
});Run it with Bun's native runner:
bun test test/Why
@playwright/test spawns Chromium and speaks CDP over a WebSocket. bxc already
is a CDP engine: src/cdp/** answers CDP method calls in-process, and
src/api/browser.ts drives navigation + DOM queries with no external binary.
This package mirrors the @playwright/test author surface (test/expect/
page/locator/getBy*) on top of that engine, so site tests run entirely
inside Bun.
Surface
- Runner:
test,test.describe,describe,beforeEach/afterEach/beforeAll/afterAll,mock— re-exported frombun:test.test(name, async ({ page }) => …)injects a freshTestPage, closed automatically. - Page:
goto,setContent,title,content,url,locator,getByTestId,getByRole,getByText,getByLabel,getByPlaceholder,getByAltText,getByTitle. - Locator (
BxcLocator):click,fill,textContent,getAttribute,isVisible,count,waitFor,filter({ hasText }),first/last/nth. - Web-first
expect(locator)(auto-retrying):toBeVisible,toBeHidden,toHaveText,toContainText,toHaveCount,toHaveAttribute,toBeEnabled,toBeDisabled, and.not.expect(value)on non-locators falls through tobun:test. - Config:
defineConfig({ use: { baseURL, testIdAttribute, profile }, expect: { timeout } })— aplaywright.config.ts-shaped object consumed bycreateTest(config).
Compatibility & limits
bxc's default static profile has no JS engine and no layout, so a few things
are adapted or not-yet:
getByRoleuses a role→CSS heuristic + text filter, not a full ARIA tree.- "Visible" means attached and not hidden (
hidden/display:none/aria-hidden), not "non-zero box" — there is no layout instatic. toHaveScreenshot/ trace viewer / video need a rendering engine (use thefastLightpanda profile) and are roadmap, not stubbed.
Full matrix and design rationale: ../../docs/test-package-plan.md.
