Skip to main content

UI Testing with YAML

Proofarc UI tests are defined in simple YAML — no page objects, no framework boilerplate. The same YAML runs on both Selenium and Playwright for cross-engine browser compatibility testing.

Example Test

steps:
- action: NAVIGATE_TO
value: "{{baseUrl}}"
- action: CLEAR
selector: "#username"
- action: SEND_KEYS
selector: "#username"
value: "{{username}}"
- action: CLEAR
selector: "#password"
- action: SEND_KEYS
selector: "#password"
value: "{{password}}"
- action: CLICK
selector: "button[type=submit]"
- action: VALIDATE_TEXT
selector: "body"
expectedText: "Dashboard"
- action: TAKE_SCREENSHOT

Variables

Both {{variable}} and ${variable} syntax are supported. Variables are resolved from:

  1. Credentials — injected from environment default credential ({{username}}, {{password}})
  2. Target URL{{baseUrl}} is the target's configured URL
  3. Environment variables{{env.MY_VAR}}

Variable lookup is case-insensitive: {{userName}}, {{username}}, {{USERNAME}} all resolve the same.

Step Fields

FieldUsed byDescription
actionAllAction to perform (see table below)
selectorMostCSS selector for the target element
valueInput actionsData to type, select, or navigate to
expectedTextValidation actionsText to assert (uses contains match)
timeoutWait actionsSeconds to wait (default: 30)
attributeVALIDATE_ATTRIBUTEAttribute name to check
filenameTAKE_SCREENSHOTCustom screenshot filename

Supported Actions

ActionFieldsDescription
NAVIGATE_TOvalue (URL)Navigate to URL
NAVIGATE_BACKBrowser back button
NAVIGATE_FORWARDBrowser forward button
REFRESHReload the current page
SWITCH_FRAMEselector or valueSwitch context into an iframe (pass empty/default to switch back)
SWITCH_TABvalue (index)Switch to another browser tab

Interaction

ActionFieldsDescription
CLICKselectorClick element
DOUBLE_CLICKselectorDouble-click element
RIGHT_CLICKselectorRight-click (native context menu)
SEND_KEYSselector, valueType text into input field
CLEARselectorClear input field
SELECT_BY_TEXTselector, valueSelect dropdown option by visible text
SELECT_BY_VALUEselector, valueSelect dropdown option by value attribute
SELECT_BY_INDEXselector, valueSelect dropdown option by zero-based index
HOVERselectorHover over element
SCROLL_TO_ELEMENTselectorScroll element into view
SUBMITselector (form)Submit a form
FILL_FORMformData list of {selector, value}Fill multiple fields in one step

Validation

ActionFieldsMatch TypeDescription
VALIDATE_TEXTselector, expectedTextContainsVerify element contains text
VALIDATE_TITLEexpectedTextContainsVerify page title contains text
VALIDATE_URLexpectedTextContainsVerify current URL contains text
VALIDATE_VISIBLEselectorVerify element is visible
VALIDATE_ELEMENT_VISIBLEselectorAlias of VALIDATE_VISIBLE
VALIDATE_ELEMENT_EXISTSselectorVerify element exists in DOM
VALIDATE_ATTRIBUTEselector, attribute, expectedTextExactVerify attribute equals value

Wait

ActionFieldsDescription
WAIT_FOR_ELEMENTselector, value (seconds)Wait for element to appear
WAIT_FOR_VISIBLEselector, value (seconds)Wait for element to be visible
WAIT_FOR_CLICKABLEselector, value (seconds)Wait for element to be enabled/clickable
WAIT_FOR_TEXTselector, expectedText, value (seconds)Wait for text to appear

Read element state

The captured value lands in the step's output and is available for later assertions.

ActionFieldsDescription
GET_TEXTselectorRead element innerText
GET_ATTRIBUTEselector, attributeRead a specific attribute
GET_VALUEselectorRead the value of a form control

Utility

ActionFieldsDescription
TAKE_SCREENSHOTfilename (optional)Capture page screenshot
MAXIMIZE_WINDOWMaximize browser window
EXECUTE_JSvalue (or script)Execute JavaScript — single line, or multi-line with value: | (see "Embedding multi-line JavaScript" below)

No SLEEP action. Blind sleeps are anti-pattern. Use WAIT_FOR_ELEMENT / WAIT_FOR_VISIBLE / WAIT_FOR_CLICKABLE / WAIT_FOR_TEXT with a value (timeout in seconds) instead — they wait for a real condition rather than a fixed duration.

Cross-Engine Testing

The same YAML runs on two browser engines simultaneously:

  • Selenium WebDriver (via ui-test-agent)
  • Playwright (via playwright-agent) — Chromium + WebKit + Firefox

If a test passes on Selenium but fails on Playwright (WebKit), that's a browser compatibility bug — not a test bug. Proofarc detects and classifies these automatically.

To run a single suite on both engines in one call, pass drivers in the run request — see the UI Test Suites page.

Embedding multi-line JavaScript

Use YAML's literal block scalar (| after the field name) for multi-line code. Newlines and indentation are preserved verbatim, no escaping needed:

- action: EXECUTE_JS
value: |
const token = localStorage.getItem('token');
return fetch('/api/findings/' + 60 + '/status', {
method: 'PUT',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token},
body: JSON.stringify({status: 'TRIAGED'})
}).then(function(r) { return r.json(); });

Engine differences for EXECUTE_JS

The two engines treat the EXECUTE_JS script slightly differently:

EngineWraps script asTop-level returnAsync / Promises
Selenium WebDriverfunction() { ... }✅ legal❌ does not await; the Promise is returned as-is and the test moves on
Playwright(() => { ... })() (IIFE)✅ legalpage.evaluate awaits the returned Promise

For tests that need to await asynchronous work (e.g. multiple fetch calls), use .then() chains that return a Promise; pin driver: PLAYWRIGHT if the test must wait on async results. To assert on async outcomes from a later step in either engine, write a marker to document.title from inside the .then() and use VALIDATE_TITLE afterwards.

Strict-mode selector caveat

Playwright is strict by defaultlocator(".MuiDrawer-root, nav") throws if the selector matches multiple elements. Selenium silently picks the first. The agents normalise this where possible (Playwright VALIDATE_VISIBLE uses .first), but if a test assertion fails on Playwright with strict mode violation, narrow the selector to a single element.

Visual Element Picker

Don't know CSS selectors? Use the visual picker:

  1. Navigate to a page
  2. Take a screenshot
  3. Click on elements in the screenshot
  4. Proofarc extracts the selector automatically