API Reference (curated)
The most-used exports from @meintest/cc-testframework, plus the Self-Healing Writeback and Custom-Step additions. For the full export list, see the package’s TypeScript declarations under pm/node_modules/@meintest/cc-testframework/dist/*.d.ts.
← Back to overview · 🇩🇪 Deutsch · ← Concepts · Self-Healing →
Conventions
- All async functions return
Promise<void>unless noted. - All UI-locating functions take a view-name + view-type prefix to scope the lookup (e.g.,
'Login', 'dialog'finds elements inside a dialog titled “Login”). - All TestStep-level helpers log their action to the test-step report — you don’t need to add manual logging.
1. Action
Low-level action primitives: clicks, fills, hovers, scrolls, navigation.
import { Action } from '@meintest/cc-testframework';
await Action.click(locator, 'Submit button');
await Action.fill(locator, 'jane@example.com', 'Email field');
await Action.hover(locator, 'Menu item');
await Action.scroll(page, 500);
When to use directly: inside your Step_*.ts files, after a Control has resolved a locator. Don’t call from TestCases — use TestSteps instead.
2. Check
Assertion primitives for labels, URLs, element existence, dialog states.
import { Check } from '@meintest/cc-testframework';
await Check.label_ByXpath_IsEqual(page, './/h1', 'Welcome');
await Check.label_ByXpath_Contains(page, './/p', 'Successfully created');
await Check.urlContains(page, '/dashboard');
await Check.elementExists(page, '#user-menu');
Each Check throws an informative error on mismatch (Playwright’s standard expect() semantics, with framework-friendly error messages).
3. Step
Block structures and step-level orchestration.
import { Step } from '@meintest/cc-testframework';
Step.setCurrentTestCaseName('TC_UserCreation');
await Step.numberedStepBlock('Login', async () => {
// contents become numbered child steps in the test report
});
await Step.logParam('username', 'jane@example.com');
numberedStepBlock is the mandatory grouping mechanism — every TestCase wraps its work in numberedStepBlocks so the test report shows readable structure.
4. baseConfig
A PlaywrightTestConfig object you spread into your project’s playwright.config.ts. Contains framework defaults that don’t change between projects.
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
import { baseConfig } from '@meintest/cc-testframework';
export default defineConfig({
...baseConfig,
timeout: 300000,
testDir: './3_Cases',
use: {
...baseConfig.use,
baseURL: 'https://<your-app>',
headless: false,
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
],
});
What’s in baseConfig: fullyParallel, forbidOnly, retries, workers, reportSlowTests, reporter, and use.{ignoreHTTPSErrors, acceptDownloads, screenshot, trace, video}. Not in it: anything project-specific (testDir, baseURL, projects, headless, slowMo, globalSetup).
reporter always includes ['html']. It also conditionally includes SelfHealingWritebackReporter, appended automatically whenever SELF_HEALING_WRITEBACK or SELF_HEALING_WRITEBACK_DISCOVERY is set to true in the environment at the moment this file loads — see Self-Healing Locators — Setup. A project that overrides reporter in its own config (rather than spreading baseConfig.reporter) needs to add the reporter itself if it wants it.
5. SearchEngine
Locator strategies with hierarchical fallback.
import { SearchEngine } from '@meintest/cc-testframework';
const locator = await SearchEngine.findLocators(page, {
view: { name: 'Login', type: 'dialog' },
element: { tag: 'button', text: 'Sign in' },
});
The SearchEngine handles edge cases: elements inside iframes, shadow DOM, multiple match-disambiguation, retry-on-not-yet-rendered. Use this from inside your Control files rather than page.locator() directly — you get the framework’s robustness for free.
6. AppReady
Page/browser lifecycle helpers.
import { AppReady } from '@meintest/cc-testframework';
await AppReady.waitForPageLoad(page, { timeout: 30000 });
await AppReady.waitForNetworkIdle(page);
Useful inside TestSteps that need to ensure the application is fully loaded before interacting. Reduces flakiness from “click happened too early” scenarios.
7. Filesystem / I_Filesystem
File I/O utilities. The Filesystem export is internal; the I_Filesystem export is the public interface for use in TestSteps.
import { I_Filesystem } from '@meintest/cc-testframework';
const content = await I_Filesystem.readFile('./data/users.csv');
await I_Filesystem.writeFile('./output/result.json', JSON.stringify(data));
8. Logger
Structured logging that’s integrated with the test report.
import { Logger } from '@meintest/cc-testframework';
Logger.info('Starting test setup');
Logger.warn('Falling back to second selector strategy');
Logger.error('Element not found after retries');
Output appears in both the console and in the per-test artifacts. Use this instead of console.log for any test-relevant messages.
9. I_PasswordManager
Password retrieval — useful for tests that need credentials without hard-coding them.
import { I_PasswordManager } from '@meintest/cc-testframework';
const password = await I_PasswordManager.TS_GetPassword('TestUser');
The implementation reads from a configured secret store (env vars, keystore, or encrypted file — depending on your setup). Never log the result.
10. I_Utils
Misc utilities — date formatting, random IDs, etc.
import { I_Utils } from '@meintest/cc-testframework';
const timestamp = I_Utils.GetDate('ssms'); // → "20260603143015123"
const dateStr = I_Utils.GetDate('iso'); // → "2026-06-03"
const randomId = I_Utils.GenerateRandomId(8); // → "kP9xQ2bA"
Date-formatting is especially useful for generating unique email addresses in registration tests: ${user}${I_Utils.GetDate('ssms')}@mailinator.com.
11. Self-Healing exports (Core.xpath, SelfHealingWritebackReporter, withCoordinatedWrite)
Locator-repair infrastructure — see Self-Healing Locators for the full setup guide, this section only lists the exports themselves.
import { xpath, SelfHealingWritebackReporter, withCoordinatedWrite, getProjectConfig, resolveSelfHealingConfig, PROJECT_CONFIG_FILE_NAME, setTestCaseId, getTestCaseId } from '@meintest/cc-testframework';
import type { WritebackResult, WriteResult, ProjectConfig, SelfHealingResolution } from '@meintest/cc-testframework';
// Inside a Control — tag a locator so it becomes writeback-eligible
Core.xpath`(//*[@ControlType='ControlType.DataItem'])[${rowIndex}]`;
// Top of a TC_*.spec.ts file — give the TestCase a stable, rename-safe id
Core.setTestCaseId('tc_<your-scenario>');
Core.setTestCaseId(uid: string): void— sets a stable, filesystem-safe id for the current TestCase, used to key its reference-asset folder (7_Assets/<uid>/) independently of the Playwright test title. Recommended slug format:tc_[a-z0-9-]{4,}. See Self-Healing Locators — Giving a TestCase a stable id for where and when to call it, and the full path-resolution and migration story.Core.getTestCaseId(): string | null— reads back the id set for the current TestCase viasetTestCaseId;nullif none has been set.Core.xpath— a tagged template literal. Produces the exact same string as an equivalent raw template literal; the tag additionally lets the framework trace the locator back to its file:line for self-healing. Purely additive — untagged locators keep working unchanged.SelfHealingWritebackReporter— a PlaywrightReporterclass you register inplaywright.config.ts’sreporterarray — or thatbaseConfigregisters for you automatically onceSELF_HEALING_WRITEBACK/_DISCOVERYis set (see Section 4). Runs once at the end of the test run and persists any successful heals into their owning Control files (opt-in viaSELF_HEALING_WRITEBACK=true, an environment variable or the persisted config file). Routes its writes throughwithCoordinatedWrite(see below) so it never conflicts with a colleague editing the same file — see Self-Healing Locators — Multi-user coordination. Also reachable via the dedicated sub-path export@meintest/cc-testframework/reporter/self-healing-writeback(both a named and a default export, resolving to the same class) for a project with its ownreporter[]array that doesn’t import the package’s full barrel — see Self-Healing Locators — Registering the reporter manually. The older, wildcard-derived path@meintest/cc-testframework/Reporter/SelfHealingWritebackReporter(uppercase) still resolves for existing configs; the lowercase sub-path above is the canonical form going forward.WritebackResult(type-only) — the shape of a single writeback outcome (per healed locator: applied vs. skipped, and why); exported for advanced tooling that wraps or inspects the writeback step programmatically. Most Customers only need the JSON report file (.self-healing-report.json), not this type directly.withCoordinatedWrite(files, writeFn)— a reusable coordination wrapper: runswriteFnunder a git-based lock so concurrent writes to the same tracked files (from a colleague, another CI job, or any other code built on this same function) never produce a merge conflict. In projects without anoriginremote it degrades to a zero-overhead no-op. Most Customers never call this directly —SelfHealingWritebackReporteralready uses it internally — but it’s exported for teams building their own agent-driven write tooling on top of the framework.WriteResult(type-only) — the return shape ofwithCoordinatedWrite:status('applied' | 'skipped' | 'partial' | 'error'),mode('local-only' | 'coordinated'), the list offilesWritten, and — on a skip —lockedFilesnaming each blocking lock’s owner and acquisition time.getProjectConfig(startDir?)— reads and validates the project-level.cc-testframework.local.jsonconfig file (upward-searched fromstartDir, defaultprocess.cwd()). Returnsnullfor a missing file, invalid JSON, an unsupportedschemaVersion, or when no repo root could be found — never throws. Most Customers use thenpx cc-testframework config self-healing <action>CLI (see Self-Healing Locators — Persisting the setup across sessions) instead of calling this directly.resolveSelfHealingConfig()— merges theSELF_HEALING_WRITEBACK/SELF_HEALING_WRITEBACK_DISCOVERY/SELF_HEALING_AGENT_IDENTITYenvironment variables with the config file’sselfHealingblock into oneSelfHealingResolution, following the same env-var-wins-over-config-file-wins-over-default priority chain the Credential Management chain also follows.PROJECT_CONFIG_FILE_NAME— the literal filename.cc-testframework.local.json, exported so tooling doesn’t need to hardcode it.ProjectConfig(type-only) — the on-disk shape:schemaVersion: 1, optionalselfHealing: { enabled?, discoveryMode?, agentIdentity? }.SelfHealingResolution(type-only) — the merged result:enabled,discoveryMode,agentIdentity: string | null, plus asourceobject naming which tier ('env' | 'config' | 'default') produced each of the three values.
12. Custom-Step exports (discoverCustomSteps, validateCustomStep, runAuthoringAgent, runAuthorCli, runAuthorTestRunner)
Convention, discovery, validation, automated implementation, and the Test-Case-driven Runtime-Authoring-Loop for steps without an automated implementation yet — see Custom Steps for the full authoring guide, this section only lists the exports themselves.
import {
discoverCustomSteps, validateCustomStep, runAuthoringAgent, AnthropicElementFinderClient,
runAuthorCli, runAuthorTestRunner, classifyFailure, synthesizeCustomStepFromFailure,
} from '@meintest/cc-testframework';
import type {
CustomSpec, CustomStepDiscovery, ValidationResult,
AuthoringAgentOptions, AuthoringProgressEvent, AuthoringResult,
AppliedStep, SkippedStep, ErrorStep,
IElementFinderClient, ElementFinderResult, GeneratedImplementation,
AuthorCliOptions, AuthorCliResult,
AuthorTestRunnerOptions, AuthorTestResult, AuthorTestProgressEvent, TestRunResult,
FixContext, FixResult, IterationRecord, FixRecord,
FailureClassification, FailureKind,
} from '@meintest/cc-testframework';
const discoveries = await discoverCustomSteps(path.join(process.cwd(), 'tests'));
const result = validateCustomStep(discoveries[0]);
const authoringResult = await runAuthoringAgent({
rootDir: path.join(process.cwd(), 'tests'),
treeDigest: myLiveTreeDigest,
});
const cliResult = await runAuthorCli({ app: 'DemoApp', batchMode: true }); // boots the App itself, no treeDigest needed
const testResult = await runAuthorTestRunner({ testPath: 'pm/3_Cases/TC_<YourFlow>.spec.ts' });
discoverCustomSteps(rootDir)— scans<rootDir>/2_Apps/*/2_Steps/*.tsforTS_*exports marked with a@customJSDoc block and returns oneCustomStepDiscoveryper step, in file order. Returns an empty array if2_Appsdoesn’t exist. Duplicate@stepIDs across files are logged as a warning but both are still returned.validateCustomStep(discovery)— checks a singleCustomStepDiscoveryfor common authoring mistakes and returns aValidationResultwith separateerrors(blocking) andwarnings(informational) arrays.CustomSpec(type-only) — the parsed@customJSDoc block:description,intent('check' | 'action'), optionaltarget({ view, section, control, label }), optionalproperty/operator/expected, and the requiredstepId.CustomStepDiscovery(type-only) — one discovered step:file,stepName,line, the parsedspec, andisNotImplemented(true while the body still throws the “not yet automated” placeholder).ValidationResult(type-only) —isValid,warnings: string[],errors: string[].runAuthoringAgent(options)— discovers, validates, and (per step, where confidence allows) implements Custom Steps against a supplied UI-tree digest. See Custom Steps — Automated implementation for the full setup, configuration env-vars, and skip-reason table.AnthropicElementFinderClient— the defaultIElementFinderClientimplementation, calling the Anthropic API (BYOK viaANTHROPIC_API_KEY, model override viaAI_VISION_MODELornpx cc-testframework set-ai-vision-model <model>). Most Customers never construct this directly —runAuthoringAgentdoes so internally unless you pass your own client via advanced options.AuthoringAgentOptions(type-only) —rootDir,treeDigest, optionaldryRun/maxSteps/onProgress/anthropicApiKey.AuthoringProgressEvent(type-only) — one streamed progress notification:phase('discover' | 'validate' | 'infer' | 'generate' | 'write' | 'done'), optionalstep,message, optionaldetail.AuthoringResult(type-only) — the return value ofrunAuthoringAgent:schemaVersion: 1,runTimestamp,mode('applied' | 'dry-run'),totalDiscovered,applied: AppliedStep[],skipped: SkippedStep[],errors: ErrorStep[], optionalcommitSha, optionallockedByHumans.AppliedStep/SkippedStep/ErrorStep(type-only) — one entry each inAuthoringResult.applied/.skipped/.errors; see Custom Steps — Why a step gets skipped for the fullSkippedStep.reasonenumeration.IElementFinderClient/ElementFinderResult(type-only) — the pluggable Vision-client contract behindAnthropicElementFinderClient, for teams supplying their own element-finding backend.GeneratedImplementation(type-only) — the shaperunAuthoringAgent’s internal code generator produces before writing it into a Custom-Step’s body; exported for advanced tooling that wants to inspect a generated implementation before it’s applied.runAuthorCli(options)— the logic behindnpx cc-testframework author, exported for teams that want to invoke it programmatically instead of shelling out. Runs in one of two mutually exclusive modes depending on which option is set — Runtime (options.testPath, delegates torunAuthorTestRunner) or Batch (options.batchMode: true+options.app, resolves the App’s runtime strategy, boots a session, captures the UI-tree digest, callsrunAuthoringAgent, persists the result as JSON, and closes the session). See Custom Steps — Running the agent from the command line for the full CLI-facing contract (options, environment variables, exit codes) of both modes.AuthorCliOptions(type-only) —app(required only whenbatchMode: true),testPath(required for Runtime mode) /batchMode, optionalmaxIterations/maxAttemptsPerStep(Runtime mode), optionaltestsRoot/appsConfig/maxSteps(Batch mode), plusdryRun/reportPath/anthropicApiKeyshared by both.AuthorCliResult(type-only) —exitCode(0 | 1 | 2 | 3 | 4;3is Batch-mode-only,4is the credential-related error described in Section 13), optionalresult: AuthoringResult(Batch mode) ortestResult: AuthorTestResult(Runtime mode) — never both, optionalerror(set only forexitCode: 2).runAuthorTestRunner(options)— the Runtime-Authoring-Loop: runsoptions.testPathiteratively as a fresh Playwright subprocess per attempt, classifying every failure (classifyFailure) and, for the three fixable kinds, dispatching the Authoring Agent, until the Test-Case passes or a non-fixable/circuit-breaker condition is hit. Persists anAuthorTestResultJSON report and always returns it (it does not throw for a fixable-but-failing run). See Custom Steps — Runtime mode.AuthorTestRunnerOptions(type-only) —testPath(required), optionalprojectRoot/maxIterations/maxAttemptsPerStep/dryRun/reportPath/anthropicApiKey/onProgress.AuthorTestResult(type-only) —schemaVersion: 1,runTimestamp,mode('runtime' | 'runtime-dry-run'),testPath,finalStatus('passed' | 'failed-non-fixable' | 'stuck-in-loop' | 'max-iterations-reached' | 'credential-error'),totalIterations,iterations: IterationRecord[],fixes: FixRecord[],commitShas: string[], optionalcredentialIssues: CredentialIssueRecord[]— populated whenfinalStatus === 'credential-error'(credential-related entries), and/or whenever the zero-matched-tests guard fired during an otherwise-normal run (kind: 'playwright-0-tests') — check this array even after an apparentfinalStatus: 'passed'. See Section 13.AuthorTestProgressEvent(type-only) — one streamed loop event:phase('test-run' | 'test-pass' | 'test-fail' | 'classify' | 'fix-attempt' | 'fix-applied' | 'fix-failed' | 'stuck' | 'real-fail' | 'done' | 'credential-expired' | 'credential-expiring-soon' | 'credential-missing' | 'credential-invalid' | 'interactive-prompt-required' | 'interactive-prompt-shown' | 'playwright-0-tests'),iteration,message, optionaldetail.TestRunResult(type-only) — one Playwright subprocess run’s outcome:passed,exitCode,stdout/stderr, optional parsedjsonReport, optionalscreenshotPath/htmlSnapshotPathextracted from its attachments.FixContext/FixResult(type-only) — the contract between the loop and its Agent-dispatch step: aFailureClassificationplus artifact paths in, an'applied' | 'skipped' | 'error'status (plus optionalcommitSha) out. Mainly relevant to teams supplying their own_agentDispatchertest-double or dispatch strategy.IterationRecord/FixRecord(type-only) — one loop iteration’s outcome, and one fix-location’s cumulative outcome across the whole run, respectively — both persisted insideAuthorTestResult.classifyFailure(errorText, stackTrace?, testFileContent?)— pure, dependency-free classification of a Playwright failure’s error text into one of nineFailureKinds (only three of which arefixable: true). Used internally byrunAuthorTestRunner’s default wiring; exported standalone for teams building their own failure-triage tooling on top of it. See Custom Steps — Runtime mode for what each fixable kind means.FailureClassification(type-only) —kind: FailureKind,fixable, optionalfile/line/stepName,originalError.FailureKind(type-only) — the nine-value string union:'custom-not-implemented' | 'element-not-found-no-refid' | 'element-not-found-refid-exhausted' | 'timeout-no-refid' | 'assertion-fail' | 'runtime-error' | 'network-fail' | 'app-crash' | 'unknown'.synthesizeCustomStepFromFailure(file, line, failedXPath, failedActionText?)— builds a syntheticCustomStepDiscoveryfor an already-implemented step with no@customtag, so the same Authoring-Agent machinery that implements Custom Steps can also attempt to identify a fix for it. Used internally for theelement-not-found-no-refid/timeout-no-refidclassifications; exported standalone for advanced tooling.
13. Credential-Management exports (getCredential, setCredential, resolveCredentialWithPrompt)
A cross-platform OS-credential-store abstraction (Windows Credential Manager / macOS Keychain / Linux Secret Service) plus the shared resolution logic consumed by the Authoring Agent CLI — see Credential Management for the full setup guide (the config CLI subcommand, project scoping, expiry handling), this section only lists the exports themselves.
import {
getCredential, setCredential, deleteCredential, listCredentials,
getCredentialEnvelope, checkCredentialStatus, detectProjectId,
normalizeGitRemoteUrl, KNOWN_CREDENTIAL_TYPES, resolveCredentialWithPrompt,
} from '@meintest/cc-testframework';
import type {
CredentialScope, CredentialTypeSpec, CredentialStore, CredentialEnvelope, CredentialStatus,
CredentialSource, ResolvedCredential, CredentialProgressPhase,
CredentialResolverProgressEvent, CredentialResolverOptions, CredentialIssueRecord,
} from '@meintest/cc-testframework';
const key = await getCredential('anthropic-api-key');
await setCredential('github-token', myFreshToken, { source: 'oauth-device', expiresAt: '2026-07-15T18:00:00Z' });
const status = await checkCredentialStatus('anthropic-api-key');
if (status.expired) { /* re-authenticate and set a fresh value */ }
getCredential(name, options?)— reads a credential’s plain value from the OS store (project-scoped entry first, then global-scoped, per the type’s default scope). Returnsnullwhen nothing is stored, or when the OS store is unavailable on this machine — never throws for “not there”.setCredential(name, value, options?)— validates the value against the credential type’s format rule and stores it as a JSON envelope.optionsacceptsproject/scope/expiresAt/source. Throws when a project-scoped type has no resolvable project context (not inside a git repository with anoriginremote) and none was passed explicitly.deleteCredential(name, options?)— removes a stored credential. Returnstrueif an entry was actually deleted,falsefor a no-op (nothing was there).listCredentials()— lists every stored credential as{ name, scope, projectId? }tuples, independent of whethernameis a currently-known credential type.getCredentialEnvelope(name, options?)— likegetCredential, but returns the fullCredentialEnvelope(value plus expiry/source metadata) instead of just the value.checkCredentialStatus(name, options?)— checks existence and expiry without exposing the value — safe to log or include in a report. Returns aCredentialStatus.detectProjectId(cwd?)— resolves the current project’s id fromgit config --get remote.origin.url, normalized vianormalizeGitRemoteUrl. Returnsnulloutside a git repository or without anoriginremote — never throws.normalizeGitRemoteUrl(url)— normalizes an SSH/HTTPS/git://remote URL into the stable<host>/<owner>/<repo>form used as the project-scoping key.KNOWN_CREDENTIAL_TYPES— the static registry of the two credential types the framework knows about today (anthropic-api-key,github-token), each aCredentialTypeSpec. See Credential Management — Known credential types.CredentialScope(type-only) —'global' | 'project'.CredentialTypeSpec(type-only) —name,defaultScope,description, optionalenvVar, optionalvalidate(value).CredentialStore(type-only) — the{ get, set, delete, list }contract a custom backing store would need to implement; most Customers never need this, it exists for advanced/test tooling.CredentialEnvelope(type-only) — the on-disk shape: requiredv(the value), optionalexp(ISO-8601 expiry),src(informational source tag),meta(reserved for future use).CredentialStatus(type-only) —exists, optionalexpired/expiresAt/secondsUntilExpiry/withinGracePeriod, optionalsource/scope/projectId.resolveCredentialWithPrompt(name, options?)— the 5-tier priority chain described in Credential Management: CLI-arg value, env-var, OS store (project-scoped), OS store (global-scoped), then an interactive first-run prompt (TTY only). Returnsnullwhen nothing could be resolved anywhere, including a Non-TTY context where the prompt cannot run.CredentialSource(type-only) —'cli-arg' | 'env' | 'store' | 'prompt', identifying which tier aResolvedCredentialcame from.ResolvedCredential(type-only) —{ value, source: CredentialSource }.CredentialProgressPhase(type-only) — the six credential-related progress phases:'credential-expired' | 'credential-expiring-soon' | 'credential-missing' | 'credential-invalid' | 'interactive-prompt-required' | 'interactive-prompt-shown'.CredentialResolverProgressEvent(type-only) — one streamed event:phase: CredentialProgressPhase,credential,message, optionalexpiredAt/secondsUntilExpiry/secondsExpired/source.CredentialResolverOptions(type-only) — options accepted byresolveCredentialWithPrompt: optionalcliArgValue/project/onProgress.CredentialIssueRecord(type-only) — one notable issue recorded inAuthorTestResult.credentialIssues(see Section 12):kind('credential-expired' | 'credential-expiring-soon' | 'credential-missing' | 'credential-invalid' | 'interactive-prompt-required' | 'playwright-0-tests'),message, and optional fields depending onkind—credential/expiredAt/sourcefor the credential-related kinds, orpattern(the--testpath/pattern that matched zero files) for'playwright-0-tests'. The array doubles as this runner’s general “notable diagnostic” bucket rather than growing a second, parallel one.
14. Appium URL resolution (resolveAppiumUrl)
For a Desktop AUT (Windows, via Appium), the framework resolves the Appium server URL internally before opening a session — this export surfaces that same logic for advanced setups, e.g. a custom pre-flight check.
import { resolveAppiumUrl } from '@meintest/cc-testframework';
import type { AppiumUrlResolutionResult } from '@meintest/cc-testframework';
const resolution = resolveAppiumUrl(myAppConfig.appiumUrl);
console.log(resolution.url, resolution.source, resolution.platform);
resolveAppiumUrl(explicitAppiumUrl?)— resolves the effective Appium server URL via a three-tier priority chain: the explicit value passed in (your AUT’sappiumUrlinGlobalConfig.apps, if set), then theAPPIUM_URLenvironment variable, then a platform-based default (http://localhost:4723when the test process itself runs natively on Windows,http://host.docker.internal:4723otherwise). See FAQ — How does the framework know where to find the Appium server for Desktop tests?.AppiumUrlResolutionResult(type-only) —{ url, source, platform };sourceis'explicit-config' | 'env-var' | 'platform-default'.
15. Step-description i18n catalogs (.i18n.json convention + validator)
Not a TypeScript export — a file convention plus a standalone validator script, both shipped by the @meintest/cc-testframework-templates package. Any step file <StepFile>.ts may have a same-named sibling <StepFile>.i18n.json, keyed by exported step-function name, mapping locale codes to translated copies of that step’s numberedStep/description/logTitle text:
{
"TS_Main_Button_Click": {
"en": "On Main, click button '${label}'",
"de": "Auf 'Main', Schaltfläche '${label}' klicken"
}
}
Every locale entry must use the exact same ${paramName} placeholders as the en entry — the catalog’s source-of-truth. A missing catalog, or a missing locale within one, falls back to English — this is the normal, non-error case.
From inside pm/ (once @meintest/cc-testframework-templates is installed there as a dev dependency):
node ./node_modules/@meintest/cc-testframework-templates/bin/validate-i18n.js <path>
Validates the KEYs referenced in every step file against their sibling .i18n.json catalog: every referenced KEY needs an en entry (missing entirely is a failure; an unreferenced catalog key is a warning), and every other locale’s placeholder set must match en’s exactly. Exit code 0 on success (including “no catalogs found” and warning-only findings), 1 on any failure-level finding, with a file/key/locale-scoped error list. See Step-Description Localization for the full convention, a worked example, and how a programmatic consumer renders the localized text.
Core.i18n — runtime localization API
Unlike the file convention above, Core.i18n is a real TypeScript export — the framework’s own execution reads it to localize what it renders itself (Playwright’s reports, console output, the Self-Healing writeback report). See Runtime localization for the full priority chain and behavior.
import { i18n } from '@meintest/cc-testframework';
import type { SupportedLocale, TranslateOptions } from '@meintest/cc-testframework';
i18n.setLocale('de');
i18n.getLocale(); // 'de'
const text = i18n.t('TS_Main_Button_Click', { label: 'Save' });
Core.i18n.getLocale(): SupportedLocale— resolves the effective locale via the priority chain:Core.i18n.setLocale(...)override, then theCC_TESTFRAMEWORK_LOCALEenvironment variable, thenGlobalConfig.language, then the'en'default.Core.i18n.setLocale(locale: SupportedLocale): void— sets an explicit in-process override, primarily for tests or a one-off runtime switch; outranks the environment variable andGlobalConfig.language.Core.i18n.t(key: string, values?: Record<string, unknown>, options?: TranslateOptions): string— resolveskeyagainst the sibling.i18n.jsoncatalog for the calling step file (auto-detected from the call stack, oroptions.callerFilewhen passed explicitly) and substitutes every${paramName}placeholder found invalues.options.fallbackis optional and used ONLY when no catalog is expected for the caller — e.g. runtime-generated Custom-Steps (seeTS_Custom.tsfor the canonical pattern). Under the standard convention, the sibling catalog’senentry is the source-of-truth andfallbackshould be omitted; when both a catalog andfallbackare absent for a given key,t()logs a warning once per missing key and returns the rawkeyliteral. Never throws.SupportedLocale(type-only) —'de' | 'en'.TranslateOptions(type-only) —{ callerFile?: string; fallback?: string }.fallbackis a Custom-Step-only escape hatch — see When to use fallback.
Core.defineTestStep and Core.defineExecutionStep accept an optional descriptionI18n field as an alternative to logTitle/description — { key, values(...args), fallback?(...args) } (typed as TestStepDescriptionI18nSpec / ExecutionStepDescriptionI18nSpec). fallback is optional and, like TranslateOptions.fallback above, a Custom-Step-only escape hatch — a factory-based step with a catalog omits it and relies on the catalog’s en entry instead. See Writing new steps with i18n support for worked examples of both the factory-based and direct-t()-call forms.
16. Core.defineExecutionStep
App-lifecycle steps. Scaffolds a tester-facing TS_Execution_<Action> step (browser start/close/restart/navigate for a Web AUT, process start/close for a Desktop AUT) from a declarative factory, without hand-wiring a Playwright page or a hardcoded URL. See Writing your first TestCase — Step-naming convention for where this fits into the overall naming scheme.
import * as Core from '@meintest/cc-testframework';
export const TS_Execution_Start = Core.defineExecutionStep(
'MyApp',
'Start',
(env) => ({
descriptionI18n: {
key: 'TS_Execution_Start',
values: () => ({ url: env.url }),
},
run: () => Core.I_BrowserHandler.start(env.page, env.url, { waitForReady: true }),
}),
);
defineExecutionStep(appName, action, factory)—appNameis the App’s key inGlobalConfig.apps, not part of the generated function’s exported name (it staysTS_Execution_Start, notTS_MyApp_Execution_Start— see Writing your first TestCase for why); it tells the framework which App entry to resolveenvfrom.actionis a freeform label ('Start','Close','Restart','NavigateTo', …) folded into the generated function’s identity for readability — the framework doesn’t interpret its value.factory(env)receives anenvobject the framework assembles for you fromGlobalConfig.apps[appName]— no manualpage/url/Playwright-fixture wiring in your step file.
Family-aware env shape, resolved from the matching GlobalConfig.apps[appName] entry:
| App family | env fields |
|---|---|
| Web (Playwright) | page: Core.Page, url: string, appConfig: WebPlaywrightAppConfig |
| Desktop (Appium-Windows) | executable: string, appiumUrl: string, appConfig: DesktopAppiumWindowsAppConfig |
env.appConfig is the full, family-typed app entry from GlobalConfig.apps[appName] — reach for it when a step needs a field the two shapes above don’t surface directly.
Why the env-based shape: it lets a test-management tool’s UI — or a tester without TypeScript experience — scaffold an App-lifecycle step for a given App without ever typing page, a Playwright fixture, or a hardcoded URL; the framework resolves all of that from the App’s own GlobalConfig entry. See Custom Steps — What is a Custom Step? for how this differs from a hand-written or agent-generated Custom Step.
Backward compatibility: the older 2-argument form still works unchanged:
export const TS_Execution_Start = Core.defineExecutionStep(
'MyApp',
(page, url) => ({
description: `Start browser and navigate to '${url}'`,
run: () => Core.I_BrowserHandler.start(page, url, { waitForReady: true }),
}),
);
Calling it this way still works exactly as before, and emits a one-time deprecation warning per call site (console.warn, deduplicated by caller file:line) recommending the migration to the env-based form — no functional change, no forced rewrite.
17. Debug-Session exports (resolveDebugSession, runSessionCli)
Persistent-debug-session infrastructure — see Persistent Debug Session for the full setup guide, this section only lists the exports themselves.
import { resolveDebugSession, runSessionCli } from '@meintest/cc-testframework';
import type { DebugSessionResolution, SessionCliDeps, SessionCliResult } from '@meintest/cc-testframework';
resolveDebugSession()— merges theCC_DEBUG_SESSIONenvironment variable with the config file’sdebugSessionkey into oneDebugSessionResolution, following the same env-var-wins-over-config-file-wins-over-default priority chain asresolveSelfHealingConfigabove. Most Customers never call this directly — it drives the framework’s own attach-or-launch decision at test-runner startup.DebugSessionResolution(type-only) — the merged result:enabled: booleanplussource: 'env' | 'config' | 'default'.runSessionCli(argv, deps)— the implementation behindnpx cc-testframework session status/close(see Persistent Debug Session — Manage the session from the command line). Exported for advanced tooling that wants to drive the same status/close logic programmatically; most Customers use the CLI directly instead.SessionCliDeps(type-only) — the injectable dependency surfacerunSessionCliaccepts (state read/clear, endpoint reachability check, process termination, output sinks); relevant only when callingrunSessionClidirectly.SessionCliResult(type-only) —{ exitCode: number }, the outcome of arunSessionClicall.
Re-exports for convenience
The framework also re-exports common Playwright + Node bits, so you don’t need separate imports in your test files:
import { test, expect, fs, path, moment, pdfParse, csvParser, authenticator, crypto }
from '@meintest/cc-testframework';
This means a typical TestCase has one import line — @GlobalRef (your barrel) — and everything is available via Project.Core.* and Project.<YourApp>.*.
Discovering the full surface
If you need an export that’s not listed above, the TypeScript declarations in pm/node_modules/@meintest/cc-testframework/dist/References.d.ts are the authoritative list. Your IDE (VS Code, WebStorm, etc.) will auto-complete from there.
📧 Need a function that isn’t there? Suggest it via jens.szelag@itsbusiness.ch.
itsbusiness AG · Bern · Switzerland