TaskSultan Docs tasksultan.com

Capabilities

Web

Drive a Chromium browser through Playwright on the run context, address elements by name through the Target Repository and let the runner handle tracing, screenshots and native dialogs.

The web capability is browser automation on Playwright. There is no separate ctx.web object. The surface is the Playwright objects the runner puts on the run context. The capability token is the declaration an automation makes when it uses them.

#The browser surface

Three members of RunContext are the browser:

  • ctx.page is the single Playwright Page an automation drives. It carries the baseURL, so ctx.page.goto('/orders') resolves against the automation's url.
  • ctx.context is the BrowserContext, created with a 1440 by 900 viewport and an en-US locale.
  • ctx.browser is the launched Browser.

The runner launches Chromium headless by default (options.headless ?? true). ctx.page gets a default timeout of 15 seconds and a default navigation timeout of 20 seconds before any automation code runs.

Tracing is on by default. The runner starts a Playwright trace at the beginning of the run and writes trace.zip beside the run summary. A failure captures a screenshot of the page into the run's screenshots folder without the automation asking for one.

#Addressing elements by name

An automation does not write a CSS selector. It resolves a named Target through the Target Repository. A target carries an ordered list of authored strategies with a reason on each one. When the first strategy stops matching, the resolver falls through to the next rather than failing the run.

import type { RunContext, Transaction } from '../framework';
import { useTarget } from '../targets';

async function submitOrder(ctx: RunContext, tx: Transaction): Promise<void> {
  await ctx.page.goto('/orders');
  const submit = await useTarget(ctx, 'orders.submit');
  await submit.locator.click();
}

A target strategy is a function of the page, such as (page: Page) => page.getByRole('button', { name: 'Submit Order' }), so it is a semantic locator rather than a recorded path. useTarget logs which priority matched, so the run log says whether the fallback was used and why.

#Native dialogs

Playwright's own default is to auto-dismiss an unhandled alert, confirm or prompt, which turns "the user never confirmed" into a green run. TaskSultan refuses instead. With no declared policy, a dialog fails the transaction as a BusinessException and records the dialog's kind and message. Declaring a policy makes the decision explicit:

import { defineAutomation } from '../framework';

export default defineAutomation({
  id: 'process-payments',
  displayName: 'Process payments',
  capabilities: ['web'],
  url: 'http://localhost:4300',
  dialogs: { on: 'accept', kinds: ['confirm'] },
  getTransaction: async () => null,
  processTransaction: async () => {},
});

on is accept, dismiss or refuse. An absent policy means refuse. Both accept and dismiss are recorded in the run log, so a run never carries out a confirmation the application never gave without saying so.

#Things that catch people out

Declare 'web' in the automation. It does not gate a facade the way the engine-backed capabilities do, so a missing declaration will not fail on its own, but the Orchestrator uses the token to place the job on a robot that can run a browser.

The page timeout is 15 seconds. A step that legitimately waits longer, such as a slow submit, should pass its own timeout to waitForResponse or waitFor rather than change the default for the whole run.

A web target is only as good as the strategies someone authored. Add a named strategy with a reason; do not add a selector a machine guessed, because it breaks the first time the page is rebuilt.