@jbrowse/capture 5.0.0-beta.1 → 5.0.0-beta.10
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 +82 -30
- package/esm/args.d.ts +8 -8
- package/esm/args.js +83 -71
- package/esm/bin.js +64 -56
- package/esm/browser.d.ts +13 -1
- package/esm/browser.js +17 -25
- package/esm/capture.d.ts +19 -87
- package/esm/capture.js +54 -237
- package/esm/catalog.d.ts +32 -0
- package/esm/catalog.js +84 -0
- package/esm/hub.d.ts +16 -15
- package/esm/hub.js +36 -29
- package/esm/imagePath.d.ts +1 -0
- package/esm/imagePath.js +8 -0
- package/esm/index.d.ts +12 -9
- package/esm/index.js +8 -7
- package/esm/instanceVersion.d.ts +5 -0
- package/esm/instanceVersion.js +21 -0
- package/esm/poll.d.ts +14 -0
- package/esm/poll.js +30 -0
- package/esm/ready.d.ts +29 -0
- package/esm/ready.js +44 -0
- package/esm/session.d.ts +24 -12
- package/esm/session.js +47 -32
- package/esm/sessionGate.d.ts +38 -105
- package/esm/sessionGate.js +82 -176
- package/esm/sessionOverflow.d.ts +6 -0
- package/esm/sessionOverflow.js +22 -0
- package/esm/url.d.ts +28 -17
- package/esm/url.js +51 -27
- package/esm/version.d.ts +1 -0
- package/esm/version.js +1 -0
- package/esm/waits.d.ts +23 -202
- package/esm/waits.js +77 -404
- package/package.json +3 -3
package/esm/version.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const version = "5.0.0-beta.10";
|
package/esm/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const version = '5.0.0-beta.10';
|
package/esm/waits.d.ts
CHANGED
|
@@ -1,214 +1,35 @@
|
|
|
1
1
|
import type { ElementHandle, Page } from 'puppeteer';
|
|
2
|
-
|
|
3
|
-
export declare const LOADING_OVERLAY = "[data-testid=\"loading-overlay\"]";
|
|
4
|
-
/**
|
|
5
|
-
* The whole readiness contract, in one selector.
|
|
6
|
-
*
|
|
7
|
-
* `AppReadyMarker` renders it from the session: it reads `ready` when no view
|
|
8
|
-
* is resolving an assembly and no display is fetching, and `loading` whenever
|
|
9
|
-
* one is. Waiting for it is the entire job — everything else in this module is
|
|
10
|
-
* either a narrower question (has THIS display painted) or a fallback for a
|
|
11
|
-
* deployment too old to publish it.
|
|
12
|
-
*
|
|
13
|
-
* It is POSITIVE, which is the property that matters. Every other signal here
|
|
14
|
-
* is an absence, and an absence is equally true of an app that has not started:
|
|
15
|
-
* measured on a two-track session, the gap between "the session holds the
|
|
16
|
-
* tracks" and "the first loading indicator appears" is about a second, and a
|
|
17
|
-
* capture taken in it is a picture of an empty browser.
|
|
18
|
-
*/
|
|
19
|
-
export declare const APP_READY = "[data-app-phase=\"ready\"]";
|
|
20
|
-
export declare function waitForLoadingComplete(page: Page, { timeout, waitForDownloads, }?: {
|
|
21
|
-
timeout?: number;
|
|
22
|
-
waitForDownloads?: boolean;
|
|
23
|
-
}): Promise<boolean>;
|
|
24
|
-
/**
|
|
25
|
-
* Wait until nothing on the page is in flight.
|
|
26
|
-
*
|
|
27
|
-
* Every signal it reads is one the app publishes deliberately — the loading
|
|
28
|
-
* overlay, `data-busy`, the display and view phases, and each display's own
|
|
29
|
-
* status message on the session model. See `isPageBusyInPage`.
|
|
30
|
-
*
|
|
31
|
-
* It used to scan rendered text for /^(loading|rendering|computing)/ and resolve
|
|
32
|
-
* `getComputedStyle` on each match to decide whether it was on screen. That is a
|
|
33
|
-
* heuristic over a rendering: it broke on a reworded or translated message, it
|
|
34
|
-
* needed the visibility check only because the loading overlay keeps the word
|
|
35
|
-
* "Loading" in the DOM at `opacity: 0`, and an unset opacity parses to zero
|
|
36
|
-
* outside a full layout engine, which reads every ordinary element as hidden. A
|
|
37
|
-
* component that wants to be waited for now says so with an attribute.
|
|
38
|
-
*
|
|
39
|
-
* Best-effort: a view genuinely stuck loading would otherwise burn the whole
|
|
40
|
-
* timeout, so this reports false rather than throwing and the caller decides.
|
|
41
|
-
*/
|
|
42
|
-
export declare function waitForQuiescent(page: Page, { timeout }?: {
|
|
2
|
+
interface WaitOptions {
|
|
43
3
|
timeout?: number;
|
|
44
|
-
}
|
|
4
|
+
}
|
|
5
|
+
/** The app's own verdict: no view is resolving an assembly, no display is fetching. */
|
|
6
|
+
export declare const APP_READY = "[data-app-phase=\"ready\"]";
|
|
7
|
+
/** Displays that have not yet drawn anything. */
|
|
45
8
|
export declare const PENDING_DISPLAYS = "[data-display-drawn=\"false\"]";
|
|
46
|
-
/**
|
|
47
|
-
* `page.waitForSelector`, with the display census in the timeout.
|
|
48
|
-
*
|
|
49
|
-
* The waits below are best-effort and hand their outcome back as a boolean, so
|
|
50
|
-
* a caller can say what was still unsettled. A *selector* wait is the opposite
|
|
51
|
-
* shape — it throws, and it runs FIRST, before any of them: a capture whose
|
|
52
|
-
* display never paints dies here on puppeteer's `TimeoutError`, which names the
|
|
53
|
-
* selector and nothing else, and the census that would have named the display
|
|
54
|
-
* runs later or not at all.
|
|
55
|
-
*
|
|
56
|
-
* So the census runs on the way out. It is re-read from the DOM here rather
|
|
57
|
-
* than taken off a handle the wait held: a handle to an element that has since
|
|
58
|
-
* re-rendered throws `Node is detached from document`, which is how the first
|
|
59
|
-
* attempt at this turned four diagnosable timeouts into nine opaque puppeteer
|
|
60
|
-
* errors (reverted in 28c6ee6d90).
|
|
61
|
-
*
|
|
62
|
-
* What it reports is the phase, and that is the part a longer timeout cannot
|
|
63
|
-
* substitute for: `loading` is a slow fetch, `error` is a display that has
|
|
64
|
-
* finished badly and is showing a banner, and `ready` is a display claiming it
|
|
65
|
-
* finished without drawing — a bug in the display rather than in the wait.
|
|
66
|
-
*
|
|
67
|
-
* An EMPTY census is the other answer, and `tooLarge` / `renderError` are why it
|
|
68
|
-
* is not good news. Those two replace the display's subtree outright, so they
|
|
69
|
-
* publish neither attribute and appear here as nothing at all: a wait on such a
|
|
70
|
-
* display can never resolve and can never be reported. Nothing pending means
|
|
71
|
-
* either that, or a selector that was never a display's.
|
|
72
|
-
*/
|
|
73
|
-
export declare function waitForSelectorAttributed(page: Page, selector: string, timeoutMs: number): Promise<ElementHandle>;
|
|
74
|
-
/**
|
|
75
|
-
* The census as one clause, for a message. Best-effort in its own right: a page
|
|
76
|
-
* whose execution context is gone cannot be asked, and saying so is the answer.
|
|
77
|
-
*/
|
|
78
|
-
export declare function describePendingDisplaysNow(page: Page): Promise<string>;
|
|
9
|
+
/** A display of this type that has drawn something, possibly mid-fetch. */
|
|
79
10
|
export declare const displayPainted: (testid: string) => string;
|
|
80
|
-
/**
|
|
81
|
-
* The stronger one. `drawn` flips on FIRST paint — an empty canvas with the
|
|
82
|
-
* fetch still in flight satisfies it — so a figure that must show *data* waits
|
|
83
|
-
* on the phase instead.
|
|
84
|
-
*/
|
|
11
|
+
/** A display of this type whose fetch has finished. */
|
|
85
12
|
export declare const displaySettled: (testid: string) => string;
|
|
86
|
-
/** One display, by its config's `displayId` rather than by type. */
|
|
87
|
-
export declare const displayById: (displayId: string) => string;
|
|
88
|
-
export declare function waitForDisplaysDone(page: Page, timeoutMs: number): Promise<boolean>;
|
|
89
|
-
export declare function waitForDisplayPhases(page: Page, timeoutMs: number): Promise<boolean>;
|
|
90
|
-
export declare function waitForViewPhases(page: Page, timeoutMs: number): Promise<import("puppeteer").JSHandle<false> | import("puppeteer").JSHandle<true>>;
|
|
91
|
-
/**
|
|
92
|
-
* Everything the app publishes to say it is working, as one selector.
|
|
93
|
-
*
|
|
94
|
-
* All four are attributes a component sets deliberately, which is the whole
|
|
95
|
-
* point: the alternative — scanning rendered text for /^loading/ and resolving
|
|
96
|
-
* `getComputedStyle` to decide whether each match is on screen — makes a
|
|
97
|
-
* reworded message, a translation or an opacity animation change the answer.
|
|
98
|
-
*
|
|
99
|
-
* `loading-overlay` the view-level scrim, present in every build
|
|
100
|
-
* `data-busy` LoadingEllipses, which is what the app renders
|
|
101
|
-
* wherever it tells a user it is working
|
|
102
|
-
* `data-display-phase` one display's own fetch, newer builds
|
|
103
|
-
* `data-view-phase` a view still resolving its assembly, newer builds
|
|
104
|
-
*/
|
|
105
|
-
export declare const BUSY_SELECTOR: string;
|
|
106
13
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* Serialized into the page, so it declares everything it uses. Two sources: the
|
|
110
|
-
* selector above, and the live session model's own per-display status, which is
|
|
111
|
-
* the only PER-DISPLAY signal a build with no readiness attributes has left.
|
|
112
|
-
* Both are contracts rather than renderings — a model field and a set of data
|
|
113
|
-
* attributes — so neither moves when the UI is restyled.
|
|
114
|
-
*
|
|
115
|
-
* Exported so a test can call the real function rather than a copy of it.
|
|
14
|
+
* `page.waitForSelector`, whose timeout names each display that had not
|
|
15
|
+
* painted and the phase it was in.
|
|
116
16
|
*/
|
|
117
|
-
export declare function
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
*
|
|
121
|
-
* The gate for a build that publishes no readiness attributes, where every
|
|
122
|
-
* other wait in this module is an assertion about an absent selector and so
|
|
123
|
-
* cannot fail. Absence answers "is it working NOW"; a capture needs "has it
|
|
124
|
-
* finished", and the two differ in both directions:
|
|
125
|
-
*
|
|
126
|
-
* BEFORE the work starts. Measured on jbrowse.org/code/jb2/latest with two
|
|
127
|
-
* remote tracks: the session reports both tracks open at ~2.5s and the
|
|
128
|
-
* loading overlay does not go up until ~3.5s. Every absence-based gate passes
|
|
129
|
-
* during that second, over an app that has drawn nothing.
|
|
130
|
-
*
|
|
131
|
-
* BETWEEN two pieces of work. A track that finishes one fetch and starts the
|
|
132
|
-
* next is momentarily idle, and a single-sample gate takes it.
|
|
133
|
-
*
|
|
134
|
-
* Requiring the idle to HOLD closes both without needing to know which signals
|
|
135
|
-
* a given build has. Polled from node rather than in-page: chrome throttles
|
|
136
|
-
* in-page timers and rAF once the tab is not visible, which is the state a
|
|
137
|
-
* headless capture sits in.
|
|
138
|
-
*
|
|
139
|
-
* Returns false on timeout rather than throwing, like its neighbours — the
|
|
140
|
-
* caller decides whether a page that never went quiet is a failure or a slow
|
|
141
|
-
* page worth capturing anyway.
|
|
142
|
-
*/
|
|
143
|
-
export declare function waitForQuietPeriod(page: Page, { quietMs, timeout, pollMs, busyWindowMs, }?: {
|
|
144
|
-
quietMs?: number;
|
|
145
|
-
timeout?: number;
|
|
17
|
+
export declare function waitForSelectorAttributed(page: Page, selector: string, { timeout }?: WaitOptions): Promise<ElementHandle>;
|
|
18
|
+
type SettleOptions = WaitOptions & {
|
|
19
|
+
holdMs?: number;
|
|
146
20
|
pollMs?: number;
|
|
147
|
-
|
|
148
|
-
* Wait for the app to be seen BUSY before any idle counts, giving up on
|
|
149
|
-
* that after this long. Zero (the default) accepts idle immediately.
|
|
150
|
-
*
|
|
151
|
-
* This is what turns the wait positive. Idle is still an absence, so an app
|
|
152
|
-
* that has not begun looks exactly like one that has finished — measured on
|
|
153
|
-
* jbrowse.org/code/jb2/latest, where a chain starting at the session gate
|
|
154
|
-
* saw an idle page at 1.6s and the tracks did not draw until past 10s.
|
|
155
|
-
* Seeing the transition INTO work and back out of it is an observation of
|
|
156
|
-
* the work itself.
|
|
157
|
-
*
|
|
158
|
-
* The window is bounded because a page with nothing to fetch never goes
|
|
159
|
-
* busy at all, and hanging on that would be worse than the race it closes.
|
|
160
|
-
* Size it above the gap between the session gate passing and the first
|
|
161
|
-
* indicator appearing, measured at ~1s on that instance.
|
|
162
|
-
*/
|
|
163
|
-
busyWindowMs?: number;
|
|
164
|
-
}): Promise<boolean>;
|
|
21
|
+
};
|
|
165
22
|
/**
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* One selector, no chain: `[data-app-phase="ready"]` is rendered by the session
|
|
169
|
-
* itself, so it cannot be satisfied before the app exists. Returns false if the
|
|
170
|
-
* page never publishes it, which is how a caller tells "not ready yet" from "a
|
|
171
|
-
* build too old to have the marker" and falls back.
|
|
23
|
+
* `waitForAppSettled`, answering with what was still blocking at the timeout,
|
|
24
|
+
* or undefined once the hold passed.
|
|
172
25
|
*/
|
|
173
|
-
export declare function
|
|
174
|
-
timeout?: number;
|
|
175
|
-
}): Promise<boolean>;
|
|
176
|
-
/** Whether this build publishes the app-level readiness marker at all. */
|
|
177
|
-
export declare function hasAppReadyMarker(page: Page): Promise<boolean>;
|
|
26
|
+
export declare function appSettledBlocker(page: Page, { timeout, holdMs, pollMs, }?: SettleOptions): Promise<string | undefined>;
|
|
178
27
|
/**
|
|
179
|
-
* Wait
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
* answers it. After an interaction the app is already `ready` — it was finished a
|
|
185
|
-
* moment ago — and stays that way until the click's work registers, so the same
|
|
186
|
-
* read returns instantly, on the pre-click frame.
|
|
187
|
-
*
|
|
188
|
-
* What it replaces is a fixed sleep, which is wrong in both directions and only
|
|
189
|
-
* ever caught in one: too short captures the work in progress, and the figure it
|
|
190
|
-
* produces looks finished, while too long is dead time on every run.
|
|
191
|
-
*
|
|
192
|
-
* **Not "seen busy, then ready"**, which is the obvious shape and was built and
|
|
193
|
-
* measured first. Waiting for `loading` to appear before accepting `ready` needs
|
|
194
|
-
* a cap, since an interaction that only opened a menu never makes the app busy at
|
|
195
|
-
* all — and on the figure spec it was measured against
|
|
196
|
-
* (`search_feature_highlight`) the app was never seen busy either, because that
|
|
197
|
-
* spec's own selector wait had already outlasted the redraw. The busy window then
|
|
198
|
-
* ran to its 2s cap having watched nothing, costing more than the 1.2s sleep it
|
|
199
|
-
* replaced. Requiring the idle to HOLD costs the hold and no more, and catches
|
|
200
|
-
* the same late-starting work.
|
|
201
|
-
*
|
|
202
|
-
* Polled from Node rather than by `page.waitForSelector`, for the reason
|
|
203
|
-
* `waitForQuietPeriod` is: chrome throttles in-page timers and rAF once the tab
|
|
204
|
-
* is not visible, which is exactly the state a headless capture sits in.
|
|
205
|
-
*
|
|
206
|
-
* Falls back to the quiet period on a build too old for the marker, rather than
|
|
207
|
-
* passing instantly. A no-op that reports success is how a spec that dropped its
|
|
208
|
-
* sleep for this ends up capturing the frame the sleep was there to avoid.
|
|
28
|
+
* Wait until every app on the page has read ready, with nothing loading or
|
|
29
|
+
* animating, for an unbroken `holdMs`. False on timeout. Right after a
|
|
30
|
+
* navigation it first waits for the marker to mount; a page that never
|
|
31
|
+
* publishes `[data-app-phase]` throws, since nothing positive exists to wait
|
|
32
|
+
* for.
|
|
209
33
|
*/
|
|
210
|
-
export declare function waitForAppSettled(page: Page,
|
|
211
|
-
|
|
212
|
-
holdMs?: number;
|
|
213
|
-
pollMs?: number;
|
|
214
|
-
}): Promise<boolean>;
|
|
34
|
+
export declare function waitForAppSettled(page: Page, options?: SettleOptions): Promise<boolean>;
|
|
35
|
+
export {};
|