API-Referenz (kuratiert)

Die meistgenutzten Exports von @meintest/cc-testframework, plus die Self-Healing-Writeback- und Custom-Step-Ergänzungen. Für die vollständige Export-Liste siehe die TypeScript-Deklarationen im Paket unter pm/node_modules/@meintest/cc-testframework/dist/*.d.ts.

← Zurück zur Übersicht · 🇬🇧 English · ← Konzepte · Self-Healing →


Konventionen

  • Alle async-Funktionen geben Promise<void> zurück, sofern nicht anders vermerkt.
  • Alle UI-suchenden Funktionen nehmen ein view-name + view-type Präfix, um den Lookup zu skopen (z.B. 'Login', 'dialog' sucht Elemente in einem Dialog mit Titel “Login”).
  • Alle TestStep-Level-Helfer loggen ihre Aktion in den Test-Step-Report — du musst kein manuelles Logging hinzufügen.

1. Action

Low-Level-Aktions-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-Feld');
await Action.hover(locator, 'Menü-Item');
await Action.scroll(page, 500);

Wann direkt nutzen: in Step_*.ts-Dateien, nachdem ein Control den Locator aufgelöst hat. Nicht aus TestCases aufrufen — dort TestSteps verwenden.


2. Check

Assertion-Primitives für Labels, URLs, Element-Existenz, Dialog-Zustände.

import { Check } from '@meintest/cc-testframework';

await Check.label_ByXpath_IsEqual(page, './/h1', 'Welcome');
await Check.label_ByXpath_Contains(page, './/p', 'Erfolgreich angelegt');
await Check.urlContains(page, '/dashboard');
await Check.elementExists(page, '#user-menu');

Jeder Check wirft einen aussagekräftigen Error bei Nichtübereinstimmung (Playwright-Standard-expect()-Semantik, mit framework-freundlichen Fehlermeldungen).


3. Step

Block-Strukturen und Step-Level-Orchestrierung.

import { Step } from '@meintest/cc-testframework';

Step.setCurrentTestCaseName('TC_UserCreation');

await Step.numberedStepBlock('Login', async () => {
    // Inhalt wird zu nummerierten Kind-Steps im Test-Report
});

await Step.logParam('username', 'jane@example.com');

numberedStepBlock ist der verbindliche Gruppierungs-Mechanismus — jeder TestCase wickelt seine Arbeit in numberedStepBlocks ein, damit der Test-Report eine lesbare Struktur zeigt.


4. baseConfig

Ein PlaywrightTestConfig-Objekt, das du in die playwright.config.ts deines Projekts spreadest. Enthält Framework-Defaults, die sich zwischen Projekten nicht ändern.

// 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://<deine-app>',
        headless: false,
    },
    projects: [
        { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    ],
});

Was drin ist: fullyParallel, forbidOnly, retries, workers, reportSlowTests, reporter und use.{ignoreHTTPSErrors, acceptDownloads, screenshot, trace, video}. Nicht drin: alles Projekt-spezifische (testDir, baseURL, projects, headless, slowMo, globalSetup).

reporter enthält immer ['html']. Zusätzlich enthält es bedingt SelfHealingWritebackReporter, automatisch angehängt, sobald SELF_HEALING_WRITEBACK oder SELF_HEALING_WRITEBACK_DISCOVERY in der Umgebung auf true gesetzt ist, in dem Moment, in dem diese Datei lädt — siehe Self-Healing Locators — Setup. Ein Projekt, das reporter in seiner eigenen Config überschreibt (statt baseConfig.reporter zu spreaden), muss den Reporter selbst ergänzen, wenn es ihn nutzen will.


5. SearchEngine

Locator-Strategien mit hierarchischem Fallback.

import { SearchEngine } from '@meintest/cc-testframework';

const locator = await SearchEngine.findLocators(page, {
    view: { name: 'Login', type: 'dialog' },
    element: { tag: 'button', text: 'Sign in' },
});

Die SearchEngine handhabt Edge-Cases: Elemente in iframes, Shadow DOM, Multi-Match-Disambiguation, Retry-on-not-yet-rendered. Aus Control-Dateien heraus nutzen statt page.locator() direkt — du bekommst die Framework-Robustheit gratis.


6. AppReady

Page/Browser-Lifecycle-Helfer.

import { AppReady } from '@meintest/cc-testframework';

await AppReady.waitForPageLoad(page, { timeout: 30000 });
await AppReady.waitForNetworkIdle(page);

Nützlich in TestSteps, die sicherstellen müssen, dass die Anwendung fertig geladen ist, bevor interagiert wird. Reduziert Flakiness von “Click war zu früh”-Szenarien.


7. Filesystem / I_Filesystem

File-I/O-Utilities. Der Filesystem-Export ist intern; der I_Filesystem-Export ist das Public-Interface für 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

Strukturiertes Logging, integriert mit dem Test-Report.

import { Logger } from '@meintest/cc-testframework';

Logger.info('Starte Test-Setup');
Logger.warn('Falle auf zweite Selector-Strategie zurück');
Logger.error('Element nach Retries nicht gefunden');

Output erscheint sowohl in der Konsole als auch in den per-Test-Artefakten. Statt console.log für jegliche test-relevante Meldungen verwenden.


9. I_PasswordManager

Passwort-Abruf — nützlich für Tests, die Credentials brauchen, ohne sie hart zu codieren.

import { I_PasswordManager } from '@meintest/cc-testframework';

const password = await I_PasswordManager.TS_GetPassword('TestUser');

Die Implementierung liest aus einem konfigurierten Secret-Store (Env-Vars, Keystore oder verschlüsselte Datei — je nach Setup). Niemals das Ergebnis loggen.


10. I_Utils

Misc-Utilities — Datums-Formatierung, 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"

Datums-Formatierung ist besonders nützlich für eindeutige Email-Adressen in Registrierungs-Tests: ${user}${I_Utils.GetDate('ssms')}@mailinator.com.


11. Self-Healing-Exports (Core.xpath, SelfHealingWritebackReporter, withCoordinatedWrite)

Locator-Reparatur-Infrastruktur — siehe Self-Healing Locators für die vollständige Setup-Anleitung, dieser Abschnitt listet nur die Exports selbst.

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';

// In einem Control — einen Locator taggen, damit er writeback-fähig wird
Core.xpath`(//*[@ControlType='ControlType.DataItem'])[${rowIndex}]`;

// Am Anfang einer TC_*.spec.ts-Datei — dem TestCase eine stabile, umbenennungssichere ID geben
Core.setTestCaseId('tc_<dein-szenario>');
  • Core.setTestCaseId(uid: string): void — setzt eine stabile, dateisystem-sichere ID für den aktuellen TestCase, über die dessen Referenz-Asset-Ordner (7_Assets/<uid>/) unabhängig vom Playwright-Test-Titel referenziert wird. Empfohlenes Slug-Format: tc_[a-z0-9-]{4,}. Siehe Self-Healing Locators — Einem TestCase eine stabile ID geben für wann/wo der Aufruf erfolgt und die vollständige Pfadauflösungs- und Migrations-Geschichte.
  • Core.getTestCaseId(): string | null — liest die über setTestCaseId gesetzte ID des aktuellen TestCase zurück; null, wenn keine gesetzt wurde.
  • Core.xpath — ein Tagged-Template-Literal. Erzeugt exakt denselben String wie ein äquivalentes rohes Template-Literal; der Tag erlaubt dem Framework zusätzlich, den Locator bis zu seiner Datei:Zeile zurückzuverfolgen für Self-Healing. Rein additiv — ungetaggte Locators funktionieren unverändert weiter.
  • SelfHealingWritebackReporter — eine Playwright-Reporter-Klasse, die du im reporter-Array deiner playwright.config.ts registrierst — oder die baseConfig automatisch für dich registriert, sobald SELF_HEALING_WRITEBACK/_DISCOVERY gesetzt ist (siehe Sektion 4). Läuft einmalig am Ende des Test-Laufs und persistiert erfolgreiche Heilungen in ihre jeweiligen Control-Dateien (Opt-in via SELF_HEALING_WRITEBACK=true, als Umgebungs-Variable oder über die persistierte Config-Datei). Leitet ihre Schreibzugriffe über withCoordinatedWrite (siehe unten), sodass sie nie mit einem Kollegen kollidiert, der dieselbe Datei bearbeitet — siehe Self-Healing Locators — Multi-User-Koordination. Auch erreichbar über den dedizierten Sub-Pfad-Export @meintest/cc-testframework/reporter/self-healing-writeback (sowohl ein benannter als auch ein Default-Export, beide zur selben Klasse aufgelöst) für ein Projekt mit eigenem reporter[]-Array, das nicht das komplette Paket-Barrel importiert — siehe Self-Healing Locators — Den Reporter manuell registrieren. Der ältere, wildcard-abgeleitete Pfad @meintest/cc-testframework/Reporter/SelfHealingWritebackReporter (großgeschrieben) löst für bestehende Configs weiterhin auf; der kleingeschriebene Sub-Pfad oben ist ab jetzt die kanonische Form.
  • WritebackResult (nur Typ) — die Form eines einzelnen Writeback-Ergebnisses (pro geheiltem Locator: angewendet vs. übersprungen, und warum); exportiert für fortgeschrittenes Tooling, das den Writeback-Schritt programmatisch umschließt oder inspiziert. Die meisten Kunden brauchen nur die JSON-Report-Datei (.self-healing-report.json), nicht diesen Typ direkt.
  • withCoordinatedWrite(files, writeFn) — ein wiederverwendbarer Koordinations-Wrapper: führt writeFn unter einem Git-basierten Lock aus, sodass gleichzeitige Schreibzugriffe auf dieselben getrackten Dateien (von einem Kollegen, einem anderen CI-Job oder anderem Code, der auf derselben Funktion aufbaut) nie einen Merge-Konflikt erzeugen. In Projekten ohne origin-Remote degradiert er zu einem Overhead-freien No-op. Die meisten Kunden rufen das nie direkt auf — SelfHealingWritebackReporter nutzt es bereits intern —, aber es ist exportiert für Teams, die eigenes Agent-gesteuertes Schreib-Tooling auf dem Framework aufbauen.
  • WriteResult (nur Typ) — die Rückgabe-Form von withCoordinatedWrite: status ('applied' | 'skipped' | 'partial' | 'error'), mode ('local-only' | 'coordinated'), die Liste filesWritten, und — bei einem Skip — lockedFiles mit Owner und Erwerbszeitpunkt jedes blockierenden Locks.
  • getProjectConfig(startDir?) — liest und validiert die projekt-lokale Config-Datei .cc-testframework.local.json (aufwärts gesucht ab startDir, Default process.cwd()). Liefert null bei fehlender Datei, ungültigem JSON, nicht unterstützter schemaVersion, oder wenn kein Repo-Root gefunden wurde — wirft nie. Die meisten Kunden nutzen dafür die CLI npx cc-testframework config self-healing <action> (siehe Self-Healing Locators — Setup dauerhaft speichern) statt das direkt aufzurufen.
  • resolveSelfHealingConfig() — merged die Umgebungs-Variablen SELF_HEALING_WRITEBACK / SELF_HEALING_WRITEBACK_DISCOVERY / SELF_HEALING_AGENT_IDENTITY mit dem selfHealing-Block der Config-Datei zu einer SelfHealingResolution, nach derselben Priority-Chain (Env-Var vor Config-Datei vor Default), die auch Credential Management (Abschnitt “Priority-Chain für die automatische Auflösung”) befolgt.
  • PROJECT_CONFIG_FILE_NAME — der wörtliche Dateiname .cc-testframework.local.json, exportiert, damit Tooling ihn nicht hardcoden muss.
  • ProjectConfig (nur Typ) — die On-Disk-Form: schemaVersion: 1, optional selfHealing: { enabled?, discoveryMode?, agentIdentity? }.
  • SelfHealingResolution (nur Typ) — das gemergte Ergebnis: enabled, discoveryMode, agentIdentity: string | null, plus ein source-Objekt, das für jeden der drei Werte benennt, welche Stufe ('env' | 'config' | 'default') ihn geliefert hat.

12. Custom-Step-Exports (discoverCustomSteps, validateCustomStep, runAuthoringAgent, runAuthorCli, runAuthorTestRunner)

Konvention, Discovery, Validierung, automatisierte Implementierung und der Test-Case-getriebene Runtime-Authoring-Loop für Steps ohne bisherige automatisierte Implementierung — siehe Custom Steps für die vollständige Authoring-Anleitung, dieser Abschnitt listet nur die Exports selbst.

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 }); // bootet die App selbst, kein treeDigest nötig

const testResult = await runAuthorTestRunner({ testPath: 'pm/3_Cases/TC_<DeinAblauf>.spec.ts' });
  • discoverCustomSteps(rootDir) — durchsucht <rootDir>/2_Apps/*/2_Steps/*.ts nach TS_*-Exports mit @custom-JSDoc-Block und liefert pro Step eine CustomStepDiscovery, in Datei-Reihenfolge. Liefert ein leeres Array, wenn 2_Apps nicht existiert. Doppelte @step-IDs über Dateien hinweg werden als Warnung geloggt, beide werden trotzdem zurückgegeben.
  • validateCustomStep(discovery) — prüft eine einzelne CustomStepDiscovery auf gängige Authoring-Fehler und liefert ein ValidationResult mit getrennten errors- (blockierend) und warnings-Arrays (informativ).
  • CustomSpec (nur Typ) — der geparste @custom-JSDoc-Block: description, intent ('check' | 'action'), optional target ({ view, section, control, label }), optional property / operator / expected, sowie die erforderliche stepId.
  • CustomStepDiscovery (nur Typ) — ein entdeckter Step: file, stepName, line, das geparste spec sowie isNotImplemented (true, solange der Body noch den “not yet automated”-Platzhalter wirft).
  • ValidationResult (nur Typ) — isValid, warnings: string[], errors: string[].
  • runAuthoringAgent(options) — entdeckt, validiert und implementiert (pro Step, wo das Vertrauen es zulässt) Custom Steps anhand eines übergebenen UI-Baum-Digests. Siehe Custom Steps — Automatisierte Implementierung für das vollständige Setup, die Konfigurations-Env-Vars und die Skip-Reason-Tabelle.
  • AnthropicElementFinderClient — die Standard-IElementFinderClient-Implementierung, die die Anthropic-API aufruft (BYOK via ANTHROPIC_API_KEY, Modell-Override via AI_VISION_MODEL oder npx cc-testframework set-ai-vision-model <model>). Die meisten Kunden konstruieren das nie direkt — runAuthoringAgent tut das intern, sofern du nicht über erweiterte Optionen einen eigenen Client übergibst.
  • AuthoringAgentOptions (nur Typ) — rootDir, treeDigest, optional dryRun / maxSteps / onProgress / anthropicApiKey.
  • AuthoringProgressEvent (nur Typ) — eine gestreamte Progress-Benachrichtigung: phase ('discover' | 'validate' | 'infer' | 'generate' | 'write' | 'done'), optional step, message, optional detail.
  • AuthoringResult (nur Typ) — der Rückgabewert von runAuthoringAgent: schemaVersion: 1, runTimestamp, mode ('applied' | 'dry-run'), totalDiscovered, applied: AppliedStep[], skipped: SkippedStep[], errors: ErrorStep[], optional commitSha, optional lockedByHumans.
  • AppliedStep / SkippedStep / ErrorStep (nur Typ) — je ein Eintrag in AuthoringResult.applied / .skipped / .errors; siehe Custom Steps (Abschnitt “Warum ein Step übersprungen wird”) für die vollständige Aufzählung von SkippedStep.reason.
  • IElementFinderClient / ElementFinderResult (nur Typ) — der austauschbare Vision-Client-Contract hinter AnthropicElementFinderClient, für Teams mit eigenem Element-Finding-Backend.
  • GeneratedImplementation (nur Typ) — die Form, die der interne Code-Generator von runAuthoringAgent erzeugt, bevor sie in den Body eines Custom Steps geschrieben wird; exportiert für fortgeschrittenes Tooling, das eine generierte Implementierung vor dem Anwenden inspizieren will.
  • runAuthorCli(options) — die Logik hinter npx cc-testframework author, exportiert für Teams, die sie programmatisch aufrufen wollen statt über die Shell. Läuft in einem von zwei sich gegenseitig ausschließenden Modi, je nachdem welche Option gesetzt ist — Runtime (options.testPath, delegiert an runAuthorTestRunner) oder Batch (options.batchMode: true + options.app, löst die Runtime-Strategie der App auf, startet eine Session, erfasst das UI-Baum-Digest, ruft runAuthoringAgent auf, persistiert das Ergebnis als JSON und schließt die Session). Siehe Custom Steps — Der Agent als Kommandozeilen-Befehl für den vollständigen CLI-Contract (Optionen, Umgebungs-Variablen, Exit-Codes) beider Modi.
  • AuthorCliOptions (nur Typ) — app (nur erforderlich bei batchMode: true), testPath (erforderlich für Runtime-Modus) / batchMode, optional maxIterations / maxAttemptsPerStep (Runtime-Modus), optional testsRoot / appsConfig / maxSteps (Batch-Modus), plus dryRun / reportPath / anthropicApiKey gemeinsam für beide.
  • AuthorCliResult (nur Typ) — exitCode (0 | 1 | 2 | 3 | 4; 3 nur im Batch-Modus, 4 der Credential-bezogene Fehler aus Sektion 13), optional result: AuthoringResult (Batch-Modus) oder testResult: AuthorTestResult (Runtime-Modus) — nie beide, optional error (nur bei exitCode: 2 gesetzt).
  • runAuthorTestRunner(options) — der Runtime-Authoring-Loop: führt options.testPath iterativ als frischen Playwright-Subprozess pro Versuch aus, klassifiziert jeden Fehlschlag (classifyFailure) und ruft, für die drei behebbaren Kategorien, den Authoring-Agenten auf, bis der Test-Case besteht oder ein nicht behebbarer Fehler bzw. ein Circuit-Breaker greift. Persistiert einen AuthorTestResult-JSON-Report und gibt ihn immer zurück (wirft nicht bei einem behebbaren, aber fehlgeschlagenen Lauf). Siehe Custom Steps — Runtime-Modus.
  • AuthorTestRunnerOptions (nur Typ) — testPath (erforderlich), optional projectRoot / maxIterations / maxAttemptsPerStep / dryRun / reportPath / anthropicApiKey / onProgress.
  • AuthorTestResult (nur Typ) — 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[], optional credentialIssues: CredentialIssueRecord[] — gesetzt, wenn finalStatus === 'credential-error' (Credential-bezogene Einträge), und/oder immer dann, wenn die Null-Treffer-Guard während eines sonst normalen Laufs ausgelöst hat (kind: 'playwright-0-tests') — prüfe dieses Array auch nach einem scheinbaren finalStatus: 'passed'. Siehe Sektion 13.
  • AuthorTestProgressEvent (nur Typ) — ein gestreamtes Loop-Ereignis: 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, optional detail.
  • TestRunResult (nur Typ) — das Ergebnis eines Playwright-Subprozess-Laufs: passed, exitCode, stdout / stderr, optional geparster jsonReport, optional aus dessen Attachments extrahierte screenshotPath / htmlSnapshotPath.
  • FixContext / FixResult (nur Typ) — der Contract zwischen dem Loop und seinem Agent-Dispatch-Schritt: eine FailureClassification plus Artefakt-Pfade rein, ein Status 'applied' | 'skipped' | 'error' (plus optional commitSha) raus. Vor allem relevant für Teams, die einen eigenen _agentDispatcher-Test-Double oder eine eigene Dispatch-Strategie liefern.
  • IterationRecord / FixRecord (nur Typ) — das Ergebnis einer einzelnen Loop-Iteration bzw. das kumulierte Ergebnis einer einzelnen Fix-Stelle über den gesamten Lauf — beide innerhalb von AuthorTestResult persistiert.
  • classifyFailure(errorText, stackTrace?, testFileContent?) — reine, abhängigkeitsfreie Klassifizierung des Fehlertexts eines Playwright-Fehlschlags in einen von neun FailureKind-Werten (von denen nur drei fixable: true sind). Wird intern von der Standard-Verdrahtung von runAuthorTestRunner genutzt; eigenständig exportiert für Teams, die eigenes Fehler-Triage-Tooling darauf aufbauen. Siehe Custom Steps — Runtime-Modus für die Bedeutung jeder behebbaren Kategorie.
  • FailureClassification (nur Typ) — kind: FailureKind, fixable, optional file / line / stepName, originalError.
  • FailureKind (nur Typ) — die neunwertige 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?) — baut eine synthetische CustomStepDiscovery für einen bereits implementierten Step ohne @custom-Tag, damit dieselbe Authoring-Agent-Maschinerie, die Custom Steps implementiert, auch versuchen kann, einen Fix dafür zu identifizieren. Wird intern für die Klassifizierungen element-not-found-no-refid / timeout-no-refid genutzt; eigenständig exportiert für fortgeschrittenes Tooling.

13. Credential-Management-Exports (getCredential, setCredential, resolveCredentialWithPrompt)

Eine plattformübergreifende OS-Credential-Store-Abstraktion (Windows Credential Manager / macOS Keychain / Linux Secret Service) plus die gemeinsame Auflösungs-Logik, die von der Authoring-Agent-CLI genutzt wird — siehe Credential Management für die vollständige Setup-Anleitung (den config-CLI-Subcommand, Projekt-Scoping, Ablauf-Handling), dieser Abschnitt listet nur die Exports selbst.

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) { /* neu authentifizieren und einen frischen Wert setzen */ }
  • getCredential(name, options?) — liest den rohen Wert einer Zugangsdaten aus dem OS-Store (erst der projekt-gescopte Eintrag, dann der global-gescopte, je nach Default-Scope des Typs). Liefert null, wenn nichts gespeichert ist oder der OS-Store auf dieser Maschine nicht verfügbar ist — wirft nie für “nicht vorhanden”.
  • setCredential(name, value, options?) — validiert den Wert gegen die Format-Regel des Credential-Typs und speichert ihn als JSON-Envelope. options akzeptiert project / scope / expiresAt / source. Wirft, wenn ein projekt-gescopter Typ keinen auflösbaren Projekt-Kontext hat (nicht innerhalb eines Git-Repositorys mit origin-Remote) und keiner explizit übergeben wurde.
  • deleteCredential(name, options?) — entfernt eine gespeicherte Zugangsdaten. Liefert true, wenn tatsächlich ein Eintrag gelöscht wurde, false bei einem No-op (nichts war dort).
  • listCredentials() — listet jede gespeicherte Zugangsdaten als { name, scope, projectId? }-Tupel, unabhängig davon, ob name ein aktuell bekannter Credential-Typ ist.
  • getCredentialEnvelope(name, options?) — wie getCredential, liefert aber das vollständige CredentialEnvelope (Wert plus Ablauf-/Source-Metadaten) statt nur den Wert.
  • checkCredentialStatus(name, options?) — prüft Existenz und Ablauf, ohne den Wert offenzulegen — sicher zu loggen oder in einen Report aufzunehmen. Liefert ein CredentialStatus.
  • detectProjectId(cwd?) — löst die Id des aktuellen Projekts aus git config --get remote.origin.url auf, normalisiert über normalizeGitRemoteUrl. Liefert null außerhalb eines Git-Repositorys oder ohne origin-Remote — wirft nie.
  • normalizeGitRemoteUrl(url) — normalisiert eine SSH-/HTTPS-/git://-Remote-URL in die stabile <host>/<owner>/<repo>-Form, die als Projekt-Scoping-Key genutzt wird.
  • KNOWN_CREDENTIAL_TYPES — die statische Registry der zwei Credential-Typen, die das Framework heute kennt (anthropic-api-key, github-token), jeweils ein CredentialTypeSpec. Siehe Credential Management — Bekannte Credential-Typen.
  • CredentialScope (nur Typ) — 'global' | 'project'.
  • CredentialTypeSpec (nur Typ) — name, defaultScope, description, optional envVar, optional validate(value).
  • CredentialStore (nur Typ) — der { get, set, delete, list }-Contract, den ein eigener Backing-Store implementieren müsste; die meisten Kunden brauchen das nie, existiert für fortgeschrittenes Tooling/Tests.
  • CredentialEnvelope (nur Typ) — die On-Disk-Form: erforderliches v (der Wert), optional exp (ISO-8601-Ablauf), src (informativer Source-Tag), meta (für künftige Erweiterungen reserviert).
  • CredentialStatus (nur Typ) — exists, optional expired / expiresAt / secondsUntilExpiry / withinGracePeriod, optional source / scope / projectId.
  • resolveCredentialWithPrompt(name, options?) — die 5-stufige Priority-Chain, beschrieben in Credential Management (Abschnitt “Priority-Chain für die automatische Auflösung”): expliziter CLI-Arg-Wert, Env-Var, OS-Store (projekt-gescoped), OS-Store (global-gescoped), dann ein interaktiver First-Run-Prompt (nur TTY). Liefert null, wenn nirgends etwas aufgelöst werden konnte, auch in einem Non-TTY-Kontext, wo der Prompt nicht laufen kann.
  • CredentialSource (nur Typ) — 'cli-arg' | 'env' | 'store' | 'prompt', identifiziert, aus welcher Stufe ein ResolvedCredential stammt.
  • ResolvedCredential (nur Typ) — { value, source: CredentialSource }.
  • CredentialProgressPhase (nur Typ) — die sechs Credential-bezogenen Progress-Phasen: 'credential-expired' | 'credential-expiring-soon' | 'credential-missing' | 'credential-invalid' | 'interactive-prompt-required' | 'interactive-prompt-shown'.
  • CredentialResolverProgressEvent (nur Typ) — ein gestreamtes Ereignis: phase: CredentialProgressPhase, credential, message, optional expiredAt / secondsUntilExpiry / secondsExpired / source.
  • CredentialResolverOptions (nur Typ) — von resolveCredentialWithPrompt akzeptierte Optionen: optional cliArgValue / project / onProgress.
  • CredentialIssueRecord (nur Typ) — ein bemerkenswertes Problem, das in AuthorTestResult.credentialIssues festgehalten wird (siehe Sektion 12): kind ('credential-expired' | 'credential-expiring-soon' | 'credential-missing' | 'credential-invalid' | 'interactive-prompt-required' | 'playwright-0-tests'), message, sowie je nach kind optionale Felder — credential / expiredAt / source für die Credential-bezogenen Kinds, oder pattern (der --test-Pfad/das Pattern, das null Dateien getroffen hat) für 'playwright-0-tests'. Das Array dient diesem Runner als allgemeiner “bemerkenswertes Problem entdeckt”-Sammeltopf statt ein zweites, paralleles Array wachsen zu lassen.

