@applitools/eyes-results 0.2.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/CHANGELOG.md +8 -0
- package/LICENSE +26 -0
- package/dist/api/api.js +17 -0
- package/dist/api/compare-step.js +20 -0
- package/dist/api/diff-fetch.js +13 -0
- package/dist/api/dom-diff.js +139 -0
- package/dist/api/dom-fetch.js +39 -0
- package/dist/api/find-regions.js +24 -0
- package/dist/api/fs-cache.js +19 -0
- package/dist/api/gzip.js +12 -0
- package/dist/api/image-fetch.js +31 -0
- package/dist/api/polling.js +117 -0
- package/dist/api/req-results.js +77 -0
- package/dist/api/same-diff-as.js +25 -0
- package/dist/api/selector-mapping.js +15 -0
- package/dist/api/session-fetch.js +35 -0
- package/dist/api/session-history-fetch.js +73 -0
- package/dist/api/session-updates.js +37 -0
- package/dist/api/tasks.js +48 -0
- package/dist/api/url-parsing.js +33 -0
- package/dist/common/common.js +2 -0
- package/dist/common/diff-rects.js +64 -0
- package/dist/common/region-mapping.js +50 -0
- package/dist/geometry/geometry.js +72 -0
- package/dist/index.js +14 -0
- package/dist/lib/api-key-provider.js +26 -0
- package/dist/lib/env.js +26 -0
- package/dist/lib/phase-tracker.js +223 -0
- package/dist/sessions/batch.js +98 -0
- package/dist/sessions/diffs.js +210 -0
- package/dist/sessions/dom-history.js +107 -0
- package/dist/sessions/dom-search.js +1150 -0
- package/dist/sessions/dom.js +513 -0
- package/dist/sessions/match.js +56 -0
- package/dist/sessions/regions.js +280 -0
- package/dist/sessions/session.js +115 -0
- package/llm-docs/dom-search.md +164 -0
- package/package.json +69 -0
- package/types/api/api.d.ts +17 -0
- package/types/api/compare-step.d.ts +52 -0
- package/types/api/diff-fetch.d.ts +21 -0
- package/types/api/dom-diff.d.ts +53 -0
- package/types/api/dom-fetch.d.ts +29 -0
- package/types/api/find-regions.d.ts +26 -0
- package/types/api/fs-cache.d.ts +12 -0
- package/types/api/gzip.d.ts +5 -0
- package/types/api/image-fetch.d.ts +29 -0
- package/types/api/polling.d.ts +41 -0
- package/types/api/req-results.d.ts +37 -0
- package/types/api/same-diff-as.d.ts +38 -0
- package/types/api/selector-mapping.d.ts +28 -0
- package/types/api/session-fetch.d.ts +34 -0
- package/types/api/session-history-fetch.d.ts +56 -0
- package/types/api/session-updates.d.ts +26 -0
- package/types/api/tasks.d.ts +33 -0
- package/types/api/url-parsing.d.ts +20 -0
- package/types/common/common.d.ts +2 -0
- package/types/common/diff-rects.d.ts +39 -0
- package/types/common/region-mapping.d.ts +26 -0
- package/types/geometry/geometry.d.ts +24 -0
- package/types/index.d.ts +14 -0
- package/types/lib/api-key-provider.d.ts +31 -0
- package/types/lib/env.d.ts +14 -0
- package/types/lib/phase-tracker.d.ts +146 -0
- package/types/sessions/batch.d.ts +67 -0
- package/types/sessions/diffs.d.ts +26 -0
- package/types/sessions/dom-history.d.ts +119 -0
- package/types/sessions/dom-search.d.ts +113 -0
- package/types/sessions/dom.d.ts +263 -0
- package/types/sessions/match.d.ts +72 -0
- package/types/sessions/regions.d.ts +171 -0
- package/types/sessions/session.d.ts +97 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type FetchLike } from './polling.js';
|
|
2
|
+
import type { ImageRecord } from './selector-mapping.js';
|
|
3
|
+
import type { ImageMatchSettings } from '../sessions/match.js';
|
|
4
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
5
|
+
export interface CompareStepOptions {
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
accountId: string;
|
|
8
|
+
keys: ApiKeyProvider;
|
|
9
|
+
}
|
|
10
|
+
export interface CompareStepBody {
|
|
11
|
+
matchSettings: ImageMatchSettings;
|
|
12
|
+
image1: ImageRecord;
|
|
13
|
+
image2: ImageRecord;
|
|
14
|
+
sessionId: string;
|
|
15
|
+
batchId: string;
|
|
16
|
+
runningSessionId: string;
|
|
17
|
+
stepIndex: number;
|
|
18
|
+
}
|
|
19
|
+
export interface CompareDiffRect {
|
|
20
|
+
left: number;
|
|
21
|
+
top: number;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
diffDescriptions?: unknown[];
|
|
25
|
+
}
|
|
26
|
+
export interface CompareStepResult {
|
|
27
|
+
isMatch: boolean;
|
|
28
|
+
image1Size: {
|
|
29
|
+
width: number;
|
|
30
|
+
height: number;
|
|
31
|
+
};
|
|
32
|
+
image1: CompareDiffRect[];
|
|
33
|
+
image2Size: {
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
};
|
|
37
|
+
image2: CompareDiffRect[];
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Recomputes a step's visual diff against arbitrary match settings/regions — the same
|
|
42
|
+
* comparison the dashboard's own region editor uses for a live preview, confirmed live to
|
|
43
|
+
* accept both a `{domSelector}` region (resolved against both images' own DOM, since
|
|
44
|
+
* `useDom`/`hasDom` are true) and a plain `{left,top,width,height}` region. `image1`/`image2`
|
|
45
|
+
* in the response are a genuine two-way diff — rects in each image's own coordinate space,
|
|
46
|
+
* not a single shared list — mirroring the request's own `image1`/`image2` sides.
|
|
47
|
+
*
|
|
48
|
+
* Confirmed live to be sometimes synchronous (200) and sometimes an async job (202 +
|
|
49
|
+
* `Location`) depending on whether the exact payload was already computed — `getJsonResult`
|
|
50
|
+
* handles both transparently.
|
|
51
|
+
*/
|
|
52
|
+
export declare function compareStep(body: CompareStepBody, options: CompareStepOptions, fetchImpl?: FetchLike): Promise<CompareStepResult>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type FetchLike } from './polling.js';
|
|
2
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
3
|
+
export interface FetchStepDiffOptions {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
batchId: string;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
stepIndex: number;
|
|
8
|
+
accountId: string;
|
|
9
|
+
keys: ApiKeyProvider;
|
|
10
|
+
}
|
|
11
|
+
export interface StepDiffResult {
|
|
12
|
+
image1: any[];
|
|
13
|
+
image2: any[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The cheap, already-computed two-way diff for one step, straight off the dashboard's own
|
|
17
|
+
* `GET .../diff` endpoint — used whenever nothing about the step's effective match settings
|
|
18
|
+
* differs from what the test actually ran with (see `eyes-inspect`'s `fetchDiffRects`, this
|
|
19
|
+
* function's only caller, for when the more expensive `compareStep` path is needed instead).
|
|
20
|
+
*/
|
|
21
|
+
export declare function fetchStepDiff(options: FetchStepDiffOptions, fetchImpl?: FetchLike): Promise<StepDiffResult>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Fetch } from '@applitools/req';
|
|
2
|
+
import { type FsCacheDeps } from './fs-cache.js';
|
|
3
|
+
import { type ReqResultsLogger } from './req-results.js';
|
|
4
|
+
import type { DomAlignment } from '../sessions/dom.js';
|
|
5
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
6
|
+
export declare const DOM_DIFF_PATH = "/api/images/dom/diff";
|
|
7
|
+
export interface FetchDomDiffDeps extends FsCacheDeps {
|
|
8
|
+
/** Test seam — swaps the configured req's network layer, never its behavior. */
|
|
9
|
+
fetch?: Fetch;
|
|
10
|
+
logger?: ReqResultsLogger;
|
|
11
|
+
}
|
|
12
|
+
export declare const defaultFetchDomDiffDeps: FetchDomDiffDeps;
|
|
13
|
+
export type DomDiffResult = {
|
|
14
|
+
status: 'ready';
|
|
15
|
+
alignment: DomAlignment;
|
|
16
|
+
} | {
|
|
17
|
+
status: 'running';
|
|
18
|
+
taskId: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Fetches (or reads from cache) the alignment of two DOM snapshots, computed server-side. The
|
|
22
|
+
* request carries the two domIds alone — the server resolves them against its own snapshot
|
|
23
|
+
* storage, so no DOM travels either way — and a ready result is the compact `{matches, diff}`
|
|
24
|
+
* alignment: `matches` is what lets a caller extract one node's own diff afterwards
|
|
25
|
+
* (`sessions/dom`'s `extractNodeDiff`) without paying for a second alignment of the same pair.
|
|
26
|
+
* Cropping to an area (`filterDiffToArea`), excluding non-visual entries
|
|
27
|
+
* (`excludeNonVisualNodeDiffs`) and serializing (`serializeDiff`) all stay with the caller.
|
|
28
|
+
*
|
|
29
|
+
* No client-side polling: a 202 submit is probed once via `getTaskStatus`; if the task is still
|
|
30
|
+
* running, the taskId is returned and the caller decides when to check again
|
|
31
|
+
* (`checkDomDiffTask`). A direct 200 with the alignment body also parses — forward tolerance for
|
|
32
|
+
* a server answering an already-computed pair synchronously; the current backend always answers
|
|
33
|
+
* 202 (its async-task framework has no synchronous arm).
|
|
34
|
+
*
|
|
35
|
+
* Content-addressed cache, keyed on the two domIds alone — both are already immutable, unlike an
|
|
36
|
+
* area or a step's match settings, so one ready alignment is reused across every caller of that
|
|
37
|
+
* pair. A `running` outcome is never cached.
|
|
38
|
+
*
|
|
39
|
+
* Every alignment is shape-checked at this boundary before it is returned or cached — see
|
|
40
|
+
* `assertDomAlignment`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function fetchDomDiff(baseUrl: string, baselineDomId: string, checkpointDomId: string, keys: ApiKeyProvider, deps?: FetchDomDiffDeps): Promise<DomDiffResult>;
|
|
43
|
+
/**
|
|
44
|
+
* The caller's re-check for a `running` `fetchDomDiff` — one `getTaskStatus` probe, with a ready
|
|
45
|
+
* alignment landing in the same domId-pair cache a direct fetch would have written, so later
|
|
46
|
+
* calls for the pair stay cache hits regardless of which path produced the alignment.
|
|
47
|
+
*
|
|
48
|
+
* Cache-first, like `fetchDomDiff`: the pair may already be ready on disk (an earlier probe, or
|
|
49
|
+
* any other caller of the same pair, landed it), and a cached pair must win even when the taskId
|
|
50
|
+
* in hand has since expired — so a re-check with a stale taskId never fails on a result that's
|
|
51
|
+
* already here.
|
|
52
|
+
*/
|
|
53
|
+
export declare function checkDomDiffTask(baseUrl: string, taskId: string, baselineDomId: string, checkpointDomId: string, keys: ApiKeyProvider, deps?: FetchDomDiffDeps): Promise<DomDiffResult>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Fetch } from '@applitools/req';
|
|
2
|
+
import { type FsCacheDeps } from './fs-cache.js';
|
|
3
|
+
import { type ReqResultsLogger } from './req-results.js';
|
|
4
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
5
|
+
import type { PrunedDom } from '../sessions/dom.js';
|
|
6
|
+
export declare const PRUNED_DOM_PATH: (domId: string) => string;
|
|
7
|
+
export interface FetchPrunedDomOptions {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
domId: string;
|
|
10
|
+
keys: ApiKeyProvider;
|
|
11
|
+
}
|
|
12
|
+
export interface FetchPrunedDomDeps extends FsCacheDeps {
|
|
13
|
+
/** Test seam — swaps the configured req's network layer, never its behavior. */
|
|
14
|
+
fetch?: Fetch;
|
|
15
|
+
logger?: ReqResultsLogger;
|
|
16
|
+
}
|
|
17
|
+
export declare const defaultFetchPrunedDomDeps: FetchPrunedDomDeps;
|
|
18
|
+
/**
|
|
19
|
+
* Fetches (or reads from cache) an Applitools DOM snapshot already pruned server-side: URLs
|
|
20
|
+
* normalized, node ids assigned, metadata fields and whitespace-only text nodes gone. Same
|
|
21
|
+
* `eyes-<domId>` cache entry a client-side pruner writes, so entries stay valid either way.
|
|
22
|
+
* Takes no `area` — cropping is a separate, uncached step (`sessions/dom`'s `getDomArea`).
|
|
23
|
+
*
|
|
24
|
+
* The 200 body may be a gzip payload (a gzip *body*, not `Content-Encoding` — which the
|
|
25
|
+
* transport already undoes transparently), so it's gunzipped when it is one and parsed as-is
|
|
26
|
+
* when it isn't. Any non-200 throws via the configured req's expected-status hook, carrying the
|
|
27
|
+
* request name, status, and response body.
|
|
28
|
+
*/
|
|
29
|
+
export declare function fetchPrunedDom(options: FetchPrunedDomOptions, deps?: FetchPrunedDomDeps): Promise<PrunedDom>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type FetchLike } from './polling.js';
|
|
2
|
+
import type { ImageRecord } from './selector-mapping.js';
|
|
3
|
+
import type { Region } from '../sessions/regions.js';
|
|
4
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
5
|
+
export interface FindRegionsOptions {
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
accountId: string;
|
|
8
|
+
keys: ApiKeyProvider;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Searches every one of `targets` for each of `regions` — regions defined against
|
|
12
|
+
* `sourceImage`'s own DOM or, since `domSelector` is optional, its raw rectangle — and returns
|
|
13
|
+
* a map keyed by each target's `ImageRecord.id`. A target with no match at all is still present
|
|
14
|
+
* in the map, with an empty array (its key is never omitted). When several regions are searched
|
|
15
|
+
* at once, a target's array holds only the ones actually found there — there is no positional
|
|
16
|
+
* correspondence to `regions`, so a caller distinguishes which one matched by comparing
|
|
17
|
+
* `domSelector` back against the region it sent (both confirmed live: a single-region miss
|
|
18
|
+
* comes back as `[]`; a two-region call with one hit and one miss comes back with exactly one
|
|
19
|
+
* entry, the hit).
|
|
20
|
+
*
|
|
21
|
+
* Confirmed live to be an async job: the initial POST returns 202 with a `Location` header
|
|
22
|
+
* to a status URL; polling that returns 201, but the result itself lives at a *second*,
|
|
23
|
+
* separate URL given by that 201 response's own `Location` header — `getJsonResult`/
|
|
24
|
+
* `pollUntilResult` (`./polling.js`) handle this double-redirect.
|
|
25
|
+
*/
|
|
26
|
+
export declare function findRegionsInImages(sourceImage: ImageRecord, regions: Region[], targets: ImageRecord[], options: FindRegionsOptions, fetchImpl?: FetchLike, sleepFn?: (ms: number) => Promise<void>): Promise<Record<string, Region[]>>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface FsCacheDeps {
|
|
2
|
+
readFile: (path: string) => string | null;
|
|
3
|
+
writeFile: (path: string, contents: string) => void;
|
|
4
|
+
cacheDir: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const defaultFsCacheDeps: FsCacheDeps;
|
|
7
|
+
/**
|
|
8
|
+
* Builds a content-addressed cache file path, sanitizing `key` the same way the
|
|
9
|
+
* repo's existing cache-file naming already does (only `~`/`,` need escaping —
|
|
10
|
+
* these characters can appear in Applitools image/dom ids and are not filesystem-safe).
|
|
11
|
+
*/
|
|
12
|
+
export declare function cacheFilePath(deps: FsCacheDeps, prefix: string, key: string, ext?: string): string;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
import { Buffer } from 'buffer';
|
|
4
|
+
/** Promisified zlib.gunzip. Rejects if the input isn't valid gzip data — callers decide the fallback. */
|
|
5
|
+
export declare function gunzip(buffer: Buffer): Promise<Buffer>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
import { Buffer } from 'buffer';
|
|
4
|
+
import { type FetchLike } from './polling.js';
|
|
5
|
+
import type { Rect } from '../geometry/geometry.js';
|
|
6
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
7
|
+
export interface FetchCheckpointImageOptions {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
batchId: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
stepIndex: number;
|
|
12
|
+
accountId: string;
|
|
13
|
+
keys: ApiKeyProvider;
|
|
14
|
+
area?: Rect;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A step's checkpoint screenshot, as a raw PNG buffer — a binary response, so this calls `fetch`
|
|
18
|
+
* directly rather than through `postJson`/`getJson` (which assume JSON), the one documented
|
|
19
|
+
* exception among `api/`'s REST wrappers.
|
|
20
|
+
*/
|
|
21
|
+
export declare function fetchCheckpointImage(options: FetchCheckpointImageOptions, fetchImpl?: FetchLike): Promise<Buffer>;
|
|
22
|
+
export interface FetchImageByIdOptions {
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
imageId: string;
|
|
25
|
+
keys: ApiKeyProvider;
|
|
26
|
+
area?: Rect;
|
|
27
|
+
}
|
|
28
|
+
/** A baseline or checkpoint screenshot by its own image id, as a raw PNG buffer — same binary-response exception as `fetchCheckpointImage`. */
|
|
29
|
+
export declare function fetchImageById(options: FetchImageByIdOptions, fetchImpl?: FetchLike): Promise<Buffer>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
|
|
2
|
+
/**
|
|
3
|
+
* The older api modules' transport seam — a fresh `makeReqResults` instance per invocation, the
|
|
4
|
+
* DOM-diff flow's conventions (standard retry policy, explicit request/connection timeouts). The
|
|
5
|
+
* full retry budget every request gets is guaranteed by `makeReqResults` itself
|
|
6
|
+
* (`isolateRetryPerRequest`), not by this per-invocation build; building here keeps one shape
|
|
7
|
+
* across the package and scopes the resolved server URL to the request it came from.
|
|
8
|
+
* These modules bake the apiKey into their URLs themselves, so it is read back out of the URL
|
|
9
|
+
* here rather than threaded separately; no `expected` statuses are passed, so the instance's
|
|
10
|
+
* unexpected-status hook stays inert and the modules' own status checks remain in charge. Only
|
|
11
|
+
* how a single request executes lives here: the task flow (202/Location → status → result),
|
|
12
|
+
* JSON parsing, and error wording all stay above it.
|
|
13
|
+
*/
|
|
14
|
+
export declare const reqTransport: FetchLike;
|
|
15
|
+
/** POST a JSON body. */
|
|
16
|
+
export declare function postJson(url: string, body: unknown, fetchImpl?: FetchLike): Promise<Response>;
|
|
17
|
+
/** GET and parse a JSON response, throwing a descriptive error on a non-ok status. */
|
|
18
|
+
export declare function getJson(url: string, fetchImpl?: FetchLike): Promise<any>;
|
|
19
|
+
/**
|
|
20
|
+
* Polls a job-status URL until it reports done, then fetches and returns the job's result.
|
|
21
|
+
* Confirmed live against the real API — for every async endpoint checked so far (`images/find`,
|
|
22
|
+
* `sessions/batches/{batchId}/updates`), not just the ones that produce a real payload — a
|
|
23
|
+
* `201` isn't itself the result: it carries its *own* `Location` header (distinct from the
|
|
24
|
+
* original 202's) pointing at a separate result URL, which resolves with either a real JSON
|
|
25
|
+
* body (`images/find`) or an empty one (`updates`, `save`, etc. — a 204). Both are handled
|
|
26
|
+
* uniformly here; a caller with nothing to do with the result just ignores the return value.
|
|
27
|
+
* 200 = still running (wait and retry), anything else on the status poll = error.
|
|
28
|
+
*/
|
|
29
|
+
export declare function pollUntilResult(statusUrl: string, apiKey: string, fetchImpl?: FetchLike, sleepFn?: (ms: number) => Promise<void>): Promise<any>;
|
|
30
|
+
/**
|
|
31
|
+
* Handles the Eyes dashboard's async-job response convention end to end: a `202` with a
|
|
32
|
+
* `Location` header means the job is running and is polled via `pollUntilResult` through to
|
|
33
|
+
* its actual result; a plain ok response is parsed as JSON directly (tolerating an empty
|
|
34
|
+
* body). One function for every endpoint, whether or not its result is ever read — a caller
|
|
35
|
+
* that only cares that the call succeeded (e.g. `accept`/`reject`/`save`) just discards the
|
|
36
|
+
* return value instead of needing a separate "no result expected" variant.
|
|
37
|
+
*
|
|
38
|
+
* `requestUrl` backs up `response.url` as the base for a relative Location: `response.url` is
|
|
39
|
+
* '' under req's HTTP/2 rewrap, so callers pass the URL they requested.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getJsonResult(response: Response, apiKey: string, fetchImpl?: FetchLike, sleepFn?: (ms: number) => Promise<void>, requestUrl?: string): Promise<any>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type Fetch, type Options, type Req } from '@applitools/req';
|
|
2
|
+
export interface ReqResultsLogger {
|
|
3
|
+
log(...args: unknown[]): void;
|
|
4
|
+
error(...args: unknown[]): void;
|
|
5
|
+
}
|
|
6
|
+
export interface ReqResultsOptions extends Options {
|
|
7
|
+
/** Response statuses the caller treats as business results; any other status throws. */
|
|
8
|
+
expected?: number | number[];
|
|
9
|
+
/** Names the request in thrown errors. */
|
|
10
|
+
name?: string;
|
|
11
|
+
logger?: ReqResultsLogger;
|
|
12
|
+
}
|
|
13
|
+
export interface MakeReqResultsOptions {
|
|
14
|
+
serverUrl: string;
|
|
15
|
+
/** Baked into every request as the `apiKey` query parameter — the convention all eyes-results endpoints use. */
|
|
16
|
+
apiKey: string;
|
|
17
|
+
/** Test seam — swaps the instance's network layer, never its behavior. */
|
|
18
|
+
fetch?: Fetch;
|
|
19
|
+
logger?: ReqResultsLogger;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Builds a configured `req` — core-base's `makeReqEyes` concept adapted to this package: the
|
|
23
|
+
* instance owns the server URL, the `apiKey` query parameter, the transient-retry policy, and the
|
|
24
|
+
* `expected`-status convention above, so api functions take the configured req plus business
|
|
25
|
+
* parameters and never thread baseUrl/apiKey/transport themselves. Flat options on purpose: an api
|
|
26
|
+
* function's own deps spread straight in — `makeReqResults({serverUrl, apiKey, ...deps})`.
|
|
27
|
+
*
|
|
28
|
+
* **Build one per call, not one per module.** Every call site here does (`api/dom-diff.ts`,
|
|
29
|
+
* `api/dom-fetch.ts`, `api/tasks.ts`, `api/polling.ts`'s `reqTransport`), because req's retry
|
|
30
|
+
* counter lives on the retry object the instance carries — see `isolateRetryPerRequest` above for
|
|
31
|
+
* what that costs a long-lived instance. That hook is what actually guarantees the budget is
|
|
32
|
+
* per-request, so hoisting an instance is safe rather than silently degrading; per-call
|
|
33
|
+
* construction stays the convention because it also keeps the apiKey and server URL scoped to the
|
|
34
|
+
* flow that resolved them. `test/api/req-results.test.ts`'s "retry isolation" suite makes several
|
|
35
|
+
* calls through a single instance and pins both properties.
|
|
36
|
+
*/
|
|
37
|
+
export declare function makeReqResults({ serverUrl, apiKey, fetch, logger }: MakeReqResultsOptions): Req<ReqResultsOptions>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type FetchLike } from './polling.js';
|
|
2
|
+
import type { ImageMatchSettings } from '../sessions/match.js';
|
|
3
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
4
|
+
export interface SameDiffAsOptions {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
accountId: string;
|
|
7
|
+
keys: ApiKeyProvider;
|
|
8
|
+
}
|
|
9
|
+
export interface SameDiffAsStep {
|
|
10
|
+
batchId: string;
|
|
11
|
+
sessionId: string;
|
|
12
|
+
stepIndex: number;
|
|
13
|
+
image1: string;
|
|
14
|
+
image2: string;
|
|
15
|
+
matchSettings: ImageMatchSettings;
|
|
16
|
+
}
|
|
17
|
+
export interface SameDiffAsBody {
|
|
18
|
+
reference: SameDiffAsStep;
|
|
19
|
+
steps: SameDiffAsStep[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Given a reference step and a candidate list of other steps, returns which of `steps` actually
|
|
23
|
+
* have the same diff as `reference` — the real target steps an accept/reject decision should
|
|
24
|
+
* propagate to, as opposed to every step a scenario-name match happened to include. `image1`/
|
|
25
|
+
* `image2` here are plain baseline/checkpoint image id strings, not full `ImageRecord` objects
|
|
26
|
+
* (unlike `compareStep`'s own request shape) — each entry (including `reference`) carries its
|
|
27
|
+
* own step's `matchSettings`, never another step's.
|
|
28
|
+
*
|
|
29
|
+
* Confirmed live: an async job (202 + Location), same as every other endpoint in this file.
|
|
30
|
+
* **The result is `number[]` — zero-based indices into the request's own `steps` array, e.g.
|
|
31
|
+
* `[0, 1]` meaning `steps[0]` and `steps[1]` both matched — never step objects, and never
|
|
32
|
+
* `{sessionId, stepIndex}` identifiers.** A caller must resolve each index back against its own
|
|
33
|
+
* original `steps`/candidate array; the response carries nothing else to identify a match by.
|
|
34
|
+
* When nothing in `steps` matches `reference`, the job's own result is `204 No Content` — an
|
|
35
|
+
* empty body, which `getJsonResult` parses as `undefined` — normalized here to `[]` so callers
|
|
36
|
+
* can always assume an array.
|
|
37
|
+
*/
|
|
38
|
+
export declare function findSameDiffSteps(body: SameDiffAsBody, options: SameDiffAsOptions, fetchImpl?: FetchLike): Promise<number[]>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type FetchLike } from './polling.js';
|
|
2
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
3
|
+
export interface ImageRecord {
|
|
4
|
+
id: string;
|
|
5
|
+
domId: string;
|
|
6
|
+
size: {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
};
|
|
10
|
+
hasDom: boolean;
|
|
11
|
+
location: {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
};
|
|
15
|
+
rectangle: string;
|
|
16
|
+
}
|
|
17
|
+
export interface GetCompatibleSelectorsOptions {
|
|
18
|
+
baseUrl: string;
|
|
19
|
+
accountId: string;
|
|
20
|
+
keys: ApiKeyProvider;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Maps each of `selectors` from `image1`'s DOM to its structurally-equivalent selector on
|
|
24
|
+
* `image2`'s DOM — e.g. translating a region's domSelector from a baseline to a checkpoint,
|
|
25
|
+
* or the reverse. Returns one entry per input selector, in the same order; an entry is
|
|
26
|
+
* `null` when no compatible element exists on `image2`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getCompatibleSelectors(options: GetCompatibleSelectorsOptions, image1: ImageRecord, image2: ImageRecord, selectors: string[], fetchImpl?: FetchLike): Promise<(string | null)[]>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type FetchLike } from './polling.js';
|
|
2
|
+
import { type SimplifiedSession, type SessionStep } from '../sessions/session.js';
|
|
3
|
+
import { type BatchInfo } from '../sessions/batch.js';
|
|
4
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
5
|
+
export interface SessionUrlOptions {
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
batchId: string;
|
|
8
|
+
accountId: string;
|
|
9
|
+
keys: ApiKeyProvider;
|
|
10
|
+
}
|
|
11
|
+
/** Fetches the raw Eyes session API response — no shaping. */
|
|
12
|
+
export declare function fetchRawSession(options: SessionUrlOptions & {
|
|
13
|
+
sessionId: string;
|
|
14
|
+
}, fetchImpl?: FetchLike): Promise<any>;
|
|
15
|
+
/** Fetches a session and shapes it via `sessions/session`'s `simplifySession`. */
|
|
16
|
+
export declare function fetchSession(options: SessionUrlOptions & {
|
|
17
|
+
sessionId: string;
|
|
18
|
+
}, fetchImpl?: FetchLike): Promise<SimplifiedSession & {
|
|
19
|
+
steps: SessionStep[];
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Fetches the raw list of sessions in a batch — no shaping.
|
|
23
|
+
* Normalizes the response shape: the Eyes API returns either a bare array or `{ sessions: [...] }`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function fetchRawBatchSessions(options: SessionUrlOptions, fetchImpl?: FetchLike): Promise<any[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Fetches the raw batch entity itself (name, timing, and — the reason this exists —
|
|
28
|
+
* its server-maintained aggregate counts, shaped by `sessions/batch`'s `toBatchStats` —
|
|
29
|
+
* see `BatchInfo` there) — a different endpoint from `fetchRawBatchSessions`, which lists
|
|
30
|
+
* the batch's individual sessions. This aggregate is eventually consistent: it can lag
|
|
31
|
+
* behind a resolve/save call by several seconds, unlike a session list (or anything derived
|
|
32
|
+
* from one), which is always current.
|
|
33
|
+
*/
|
|
34
|
+
export declare function fetchBatchInfo(options: SessionUrlOptions, fetchImpl?: FetchLike): Promise<BatchInfo>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type FetchLike } from './polling.js';
|
|
2
|
+
import { type FsCacheDeps } from './fs-cache.js';
|
|
3
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
4
|
+
export interface SessionHistoryEnv {
|
|
5
|
+
hostingApp: string | null;
|
|
6
|
+
os: string | null;
|
|
7
|
+
displaySize: {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
} | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Builds the `where=` filter clauses for a session-history query. Each clause's payload is a
|
|
14
|
+
* plain UTF-8 string, base64-encoded — not `encodeURIComponent(JSON.stringify(...))` — and
|
|
15
|
+
* `IsViewport` in particular is a custom `{width:N,height:N}` literal (unquoted keys, not
|
|
16
|
+
* valid JSON), confirmed by decoding a real sample URL. Returns only the clauses for fields
|
|
17
|
+
* actually present in `env`, `&&`-joined; a caller further `encodeURIComponent`s the whole
|
|
18
|
+
* result when building the request URL — this returns the raw (unencoded) filter text.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildSessionHistoryEnvFilter(env: SessionHistoryEnv): string;
|
|
21
|
+
export interface SessionHistoryOptions {
|
|
22
|
+
baseUrl: string;
|
|
23
|
+
scenarioId: string;
|
|
24
|
+
accountId: string;
|
|
25
|
+
keys: ApiKeyProvider;
|
|
26
|
+
env: SessionHistoryEnv;
|
|
27
|
+
ranAtOrBefore: string;
|
|
28
|
+
count: number;
|
|
29
|
+
}
|
|
30
|
+
export interface FetchSessionHistoryDeps extends FsCacheDeps {
|
|
31
|
+
fetchImpl: FetchLike;
|
|
32
|
+
sleepFn?: (ms: number) => Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export declare const defaultFetchSessionHistoryDeps: FetchSessionHistoryDeps;
|
|
35
|
+
/**
|
|
36
|
+
* Fetches (or reads from cache) a page of a scenario's historic sessions matching `env`, at or
|
|
37
|
+
* before `ranAtOrBefore`. Confirmed live as an async-job endpoint (a `202` with a `Location`
|
|
38
|
+
* status-poll header, same convention as `images/get-compatible-selectors` in
|
|
39
|
+
* `selector-mapping.ts` — there a POST initiates it, here a plain GET does), so this goes
|
|
40
|
+
* through `getJsonResult`, not `getJson` (which assumes a synchronous body).
|
|
41
|
+
*
|
|
42
|
+
* Named for what it returns — a session history — not for `scenarioId`, which is only one of
|
|
43
|
+
* several inputs (alongside `env`) narrowing which sessions come back; the endpoint itself is
|
|
44
|
+
* scoped by scenario, but the result is a plain list of full raw sessions, not scenario-level
|
|
45
|
+
* aggregate data.
|
|
46
|
+
*
|
|
47
|
+
* Cached indefinitely, keyed by a hash of every input that affects the result — unlike a
|
|
48
|
+
* session/batch fetch (deliberately never cached elsewhere in `api/`, since those can change),
|
|
49
|
+
* a `ranAtOrBefore`-pinned query against the past is immutable once made.
|
|
50
|
+
*
|
|
51
|
+
* Confirmed live: the response is `{ "sessions": [...] }`, each entry a full raw session
|
|
52
|
+
* object (the same shape `fetchRawSession` returns) — but a bare-array response is still
|
|
53
|
+
* normalized defensively, mirroring `fetchRawBatchSessions`, in case an edge case omits the
|
|
54
|
+
* wrapper.
|
|
55
|
+
*/
|
|
56
|
+
export declare function fetchSessionHistory(options: SessionHistoryOptions, deps?: FetchSessionHistoryDeps): Promise<any[]>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type FetchLike } from './polling.js';
|
|
2
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
3
|
+
export interface BatchScopeOptions {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
batchId: string;
|
|
6
|
+
accountId: string;
|
|
7
|
+
keys: ApiKeyProvider;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* POSTs a batch of per-session step updates (accept/reject decisions, region changes) in one
|
|
11
|
+
* call — confirmed live to accept multiple sessions at once, one entry per session id.
|
|
12
|
+
*/
|
|
13
|
+
export declare function postStepUpdates(options: BatchScopeOptions, stepUpdatesBySession: Map<string, any[]>, fetchImpl?: FetchLike): Promise<void>;
|
|
14
|
+
/** Commits every pending accept/reject/region change in the batch to the baseline. The endpoint returns nothing useful to the caller — a resolved promise signals success. */
|
|
15
|
+
export declare function saveBaselines(options: BatchScopeOptions, fetchImpl?: FetchLike): Promise<void>;
|
|
16
|
+
export interface RestoreBaselineOptions {
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
accountId: string;
|
|
19
|
+
baselineId: string;
|
|
20
|
+
baselineRev: string;
|
|
21
|
+
keys: ApiKeyProvider;
|
|
22
|
+
}
|
|
23
|
+
/** Reverts a session's shared baseline object to the revision it originally ran against. */
|
|
24
|
+
export declare function restoreBaseline(options: RestoreBaselineOptions, fetchImpl?: FetchLike): Promise<void>;
|
|
25
|
+
/** Clears every given session's pending (unsaved) accept/reject/region resolution back to unresolved — a no-op, not an error, for a session with nothing pending. */
|
|
26
|
+
export declare function resetBatchSessions(options: BatchScopeOptions, sessionIds: string[], fetchImpl?: FetchLike): Promise<void>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type MakeReqResultsOptions } from './req-results.js';
|
|
2
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
3
|
+
export declare const TASK_STATUS_PATH: (taskId: string) => string;
|
|
4
|
+
export declare const TASK_RESULT_PATH: (taskId: string) => string;
|
|
5
|
+
export type TaskDeps = Pick<MakeReqResultsOptions, 'fetch' | 'logger'>;
|
|
6
|
+
/** Extracts the taskId out of a submit response's `Location` (`/api/tasks/{taskId}/status`). */
|
|
7
|
+
export declare function taskIdFromLocation(location: string): string;
|
|
8
|
+
export type TaskStatus<T> = {
|
|
9
|
+
status: 'running';
|
|
10
|
+
taskId: string;
|
|
11
|
+
} | {
|
|
12
|
+
status: 'ready';
|
|
13
|
+
result: T;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* One probe of a task's status — no client-side polling loop: `running` hands the taskId back so
|
|
17
|
+
* the caller decides when (and whether) to check again; `201` means done, and the result the
|
|
18
|
+
* response's `Location` points at is fetched and returned in the same call, so a ready task never
|
|
19
|
+
* costs the caller a second round trip. `404` (unknown or expired task) is terminal and throws
|
|
20
|
+
* with the contract's own wording. A *rejected* task also finishes as `201` here — its rejection
|
|
21
|
+
* surfaces as `503` on the result fetch (TasksController puts it there, not on status); transient
|
|
22
|
+
* transport failures are the configured req's standard retry policy, not handled here.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getTaskStatus<T = any>(baseUrl: string, taskId: string, keys: ApiKeyProvider, deps?: TaskDeps): Promise<TaskStatus<T>>;
|
|
25
|
+
/**
|
|
26
|
+
* Fetches a finished task's result and parses it as JSON. The response is gzipped on the wire
|
|
27
|
+
* when the request advertises `Accept-Encoding` — the transport negotiates and decompresses that
|
|
28
|
+
* transparently, so no explicit gunzip step exists here (unlike endpoints that return a gzip
|
|
29
|
+
* *body*, e.g. `fetchPrunedDom`). `503` is the result endpoint's "task rejected" — terminal by
|
|
30
|
+
* the task contract (and excluded from the retry policy for exactly that reason), thrown with
|
|
31
|
+
* the contract's own wording.
|
|
32
|
+
*/
|
|
33
|
+
export declare function fetchTaskResult(baseUrl: string, resultUrl: string, keys: ApiKeyProvider, deps?: TaskDeps): Promise<any>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface ParsedApplitoolsUrl {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
batchId: string;
|
|
4
|
+
sessionId: string | null;
|
|
5
|
+
accountId: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Parses an Applitools dashboard URL (session or batch) into its components.
|
|
9
|
+
* Does not require a sessionId to be present — use parseSessionUrl/parseBatchUrl
|
|
10
|
+
* for callers that need to enforce one shape or the other.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseApplitoolsUrl(url: string): ParsedApplitoolsUrl;
|
|
13
|
+
/** Throws if the URL doesn't include a sessionId segment (i.e. it's a batch-only URL). */
|
|
14
|
+
export declare function parseSessionUrl(url: string): ParsedApplitoolsUrl & {
|
|
15
|
+
sessionId: string;
|
|
16
|
+
};
|
|
17
|
+
/** Batch-scoped: parses the batchId/accountId and always forces sessionId to null, ignoring any session segment. */
|
|
18
|
+
export declare function parseBatchUrl(url: string): ParsedApplitoolsUrl & {
|
|
19
|
+
sessionId: null;
|
|
20
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defaultFsCacheDeps, compareStep, fetchStepDiff } from '../api/api.js';
|
|
2
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
3
|
+
import { type Rect } from '../geometry/geometry.js';
|
|
4
|
+
export interface FetchRawDiffsDeps {
|
|
5
|
+
fetchStepDiff: typeof fetchStepDiff;
|
|
6
|
+
compareStep: typeof compareStep;
|
|
7
|
+
readFile: typeof defaultFsCacheDeps.readFile;
|
|
8
|
+
writeFile: typeof defaultFsCacheDeps.writeFile;
|
|
9
|
+
}
|
|
10
|
+
export declare const defaultFetchRawDiffsDeps: FetchRawDiffsDeps;
|
|
11
|
+
/**
|
|
12
|
+
* The two-way visual diff for one step — `image1` in the baseline image's own coordinate
|
|
13
|
+
* space, `image2` in the checkpoint's, exactly mirroring both the plain `GET .../diff`
|
|
14
|
+
* endpoint's and `compareStep`'s own response shape. When the step's resolution state is
|
|
15
|
+
* unchanged from the original test run (`appOutputResolution[stepIndex].isChanged` is not
|
|
16
|
+
* `true`), the cheap `GET .../diff` endpoint is used as-is — nothing about the step's
|
|
17
|
+
* effective match settings differs from what the test already ran with. Otherwise, the step's
|
|
18
|
+
* current effective regions are folded into a fresh `compareStep` request so the returned diff
|
|
19
|
+
* reflects any region added since the test ran — that (more expensive) result is cached on
|
|
20
|
+
* disk, keyed by a hash of the full request body, so repeated calls against the same resolved
|
|
21
|
+
* state don't repeatedly hit the endpoint.
|
|
22
|
+
*
|
|
23
|
+
* Takes an already-fetched `rawSession` rather than fetching its own — `batchId`/`sessionId`
|
|
24
|
+
* are read straight off it (`rawSession.batchId`/`rawSession.id`), so a caller that already has
|
|
25
|
+
* the raw session in hand (e.g. for its own domId lookups) never pays for a second fetch just
|
|
26
|
+
* to hand this function a `url` it would otherwise re-resolve into the same session itself.
|
|
27
|
+
*
|
|
28
|
+
* `matchSettings` comes straight from `getEffectiveMatchSettings` — the raw session's own
|
|
29
|
+
* scalars/regions, shaped directly into the request format, with no baseline/checkpoint
|
|
30
|
+
* pairing and no healing: that shaping only exists for diagnostic region output (which needs
|
|
31
|
+
* both sides shown, healing in whichever one the raw session doesn't encode), never for a
|
|
32
|
+
* compare request. Re-deriving "accepted ⇒ checkpoint, else baseline" here would duplicate
|
|
33
|
+
* logic the raw session's own `annotations` field already resolves — and healing in the other
|
|
34
|
+
* side would cost an extra network round trip per region for nothing a compare request needs.
|
|
35
|
+
*/
|
|
36
|
+
export declare function fetchRawDiffs(rawSession: any, stepIndex: number, baseUrl: string, accountId: string, keys: ApiKeyProvider, deps?: FetchRawDiffsDeps): Promise<{
|
|
37
|
+
image1: Rect[];
|
|
38
|
+
image2: Rect[];
|
|
39
|
+
}>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getCompatibleSelectors } from '../api/api.js';
|
|
2
|
+
import { type RegionPair } from '../sessions/regions.js';
|
|
3
|
+
import type { ApiKeyProvider } from '../lib/api-key-provider.js';
|
|
4
|
+
export interface MapAnchoredRegionsDeps {
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
accountId: string;
|
|
7
|
+
keys: ApiKeyProvider;
|
|
8
|
+
fetchDomForSide: (rawSession: any, stepIndex: number, side: 'baseline' | 'checkpoint', baseUrl: string) => Promise<any>;
|
|
9
|
+
getCompatibleSelectors: typeof getCompatibleSelectors;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Maps every `anchored` pair's `domSelector` to the other side via one batched
|
|
13
|
+
* get-compatible-selectors call, resolving each mapped selector's accurate rect locally
|
|
14
|
+
* against that side's DOM (the API only returns the mapped selector, never a rect). Falls
|
|
15
|
+
* back to treating every selector as unmapped if the batch call itself fails for some reason
|
|
16
|
+
* other than a bad input selector (`sessions`'s own `checkRegions` already filters those out).
|
|
17
|
+
* Mutates each pair's missing side in place. Returns whether anything was attempted (i.e.
|
|
18
|
+
* `anchored` was non-empty and both sides have an image to map between).
|
|
19
|
+
*
|
|
20
|
+
* Lives here, not in `atoms/sessions` (where the rest of the region-healing pipeline this composes
|
|
21
|
+
* into — `checkRegions`/`clearStaleSelectors`/`healNonAnchoredRegionsBySourceRect` — lives):
|
|
22
|
+
* this is the one step of that pipeline that actually calls the network (`getCompatibleSelectors`),
|
|
23
|
+
* and `atoms` must never depend on `api`/`common` (so it can't reference `ApiKeyProvider` or make
|
|
24
|
+
* network calls) — the orchestration belongs in `common`, which depends on both instead.
|
|
25
|
+
*/
|
|
26
|
+
export declare function mapAnchoredRegionsBySelector(rawSession: any, stepIndex: number, anchored: RegionPair[], deps: MapAnchoredRegionsDeps): Promise<boolean>;
|