prompttest 1.4.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -61
- package/TERMS.md +138 -134
- package/dist/bin/prompttest.js +520 -260
- package/dist/engine.bundle.js +240 -199
- package/dist/index.js +240 -199
- package/dist/lib/adaptive-timing.d.ts +55 -0
- package/dist/lib/adb.d.ts +28 -2
- package/dist/lib/ci.d.ts +49 -0
- package/dist/lib/jail-guard.d.ts +59 -0
- package/dist/lib/license.d.ts +51 -0
- package/dist/lib/profiler.d.ts +75 -0
- package/dist/lib/prompt-runner.d.ts +1 -0
- package/dist/lib/quiescence.d.ts +44 -0
- package/dist/lib/reporter.d.ts +14 -0
- package/dist/lib/runner-utils.d.ts +26 -0
- package/dist/lib/scaffold.d.ts +53 -0
- package/dist/lib/step-handlers.d.ts +2 -0
- package/docs/ARCHITECTURE.md +4 -4
- package/docs/CLI_CONTRACT.md +131 -0
- package/docs/CLI_STUDIO_CONTRACT.md +123 -0
- package/docs/PERFORMANCE_BASELINE.md +71 -0
- package/docs/PRODUCT_STATUS.md +56 -0
- package/docs/USER_MANUAL.md +6 -7
- package/package.json +10 -5
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module adaptive-timing
|
|
3
|
+
* @description Device-Aware Adaptive Dynamic Waiting & Auto-Profiling.
|
|
4
|
+
*
|
|
5
|
+
* Automatically balances test timing between ultra-fast physical devices (USB 3.0)
|
|
6
|
+
* and resource-constrained CI emulators (software-rendered VMs in GitHub Actions).
|
|
7
|
+
*
|
|
8
|
+
* Implements exponential backoff condition-driven polling with instant short-circuiting:
|
|
9
|
+
* fast devices finish immediately upon event completion, while slow emulators receive
|
|
10
|
+
* adaptive headroom without CPU exhaustion.
|
|
11
|
+
*/
|
|
12
|
+
import type { AndroidDriver } from './adb.js';
|
|
13
|
+
export interface DeviceProfile {
|
|
14
|
+
/** Whether the target device is an emulator / virtual device */
|
|
15
|
+
isEmulator: boolean;
|
|
16
|
+
/** Whether the process is executing inside a CI / CD environment (e.g. GitHub Actions) */
|
|
17
|
+
isCI: boolean;
|
|
18
|
+
/** Calculated dynamic velocity multiplier (1.0 = real device, 1.5 = local emulator, 2.5 = CI) */
|
|
19
|
+
velocityMultiplier: number;
|
|
20
|
+
/** Default timeout ceiling for UI element detection */
|
|
21
|
+
defaultTimeoutMs: number;
|
|
22
|
+
/** Extended timeout ceiling for multi-step transitions and cold loads */
|
|
23
|
+
extendedTimeoutMs: number;
|
|
24
|
+
/** Minimum stability duration for dual-sample quiescence verification */
|
|
25
|
+
quiescenceSettleMs: number;
|
|
26
|
+
/** Initial polling interval in milliseconds */
|
|
27
|
+
initialPollMs: number;
|
|
28
|
+
/** Maximum backoff polling interval in milliseconds */
|
|
29
|
+
maxPollIntervalMs: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Probes the connected device and host runtime to construct an adaptive timing profile.
|
|
33
|
+
* Cached per session so that subsequent steps reuse the profiled characteristics.
|
|
34
|
+
*
|
|
35
|
+
* @param driver - Android driver instance
|
|
36
|
+
* @param serial - Optional target device serial
|
|
37
|
+
*/
|
|
38
|
+
export declare function profileDeviceEnvironment(driver: AndroidDriver, serial?: string): Promise<DeviceProfile>;
|
|
39
|
+
/**
|
|
40
|
+
* Resets the cached device profile (primarily used in testing).
|
|
41
|
+
*/
|
|
42
|
+
export declare function resetDeviceProfile(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Polls an asynchronous condition using adaptive backoff with immediate short-circuiting.
|
|
45
|
+
*
|
|
46
|
+
* Fast devices short-circuit the instant the condition returns a truthy value.
|
|
47
|
+
* Slow emulators receive backoff polling that preserves CPU cycles for rendering.
|
|
48
|
+
*
|
|
49
|
+
* @param checkFn - Async callback returning a truthy value when the condition is met.
|
|
50
|
+
* @param timeoutMs - Maximum duration to wait before giving up.
|
|
51
|
+
* @param initialIntervalMs - Starting interval between checks.
|
|
52
|
+
* @param maxIntervalMs - Cap for the backoff interval.
|
|
53
|
+
* @returns The resolved value of the condition, or throws a timeout Error.
|
|
54
|
+
*/
|
|
55
|
+
export declare function pollWithAdaptiveBackoff<T>(checkFn: () => Promise<T | null | undefined | false>, timeoutMs: number, initialIntervalMs?: number, maxIntervalMs?: number): Promise<T>;
|
package/dist/lib/adb.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export interface AndroidDevice {
|
|
|
18
18
|
model?: string;
|
|
19
19
|
/** The product name of the device (optional) */
|
|
20
20
|
product?: string;
|
|
21
|
+
/** Transport connection type: 'usb' | 'wifi' | 'emulator' */
|
|
22
|
+
connectionType?: 'usb' | 'wifi' | 'emulator';
|
|
21
23
|
}
|
|
22
24
|
export interface DeviceMetrics {
|
|
23
25
|
battery?: {
|
|
@@ -42,6 +44,16 @@ export interface DeviceMetrics {
|
|
|
42
44
|
};
|
|
43
45
|
}
|
|
44
46
|
export declare function parseDeviceMetrics(batteryOutput: string, displayOutput: string, memoryOutput: string, graphicsOutput: string): DeviceMetrics;
|
|
47
|
+
/**
|
|
48
|
+
* Classifies a device connection type from its serial or model properties.
|
|
49
|
+
*/
|
|
50
|
+
export declare function classifyDeviceConnection(serial: string): 'usb' | 'wifi' | 'emulator';
|
|
51
|
+
/**
|
|
52
|
+
* Deduplicates multiple transport connections for the same physical Android hardware.
|
|
53
|
+
* Priority: USB > Wi-Fi (IP:port) > Wi-Fi (mDNS) > Emulator.
|
|
54
|
+
* Prevents simultaneous execution collisions on the same physical phone.
|
|
55
|
+
*/
|
|
56
|
+
export declare function deduplicateDevices(devices: AndroidDevice[]): AndroidDevice[];
|
|
45
57
|
/**
|
|
46
58
|
* AndroidDriver is responsible for executing ADB commands and handling device interactions.
|
|
47
59
|
* It manages the default targeted device, executes shell commands, extracts device state,
|
|
@@ -113,10 +125,23 @@ export declare class AndroidDriver {
|
|
|
113
125
|
*/
|
|
114
126
|
execAdbBinary(args: readonly string[] | string[], serial?: string, timeoutMs?: number): Promise<Buffer>;
|
|
115
127
|
/**
|
|
116
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Retrieves all raw connected Android devices from ADB without deduplication.
|
|
130
|
+
*/
|
|
131
|
+
getRawConnectedDevices(): Promise<AndroidDevice[]>;
|
|
132
|
+
/**
|
|
133
|
+
* Retrieves a list of currently connected Android devices.
|
|
134
|
+
* By default, deduplicates multiple transport channels for the same physical phone (prioritizing USB > Wi-Fi).
|
|
135
|
+
* @param options.deduplicate Set to false to return raw unfiltered endpoints.
|
|
117
136
|
* @returns A promise resolving to an array of AndroidDevice objects.
|
|
118
137
|
*/
|
|
119
|
-
getConnectedDevices(
|
|
138
|
+
getConnectedDevices(options?: {
|
|
139
|
+
deduplicate?: boolean;
|
|
140
|
+
}): Promise<AndroidDevice[]>;
|
|
141
|
+
/**
|
|
142
|
+
* Helper utility to deduplicate a list of AndroidDevice items.
|
|
143
|
+
*/
|
|
144
|
+
deduplicateDevices(devices: AndroidDevice[]): AndroidDevice[];
|
|
120
145
|
/**
|
|
121
146
|
* Wakes up the device screen and attempts to dismiss the keyguard.
|
|
122
147
|
* @param serial Optional target device serial.
|
|
@@ -406,6 +431,7 @@ export declare class AndroidDriver {
|
|
|
406
431
|
}, localDestPath: string, serial?: string): Promise<string>;
|
|
407
432
|
/**
|
|
408
433
|
* Checks if the virtual software keyboard (IME) is currently active and visible on screen.
|
|
434
|
+
* Uses fast shell grep filtering across Android IME & Window properties with resilient fallbacks.
|
|
409
435
|
* @param serial Optional target device serial.
|
|
410
436
|
* @returns Promise resolving to true if virtual keyboard is displayed.
|
|
411
437
|
*/
|
package/dist/lib/ci.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file ci.ts
|
|
3
|
+
* @description One-Command CI/CD Workflow Scaffolder for PromptTest (CI-01).
|
|
4
|
+
* Generates automated regression workflows for GitHub Actions (using reactivecircus/android-emulator-runner)
|
|
5
|
+
* and GitLab CI with headless emulator virtualization and artifact reporting.
|
|
6
|
+
*/
|
|
7
|
+
export type CiProvider = 'github-actions' | 'gitlab-ci';
|
|
8
|
+
export type CiTrigger = 'push' | 'pull_request' | 'schedule';
|
|
9
|
+
export type CiTarget = 'specs' | 'explore';
|
|
10
|
+
export interface CiWorkflowOptions {
|
|
11
|
+
/** Target CI provider platform */
|
|
12
|
+
provider?: CiProvider;
|
|
13
|
+
/** Trigger events to invoke the pipeline */
|
|
14
|
+
triggers?: CiTrigger[];
|
|
15
|
+
/** Execution mode: running specs vs autonomous exploration */
|
|
16
|
+
target?: CiTarget;
|
|
17
|
+
/** Spec file or glob pattern to execute */
|
|
18
|
+
specPattern?: string;
|
|
19
|
+
/** Target Android package name (required for explore target) */
|
|
20
|
+
packageName?: string;
|
|
21
|
+
/** Node.js runtime version to configure */
|
|
22
|
+
nodeVersion?: number;
|
|
23
|
+
/** Android API level for the emulator runner */
|
|
24
|
+
apiLevel?: number;
|
|
25
|
+
/** CPU architecture for the emulator image */
|
|
26
|
+
arch?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CiInitResult {
|
|
29
|
+
provider: CiProvider;
|
|
30
|
+
filePath: string;
|
|
31
|
+
fileName: string;
|
|
32
|
+
content: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Synthesizes a production-ready GitHub Actions YAML workflow
|
|
36
|
+
* utilizing headless Android emulator runners and artifact publishing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function generateGithubWorkflow(options?: CiWorkflowOptions): string;
|
|
39
|
+
/**
|
|
40
|
+
* Synthesizes a GitLab CI YAML configuration.
|
|
41
|
+
*/
|
|
42
|
+
export declare function generateGitlabWorkflow(options?: CiWorkflowOptions): string;
|
|
43
|
+
/**
|
|
44
|
+
* Scaffolds the CI workflow file directly into the repository directory.
|
|
45
|
+
*/
|
|
46
|
+
export declare function initCi(options?: CiWorkflowOptions & {
|
|
47
|
+
destDir?: string;
|
|
48
|
+
customFileName?: string;
|
|
49
|
+
}): Promise<CiInitResult>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module jail-guard
|
|
3
|
+
* @description Zero-Overhead In-Memory App Boundary Guardian for PromptTest.
|
|
4
|
+
*
|
|
5
|
+
* Enforces strict package boundary isolation to guarantee that automation
|
|
6
|
+
* NEVER sends touch, text, or gesture events into third-party personal apps
|
|
7
|
+
* (e.g. banking apps, email, browsers) or home screen launchers.
|
|
8
|
+
*
|
|
9
|
+
* Operates directly on the in-memory parsed hierarchy (UiNode.packageName)
|
|
10
|
+
* with 0 ms additional ADB overhead in normal operation.
|
|
11
|
+
*/
|
|
12
|
+
import type { UiNode } from './crawler.js';
|
|
13
|
+
import type { AndroidDriver } from './adb.js';
|
|
14
|
+
/**
|
|
15
|
+
* Registry of known Android OEM launchers and desktop interfaces.
|
|
16
|
+
*/
|
|
17
|
+
export declare const KNOWN_LAUNCHER_PACKAGES: readonly string[];
|
|
18
|
+
/**
|
|
19
|
+
* Registry of allowed Android system overlay and framework packages
|
|
20
|
+
* (keyboards, permission dialogs, autofill, package installer).
|
|
21
|
+
*/
|
|
22
|
+
export declare const KNOWN_SYSTEM_PACKAGES: readonly string[];
|
|
23
|
+
/**
|
|
24
|
+
* Checks if a given package name corresponds to a known launcher or desktop interface.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isLauncherPackage(pkg: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Checks if a given package name corresponds to an allowed Android system overlay.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isAllowedSystemPackage(pkg: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Determines whether a specific node's package belongs to the target app under test
|
|
33
|
+
* or an allowed system overlay (keyboard, permission prompt, system UI).
|
|
34
|
+
*
|
|
35
|
+
* @param nodePackage - The package name of the UI node being interacted with.
|
|
36
|
+
* @param targetPackage - The target application package under test (if specified).
|
|
37
|
+
*/
|
|
38
|
+
export declare function isTargetOrAllowedSystem(nodePackage?: string, targetPackage?: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Extracts the primary / foreground package from a flattened list of UiNodes.
|
|
41
|
+
* Evaluates non-system, interactive nodes first, then falls back to the root node.
|
|
42
|
+
*/
|
|
43
|
+
export declare function detectScreenPackage(nodes: UiNode[]): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Guards the app boundary: If an escape is detected (screen belongs to a launcher or foreign app),
|
|
46
|
+
* it blocks further actions, prevents unsafe back-presses on launchers, and brings the target app
|
|
47
|
+
* back to the foreground.
|
|
48
|
+
*
|
|
49
|
+
* @param nodes - In-memory UI nodes from current hierarchy dump.
|
|
50
|
+
* @param targetPackage - The expected target application package.
|
|
51
|
+
* @param driver - Android driver instance for containment recovery.
|
|
52
|
+
* @param serial - Optional target device serial.
|
|
53
|
+
* @returns Details on whether an escape occurred and whether recovery succeeded.
|
|
54
|
+
*/
|
|
55
|
+
export declare function guardAppBoundary(nodes: UiNode[], targetPackage: string, driver: AndroidDriver, serial?: string): Promise<{
|
|
56
|
+
escaped: boolean;
|
|
57
|
+
recovered: boolean;
|
|
58
|
+
currentPackage: string | null;
|
|
59
|
+
}>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module license
|
|
3
|
+
* @description
|
|
4
|
+
* Viral Report Attribution & Offline Pro Licensing (LC-01).
|
|
5
|
+
* Cryptographically validates offline license keys, stores activation state,
|
|
6
|
+
* and controls white-label report formatting.
|
|
7
|
+
*/
|
|
8
|
+
export interface LicensePayload {
|
|
9
|
+
tier: 'free' | 'pro' | 'enterprise';
|
|
10
|
+
holder: string;
|
|
11
|
+
issuedAt: number;
|
|
12
|
+
expiresAt: number;
|
|
13
|
+
whiteLabel: boolean;
|
|
14
|
+
features: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface LicenseInfo {
|
|
17
|
+
active: boolean;
|
|
18
|
+
tier: 'free' | 'pro' | 'enterprise';
|
|
19
|
+
holder?: string;
|
|
20
|
+
expiresAt?: string;
|
|
21
|
+
whiteLabel: boolean;
|
|
22
|
+
features: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generates a signed license key string for testing or license distribution.
|
|
26
|
+
*/
|
|
27
|
+
export declare function generateLicenseKey(payload: LicensePayload, secret?: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Cryptographically verifies an offline license key string.
|
|
30
|
+
*/
|
|
31
|
+
export declare function verifyLicenseKey(key: string, secret?: string): {
|
|
32
|
+
valid: boolean;
|
|
33
|
+
payload?: LicensePayload;
|
|
34
|
+
error?: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Activates and persists a valid license key locally.
|
|
38
|
+
*/
|
|
39
|
+
export declare function activateLicense(key: string, secret?: string): {
|
|
40
|
+
success: boolean;
|
|
41
|
+
message: string;
|
|
42
|
+
payload?: LicensePayload;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Retrieves current active license state.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getLicenseInfo(secret?: string): LicenseInfo;
|
|
48
|
+
/**
|
|
49
|
+
* Removes active license key and reverts to free tier.
|
|
50
|
+
*/
|
|
51
|
+
export declare function deactivateLicense(): boolean;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module profiler
|
|
3
|
+
* @description
|
|
4
|
+
* Real-Time Mobile Performance & FPS Profiler (PF-01).
|
|
5
|
+
* Samples `dumpsys gfxinfo <pkg>` and `dumpsys meminfo <pkg>` during test execution,
|
|
6
|
+
* computes frame rendering statistics, jank percentages, and memory growth.
|
|
7
|
+
*/
|
|
8
|
+
import { AndroidDriver } from './adb.js';
|
|
9
|
+
export interface FrameStats {
|
|
10
|
+
totalFrames: number;
|
|
11
|
+
jankyFrames: number;
|
|
12
|
+
jankPercentage: number;
|
|
13
|
+
p50Ms?: number;
|
|
14
|
+
p90Ms?: number;
|
|
15
|
+
p95Ms?: number;
|
|
16
|
+
p99Ms?: number;
|
|
17
|
+
missedVsync?: number;
|
|
18
|
+
slowUiThread?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface MemorySample {
|
|
21
|
+
timestamp: number;
|
|
22
|
+
stepIndex?: number;
|
|
23
|
+
stepName?: string;
|
|
24
|
+
totalPssKb: number;
|
|
25
|
+
nativeHeapKb?: number;
|
|
26
|
+
javaHeapKb?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface PerformanceReport {
|
|
29
|
+
packageName: string;
|
|
30
|
+
durationMs: number;
|
|
31
|
+
fpsCompliance: 'PASS' | 'WARN' | 'FAIL';
|
|
32
|
+
frames: FrameStats;
|
|
33
|
+
memory: {
|
|
34
|
+
startPssKb: number;
|
|
35
|
+
peakPssKb: number;
|
|
36
|
+
endPssKb: number;
|
|
37
|
+
deltaPssKb: number;
|
|
38
|
+
samples: MemorySample[];
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parses dumpsys gfxinfo stdout to extract frame counts, jank percentage, and percentile latencies.
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseGfxInfo(stdout: string): FrameStats;
|
|
45
|
+
/**
|
|
46
|
+
* Parses dumpsys meminfo stdout to extract Total PSS, Native Heap, and Java Heap values in KB.
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseMemInfo(stdout: string): {
|
|
49
|
+
totalPssKb: number;
|
|
50
|
+
nativeHeapKb?: number;
|
|
51
|
+
javaHeapKb?: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* PerformanceProfiler tracks real-time frame times, jank metrics, and memory growth.
|
|
55
|
+
*/
|
|
56
|
+
export declare class PerformanceProfiler {
|
|
57
|
+
private driver;
|
|
58
|
+
private serial?;
|
|
59
|
+
private packageName;
|
|
60
|
+
private startTime;
|
|
61
|
+
private memorySamples;
|
|
62
|
+
constructor(driver?: AndroidDriver, serial?: string);
|
|
63
|
+
/**
|
|
64
|
+
* Starts tracking performance for the target package.
|
|
65
|
+
*/
|
|
66
|
+
start(packageName: string): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Captures a discrete memory sample at a step transition.
|
|
69
|
+
*/
|
|
70
|
+
sample(stepIndex: number, stepName: string): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Finalizes tracking and returns the performance report.
|
|
73
|
+
*/
|
|
74
|
+
stop(): Promise<PerformanceReport>;
|
|
75
|
+
}
|
|
@@ -19,6 +19,7 @@ export declare class PromptRunner {
|
|
|
19
19
|
private lastHierarchy;
|
|
20
20
|
private screenDimensions;
|
|
21
21
|
private navBarHeight;
|
|
22
|
+
private targetPackage;
|
|
22
23
|
/**
|
|
23
24
|
* Initializes a new instance of the PromptRunner.
|
|
24
25
|
* Uses dependency injection for core services, defaulting to singletons if omitted.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module quiescence
|
|
3
|
+
* @description Dynamic Screen Quiescence & Idling Sentinel for PromptTest.
|
|
4
|
+
*
|
|
5
|
+
* Implements self-synchronizing stability detection inspired by Playwright's networkidle
|
|
6
|
+
* and Android Espresso's IdlingResource. Replaces fragile static timers with dual-sample
|
|
7
|
+
* layout stabilization and active in-flight loading sentinel checks.
|
|
8
|
+
*/
|
|
9
|
+
import type { UiNode } from './crawler.js';
|
|
10
|
+
import type { ExecutionContext } from './step-handlers.js';
|
|
11
|
+
export interface QuiescenceResult {
|
|
12
|
+
/** Whether the screen reached verified stability before the timeout */
|
|
13
|
+
settled: boolean;
|
|
14
|
+
/** Milliseconds elapsed during stabilization */
|
|
15
|
+
durationMs: number;
|
|
16
|
+
/** Final structural hash of the quiescent screen */
|
|
17
|
+
finalHash: string;
|
|
18
|
+
/** Flattened UI nodes of the quiescent screen */
|
|
19
|
+
flat: UiNode[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Inspects a flattened UI hierarchy to detect active in-flight network spinners,
|
|
23
|
+
* shimmers, progress bars, or server-waiting indicators.
|
|
24
|
+
*
|
|
25
|
+
* @param nodes - Flattened array of UiNodes
|
|
26
|
+
* @returns Status indicating whether loading is in progress and why.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isLoadingInProgress(nodes: UiNode[]): {
|
|
29
|
+
loading: boolean;
|
|
30
|
+
reason?: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Dynamically waits until the application screen achieves 100% quiescence:
|
|
34
|
+
* 1. All active loading indicators and spinners have vanished.
|
|
35
|
+
* 2. Two consecutive UI hierarchy snapshots yield matching structural hashes.
|
|
36
|
+
*
|
|
37
|
+
* Exits immediately once settled, saving seconds on fast devices while providing
|
|
38
|
+
* dynamic patience for slow network requests or cloud emulators.
|
|
39
|
+
*
|
|
40
|
+
* @param ctx - Execution context providing driver and hierarchy access.
|
|
41
|
+
* @param timeoutMs - Maximum wait ceiling (defaults to 4500ms).
|
|
42
|
+
* @param sampleIntervalMs - Interval between stability probe samples (defaults to 150ms).
|
|
43
|
+
*/
|
|
44
|
+
export declare function waitForQuiescence(ctx: ExecutionContext, timeoutMs?: number, sampleIntervalMs?: number): Promise<QuiescenceResult>;
|
package/dist/lib/reporter.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* JUnit XML. It plays a critical role in providing observability and
|
|
8
8
|
* traceability for autonomous test executions.
|
|
9
9
|
*/
|
|
10
|
+
import type { PerformanceReport } from './profiler.js';
|
|
10
11
|
/**
|
|
11
12
|
* Represents a single executed step or action during the test run.
|
|
12
13
|
*/
|
|
@@ -64,6 +65,14 @@ export interface QaReportData {
|
|
|
64
65
|
errorsDetected: string[];
|
|
65
66
|
/** Optional relative path to screen recording video (MP4). */
|
|
66
67
|
videoPath?: string;
|
|
68
|
+
/** Optional performance profiler metrics (PF-01). */
|
|
69
|
+
performanceMetrics?: PerformanceReport;
|
|
70
|
+
/** Details of any locators auto-healed during the test run */
|
|
71
|
+
healsApplied?: Array<{
|
|
72
|
+
original: string;
|
|
73
|
+
healed: string;
|
|
74
|
+
stepNumber: number;
|
|
75
|
+
}>;
|
|
67
76
|
/** The chronological list of all audit steps executed. */
|
|
68
77
|
steps: AuditStep[];
|
|
69
78
|
}
|
|
@@ -148,10 +157,15 @@ export declare class QaReporter implements Reporter {
|
|
|
148
157
|
private formats;
|
|
149
158
|
private videoPath?;
|
|
150
159
|
private embedScreenshots;
|
|
160
|
+
private performanceMetrics?;
|
|
151
161
|
private screenshotBuffers;
|
|
152
162
|
private stepListeners;
|
|
153
163
|
private completeListeners;
|
|
154
164
|
private errorListeners;
|
|
165
|
+
/**
|
|
166
|
+
* Sets the performance metrics collected by the profiler.
|
|
167
|
+
*/
|
|
168
|
+
setPerformanceMetrics(metrics: PerformanceReport): void;
|
|
155
169
|
/**
|
|
156
170
|
* Constructs a new QaReporter.
|
|
157
171
|
*
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* and diagnostic error generation.
|
|
8
8
|
*/
|
|
9
9
|
import { UiNode } from './crawler.js';
|
|
10
|
+
import { AndroidDriver } from './adb.js';
|
|
10
11
|
import { MemoryEngine } from './memory.js';
|
|
11
12
|
import type { QaReportData, Reporter, ReportFormat } from './reporter.js';
|
|
12
13
|
/**
|
|
@@ -73,6 +74,8 @@ export interface RunOptions {
|
|
|
73
74
|
tags?: string;
|
|
74
75
|
/** Emit machine-readable JSON execution summary to stdout. */
|
|
75
76
|
json?: boolean;
|
|
77
|
+
/** Real-time mobile performance & FPS profiler (PF-01). */
|
|
78
|
+
profile?: boolean;
|
|
76
79
|
}
|
|
77
80
|
/**
|
|
78
81
|
* Represents a single parsed action step in a plain-English test spec.
|
|
@@ -149,6 +152,8 @@ export interface PromptStep {
|
|
|
149
152
|
emailBodyContains?: string;
|
|
150
153
|
/** Healed locator provenance (original target string) */
|
|
151
154
|
healedFrom?: string;
|
|
155
|
+
/** Healed replacement string chosen by self-healing */
|
|
156
|
+
healedTo?: string;
|
|
152
157
|
}
|
|
153
158
|
/**
|
|
154
159
|
* Recursively expands `INCLUDE '<path>'` directives within a spec file.
|
|
@@ -288,3 +293,24 @@ export declare function createSyntheticReport(packageName: string, deviceId: str
|
|
|
288
293
|
* @returns Sanitized or masked string.
|
|
289
294
|
*/
|
|
290
295
|
export declare function maskSensitiveValue(value: string, target?: string): string;
|
|
296
|
+
export interface FailureTriageParams {
|
|
297
|
+
outputDir: string;
|
|
298
|
+
specName: string;
|
|
299
|
+
currentSpecName: string;
|
|
300
|
+
stepNum: number;
|
|
301
|
+
step: PromptStep;
|
|
302
|
+
error: Error;
|
|
303
|
+
stepStartTime: number;
|
|
304
|
+
startTime: number;
|
|
305
|
+
errorShot?: Buffer;
|
|
306
|
+
lastHierarchy?: {
|
|
307
|
+
xml?: string;
|
|
308
|
+
flat?: UiNode[];
|
|
309
|
+
} | null;
|
|
310
|
+
driver: AndroidDriver;
|
|
311
|
+
serial?: string;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Assembles failure triage folder, logs, hierarchy XML, match scores, and a ZIP archive.
|
|
315
|
+
*/
|
|
316
|
+
export declare function createFailureTriageBundle(params: FailureTriageParams): Promise<string | undefined>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module scaffold
|
|
3
|
+
* @description
|
|
4
|
+
* Inspects an active Android screen (or raw XML hierarchy) and synthesizes
|
|
5
|
+
* a starter plain-English test spec (.txt) containing Launch, Wait, form Type,
|
|
6
|
+
* button Tap, and element Verify steps.
|
|
7
|
+
*/
|
|
8
|
+
import { AndroidDriver } from './adb.js';
|
|
9
|
+
import { UiNode } from './crawler.js';
|
|
10
|
+
export interface ScaffoldOptions {
|
|
11
|
+
/** Target package to scaffold. Defaults to active foreground app */
|
|
12
|
+
packageName?: string;
|
|
13
|
+
/** Specific device serial to connect to */
|
|
14
|
+
deviceSerial?: string;
|
|
15
|
+
/** Explicit output path for the generated spec. Defaults to specs/<pkg>_scaffold.txt */
|
|
16
|
+
outputPath?: string;
|
|
17
|
+
/** Driver instance for dependency injection */
|
|
18
|
+
driver?: AndroidDriver;
|
|
19
|
+
/** Whether to explore interconnected screens and generate a multi-screen journey spec */
|
|
20
|
+
journey?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ScaffoldResult {
|
|
23
|
+
packageName: string;
|
|
24
|
+
specContent: string;
|
|
25
|
+
specPath?: string;
|
|
26
|
+
stepsCount: number;
|
|
27
|
+
inputCount: number;
|
|
28
|
+
buttonCount: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sanitizes node labels by stripping Private Use Area (PUA) icon font glyphs,
|
|
32
|
+
* special/non-printable unicode codepoints, and leading/trailing punctuation.
|
|
33
|
+
*/
|
|
34
|
+
export declare function sanitizeNodeLabel(label: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Derives a human-readable clean label from a UiNode.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getNodeLabel(node: UiNode): string;
|
|
39
|
+
/**
|
|
40
|
+
* Synthesizes a valid PromptTest specification from a flat list of UiNodes.
|
|
41
|
+
*/
|
|
42
|
+
export declare function scaffoldSpecFromNodes(nodes: UiNode[], packageName?: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Validates that every generated step in a spec string parses cleanly with the PromptTest DSL.
|
|
45
|
+
*/
|
|
46
|
+
export declare function validateScaffoldedSpec(specContent: string): {
|
|
47
|
+
valid: boolean;
|
|
48
|
+
errors: string[];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Connects to the device, retrieves screen hierarchy, and writes a scaffolded spec file.
|
|
52
|
+
*/
|
|
53
|
+
export declare function scaffoldSpec(options?: ScaffoldOptions): Promise<ScaffoldResult>;
|
|
@@ -21,6 +21,8 @@ import { PromptStep } from './prompt-runner.js';
|
|
|
21
21
|
* It encapsulates the driver instance, state cache, and common UI interaction logic.
|
|
22
22
|
*/
|
|
23
23
|
export interface ExecutionContext {
|
|
24
|
+
/** Target application package name under test (used for jail guard containment). */
|
|
25
|
+
targetPackage?: string;
|
|
24
26
|
/** The ADB-based Android UI driver used to interact with the device. */
|
|
25
27
|
driver: AndroidDriver;
|
|
26
28
|
/** Memory engine used to record and learn resilient locators over time. */
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -6,7 +6,7 @@ PromptTest is a zero-code, AI-assisted Android test automation and visual QA fra
|
|
|
6
6
|
|
|
7
7
|
## 1. High-Level Architecture Overview
|
|
8
8
|
|
|
9
|
-
PromptTest operates on a modular layered architecture where test scripts written in natural language or AST-driven directives are compiled, bound to live or synthetic data, executed against connected devices via an isolated locking layer, and reported with visual diffs and interactive HTML reports.
|
|
9
|
+
PromptTest operates on a modular layered architecture where test scripts written in natural language or AST-driven directives are compiled, bound to live or synthetic data, executed against connected devices via an isolated locking layer, and reported with visual diffs and interactive HTML reports. Current release boundaries are tracked in [PRODUCT_STATUS.md](PRODUCT_STATUS.md).
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
┌───────────────────────────────────────────────────────────┐
|
|
@@ -35,14 +35,14 @@ PromptTest operates on a modular layered architecture where test scripts written
|
|
|
35
35
|
│ │ │
|
|
36
36
|
┌──────▼──────────────────────▼──────────────────────▼──────┐
|
|
37
37
|
│ Visual Testing & Diagnostics │
|
|
38
|
-
│ lib/baseline.ts (
|
|
38
|
+
│ lib/baseline.ts (pixelmatch / PNG Diff) │
|
|
39
39
|
│ lib/explorer.ts (Autonomous Crawler) │
|
|
40
40
|
└─────────────────────────────┬─────────────────────────────┘
|
|
41
41
|
│
|
|
42
42
|
┌─────────────────────────────▼─────────────────────────────┐
|
|
43
43
|
│ Reporting & Observability │
|
|
44
44
|
│ lib/reporter.ts (HTML, JSON, JUnit XML, Markdown) │
|
|
45
|
-
│ lib/live-server.ts (
|
|
45
|
+
│ lib/live-server.ts (HTTP / SSE Live Monitor) │
|
|
46
46
|
└───────────────────────────────────────────────────────────┘
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -100,7 +100,7 @@ Instead of an unwieldy switch-case statement, execution is delegated to decouple
|
|
|
100
100
|
|
|
101
101
|
### 2.6 Visual Baselines & Computer Vision (`lib/baseline.ts`, `lib/explorer.ts`)
|
|
102
102
|
|
|
103
|
-
- Pixel-
|
|
103
|
+
- Pixel-level image diffing using `pixelmatch` and PNG decoding via `pngjs`.
|
|
104
104
|
- Configurable failure thresholds (e.g. `diffThreshold: 0.02` for 2% variance).
|
|
105
105
|
- Automatic bounding box masking for dynamic regions (e.g. status bar clocks, live feeds) to eliminate false positives in visual regression testing.
|
|
106
106
|
|