14. Appium-URL-Bestimmung (resolveAppiumUrl)

Für eine Desktop-AUT (Windows, via Appium) löst das Framework die Appium-Server-URL intern auf, bevor eine Session eröffnet wird — dieser Export legt dieselbe Logik für fortgeschrittene Setups offen, z.B. einen eigenen 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?) — löst die effektive Appium-Server-URL über eine dreistufige Priority-Chain auf: der explizit übergebene Wert (das appiumUrl deiner AUT in GlobalConfig.apps, falls gesetzt), dann die Umgebungs-Variable APPIUM_URL, dann ein plattform-basierter Default (http://localhost:4723, wenn der Test-Prozess selbst nativ auf Windows läuft, sonst http://host.docker.internal:4723). Siehe FAQ — Wie findet das Framework den Appium-Server bei Desktop-Tests?.
  • AppiumUrlResolutionResult (nur Typ) — { url, source, platform }; source ist 'explicit-config' | 'env-var' | 'platform-default'.

15. Step-Description-i18n-Kataloge (.i18n.json-Konvention + Validator)

Kein TypeScript-Export — eine Datei-Konvention plus ein eigenständiges Validator-Skript, beide vom Paket @meintest/cc-testframework-templates ausgeliefert. Jede Step-Datei <StepFile>.ts kann eine gleichnamige Sibling-Datei <StepFile>.i18n.json haben, geschlüsselt nach exportiertem Step-Funktionsnamen, die Locale-Kürzel auf übersetzte Kopien des numberedStep/description/logTitle-Texts dieses Steps abbildet:

{
  "TS_Main_Button_Click": {
    "en": "On Main, click button '${label}'",
    "de": "Auf 'Main', Schaltfläche '${label}' klicken"
  }
}

Jeder Locale-Eintrag muss exakt dieselben ${paramName}-Platzhalter enthalten wie der en-Eintrag — die Quelle der Wahrheit des Katalogs. Ein fehlender Katalog, oder eine fehlende Locale darin, fällt auf Englisch zurück — das ist der normale Nicht-Fehler-Fall.

Aus pm/ heraus (sobald @meintest/cc-testframework-templates dort als Dev-Dependency installiert ist):

node ./node_modules/@meintest/cc-testframework-templates/bin/validate-i18n.js <Pfad>

Validiert die in jeder Step-Datei referenzierten KEYs gegen ihren Sibling-.i18n.json-Katalog: Jeder referenzierte KEY braucht einen en-Eintrag (fehlt er ganz, ist das ein Fehler; ein nicht referenzierter Katalog-Schlüssel ist eine Warnung), und jede andere Locale’s Platzhalter-Menge muss exakt mit der von en übereinstimmen. Exit-Code 0 bei Erfolg (auch “keine Kataloge gefunden” und reine Warnungs-Befunde), 1 bei jedem Fehler-Befund, mit einer nach Datei/Schlüssel/Locale aufgeschlüsselten Fehlerliste. Siehe Step-Description Localization für die vollständige Konvention, ein durchgerechnetes Beispiel und wie ein programmatischer Consumer den lokalisierten Text rendert.

Core.i18n — Laufzeit-Lokalisierungs-API

Anders als die Datei-Konvention oben ist Core.i18n ein echter TypeScript-Export — die Ausführung des Frameworks selbst liest ihn, um zu lokalisieren, was es selbst rendert (Playwrights Reports, Konsolen-Ausgabe, den Self-Healing-Writeback-Report). Siehe Laufzeit-Lokalisierung für die vollständige Prioritätskette und das Verhalten.

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 — löst die effektive Locale über die Prioritätskette auf: Core.i18n.setLocale(...)-Override, dann die Umgebungsvariable CC_TESTFRAMEWORK_LOCALE, dann GlobalConfig.language, dann der Standard 'en'.
  • Core.i18n.setLocale(locale: SupportedLocale): void — setzt einen expliziten In-Process-Override, vor allem für Tests oder eine einmalige Laufzeit-Umschaltung; gewinnt gegen die Umgebungsvariable und GlobalConfig.language.
  • Core.i18n.t(key: string, values?: Record<string, unknown>, options?: TranslateOptions): string — löst key gegen den Sibling-.i18n.json-Katalog der aufrufenden Step-Datei auf (automatisch aus dem Call-Stack erkannt, oder explizit via options.callerFile) und ersetzt jeden in values gefundenen ${paramName}-Platzhalter. options.fallback ist optional und wird NUR verwendet, wenn für den Aufrufer gar kein Katalog zu erwarten ist — z.B. zur Laufzeit generierte Custom-Steps (siehe TS_Custom.ts für das kanonische Muster). Nach der Standard-Konvention ist der en-Eintrag des Sibling-Katalogs die Quelle der Wahrheit, und fallback sollte weggelassen werden; fehlen für einen Schlüssel sowohl Katalog als auch fallback, loggt t() einmal pro fehlendem Schlüssel eine Warnung und gibt den rohen key literal zurück. Wirft nie.
  • SupportedLocale (nur Typ) — 'de' | 'en'.
  • TranslateOptions (nur Typ) — { callerFile?: string; fallback?: string }. fallback ist ein Custom-Step-only-Notausgang — siehe Wann fallback verwenden.

Core.defineTestStep und Core.defineExecutionStep akzeptieren ein optionales descriptionI18n-Feld als Alternative zu logTitle/description{ key, values(...args), fallback?(...args) } (typisiert als TestStepDescriptionI18nSpec / ExecutionStepDescriptionI18nSpec). fallback ist optional und, wie TranslateOptions.fallback oben, ein Custom-Step-only-Notausgang — ein Factory-basierter Step mit Katalog lässt es weg und verlässt sich stattdessen auf den en-Eintrag des Katalogs. Siehe Neue Steps mit i18n ausstatten für durchgerechnete Beispiele beider Formen — Factory-basiert und direkter t()-Aufruf.


16. Core.defineExecutionStep

App-Lifecycle-Steps. Baut aus einer deklarativen Factory einen tester-facing TS_Execution_<Action>-Step (Browser-Start/-Close/-Restart/-Navigate bei einer Web-AUT, Prozess-Start/-Close bei einer Desktop-AUT), ohne eine Playwright-page oder eine hartcodierte URL von Hand zu verdrahten. Siehe Deinen ersten TestCase schreiben — Step-Naming-Konvention dafür, wo das in die Gesamt-Namenskonvention passt.

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)appName ist der Schlüssel der App in GlobalConfig.apps, nicht Teil des Namens der generierten Funktion (der bleibt TS_Execution_Start, nicht TS_MyApp_Execution_Start — siehe Deinen ersten TestCase schreiben für das Warum); er sagt dem Framework, aus welchem App-Eintrag env aufzulösen ist. action ist ein Freiform-Label ('Start', 'Close', 'Restart', 'NavigateTo', …), das zur Lesbarkeit in die Identität der generierten Funktion einfließt — das Framework interpretiert den Wert nicht. factory(env) bekommt ein env-Objekt, das das Framework für dich zusammenstellt — aus GlobalConfig.apps[appName] — kein manuelles page-/url-/Playwright-Fixture-Verdrahten in deiner Step-Datei.

