Skip to main content

Architecture Overview

Praman v1.0 is a ground-up rebuild of the SAP UI5 test automation platform for Playwright. It ships as a single npm package (playwright-praman) with sub-path exports, organized into a strict 5-layer architecture.

5-Layer Architecture​

+---------------------------------------------------------------------+
| Test Author / AI Agent |
| import { test, expect } from 'playwright-praman'; |
| import { procurementAPI } from 'playwright-praman/intents'; |
+-----------------------------------+---------------------------------+
|
+-----------------------------------v---------------------------------+
| Layer 5: AI & Intent API |
| Sub-path exports: |
| playwright-praman/ai, /intents, /vocabulary, /fe, /reporters |
+---------------------------------------------------------------------+
| Layer 4: Fixtures + Auth + Navigation |
| core-fixtures | auth-fixtures | nav-fixtures | stability-fixtures |
| UI5Handler (18 methods) | Auth Handler (6 strategies) |
| Shell Handler | Footer Handler | WorkZone module |
+---------------------------------------------------------------------+
| Layer 3: Control Proxy + UI5Object |
| control-proxy.ts (unified proxy handler) |
| ui5-object.ts | UI5ObjectCache (TTL + LRU) |
| discovery.ts (3-tier: cache -> ID -> RecordReplay) |
+---------------------------------------------------------------------+
| Layer 2: Bridge + Browser Scripts |
| injection.ts (lazy bridge injection) |
| browser-scripts/ (inject-ui5, find-control, execute-method, etc.) |
| Interaction Strategies: UI5Native, DomFirst, Opa5 |
+---------------------------------------------------------------------+
| Layer 1: Core Infrastructure |
| Config (Zod) | Errors (13 subclasses) | Logger (pino) |
| Telemetry (OTel) | Types (199 typed interfaces) | Compat (PW ver) |
+---------------------------------------------------------------------+
| Layer 0: Playwright Test Runner |
| @playwright/test (page, browser, context, expect) |
+---------------------------------------------------------------------+

Layer Dependency Rules​

The architecture enforces a strict downward-only dependency rule:

  • Lower layers NEVER import from higher layers.
  • Layer 1 (Core) has zero internal dependencies beyond Node.js builtins.
  • Layer 2 (Bridge) imports only from Layer 1.
  • Layer 3 (Proxy) imports from Layers 1 and 2.
  • Layer 4 (Fixtures) imports from Layers 1, 2, and 3.
  • Layer 5 (AI/Intents) imports from Layers 1-4.

