@testspectra/matchers 1.0.70 → 1.1.0-rc.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.
Files changed (51) hide show
  1. package/LICENSE.md +48 -0
  2. package/dist/__tests__/intercept.test.d.ts +1 -0
  3. package/dist/__tests__/intercept.test.js +183 -0
  4. package/dist/__tests__/matcher-contracts.test.d.ts +1 -0
  5. package/dist/__tests__/matcher-contracts.test.js +498 -0
  6. package/dist/__tests__/matchers.test.d.ts +1 -0
  7. package/dist/__tests__/matchers.test.js +161 -0
  8. package/dist/contract.d.ts +173 -0
  9. package/dist/contract.js +10 -0
  10. package/dist/index.d.ts +4 -21
  11. package/dist/index.js +4 -21
  12. package/dist/intercept/cdp-handler.d.ts +22 -0
  13. package/dist/intercept/cdp-handler.js +123 -0
  14. package/dist/intercept/index.d.ts +4 -0
  15. package/dist/intercept/index.js +4 -0
  16. package/dist/intercept/mock-handle.d.ts +49 -0
  17. package/dist/intercept/mock-handle.js +124 -0
  18. package/dist/intercept/mock-registry.d.ts +18 -0
  19. package/dist/intercept/mock-registry.js +97 -0
  20. package/dist/intercept/types.d.ts +43 -0
  21. package/dist/intercept/types.js +1 -0
  22. package/dist/matchers.d.ts +15 -4
  23. package/dist/matchers.js +609 -81
  24. package/dist/proto.d.ts +26 -283
  25. package/dist/proto.js +1 -114
  26. package/dist/reporter.d.ts +30 -0
  27. package/dist/reporter.js +97 -0
  28. package/dist/runner/collection.d.ts +33 -20
  29. package/dist/runner/collection.js +104 -26
  30. package/dist/runner/single.d.ts +125 -34
  31. package/dist/runner/single.js +290 -55
  32. package/dist/semantic.d.ts +11 -0
  33. package/dist/semantic.js +141 -0
  34. package/dist/spectra.d.ts +32 -8
  35. package/dist/spectra.js +157 -40
  36. package/dist/types.d.ts +1322 -24
  37. package/package.json +13 -8
  38. package/src/contract.ts +223 -0
  39. package/src/index.ts +4 -22
  40. package/src/proto.ts +30 -433
  41. package/src/runtime/assertions.ts +453 -0
  42. package/src/runtime/element_actions.ts +178 -0
  43. package/src/runtime/element_proxy.ts +200 -0
  44. package/src/runtime/element_state.ts +94 -0
  45. package/src/runtime/spectra.ts +110 -0
  46. package/src/types.ts +1526 -92
  47. package/tsconfig.json +2 -2
  48. package/src/matchers.ts +0 -146
  49. package/src/runner/collection.ts +0 -153
  50. package/src/runner/single.ts +0 -301
  51. package/src/spectra.ts +0 -376