Family-aware env-Form, aufgelöst aus dem passenden GlobalConfig.apps[appName]-Eintrag:

App-Family env-Felder
Web (Playwright) page: Core.Page, url: string, appConfig: WebPlaywrightAppConfig
Desktop (Appium-Windows) executable: string, appiumUrl: string, appConfig: DesktopAppiumWindowsAppConfig

env.appConfig ist der vollständige, family-typisierte App-Eintrag aus GlobalConfig.apps[appName] — greif darauf zu, wenn ein Step ein Feld braucht, das die beiden Formen oben nicht direkt zeigen.

Warum die env-basierte Form: sie erlaubt es der UI eines Test-Management-Tools — oder einem Tester ohne TypeScript-Erfahrung —, einen App-Lifecycle-Step für eine gegebene App zu scaffolden, ohne je page, eine Playwright-Fixture oder eine hartcodierte URL zu tippen; das Framework löst das alles aus dem eigenen GlobalConfig-Eintrag der App auf. Siehe Custom Steps — Was ist ein Custom Step? dafür, wie sich das von einem handgeschriebenen oder Agent-generierten Custom Step unterscheidet.

Abwärtskompatibilität: die ältere 2-Argument-Form funktioniert unverändert weiter:

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 }),
    }),
);

Dieser Aufruf funktioniert weiterhin genau wie zuvor und gibt einmalig pro Call-Site eine Deprecation-Warnung aus (console.warn, dedupliziert nach Aufrufer-Datei:Zeile), die zur Migration auf die env-basierte Form rät — keine funktionale Änderung, kein erzwungenes Umschreiben.


