@testspectra/matchers 1.0.70 → 1.1.0-rc.0
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/LICENSE.md +48 -0
- package/dist/__tests__/intercept.test.d.ts +1 -0
- package/dist/__tests__/intercept.test.js +183 -0
- package/dist/__tests__/matcher-contracts.test.d.ts +1 -0
- package/dist/__tests__/matcher-contracts.test.js +498 -0
- package/dist/__tests__/matchers.test.d.ts +1 -0
- package/dist/__tests__/matchers.test.js +161 -0
- package/dist/contract.d.ts +141 -0
- package/dist/contract.js +10 -0
- package/dist/index.d.ts +4 -21
- package/dist/index.js +4 -21
- package/dist/intercept/cdp-handler.d.ts +22 -0
- package/dist/intercept/cdp-handler.js +123 -0
- package/dist/intercept/index.d.ts +4 -0
- package/dist/intercept/index.js +4 -0
- package/dist/intercept/mock-handle.d.ts +49 -0
- package/dist/intercept/mock-handle.js +124 -0
- package/dist/intercept/mock-registry.d.ts +18 -0
- package/dist/intercept/mock-registry.js +97 -0
- package/dist/intercept/types.d.ts +43 -0
- package/dist/intercept/types.js +1 -0
- package/dist/matchers.d.ts +15 -4
- package/dist/matchers.js +609 -81
- package/dist/proto.d.ts +18 -283
- package/dist/proto.js +1 -114
- package/dist/reporter.d.ts +30 -0
- package/dist/reporter.js +97 -0
- package/dist/runner/collection.d.ts +33 -20
- package/dist/runner/collection.js +104 -26
- package/dist/runner/single.d.ts +125 -34
- package/dist/runner/single.js +290 -55
- package/dist/semantic.d.ts +11 -0
- package/dist/semantic.js +141 -0
- package/dist/spectra.d.ts +32 -8
- package/dist/spectra.js +157 -40
- package/dist/types.d.ts +1226 -28
- package/package.json +13 -8
- package/src/contract.ts +182 -0
- package/src/index.ts +4 -22
- package/src/proto.ts +22 -433
- package/src/runtime/assertions.ts +450 -0
- package/src/runtime/element_actions.ts +169 -0
- package/src/runtime/element_proxy.ts +159 -0
- package/src/runtime/element_state.ts +91 -0
- package/src/runtime/spectra.ts +109 -0
- package/src/types.ts +1424 -96
- package/tsconfig.json +2 -2
- package/src/matchers.ts +0 -146
- package/src/runner/collection.ts +0 -153
- package/src/runner/single.ts +0 -301
- package/src/spectra.ts +0 -376
package/package.json
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testspectra/matchers",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0-rc.0",
|
|
4
|
+
"description": "Canonical TypeScript contracts and ambient type definitions for TestSpectra",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
7
14
|
"scripts": {
|
|
8
15
|
"build": "tsc",
|
|
9
16
|
"watch": "tsc -w",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
10
18
|
"prepublishOnly": "npm run build"
|
|
11
19
|
},
|
|
12
20
|
"devDependencies": {
|
|
13
|
-
"@types/node": "
|
|
14
|
-
"
|
|
15
|
-
"@wdio/mocha-framework": "^9.2.8",
|
|
16
|
-
"webdriverio": "^9.2.8",
|
|
17
|
-
"typescript": "^5.4.5"
|
|
21
|
+
"@types/node": "catalog:",
|
|
22
|
+
"typescript": "catalog:"
|
|
18
23
|
},
|
|
19
24
|
"type": "module",
|
|
20
|
-
"license": "
|
|
25
|
+
"license": "SEE LICENSE IN LICENSE.md"
|
|
21
26
|
}
|
package/src/contract.ts
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* # PlatformDriverBridge Contract
|
|
4
|
+
*
|
|
5
|
+
* The unified abstract driver contract consumed by `@testspectra/matchers` element proxies,
|
|
6
|
+
* fluent matchers, and the `Spectra` automation object. Every platform-specific driver
|
|
7
|
+
* (`WebCdpDriverBridge`, `AndroidTcpDriverBridge`) implements this interface so that the
|
|
8
|
+
* DSL layer contains zero platform branching.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
CDPNetworkEntry,
|
|
13
|
+
MockInterceptHandle,
|
|
14
|
+
MockRule,
|
|
15
|
+
ScrollOptions,
|
|
16
|
+
SpectraBrowserBridge,
|
|
17
|
+
SwipeOptions,
|
|
18
|
+
} from './types.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Runtime configuration injected by the Rust orchestrator via `globalThis.__TESTSPECTRA_CONFIG__`.
|
|
22
|
+
*/
|
|
23
|
+
export interface RuntimeWorkerConfig {
|
|
24
|
+
workerId?: number;
|
|
25
|
+
rootDir: string;
|
|
26
|
+
testFilePath?: string;
|
|
27
|
+
testFiles?: Array<{ id: string; title: string; filePath: string; suite: string }>;
|
|
28
|
+
activePlatform: string;
|
|
29
|
+
configuredBaseUrl: string;
|
|
30
|
+
cdpWsUrl: string;
|
|
31
|
+
driverServerUrl: string;
|
|
32
|
+
manifest?: Record<string, any>;
|
|
33
|
+
/** Target app package (Android). Paired with androidSerial/adbPath for on-demand adb actions. */
|
|
34
|
+
appPackage?: string;
|
|
35
|
+
/** Target adb device serial for this worker (Android only). */
|
|
36
|
+
androidSerial?: string;
|
|
37
|
+
/** Resolved `adb` binary path (Android only), paired with androidSerial above. */
|
|
38
|
+
adbPath?: string;
|
|
39
|
+
/** Host port this worker's own MobileMockProxyServer should listen on (Android only) — derived
|
|
40
|
+
* per-device the same way androidSerial/the driver-server port already are, so each device in
|
|
41
|
+
* a multi-device run gets its own proxy instead of every worker racing for one shared port. */
|
|
42
|
+
mockProxyPort?: number;
|
|
43
|
+
implicitWaitMs?: number;
|
|
44
|
+
timeoutMs?: number;
|
|
45
|
+
stepDelayMs?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Cross-cutting shared runtime state injected into the assembled worker script.
|
|
50
|
+
*
|
|
51
|
+
* The worker runtime is emitted as a single self-contained TypeScript module (concatenated
|
|
52
|
+
* by the Rust orchestrator). This object is created once in the harness prelude and mutated
|
|
53
|
+
* in place (`activeDriver` is bound after the platform bridge is instantiated), so fragments
|
|
54
|
+
* access it lazily at call-time through `globalThis.__TS_RUNTIME__`.
|
|
55
|
+
*/
|
|
56
|
+
export interface RuntimeContext {
|
|
57
|
+
config: RuntimeWorkerConfig;
|
|
58
|
+
activeDriver: PlatformDriverBridge | null;
|
|
59
|
+
mobileMockRules: MockRule[];
|
|
60
|
+
lastFocusedSelector: string | null;
|
|
61
|
+
currentTargetItem?: any;
|
|
62
|
+
|
|
63
|
+
emitEvent(tag: string, payload: string): void;
|
|
64
|
+
trackStep<T>(
|
|
65
|
+
category: 'action' | 'assertion' | 'browser',
|
|
66
|
+
payloadObj: Record<string, any>,
|
|
67
|
+
fn: () => Promise<T>,
|
|
68
|
+
): Promise<T>;
|
|
69
|
+
pollCondition(fn: () => Promise<boolean> | boolean, timeoutMs?: number, intervalMs?: number): Promise<boolean>;
|
|
70
|
+
getImplicitWaitMs(): number;
|
|
71
|
+
getAssertionTimeoutMs(): number;
|
|
72
|
+
matchesUrlPattern(pattern: string, url: string): boolean;
|
|
73
|
+
createMockHandle(rule: MockRule): MockInterceptHandle;
|
|
74
|
+
parseMockRule(patternOrOptions?: any, maybeMethodOrHandler?: any, maybeFixture?: any, maybeOptions?: any): MockRule;
|
|
75
|
+
|
|
76
|
+
// Opt-in duration logging (see core/orchestrator/src/worker/prelude.ts). Present at runtime only
|
|
77
|
+
// when TESTSPECTRA_DURATION_LOG is set; the wrappers are pass-through no-ops otherwise.
|
|
78
|
+
recordDuration?: (label: string, category: string, durationMs: number, extra?: Record<string, unknown>) => void;
|
|
79
|
+
withDuration?: <T>(
|
|
80
|
+
label: string,
|
|
81
|
+
category: string,
|
|
82
|
+
fn: () => Promise<T>,
|
|
83
|
+
extra?: Record<string, unknown>,
|
|
84
|
+
) => Promise<T>;
|
|
85
|
+
durationLogPath?: string | null;
|
|
86
|
+
|
|
87
|
+
// Matchers runtime factories — registered onto the context by the `tools/matchers` fragments
|
|
88
|
+
// at load time, then consumed by sibling fragments (concatenated single-scope assembly).
|
|
89
|
+
createElementActions?: (selector: string, index: number | null) => Record<string, any>;
|
|
90
|
+
createElementState?: (selector: string, index: number | null) => Record<string, any>;
|
|
91
|
+
createElementAssertions?: (selector: string, index: number | null, state: Record<string, any>) => Record<string, any>;
|
|
92
|
+
createElementProxy?: (selector: string, index?: number | null) => any;
|
|
93
|
+
createCollectionProxy?: (selector: string) => any;
|
|
94
|
+
resolveTargetProxy?: (target: any) => any;
|
|
95
|
+
buildSpectra?: () => any;
|
|
96
|
+
|
|
97
|
+
// Platform driver classes — registered by the driver bridge fragments at load time.
|
|
98
|
+
cdpBridgeClass?: any;
|
|
99
|
+
androidBridgeClass?: any;
|
|
100
|
+
mobileMockProxyClass?: any;
|
|
101
|
+
mobileMockProxy?: any;
|
|
102
|
+
|
|
103
|
+
// BDD harness lifecycle hooks & entrypoints — `bdd_runner.ts` owns the hook slots and
|
|
104
|
+
// `runSuite`; `auto_import.ts` owns `bootstrapEnvironment`. Routed through this shared context
|
|
105
|
+
// (rather than plain module-scoped bindings) because the harness fragments are concatenated
|
|
106
|
+
// into one script by the Rust orchestrator but remain separate ES modules for unit testing.
|
|
107
|
+
beforeHook?: (() => Promise<void> | void) | null;
|
|
108
|
+
afterHook?: (() => Promise<void> | void) | null;
|
|
109
|
+
beforeEachHook?: (() => Promise<void> | void) | null;
|
|
110
|
+
afterEachHook?: (() => Promise<void> | void) | null;
|
|
111
|
+
bootstrapEnvironment?: () => Promise<void>;
|
|
112
|
+
runSuite?: () => Promise<void>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The unified platform driver contract. It extends the browser surface documented in
|
|
117
|
+
* `SpectraBrowserBridge` (navigation, script execution, network interception, browser-level
|
|
118
|
+
* assertions) with the element interaction and state-inspection methods needed by the DSL,
|
|
119
|
+
* so the `tools/matchers` layer never branches on `activePlatform`.
|
|
120
|
+
*/
|
|
121
|
+
export interface PlatformDriverBridge extends SpectraBrowserBridge {
|
|
122
|
+
/** Establishes connection to the underlying runtime endpoint (WebSocket / TCP Socket). */
|
|
123
|
+
connect(): Promise<void>;
|
|
124
|
+
|
|
125
|
+
/** Cleans up open connections, servers, and listeners. */
|
|
126
|
+
close(): Promise<void>;
|
|
127
|
+
|
|
128
|
+
/** Navigates to target URL (Web) or Activity / Deep Link (Android). */
|
|
129
|
+
navigate(targetUrl: string): Promise<void>;
|
|
130
|
+
|
|
131
|
+
// --- Element Actions ---
|
|
132
|
+
click(selector: string, index?: number | null): Promise<void>;
|
|
133
|
+
doubleClick(selector: string, index?: number | null): Promise<void>;
|
|
134
|
+
rightClick(selector: string, index?: number | null): Promise<void>;
|
|
135
|
+
setValue(selector: string, value: unknown, index?: number | null): Promise<void>;
|
|
136
|
+
clearValue(selector: string, index?: number | null): Promise<void>;
|
|
137
|
+
select(selector: string, option: string, index?: number | null): Promise<void>;
|
|
138
|
+
hover(selector: string, index?: number | null): Promise<void>;
|
|
139
|
+
focus(selector: string, index?: number | null): Promise<void>;
|
|
140
|
+
dragDrop(sourceSelector: string, targetSelector: string, sourceIndex?: number | null): Promise<void>;
|
|
141
|
+
longPress(selector: string, duration: number, index?: number | null): Promise<void>;
|
|
142
|
+
scrollIntoView(selector: string, index?: number | null): Promise<void>;
|
|
143
|
+
|
|
144
|
+
// --- Element State Inspection ---
|
|
145
|
+
getText(selector: string, index?: number | null): Promise<string>;
|
|
146
|
+
getValue(selector: string, index?: number | null): Promise<string>;
|
|
147
|
+
isDisplayed(selector: string, index?: number | null): Promise<boolean>;
|
|
148
|
+
isExisting(selector: string, index?: number | null): Promise<boolean>;
|
|
149
|
+
isEnabled(selector: string, index?: number | null): Promise<boolean>;
|
|
150
|
+
isSelected(selector: string, index?: number | null): Promise<boolean>;
|
|
151
|
+
isFocused(selector: string, index?: number | null): Promise<boolean>;
|
|
152
|
+
isClickable(selector: string, index?: number | null): Promise<boolean>;
|
|
153
|
+
hasClass(selector: string, className: string, index?: number | null): Promise<boolean>;
|
|
154
|
+
getAttribute(selector: string, name: string, index?: number | null): Promise<string | null>;
|
|
155
|
+
getCSSProperty(selector: string, name: string, index?: number | null): Promise<{ value: string }>;
|
|
156
|
+
count(selector: string): Promise<number>;
|
|
157
|
+
|
|
158
|
+
// --- Gestures & Keys ---
|
|
159
|
+
pressKey(key: string | number): Promise<void>;
|
|
160
|
+
scroll(options?: ScrollOptions): Promise<void>;
|
|
161
|
+
swipe(options: SwipeOptions): Promise<void>;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Grants an Android runtime permission on demand (e.g. right after confirming an in-app
|
|
165
|
+
* rationale dialog), via `adb shell pm grant` on the host. No-op on platforms without an
|
|
166
|
+
* OS-level runtime permission model (e.g. web).
|
|
167
|
+
*/
|
|
168
|
+
grantPermission(name: string): Promise<void>;
|
|
169
|
+
|
|
170
|
+
/** Clears all active network interception rules. */
|
|
171
|
+
clearMocks(): void;
|
|
172
|
+
|
|
173
|
+
// --- State accessed by the harness & tests ---
|
|
174
|
+
mockRules: MockRule[];
|
|
175
|
+
consoleErrors: string[];
|
|
176
|
+
recordedNetwork: CDPNetworkEntry[];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
declare global {
|
|
180
|
+
// eslint-disable-next-line no-var
|
|
181
|
+
var __TS_RUNTIME__: RuntimeContext;
|
|
182
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,27 +2,9 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* # @testspectra/matchers
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* ## Features:
|
|
8
|
-
* - **`Spectra`**: Unified automation API (`Spectra.get()`, `Spectra.getAll()`, `Spectra.click()`, `Spectra.type()`, etc.)
|
|
9
|
-
* - **`SingleElementRunner`**: Fluent interaction & assertion runner for single element targets
|
|
10
|
-
* - **`MultiElementRunner`**: Fluent assertion & traversal runner for multi-element collections
|
|
11
|
-
* - **Callable Matchers**: Ambient prototypes for WebdriverIO Element & Browser (`.shouldBeVisible()`, `.shouldHaveText()`, etc.)
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* import { Spectra } from "@testspectra/matchers";
|
|
16
|
-
*
|
|
17
|
-
* await Spectra.get("#login-btn").click().should("not.be.visible");
|
|
18
|
-
* await Spectra.getAll(".list-item").should("have.length.greaterThan", 0);
|
|
19
|
-
* ```
|
|
5
|
+
* Canonical TypeScript contracts, action/assertion types, and ambient type definitions for TestSpectra.
|
|
20
6
|
*/
|
|
21
7
|
|
|
22
|
-
export * from
|
|
23
|
-
export * from
|
|
24
|
-
export * from
|
|
25
|
-
export * from "./runner/collection.js";
|
|
26
|
-
export * from "./spectra.js";
|
|
27
|
-
export * from "./proto.js";
|
|
28
|
-
|
|
8
|
+
export * from './types.js';
|
|
9
|
+
export * from './contract.js';
|
|
10
|
+
export * from './proto.js';
|