@@ -0,0 +1,97 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { MockHandle } from './mock-handle.js';
4
+ export function globToRegExp(glob) {
5
+ let regexStr = '';
6
+ let i = 0;
7
+ while (i < glob.length) {
8
+ const c = glob[i];
9
+ if (c === '*' && glob[i + 1] === '*') {
10
+ regexStr += '.*';
11
+ i += 2;
12
+ }
13
+ else if (c === '*') {
14
+ regexStr += '[^/]*';
15
+ i += 1;
16
+ }
17
+ else if (['.', '?', '+', '^', '$', '[', ']', '(', ')', '{', '}', '|', '\\'].includes(c)) {
18
+ regexStr += `\\${c}`;
19
+ i += 1;
20
+ }
21
+ else {
22
+ regexStr += c;
23
+ i += 1;
24
+ }
25
+ }
26
+ // If glob does not start with protocol and does not start with wildcard, allow leading domain
27
+ if (!glob.startsWith('http://') && !glob.startsWith('https://') && !glob.startsWith('*')) {
28
+ return new RegExp(`(?:https?://[^/]+)?${regexStr}(?:\\?.*)?$`);
29
+ }
30
+ return new RegExp(`^${regexStr}(?:\\?.*)?$`);
31
+ }
32
+ export function matchesUrl(pattern, url) {
33
+ if (pattern instanceof RegExp) {
34
+ return pattern.test(url);
35
+ }
36
+ if (pattern === url) {
37
+ return true;
38
+ }
39
+ try {
40
+ const parsed = new URL(url, 'http://localhost');
41
+ if (pattern === parsed.pathname || pattern === `${parsed.pathname}${parsed.search}`) {
42
+ return true;
43
+ }
44
+ }
45
+ catch { }
46
+ const reg = globToRegExp(pattern);
47
+ return reg.test(url);
48
+ }
49
+ export function matchesMethod(ruleMethod, reqMethod = 'GET') {
50
+ if (!ruleMethod || ruleMethod.toUpperCase() === 'ALL') {
51
+ return true;
52
+ }
53
+ return ruleMethod.toUpperCase() === reqMethod.toUpperCase();
54
+ }
55
+ export class MockRegistry {
56
+ static instance;
57
+ handles = [];
58
+ recordedResources = [];
59
+ static getInstance() {
60
+ if (!MockRegistry.instance) {
61
+ MockRegistry.instance = new MockRegistry();
62
+ }
63
+ return MockRegistry.instance;
64
+ }
65
+ register(rule) {
66
+ const handle = new MockHandle(rule);
67
+ this.handles.unshift(handle);
68
+ return handle;
69
+ }
70
+ findMatchingHandle(method, url) {
71
+ return this.handles.find((h) => {
72
+ return matchesMethod(h.rule.method, method) && matchesUrl(h.rule.url, url);
73
+ });
74
+ }
75
+ clear() {
76
+ for (const h of this.handles) {
77
+ h.clear();
78
+ }
79
+ this.handles = [];
80
+ }
81
+ recordResource(resource) {
82
+ this.recordedResources.push(resource);
83
+ }
84
+ getRecordedResources() {
85
+ return [...this.recordedResources];
86
+ }
87
+ clearRecordedResources() {
88
+ this.recordedResources = [];
89
+ }
90
+ exportNetworkResources(filePath) {
91
+ const dir = path.dirname(filePath);
92
+ if (!fs.existsSync(dir)) {
93
+ fs.mkdirSync(dir, { recursive: true });
94
+ }
95
+ fs.writeFileSync(filePath, JSON.stringify(this.recordedResources, null, 2), 'utf-8');
96
+ }
97
+ }
@@ -0,0 +1,43 @@
1
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'ALL';
2
+ export type NetworkAbortReason = 'Failed' | 'Aborted' | 'TimedOut' | 'ConnectionReset' | 'AccessDenied';
3
+ export interface MockResponse {
4
+ status?: number;
5
+ headers?: Record<string, string>;
6
+ body?: any;
7
+ delayMs?: number;
8
+ }
9
+ export interface InterceptedRequest {
10
+ id: string;
11
+ url: string;
12
+ method: string;
13
+ headers?: Record<string, string>;
14
+ body?: any;
15
+ timestamp: number;
16
+ }
17
+ export interface InterceptRule {
18
+ url: string | RegExp;
19
+ method?: HttpMethod;
20
+ response?: MockResponse | ((request: InterceptedRequest) => MockResponse | Promise<MockResponse>);
21
+ }
22
+ export interface NetworkResourceTiming {
23
+ dns: number;
24
+ tcp: number;
25
+ ssl: number;
26
+ ttfb: number;
27
+ download: number;
28
+ total: number;
29
+ }
30
+ export interface RecordedNetworkResource {
31
+ id: string;
32
+ url: string;
33
+ method: string;
34
+ status: number;
35
+ statusText: string;
36
+ resourceType: string;
37
+ requestHeaders?: Record<string, string>;
38
+ responseHeaders?: Record<string, string>;
39
+ requestBody?: any;
40
+ responseBody?: any;
41
+ timing: NetworkResourceTiming;
42
+ transferSize: number;
43
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import { SingleElementMatcher, MultiElementMatcher, ElementTarget } from "./types.js";
1
+ import { SingleElementMatcher, MultiElementMatcher, ElementTarget } from './types.js';
2
2
  /**
3
3
  * Resolves an ElementTarget (selector string, WebdriverIO.Element, or ChainablePromiseElement)
4
4
  * to an actionable WebdriverIO.Element.
@@ -6,9 +6,16 @@ import { SingleElementMatcher, MultiElementMatcher, ElementTarget } from "./type
6
6
  * @param target - Selector string or element instance.
7
7
  * @returns Resolved WebdriverIO.Element instance.
8
8
  */
9
- export declare function resolveElement(target: ElementTarget): Promise<WebdriverIO.Element>;
10
9
  /**
11
- * Executes a single element matcher against the WebdriverIO browser / element context.
10
+ * Resolves an ElementTarget (selector string, WebdriverIO.Element, Playwright Locator, or ChainablePromiseElement)
11
+ * to an actionable element instance.
12
+ *
13
+ * @param target - Selector string or element instance.
14
+ * @returns Resolved element or locator instance.
15
+ */
16
+ export declare function resolveElement(target: ElementTarget): Promise<any>;
17
+ /**
18
+ * Executes a single element matcher against the active runner context (Playwright or WebdriverIO).
12
19
  *
13
20
  * @param target - Optional element target (not required for browser-level assertions).
14
21
  * @param matcher - Single element matcher string.
@@ -16,10 +23,14 @@ export declare function resolveElement(target: ElementTarget): Promise<Webdriver
16
23
  */
17
24
  export declare function executeSingleMatcher(target: ElementTarget | undefined, matcher: SingleElementMatcher, args: any[]): Promise<void>;
18
25
  /**
19
- * Executes a multi-element collection matcher against WebdriverIO $$.
26
+ * Executes a multi-element collection matcher against $$.
20
27
  *
21
28
  * @param selector - CSS/XPath selector for the collection.
22
29
  * @param matcher - Multi-element matcher string.
23
30
  * @param args - Expected values or count limits.
24
31
  */
25
32
  export declare function executeMultiMatcher(selector: string, matcher: MultiElementMatcher, args: any[]): Promise<void>;
33
+ /**
34
+ * Executes browser-level context assertions.
35
+ */
36
+ export declare function executeBrowserAssertion(assertion: 'shouldHaveUrl' | 'shouldContainUrl' | 'shouldHaveTitle' | 'shouldContainTitle' | 'shouldBePageLoaded' | 'shouldHaveNoConsoleErrors', args?: any[]): Promise<void>;