17. Debug-Session-Exports (resolveDebugSession, runSessionCli)

Infrastruktur für die persistente Debug-Session — siehe Persistente Debug-Session fürs vollständige Setup, dieser Abschnitt listet nur die Exports selbst.

import { resolveDebugSession, runSessionCli } from '@meintest/cc-testframework';
import type { DebugSessionResolution, SessionCliDeps, SessionCliResult } from '@meintest/cc-testframework';
  • resolveDebugSession() — führt die Umgebungs-Variable CC_DEBUG_SESSION mit dem debugSession-Schlüssel der Config-Datei zu einer DebugSessionResolution zusammen, nach derselben Umgebungs-Variable-vor-Config-Datei-vor-Default-Prioritäts-Kette wie resolveSelfHealingConfig oben. Die meisten Kunden rufen das nie direkt auf — es treibt die eigene Attach-oder-Start-Entscheidung des Frameworks beim Start des Test-Runners.
  • DebugSessionResolution (nur Typ) — das zusammengeführte Ergebnis: enabled: boolean plus source: 'env' | 'config' | 'default'.
  • runSessionCli(argv, deps) — die Implementierung hinter npx cc-testframework session status/close (siehe Persistente Debug-Session — Die Session per CLI verwalten). Exportiert für fortgeschrittenes Tooling, das dieselbe Status-/Close-Logik programmatisch ansteuern will; die meisten Kunden nutzen direkt die CLI.
  • SessionCliDeps (nur Typ) — die injizierbare Dependency-Oberfläche, die runSessionCli entgegennimmt (Zustand lesen/löschen, Endpoint-Erreichbarkeits-Check, Prozess-Terminierung, Ausgabe-Senken); nur relevant, wenn runSessionCli direkt aufgerufen wird.
  • SessionCliResult (nur Typ) — { exitCode: number }, das Ergebnis eines runSessionCli-Aufrufs.

Re-Exports zur Bequemlichkeit

Das Framework re-exportiert auch gängige Playwright- und Node-Teile, damit du keine separaten Imports in deinen Test-Dateien brauchst:

import { test, expect, fs, path, moment, pdfParse, csvParser, authenticator, crypto }
    from '@meintest/cc-testframework';

Heißt: ein typischer TestCase hat eine Import-Zeile@GlobalRef (dein Barrel) — und alles ist via Project.Core.* und Project.<DeineApp>.* verfügbar.


Vollständige Oberfläche entdecken

Wenn du einen Export brauchst, der oben nicht aufgeführt ist: die TypeScript-Deklarationen unter pm/node_modules/@meintest/cc-testframework/dist/References.d.ts sind die maßgebliche Liste. Deine IDE (VS Code, WebStorm, etc.) wird von dort auto-vervollständigen.


📧 Brauchst du eine Funktion, die’s nicht gibt? Vorschlag per jens.szelag@itsbusiness.ch.

itsbusiness AG · Bern · Schweiz