Browser workflows, same Glubean model
Glubean browser workflows are powered by Puppeteer. You keep the ecosystem and low-level control you already know, while Glubean adds workflow structure, assertions, traces, screenshots, and the same promotion path you already use for API workflows.
Why the browser surface exists
Browser automation should be the continuation of the same workflow, not a second system you adopt only because the path now touches a UI.
Why browser steps matter
Authentication redirects and session state live beyond raw HTTP calls.
Real user flows often depend on form state, navigation, and visible UI transitions.
Teams should not have to switch to a second testing model just because a workflow touches the browser.
What Glubean preserves
The same workflow model, assertions, traces, and CI path continue into browser steps.
You keep Puppeteer power and plugin compatibility instead of learning a closed browser abstraction.
Browser and API activity can still belong to one workflow story instead of two disconnected tools.
Keep Puppeteer power
You do not lose browser power to gain workflow structure. You keep Puppeteer, plugin support, and raw access. Glubean adds the missing layer on top.
// Modern Puppeteer (v21+ Locator API) + Jest
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto("http://localhost:3000/login");
await page.locator("#email").fill("user@test.com");
await page.locator("#password").fill("secret");
await Promise.all([
page.waitForNavigation({ waitUntil: "load" }),
page.locator('button[type="submit"]').click(),
]);
expect(page.url()).toContain("/dashboard");
const text = await page.$eval("h1", (el) => el.textContent);
expect(text).toBe("Welcome back");
} catch (err) {
await page.screenshot({ path: "fail.png", fullPage: true });
throw err;
} finally {
await browser.close();
}
// ✓ auto-wait (Locator) ✗ assertions ✗ traces ✗ metrics// @glubean/browser
import { browserTest } from "./base.ts";
export const login = browserTest("login", async ({ page }) => {
await page.goto("/login");
await page.type("#email", "user@test.com");
await page.type("#password", "secret");
await page.clickAndNavigate('button[type="submit"]');
await page.expectURL("/dashboard");
await page.expectText("h1", "Welcome back");
});
// ✓ auto-wait ✓ assertions ✓ traces ✓ metrics ✓ screenshots
// page.raw is the native Puppeteer Page — zero capability lossSame browser engine underneath. The difference is the workflow layer: assertions, lifecycle, traces, screenshots, and promotion path.
Plugin ecosystem
Stealth plugins, captcha helpers, custom launch behavior, puppeteer-extra. If the workflow needs browser-specific power, you should not have to give that up to stay inside Glubean.
configure.ts + base.ts
// tests/configure.ts
import { configure } from "@glubean/sdk";
import { browser } from "@glubean/browser";
import puppeteerExtra from "puppeteer-extra";
import StealthPlugin from "puppeteer-extra-plugin-stealth";
import RecaptchaPlugin from "puppeteer-extra-plugin-recaptcha";
puppeteerExtra.use(StealthPlugin());
puppeteerExtra.use(RecaptchaPlugin({ provider: { id: "2captcha", token: "TOKEN" } }));
export const { chrome } = configure({
plugins: {
chrome: browser({ launch: true, puppeteer: puppeteerExtra }),
},
});
// tests/base.ts — create a per-test page fixture
import { test } from "@glubean/sdk";
import { chrome } from "./configure.ts";
export const browserTest = test.extend({
page: async (ctx, use) => {
const pg = await chrome.newPage(ctx);
try {
await use(pg);
} finally {
await pg.close();
}
},
});Why this matters
Keep stealth, recaptcha, and other puppeteer-extra plugins.
Use raw Puppeteer APIs when the workflow needs lower-level control.
Add Glubean assertions, traces, screenshots, and lifecycle on top of that stack.
Browser steps sit in the same Glubean workflow model you already use for API verification.
You keep low-level control and the plugin ecosystem you already trust instead of starting over.
The browser flow can run locally, in CI, and later in Cloud without changing what the workflow is.
Full browser workflow
When part of the path happens in the browser, you still own one workflow story from authoring to CI to Cloud.
tests/login.test.ts
import { browserTest } from "./base.ts";
export const login = browserTest("login-flow", async ({ page, secrets }) => {
await page.goto("/login");
await page.type("#email", "user@test.com");
await page.type("#password", secrets.require("TEST_PASSWORD"));
await page.clickAndNavigate('button[type="submit"]');
await page.expectURL("/dashboard");
await page.expectText("h1", "Welcome back");
});
// traces ✓ metrics ✓ network logs ✓ console errors ✓ screenshots ✓What happens around it
Inline run
Click play in the editor and the browser flow executes alongside your API tests.
Assertions with retries
URL, text, and visibility assertions wait for the UI to settle instead of failing too early.
Trace and diff
Browser actions, timings, and failures stay inspectable and comparable across runs.
Screenshots on failure
Visual evidence is captured automatically when the flow breaks.
Debuggable like code
The browser flow is still real TypeScript, so the debugging experience stays familiar.
When to use what
If you need the deepest browser framework for cross-browser grids, complex drag-drop, canvas-heavy surfaces, or visual regression at full scale, use Playwright. Glubean browser is strongest when the goal is to keep API and browser workflows in one model, one trace system, and one promotion path.
Use Glubean browser for
auth flows, forms, CRUD paths, dashboard checks, and browser steps that belong inside the same workflow as your API verification.
Reach for Playwright for
full browser lab coverage, highly interactive UI systems, and the heaviest browser-only test workloads.
Start with the same workflow
Familiar to anyone who already knows Puppeteer — with the workflow structure, observability, and promotion path that were missing.
Also available on npm