Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.qawolf.com/llms.txt

Use this file to discover all available pages before exploring further.

@qawolf/flows/web defines web flows and optional explicit launch behavior.

Primary Exports

  • flow(...)
  • launch(...)
  • expect
  • isAnonymous(...)
  • isPersistent(...)
  • isElectron(...)
  • testContextDependencies
It also exports web-specific target, launch, callback context, and flow definition types. Example:
import { expect, flow } from "@qawolf/flows/web";

export default flow(
  "Open homepage",
  { target: "Web - Chrome", launch: true },
  async ({ page, test }) => {
    await test("open homepage", async () => {
      await page.goto("https://example.com");
      await expect(page).toBeDefined();
    });
  },
);

Target Model

Web flows accept web targets only. Use the CLI entry point for Basic.
type WebFlowTargetInput =
  | WebFlowTarget
  | {
      target: WebFlowTarget;
      launch?: false | undefined;
    }
  | {
      target: WebBrowserFlowTarget;
      launch: true | BrowserLaunchOptions;
    }
  | {
      target: WebElectronFlowTarget;
      launch: ElectronFlowLaunchOptions;
    };
Examples:
import { flow, isElectron, isPersistent, launch } from "@qawolf/flows/web";

export const explicitLaunchFlow = flow("Open later", "Web - Chrome", async () => {
  const launchResult = await launch();
  if (isElectron(launchResult)) throw new Error("Expected browser launch");

  const page =
    isPersistent(launchResult)
      ? launchResult.page
      : await launchResult.context.newPage();

  await page.goto("https://example.com");
});

export const launchedFlow = flow(
  "Open immediately",
  { target: "Web - Chrome", launch: true },
  async ({ page, test }) => {
    await test("open page", async () => {
      await page.goto("https://example.com");
    });
  },
);

Launch Shapes

Browser launch accepts the generated Playwright browser and context launch options, excluding Playwright’s raw persistentContext and userDataDir fields. QA Wolf adds browserContext, reintroduces userDataDir for persistent launches, and maps those options back to the underlying Playwright shape.
type BrowserLaunchOptions = {
  kind?: "browser";
  browser?: "chrome" | "chromium" | "firefox" | "msedge" | "webkit";
  browserContext?: "incognito" | "persistent";
  userDataDir?: string;

  // Generated Playwright browser and context options are also accepted,
  // except for Playwright's raw persistentContext and userDataDir fields.
  headless?: boolean;
  permissions?: string[];
  geolocation?: {
    latitude: number;
    longitude: number;
    accuracy?: number;
  };
  polyfills?: {
    intlListFormat?: boolean;
  };
  // ...plus other generated browser/context options.
};

type LaunchOptions =
  | BrowserLaunchOptions
  | {
      kind: "electron";
      executablePath: string;
    };

type ElectronFlowLaunchOptions = {
  executablePath: string;
};

type LaunchResult =
  | AnonymousLaunchResult
  | PersistentLaunchResult
  | ElectronLaunchResult;
QA Wolf maps browserContext: "persistent" to Playwright’s persistent context mode. Pass userDataDir with browserContext: "persistent" when a profile directory should be reused. Browser example:
import { flow, launch } from "@qawolf/flows/web";

export default flow(
  "Open with persistent profile",
  "Web - Chrome",
  async () => {
    const { page } = await launch({
      browserContext: "persistent",
      userDataDir: "/tmp/qawolf-profile",
    });

    await page.goto("https://example.com");
  },
);
Electron declarative launch example:
import { flow } from "@qawolf/flows/web";

export default flow(
  "Open Electron app",
  {
    target: "Electron",
    launch: {
      executablePath: "/Applications/MyApp.app/Contents/MacOS/MyApp",
    },
  },
  async ({ page, test }) => {
    await test("open app", async () => {
      await page.goto("about:blank");
    });
  },
);
Explicit launch(...) calls are not target-typed. Include kind: "electron" and use firstWindowPage from the result:
import { flow, launch } from "@qawolf/flows/web";

export default flow("Open Electron app", "Web - Chrome", async () => {
  const { firstWindowPage } = await launch({
    kind: "electron",
    executablePath: "/Applications/MyApp.app/Contents/MacOS/MyApp",
  });

  await firstWindowPage.getByRole("button", { name: "Sign in" }).click();
});
Static launch options infer a narrow return type when they determine the result shape:
  • launch({ browserContext: "persistent" }) returns PersistentLaunchResult
  • launch({ browserContext: "incognito" }) returns AnonymousLaunchResult
  • launch({ kind: "electron", executablePath }) returns ElectronLaunchResult
  • launch() returns the full LaunchResult union because startup depends on the active flow target
Use isAnonymous(...), isPersistent(...), and isElectron(...) to narrow dynamic results before reading shape-specific fields.

Flow Callback Context

All web flow callbacks receive:
  • inputs
  • setOutput(...)
  • test(...)
Launch-enabled browser flows also receive:
  • page
  • context
  • optional browser
Electron launch-enabled flows receive the first Electron window as page.
test(...) can be omitted for simple flows where grouping steps into named sub-steps doesn’t add value. For most flows, wrapping steps in test(...) is recommended — the label appears in your results and makes failures easier to locate.

testContextDependencies

testContextDependencies is exported for runner and tooling integration. Flow authors should usually use the public callback parameters above instead of depending on the raw runner dependency list.

Defaults

  • default kind is browser launch
  • default browserContext is "incognito"
  • default browser comes from the flow target
  • GPU launch behavior is derived from the flow target
  • Electron declarative launch requires target: "Electron" and executablePath
Example:
import { flow, isElectron, isPersistent, launch } from "@qawolf/flows/web";

export default flow(
  "Use target browser defaults",
  "Web - Firefox",
  async () => {
    const launchResult = await launch();
    if (isElectron(launchResult))
      throw new Error("Expected browser launch");

    const page =
      isPersistent(launchResult)
        ? launchResult.page
        : await launchResult.context.newPage();

    await page.goto("https://example.com");
  },
);
Last modified on May 6, 2026