Skip to main content

Praman 1.2: Playwright 1.59, TypeScript 6, Unified ui5= Selector Engine, and Interactive Inspector

· 8 min read
Maheshwar Kanitkar
Creator of Praman

We are releasing Praman 1.2.0 to the latest tag on npm today. This is the largest functional update since the v1.0 launch, bringing first-class support for Playwright 1.59, TypeScript 6.x, a completely rewritten ui5= selector engine, a live interactive inspector, and a battery of quality-of-life improvements for teams building SAP UI5 test automation at scale.

What changed since v1.1.2

Sixty-six commits landed between v1.1.2 and v1.2.0, touching the selector engine, CLI tooling, configuration system, error messages, CI pipeline, and documentation. Here is everything that matters.


🎭 Playwright 1.59 — Tested, Validated, Flagged

Praman now tracks Playwright 1.59 as its peer baseline, and the CI matrix now runs both @playwright/test@stable and @playwright/test@next (canary) on every push. This means Praman validates against upcoming Playwright changes before they ship, giving teams early warning of regressions.

Playwright 1.59 introduced several powerful new APIs. Praman exposes all of them behind opt-in feature flags so your existing tests are unaffected:

FlagAPIWhat it does
playwrightFeatures.screencastpage.screencastProgrammatic video — start/stop recording, overlays, real-time frames
playwrightFeatures.ariaSnapshotDepthlocator.ariaSnapshot({ depth })Scoped accessibility tree snapshots — ideal for deep SAP component hierarchies
playwrightFeatures.setStorageStatebrowserContext.setStorageState()Replace auth state in-place without spawning a new context
playwrightFeatures.locatorNormalizelocator.normalize()Auto-convert ad-hoc selectors to aria-role / test-id best practices
playwrightFeatures.urlPatternMatcherURL Pattern API in toHaveURLModern URL Pattern matching instead of RegExp

Enable any flag in playwright.config.ts:

import { defineConfig } from 'playwright-praman';

export default defineConfig({
use: {
pramanConfig: {
playwrightFeatures: { screencast: true },
},
},
});

🔷 TypeScript 6.x — Full Support

Praman is now compiled and shipped with TypeScript 6.0.2. Every exported type, generic, and conditional type has been audited against TS 6 semantics. The CI matrix runs a TS compatibility job that builds the package against both TS 5.9 and TS 6.0.

If you are still on TypeScript 5.x, nothing changes. If you have migrated to TS 6.0, all Praman APIs now give you accurate inference, narrowing, and editor completions under the stricter TS 6 rules.


🔍 A New ui5= Selector Engine

The most architecturally significant change in v1.2 is the complete rewrite of the UI5 selector engine.

The old approach: three separate parsers

v1.1 shipped three distinct engines — a CSS engine, an XPath engine, and a legacy ui5-selector-engine. They had overlapping responsibilities, inconsistent error messages, and subtle differences in how they handled array properties or negative positions.

The new approach: one engine, two syntaxes

v1.2 ships a unified engine powered by fontoxpath (fully conformant XPath 3.1) and css-selector-parser. The CSS-style selectors you already write (sap.m.Button[text=Save]) are parsed to an AST, converted to XPath 3.1, and evaluated against an in-memory XML DOM that mirrors the live UI5 control tree of the page.

This is the same approach used by playwright-ui5 — proven in production SAP environments.

New selectors you can use today

// :labeled() — find a control by the sap.m.Label that points to it
page.locator("ui5=sap.m.Input:labeled('Vendor Number')");

// :not() — exclude controls
page.locator('ui5=sap.m.Button:not([type=Back])');

// Descendant combinator — any Button inside a Panel
page.locator('ui5=sap.m.Panel sap.m.Button[text=Save]');

// Child combinator — direct children only
page.locator('ui5=sap.m.Panel > sap.m.Button');

// Adjacent sibling — Input immediately after a Label
page.locator('ui5=sap.m.Label + sap.m.Input');

// Positional
page.locator('ui5=sap.m.ColumnListItem:nth-child(2)');
page.locator('ui5=sap.m.ColumnListItem:first-child');
page.locator('ui5=sap.m.ColumnListItem:last-child');

Migration

If your tests use the enableXpathEngine config option, remove it. The unified engine handles both CSS-style and XPath selectors — no per-engine configuration is needed. All other selectors continue to work unchanged.


🔬 npx praman inspect — Find Controls Without Guessing

The most-requested developer experience improvement: a live interactive inspector that lets you click any element in a running SAP app and instantly see the UI5 control metadata and copy-paste-ready selectors.

# Point it at your SAP Fiori Launchpad
npx praman inspect https://my-sap.example.com/sap/bc/ui5_ui5/...

# Pass a Playwright storageState file to authenticate
npx praman inspect https://my-sap.example.com --auth .auth/user.json

Click any element in the headed browser and the terminal prints:

━━━ Clicked: sap.m.Button ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ID: __button0--orderCreateBtn
Type: sap.m.Button
Visible: true Enabled: true

Properties:
text = "Create Order"
type = "Emphasized"