This is enforced at compile time via TypeScript path aliases (#core/*, #bridge/*, #proxy/*, #fixtures/*) and ESLint import rules.

// Allowed: Layer 3 imports from Layer 1
import { ErrorCode } from '#core/errors/codes.js';

// Allowed: Layer 3 imports from Layer 2
import { ensureBridgeInjected } from '#bridge/injection.js';

// FORBIDDEN: Layer 1 importing from Layer 3
// import { ControlProxy } from '#proxy/control-proxy.js'; // compile error

Sub-Path Exports​

Praman ships 6 sub-path exports, each targeting a specific concern:

Sub-Path ExportPurposeKey Modules
playwright-pramanCore fixtures, expect, testFixtures, selectors, matchers
playwright-praman/aiAI agent integrationCapabilityRegistry, RecipeRegistry, AgenticHandler
playwright-praman/intentsSAP domain intent APIsCore wrappers, 5 domain namespaces
playwright-praman/vocabularyBusiness term resolutionVocabularyService, fuzzy matcher
playwright-praman/feFiori Elements helpersListReport, ObjectPage, FE tables
playwright-praman/reportersCustom Playwright reportersComplianceReporter, ODataTraceReporter

Each export provides both ESM and CJS outputs:

{
"./ai": {
"types": {
"import": "./dist/ai/index.d.ts",
"require": "./dist/ai/index.d.cts"
},
"import": "./dist/ai/index.js",
"require": "./dist/ai/index.cjs"
}
}

All exports are validated by @arethetypeswrong/cli (attw) in CI.

Design Decisions Summary (D1-D29)​

The architecture is guided by 29 documented design decisions:

#DecisionCategory
D1Single package with sub-path exports (not monorepo)Packaging
D2Internal fixture composition via extend() chainFixtures
D3Version-negotiated bridge adapters (REMOVED Phase 3)Bridge
D4Hybrid typed proxy: 199 typed interfaces + dynamic fallbackProxy
D54-layer observability: Reporter + pino + OTel + AI telemetryObservability
D6Zod validation at external boundaries onlyValidation
D7Zod-validated praman.config.ts with env overridesConfig
D8Unified PramanError hierarchy with 13 subclassesErrors
D9AI Mode A (SKILL.md) + Mode C (agentic fixture)AI
D10Vitest unit tests + Playwright integration testsTesting
D11No plugin API in v1.0Extension
D12Auto-generated SKILL.md + Docusaurus + TypeDocDocs
D13Apache 2.0 licenseLegal
D14Playwright >=1.50.0 <2.0.0 with CI matrixCompat
D15Security: dep scanning, secret redaction, SBOM, provenanceSecurity
D16Single unified proxy (no double-proxy)Proxy
D17Bidirectional proxy conversion (UI5Object <-> UI5ControlProxy)Proxy
D18Integrated discovery factory (removed dead code)Discovery
D19Centralized __praman_getById() (3-tier API resolution)Bridge
D20Browser objectMap with TTL + cleanupMemory
D21Shared interaction logic across strategiesInteractions
D22Auto-generated method signatures (199 interfaces, 4,092 methods)Types
D23skipStabilityWait as global config + per-selector overrideStability
D24exec() with new Function() + security documentationSecurity
D25Visibility preference default (prefer visible controls)Discovery
D26UI5Object AI introspection as first-class capabilityAI
D27Module size <= 300 LOC guideline (with documented exceptions)Quality
D28Auth via Playwright project dependencies (not globalSetup)Auth
D29Enhanced error model + AI response envelopeAI/Errors

Module Decomposition Rationale​

The predecessor (dhikraft v2.5.0) suffered from monolithic files:

FileLOCProblem
ui5-handler.ts2,318God object handling all UI5 operations
dhikraft-fixtures.ts2,263All 32 fixtures in one file
ui5-control-proxy.ts1,829Double-proxy with redundant interception

Praman v1.0 decomposes these into focused modules following SRP (Single Responsibility Principle):

Fixtures are split by domain:

  • core-fixtures.ts -- UI5 control operations
  • auth-fixtures.ts -- Authentication strategies
  • nav-fixtures.ts -- Navigation and routing
  • stability-fixtures.ts -- Wait conditions and stability checks
  • ai-fixtures.ts -- AI agent fixtures
  • fe-fixtures.ts -- Fiori Elements fixtures
  • intent-fixtures.ts -- Intent API fixtures

UI5Handler was decomposed from a 2,318 LOC god object into:

  • ui5-handler.ts (588 LOC) -- 18 core methods
  • shell-handler.ts (102 LOC) -- FLP shell operations
  • footer-handler.ts (119 LOC) -- Footer bar operations
  • Navigation module (201 LOC) -- Route and hash navigation

Control proxy was simplified from a double-proxy pattern (1,829 LOC) into:

  • control-proxy.ts (653 LOC) -- Unified single proxy handler
  • ui5-object.ts (383 LOC) -- Non-control object proxy
  • discovery.ts (111 LOC) -- 3-tier control discovery
  • cache.ts (104 LOC) -- Proxy cache with RegExp keys

Every module targets <= 300 LOC. Exceptions are documented with justification comments.

Codebase Metrics​

MetricValue
Source files129
Source LOC~29,000
Public functions208
Test files109
Unit tests~2,000 passing
Typed control interfaces199 (4,092 methods)
Error subclasses13
Coverage>98% (per-file enforcement)
Lint errors0
Type errors0
ESM + CJS dual buildValidated by attw