Bindings:
text → {i18n>CREATE_ORDER}

━━━ Selectors (best → worst) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

① ui5=sap.m.Button[text=Create Order]
② ui5=sap.m.Button#orderCreateBtn
③ ui5=sap.m.Button[text=Create Order][type=Emphasized]

Fixture:
await ui5.control({ controlType: 'sap.m.Button', properties: { text: 'Create Order' } });

Selectors are ranked by stability: semantic property matches first, IDs second, composite selectors last. The browser highlights the selected control with a blue overlay so you can confirm you clicked the right element.

This makes writing your first test against an unfamiliar SAP app dramatically faster. Instead of opening DevTools, digging through the DOM, and guessing control types, you click and copy.


⚙️ Two New CLI Commands

npx praman config

Prints the fully resolved PramanConfig — every value, including those injected by environment variables — so you can quickly debug why a CI run is using different auth credentials than your local machine.

npx praman config

Nested Environment Variables

Configuration now supports deep injection via environment variables. No more editing playwright.config.ts per CI environment:

# Set auth in CI
PRAMAN_AUTH_STRATEGY=storageState
PRAMAN_AUTH_STORAGE_STATE_PATH=.auth/ci-user.json

# Set AI provider
PRAMAN_AI_PROVIDER=azure-openai
PRAMAN_AI_API_KEY=${{ secrets.AZURE_OPENAI_KEY }}

🔌 Extension System

Praman now ships a plugin API that lets shared testing libraries ship custom matchers and fixture extensions:

import { defineExtension } from 'playwright-praman';

export const approvalExtension = defineExtension({
name: 'approval-workflow',
matchers: {
toHaveApprovalStatus: async (proxy, expected) => {
const status = await proxy.getProperty('approvalStatus');
return {
pass: status === expected,
message: () => `Expected ${expected}, got ${status}`,
};
},
},
});

Register extensions in defineConfig:

export default defineConfig({
use: { pramanConfig: { extensions: [approvalExtension] } },
});

🤖 Playwright CLI Agents — Now the Default

This is a quality-of-life change with a big practical impact for teams getting started.

Previously, Playwright CLI–based agents (the token-efficient alternative to MCP) required an explicit --cli opt-in flag. Starting with this release, CLI agents are installed by default alongside MCP agents whenever you run init or init-agents. If you only want MCP agents, pass --no-cli.

Auto-install of peer dependencies

init now checks for — and installs — four packages in a single npm install call if any are missing:

PackageRole
@playwright/testPlaywright test runner
@playwright/cliPlaywright CLI for agent browser control
playwright-pramanThe plugin itself
dotenvEnvironment variable loading

This means npm install playwright-praman && npx playwright-praman init is the complete setup sequence — no separate npm install @playwright/test @playwright/cli step required.

Flag change

BeforeAfter
--cli (opt-in, default off)--no-cli (opt-out, default on)
# Install everything including CLI agents (new default)
npx playwright-praman init

# MCP agents only
npx playwright-praman init --no-cli

# init-agents — same default
npx playwright-praman init-agents --loop=claude
npx playwright-praman init-agents --loop=copilot --no-cli

A warning is printed when @playwright/cli is absent from node_modules but CLI agents are being scaffolded, so you know exactly what to run if you skipped auto-install.


Every PramanError now carries a docsUrl pointing directly to the relevant documentation anchor. The URL appears in the terminal, in serialized JSON for reporting, and in the AI-envelope when errors are surfaced to LLM agents:

ControlError: Control not found: sap.m.Button[text=Save]
code: ERR_CONTROL_NOT_FOUND
docsUrl: https://praman.dev/docs/guides/errors#err-control-not-found
suggestions:
- Verify the control type and property value in the UI5 view
- Try: npx praman inspect <url>

⬆️ Node.js 22 Minimum

Node.js 20 reached End-of-Life in April 2026. Praman v1.2 requires Node.js 22 or later.

Update your CI workflow:

- uses: actions/setup-node@v4
with:
node-version: '22'

🔒 Zero Vulnerabilities

All npm audit findings — in both the main package and the docs/ workspace — are resolved to zero. Every security bump has been validated for compatibility with Praman's zero-tolerance CI gates.


Upgrading from v1.1

npm install playwright-praman@latest

Breaking changes in v1.2: One — the enableXpathEngine configuration field has been removed. Simply delete it from your PramanConfig; the unified selector engine replaces its functionality automatically.

All fixtures, matchers, proxies, and authentication strategies remain source-compatible. No test code changes are required.


What's next

The roadmap for v1.3 focuses on:

  • OPA5 migration agent (ADR-030): An automated agent that reads existing OPA5 test files and generates equivalent Praman tests, including control mapping and assertion translation.
  • BTP Work Zone multi-tenant improvements to the btpWorkZone fixture.
  • Playwright MCP integration: First-class support for @playwright/mcp session hand-off to Praman's AI agents.

Follow the project on GitHub or subscribe to the npm package for release notifications.


Praman is open-source under the Apache-2.0 license. Docs · npm · GitHub · Discord