effect-browser 0.2.0-beta.2 → 0.2.0-beta.4
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 +15 -6
- package/dist/Browser.d.mts +1 -1
- package/dist/{BrowserData-D_zsf79q.d.mts → BrowserData-DPh3Oaof.d.mts} +28 -20
- package/dist/BrowserData.d.mts +1 -1
- package/dist/BrowserData.mjs +25 -14
- package/dist/BrowserData.mjs.map +1 -1
- package/dist/{BrowserRuntime-e7MXqjOK.d.mts → BrowserRuntime-BBAjpVFa.d.mts} +2 -2
- package/dist/{BrowserRuntime-xBCLDy_5.mjs → BrowserRuntime-DImn_Oe_.mjs} +157 -49
- package/dist/BrowserRuntime-DImn_Oe_.mjs.map +1 -0
- package/dist/BrowserRuntime.d.mts +1 -1
- package/dist/BrowserRuntime.mjs +1 -1
- package/dist/Capture.mjs +70 -29
- package/dist/Capture.mjs.map +1 -1
- package/dist/{CaptureData-B5-mXlyq.mjs → CaptureData-Dys0Ko9d.mjs} +5 -3
- package/dist/{CaptureData-B5-mXlyq.mjs.map → CaptureData-Dys0Ko9d.mjs.map} +1 -1
- package/dist/CaptureData.d.mts +6 -3
- package/dist/CaptureData.mjs +1 -1
- package/dist/Chromium.d.mts +1 -1
- package/dist/Chromium.mjs +5 -2
- package/dist/Chromium.mjs.map +1 -1
- package/dist/PageControl.d.mts +1 -1
- package/dist/Testing.d.mts +2 -2
- package/dist/Testing.mjs +54 -20
- package/dist/Testing.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/BrowserRuntime-xBCLDy_5.mjs.map +0 -1
|
@@ -1842,6 +1842,10 @@ const nativeSelection = (files) => {
|
|
|
1842
1842
|
*/
|
|
1843
1843
|
const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
1844
1844
|
const { current } = targets;
|
|
1845
|
+
let invalidatePointer = (_page) => {};
|
|
1846
|
+
const setPointerInvalidator = (invalidate) => {
|
|
1847
|
+
invalidatePointer = invalidate;
|
|
1848
|
+
};
|
|
1845
1849
|
const navigationControls = /* @__PURE__ */ new Map();
|
|
1846
1850
|
let downloadSerial = 0;
|
|
1847
1851
|
/** A result URL is only ever an http(s) address without credentials. */
|
|
@@ -1887,11 +1891,29 @@ const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
|
1887
1891
|
};
|
|
1888
1892
|
/** What is left of a step's deadline for reading back, keeping a margin for the owner. */
|
|
1889
1893
|
const readBack = (ticket, wanted) => Math.min(wanted, Math.max(0, ticket.remainingMillis() - 250));
|
|
1890
|
-
const
|
|
1891
|
-
|
|
1894
|
+
const clickElement = (page, element, ticket, capture) => {
|
|
1895
|
+
const dispatch = async () => {
|
|
1896
|
+
invalidatePointer(page);
|
|
1897
|
+
await element.click({ timeout: timeout(ticket) });
|
|
1898
|
+
};
|
|
1899
|
+
return capture === void 0 ? dispatch().then(() => void 0) : capture(dispatch, { position: null });
|
|
1900
|
+
};
|
|
1901
|
+
const click = (target, ticket, capture, policy, browserTarget) => sanitize(async () => {
|
|
1902
|
+
const { page } = current(browserTarget).entry;
|
|
1903
|
+
const input = await withElement(target, ticket, (element) => clickElement(page, element, ticket, capture), policy, browserTarget);
|
|
1892
1904
|
ticket.check();
|
|
1893
|
-
|
|
1905
|
+
if (input === void 0) throw failure(Reasons.Malformed.make({}), "unknown");
|
|
1906
|
+
return {
|
|
1907
|
+
url: postUrl(browserTarget),
|
|
1908
|
+
input
|
|
1909
|
+
};
|
|
1894
1910
|
});
|
|
1911
|
+
const clickWithoutReceipt = async (target, ticket) => {
|
|
1912
|
+
const { page } = current().entry;
|
|
1913
|
+
await withElement(target, ticket, (element) => clickElement(page, element, ticket));
|
|
1914
|
+
ticket.check();
|
|
1915
|
+
return postUrl();
|
|
1916
|
+
};
|
|
1895
1917
|
/**
|
|
1896
1918
|
* A file the provider already stores is named to the browser process, which opens it; this
|
|
1897
1919
|
* client never reads that path. Exactly one main-frame node may match, and exactly one
|
|
@@ -1977,11 +1999,12 @@ const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
|
1977
1999
|
* in the requested state, and a native radio is never asked to clear itself. Options are the
|
|
1978
2000
|
* issued nodes of the same observation, exactly as `selectOption` sends them.
|
|
1979
2001
|
*/
|
|
1980
|
-
const formStep = (target, field, ticket, policy, settleMillis) => sanitize(async () => {
|
|
2002
|
+
const formStep = (target, field, ticket, policy, settleMillis, capture) => sanitize(async () => {
|
|
1981
2003
|
const { element, check, facts } = await observation.resolve(target, ticket, policy, false, void 0, true);
|
|
1982
2004
|
check();
|
|
1983
2005
|
if (facts === void 0) throw failure(Reasons.Malformed.make({}), "undispatched");
|
|
1984
2006
|
let act;
|
|
2007
|
+
let input;
|
|
1985
2008
|
if (field.options !== void 0) {
|
|
1986
2009
|
const admitted = await observation.selectOptions(target, field.options, element, ticket, true);
|
|
1987
2010
|
act = async () => {
|
|
@@ -1994,7 +2017,9 @@ const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
|
1994
2017
|
if (facts.checked !== field.checked) {
|
|
1995
2018
|
if (!field.checked && facts.inputType === "radio") throw failure(Reasons.Unsupported.make({}), "undispatched");
|
|
1996
2019
|
await refuseInput(element);
|
|
1997
|
-
act = () =>
|
|
2020
|
+
act = async () => {
|
|
2021
|
+
input = await clickElement(current().entry.page, element, ticket, capture);
|
|
2022
|
+
};
|
|
1998
2023
|
}
|
|
1999
2024
|
} else {
|
|
2000
2025
|
const text = field.value ?? "";
|
|
@@ -2019,14 +2044,20 @@ const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
|
2019
2044
|
status: act === void 0 ? "unchanged" : "set",
|
|
2020
2045
|
reached: field.checked === void 0 || state === void 0 || holdsChecked(state, field.checked),
|
|
2021
2046
|
state,
|
|
2022
|
-
url: postUrl()
|
|
2047
|
+
url: postUrl(),
|
|
2048
|
+
...input === void 0 ? {} : { input }
|
|
2023
2049
|
};
|
|
2024
2050
|
});
|
|
2025
2051
|
/** The one submit click, on an exact observed node that may have become enabled. */
|
|
2026
|
-
const formSubmit = (target, ticket, policy) => sanitize(async () => {
|
|
2027
|
-
|
|
2052
|
+
const formSubmit = (target, ticket, capture, policy) => sanitize(async () => {
|
|
2053
|
+
const { page } = current().entry;
|
|
2054
|
+
const input = await withAdmittedElement(target, ticket, (element) => refuseInput(element), (element) => clickElement(page, element, ticket, capture), policy, void 0, true);
|
|
2028
2055
|
ticket.check();
|
|
2029
|
-
|
|
2056
|
+
if (input === void 0) throw failure(Reasons.Malformed.make({}), "unknown");
|
|
2057
|
+
return {
|
|
2058
|
+
url: postUrl(),
|
|
2059
|
+
input
|
|
2060
|
+
};
|
|
2030
2061
|
});
|
|
2031
2062
|
const selectOption = (target, options, ticket, policy) => sanitize(async () => {
|
|
2032
2063
|
await withAdmittedElement(target, ticket, (element) => observation.selectOptions(target, options, element, ticket), async (element, admitted) => {
|
|
@@ -2136,15 +2167,18 @@ const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
|
2136
2167
|
dispose: leased.release
|
|
2137
2168
|
};
|
|
2138
2169
|
});
|
|
2139
|
-
const clickAndWait = (target, ticket) => sanitize(async () => {
|
|
2170
|
+
const clickAndWait = (target, ticket, capture) => sanitize(async () => {
|
|
2140
2171
|
const { entry, frame } = current();
|
|
2141
2172
|
const observer = waitEvent((on) => entry.page.on("framenavigated", on), (off) => entry.page.off("framenavigated", off), ticket, (changedFrame) => changedFrame === frame);
|
|
2142
2173
|
try {
|
|
2143
|
-
await click(target, ticket);
|
|
2174
|
+
const clicked = await click(target, ticket, capture);
|
|
2144
2175
|
await observer.promise;
|
|
2145
2176
|
await frame.waitForLoadState("domcontentloaded", { timeout: timeout(ticket) });
|
|
2146
2177
|
ticket.check();
|
|
2147
|
-
return
|
|
2178
|
+
return {
|
|
2179
|
+
url: postUrl(),
|
|
2180
|
+
input: clicked.input
|
|
2181
|
+
};
|
|
2148
2182
|
} finally {
|
|
2149
2183
|
observer.cancel();
|
|
2150
2184
|
}
|
|
@@ -2153,7 +2187,7 @@ const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
|
2153
2187
|
const page = current().entry.page;
|
|
2154
2188
|
const observer = waitEvent((on) => page.on("download", on), (off) => page.off("download", off), ticket);
|
|
2155
2189
|
try {
|
|
2156
|
-
await
|
|
2190
|
+
await clickWithoutReceipt(target, ticket);
|
|
2157
2191
|
const download = await observer.promise;
|
|
2158
2192
|
const filename = safeDecode(SafeFilename, download.suggestedFilename());
|
|
2159
2193
|
const error = await download.failure();
|
|
@@ -2180,7 +2214,7 @@ const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
|
2180
2214
|
const page = current().entry.page;
|
|
2181
2215
|
const observer = waitEvent((on) => page.on("filechooser", on), (off) => page.off("filechooser", off), ticket);
|
|
2182
2216
|
try {
|
|
2183
|
-
await
|
|
2217
|
+
await clickWithoutReceipt(target, ticket);
|
|
2184
2218
|
const chooser = await observer.promise;
|
|
2185
2219
|
ticket.check();
|
|
2186
2220
|
if (!chooser.isMultiple() && selection.payload.length > 1) throw failure(Reasons.Unsupported.make({}));
|
|
@@ -2192,6 +2226,7 @@ const makeActions = (context, targets, observation, isTimeoutError) => {
|
|
|
2192
2226
|
}
|
|
2193
2227
|
});
|
|
2194
2228
|
return {
|
|
2229
|
+
setPointerInvalidator,
|
|
2195
2230
|
withAdmittedElement,
|
|
2196
2231
|
beginNavigation,
|
|
2197
2232
|
/** Capture the exact navigation at dialog arrival; acknowledgement never looks it up again. */
|
|
@@ -2282,11 +2317,18 @@ const makeCaptureSources = (targets) => {
|
|
|
2282
2317
|
const mainFrameId = frameId(entry.page.mainFrame());
|
|
2283
2318
|
for (const watcher of [...watchers]) {
|
|
2284
2319
|
if (frame !== void 0 && changedFrameId !== mainFrameId && changedFrameId !== watcher.frameId) continue;
|
|
2285
|
-
if (frame !== void 0 && watcher.document !== void 0 && reason === "target-changed" && changedFrameId === mainFrameId && watcher.frameId === mainFrameId) watcher.document(frame.url());
|
|
2320
|
+
if (frame !== void 0 && watcher.document !== void 0 && reason === "target-changed" && changedFrameId === mainFrameId && watcher.frameId === mainFrameId) watcher.document(frame.url(), false);
|
|
2286
2321
|
else watcher.invalidate(reason);
|
|
2287
2322
|
}
|
|
2288
2323
|
};
|
|
2324
|
+
const sameDocumentNavigated = (entry, frame) => {
|
|
2325
|
+
const watchers = captureWatchers.get(entry.id);
|
|
2326
|
+
if (watchers === void 0 || frame !== entry.page.mainFrame()) return;
|
|
2327
|
+
for (const watcher of watchers) if (watcher.frameId === frameId(frame)) watcher.document?.(frame.url(), true);
|
|
2328
|
+
};
|
|
2289
2329
|
const forget = (entry) => {
|
|
2330
|
+
const watchers = captureWatchers.get(entry.id);
|
|
2331
|
+
if (watchers !== void 0) for (const watcher of [...watchers]) watcher.invalidate("target-closed");
|
|
2290
2332
|
captureWatchers.delete(entry.id);
|
|
2291
2333
|
};
|
|
2292
2334
|
const clear = () => {
|
|
@@ -2327,39 +2369,35 @@ const makeCaptureSources = (targets) => {
|
|
|
2327
2369
|
};
|
|
2328
2370
|
watcherSet.add(watcher);
|
|
2329
2371
|
opened?.(captureFrame.url());
|
|
2372
|
+
await page.screencast.start({
|
|
2373
|
+
quality,
|
|
2374
|
+
...size === void 0 ? {} : { size },
|
|
2375
|
+
onFrame: (frame) => {
|
|
2376
|
+
receive(frame);
|
|
2377
|
+
}
|
|
2378
|
+
});
|
|
2379
|
+
}),
|
|
2380
|
+
stop: () => sanitize(async () => {
|
|
2381
|
+
if (page.isClosed()) return;
|
|
2330
2382
|
try {
|
|
2331
|
-
await page.screencast.
|
|
2332
|
-
quality,
|
|
2333
|
-
...size === void 0 ? {} : { size },
|
|
2334
|
-
onFrame: (frame) => {
|
|
2335
|
-
receive(frame);
|
|
2336
|
-
}
|
|
2337
|
-
});
|
|
2383
|
+
await page.screencast.stop();
|
|
2338
2384
|
} catch (error) {
|
|
2339
|
-
|
|
2340
|
-
watcher = void 0;
|
|
2341
|
-
if (watcherSet.size === 0) captureWatchers.delete(entry.id);
|
|
2342
|
-
throw error;
|
|
2385
|
+
if (!page.isClosed()) throw error;
|
|
2343
2386
|
}
|
|
2344
2387
|
}),
|
|
2345
|
-
|
|
2388
|
+
release: () => {
|
|
2346
2389
|
if (watcher !== void 0 && watcherSet !== void 0) {
|
|
2347
2390
|
watcherSet.delete(watcher);
|
|
2348
2391
|
watcher = void 0;
|
|
2349
2392
|
if (watcherSet.size === 0) captureWatchers.delete(entry.id);
|
|
2350
2393
|
}
|
|
2351
|
-
|
|
2352
|
-
try {
|
|
2353
|
-
await page.screencast.stop();
|
|
2354
|
-
} catch (error) {
|
|
2355
|
-
if (!page.isClosed()) throw error;
|
|
2356
|
-
}
|
|
2357
|
-
})
|
|
2394
|
+
}
|
|
2358
2395
|
}
|
|
2359
2396
|
};
|
|
2360
2397
|
});
|
|
2361
2398
|
return {
|
|
2362
2399
|
invalidate,
|
|
2400
|
+
sameDocumentNavigated,
|
|
2363
2401
|
forget,
|
|
2364
2402
|
clear,
|
|
2365
2403
|
capture
|
|
@@ -3276,6 +3314,9 @@ const makePointer = (targets, actions) => {
|
|
|
3276
3314
|
positions.set(page, point);
|
|
3277
3315
|
};
|
|
3278
3316
|
const receipt = (page) => ({ position: positions.get(page) ?? null });
|
|
3317
|
+
const invalidate = (page) => {
|
|
3318
|
+
positions.set(page, null);
|
|
3319
|
+
};
|
|
3279
3320
|
const pointerMove = (point, ticket, target) => sanitize(async () => {
|
|
3280
3321
|
const { page } = current(target).entry;
|
|
3281
3322
|
ticket.dispatch();
|
|
@@ -3349,7 +3390,8 @@ const makePointer = (targets, actions) => {
|
|
|
3349
3390
|
pointerMove,
|
|
3350
3391
|
hover,
|
|
3351
3392
|
wheel,
|
|
3352
|
-
receipt
|
|
3393
|
+
receipt,
|
|
3394
|
+
invalidate
|
|
3353
3395
|
};
|
|
3354
3396
|
};
|
|
3355
3397
|
//#endregion
|
|
@@ -3470,6 +3512,16 @@ const TargetInfo = Schema.Struct({ targetInfo: Schema.Struct({
|
|
|
3470
3512
|
}) });
|
|
3471
3513
|
const URLText = Schema.String.check(Schema.isMaxLength(8192));
|
|
3472
3514
|
/**
|
|
3515
|
+
* Playwright 1.63.0's client Frame emits this synchronous private event before the public Page
|
|
3516
|
+
* `framenavigated` event. Its `newDocument` field distinguishes document commits from URL-only
|
|
3517
|
+
* changes. A missing emitter is an unsupported runtime, never a reason to guess from the URL.
|
|
3518
|
+
*/
|
|
3519
|
+
const clientNavigationEmitter = (frame) => {
|
|
3520
|
+
const emitter = frame._eventEmitter;
|
|
3521
|
+
if (typeof emitter?.on !== "function" || typeof emitter.off !== "function") throw new Error("Playwright 1.63.0 client Frame navigation event is unavailable");
|
|
3522
|
+
return emitter;
|
|
3523
|
+
};
|
|
3524
|
+
/**
|
|
3473
3525
|
* The connection's pages, frames and document epochs, and the one selected target every other
|
|
3474
3526
|
* seam acts on. A page beyond the configured bound is handed to policy recovery, never tracked.
|
|
3475
3527
|
*/
|
|
@@ -3505,7 +3557,25 @@ const makeTargets = (browser, context, options, connectionNamespace, closing, ho
|
|
|
3505
3557
|
return entry;
|
|
3506
3558
|
}
|
|
3507
3559
|
entries.set(entry.id, entry);
|
|
3508
|
-
|
|
3560
|
+
const sameDocumentNavigations = /* @__PURE__ */ new WeakSet();
|
|
3561
|
+
const frameNavigationOff = /* @__PURE__ */ new WeakMap();
|
|
3562
|
+
const watchFrameNavigation = (frame) => {
|
|
3563
|
+
if (frameNavigationOff.has(frame)) return;
|
|
3564
|
+
const emitter = clientNavigationEmitter(frame);
|
|
3565
|
+
const onNavigated = (event) => {
|
|
3566
|
+
if (event.error !== void 0 || event.newDocument !== void 0) return;
|
|
3567
|
+
sameDocumentNavigations.add(frame);
|
|
3568
|
+
hooks.sameDocumentNavigated(entry, frame);
|
|
3569
|
+
};
|
|
3570
|
+
emitter.on("navigated", onNavigated);
|
|
3571
|
+
const off = () => emitter.off("navigated", onNavigated);
|
|
3572
|
+
frameNavigationOff.set(frame, off);
|
|
3573
|
+
entry.off.push(off);
|
|
3574
|
+
};
|
|
3575
|
+
for (const frame of page.frames()) {
|
|
3576
|
+
frameId(frame);
|
|
3577
|
+
watchFrameNavigation(frame);
|
|
3578
|
+
}
|
|
3509
3579
|
const onClose = () => {
|
|
3510
3580
|
hooks.closed(entry);
|
|
3511
3581
|
entries.delete(entry.id);
|
|
@@ -3517,6 +3587,7 @@ const makeTargets = (browser, context, options, connectionNamespace, closing, ho
|
|
|
3517
3587
|
}
|
|
3518
3588
|
};
|
|
3519
3589
|
const onNavigation = (frame) => {
|
|
3590
|
+
if (sameDocumentNavigations.delete(frame)) return;
|
|
3520
3591
|
hooks.navigating(entry, frame);
|
|
3521
3592
|
documentEpochs.set(frame, epochOf(frame) + 1);
|
|
3522
3593
|
hooks.navigated(entry, frame);
|
|
@@ -3525,6 +3596,11 @@ const makeTargets = (browser, context, options, connectionNamespace, closing, ho
|
|
|
3525
3596
|
if (selection.entry === entry && (selection.frame === frame || frame === page.mainFrame())) hooks.changed("target-changed", { pageId: entry.id });
|
|
3526
3597
|
};
|
|
3527
3598
|
const onDetached = (frame) => {
|
|
3599
|
+
const off = frameNavigationOff.get(frame);
|
|
3600
|
+
off?.();
|
|
3601
|
+
const cleanupIndex = off === void 0 ? -1 : entry.off.indexOf(off);
|
|
3602
|
+
if (cleanupIndex !== -1) entry.off.splice(cleanupIndex, 1);
|
|
3603
|
+
frameNavigationOff.delete(frame);
|
|
3528
3604
|
hooks.frameChanged(entry, frame);
|
|
3529
3605
|
if (selection.frame === frame) {
|
|
3530
3606
|
selection.frame = void 0;
|
|
@@ -3534,11 +3610,16 @@ const makeTargets = (browser, context, options, connectionNamespace, closing, ho
|
|
|
3534
3610
|
const onDialog = (dialog) => {
|
|
3535
3611
|
hooks.dialog(entry, dialog);
|
|
3536
3612
|
};
|
|
3613
|
+
const onFrameAttached = (frame) => {
|
|
3614
|
+
frameId(frame);
|
|
3615
|
+
watchFrameNavigation(frame);
|
|
3616
|
+
};
|
|
3537
3617
|
page.on("close", onClose);
|
|
3618
|
+
page.on("frameattached", onFrameAttached);
|
|
3538
3619
|
page.on("framenavigated", onNavigation);
|
|
3539
3620
|
page.on("framedetached", onDetached);
|
|
3540
3621
|
page.on("dialog", onDialog);
|
|
3541
|
-
entry.off.push(() => page.off("close", onClose), () => page.off("framenavigated", onNavigation), () => page.off("framedetached", onDetached), () => page.off("dialog", onDialog));
|
|
3622
|
+
entry.off.push(() => page.off("close", onClose), () => page.off("frameattached", onFrameAttached), () => page.off("framenavigated", onNavigation), () => page.off("framedetached", onDetached), () => page.off("dialog", onDialog));
|
|
3542
3623
|
hooks.opened(entry, creatingPage);
|
|
3543
3624
|
return entry;
|
|
3544
3625
|
};
|
|
@@ -3801,6 +3882,7 @@ const makePlaywrightDriver = async (browser, identity, options, events) => {
|
|
|
3801
3882
|
let closing = false;
|
|
3802
3883
|
let initialized = false;
|
|
3803
3884
|
let browserCdp;
|
|
3885
|
+
let sameDocumentCapture = () => {};
|
|
3804
3886
|
const targets = makeTargets(browser, context, options, identity.namespace, () => closing, {
|
|
3805
3887
|
opened: (entry, created) => {
|
|
3806
3888
|
if (initialized && !created && options.popupPolicy === "close") {
|
|
@@ -3830,13 +3912,13 @@ const makePlaywrightDriver = async (browser, identity, options, events) => {
|
|
|
3830
3912
|
}
|
|
3831
3913
|
observation.invalidate({ pageId: entry.id });
|
|
3832
3914
|
pageControl.closed(entry);
|
|
3833
|
-
captures.invalidate(entry, "target-changed");
|
|
3834
3915
|
captures.forget(entry);
|
|
3835
3916
|
},
|
|
3836
3917
|
navigating: (entry, frame) => pageControl.navigating(entry, frame),
|
|
3837
3918
|
navigated: (entry, frame) => {
|
|
3838
3919
|
if (initialized) initialization.attachFrame(frame, entry.page);
|
|
3839
3920
|
},
|
|
3921
|
+
sameDocumentNavigated: (entry, frame) => sameDocumentCapture(entry, frame),
|
|
3840
3922
|
frameChanged: (entry, frame) => {
|
|
3841
3923
|
actions.waitChanged(entry, frame);
|
|
3842
3924
|
observation.invalidate({
|
|
@@ -3865,8 +3947,10 @@ const makePlaywrightDriver = async (browser, identity, options, events) => {
|
|
|
3865
3947
|
const observation = makeObservation(targets, identity.namespace, events);
|
|
3866
3948
|
const actions = makeActions(context, targets, observation, (error) => error instanceof errors.TimeoutError);
|
|
3867
3949
|
const pointer = makePointer(targets, actions);
|
|
3950
|
+
actions.setPointerInvalidator(pointer.invalidate);
|
|
3868
3951
|
const keyboard = makeKeyboard(targets, actions, pointer.receipt);
|
|
3869
3952
|
const captures = makeCaptureSources(targets);
|
|
3953
|
+
sameDocumentCapture = captures.sameDocumentNavigated;
|
|
3870
3954
|
const pageControl = makePageControl(browser, context, options, identity.namespace, targets, callbacks, events, () => closing, (pageId) => observation.held(pageId));
|
|
3871
3955
|
const onPage = (page) => {
|
|
3872
3956
|
register(page);
|
|
@@ -4051,7 +4135,10 @@ const makeTarget = (bound) => ({
|
|
|
4051
4135
|
stop: operation.stop
|
|
4052
4136
|
}))),
|
|
4053
4137
|
readText: (request) => checked(ReadTextRequest, request, "read-text").pipe(Effect.flatMap((value) => bound.readText(value.selector)), Effect.flatMap((text) => decoded(TextResult$1, "read-text", "undispatched")({ text }))),
|
|
4054
|
-
click: (request) => checked(ClickRequest, request, "click").pipe(Effect.flatMap((value) => bound.click(value.selector)), Effect.flatMap((url) => action({
|
|
4138
|
+
click: (request) => checked(ClickRequest, request, "click").pipe(Effect.flatMap((value) => bound.click(value.selector)), Effect.flatMap(({ url, input }) => action({
|
|
4139
|
+
url,
|
|
4140
|
+
input
|
|
4141
|
+
}))),
|
|
4055
4142
|
fill: (request) => checked(FillRequest, request, "fill").pipe(Effect.flatMap((value) => bound.fill(value.selector, value.value)), Effect.flatMap((url) => action({ url }))),
|
|
4056
4143
|
scroll: (request) => checked(ScrollRequest, request, "scroll").pipe(Effect.flatMap((value) => bound.scroll(value.deltaX, value.deltaY)), Effect.flatMap((url) => action({ url }))),
|
|
4057
4144
|
pointerMove: (request) => checked(PointerMoveRequest, request, "pointer-move").pipe(Effect.flatMap((value) => bound.pointerMove(value.to)), Effect.flatMap((input) => pointerMoved({
|
|
@@ -4126,7 +4213,10 @@ const makeSession = (controls, bindings) => {
|
|
|
4126
4213
|
}))),
|
|
4127
4214
|
controlFacts: (reference) => checked(ObservedElement, reference, "control-facts").pipe(Effect.flatMap(controls.controlFacts)),
|
|
4128
4215
|
revalidateElement: (reference) => checked(ObservedElement, reference, "revalidate").pipe(Effect.flatMap((value) => controls.revalidate(value).pipe(Effect.as(value)))),
|
|
4129
|
-
clickElement: (reference, admission) => checked(ObservedElement, reference, "click").pipe(Effect.flatMap((value) => controls.operations.click(value, admission?.admit)), Effect.flatMap(
|
|
4216
|
+
clickElement: (reference, admission) => checked(ObservedElement, reference, "click").pipe(Effect.flatMap((value) => controls.operations.click(value, admission?.admit)), Effect.flatMap(({ url, input }) => action({
|
|
4217
|
+
url,
|
|
4218
|
+
input
|
|
4219
|
+
}))),
|
|
4130
4220
|
fillElement: (reference, value, admission) => checked(ObservedElement, reference, "fill").pipe(Effect.flatMap((element) => checked(FillRequest.fields.value, value, "fill").pipe(Effect.flatMap((text) => controls.operations.fill(element, text, admission?.admit)))), Effect.flatMap(navigate)),
|
|
4131
4221
|
selectOption: (reference, options, admission) => checked(ObservedElement, reference, "select-option").pipe(Effect.flatMap((element) => checked(SelectOptions, options, "select-option").pipe(Effect.flatMap((ids) => controls.selectOption(element, ids, admission?.admit)))), Effect.flatMap(navigate)),
|
|
4132
4222
|
fillForm: (request, admission, options = {}) => checked(FillFormRequest, request, "fill-form").pipe(Effect.flatMap((form) => checked(FillFormOptions, options, "fill-form").pipe(Effect.flatMap((settings) => controls.fillForm(form, admission?.admit, {
|
|
@@ -4157,7 +4247,10 @@ const makeSession = (controls, bindings) => {
|
|
|
4157
4247
|
resizeViewport: (viewport) => checked(Viewport, viewport, "resize").pipe(Effect.flatMap(controls.resize)),
|
|
4158
4248
|
waitFor: (request) => checked(Wait, request, "wait").pipe(Effect.flatMap((value) => controls.waitFor(value.selector, value.state))),
|
|
4159
4249
|
waitForElement: (request) => checked(WaitForElementRequest, request, "wait").pipe(Effect.flatMap(controls.waitForElement)),
|
|
4160
|
-
clickAndWait: (request) => checked(ClickRequest, request, "click-and-wait").pipe(Effect.flatMap((value) => controls.clickAndWait(value.selector)), Effect.flatMap((url) => action({
|
|
4250
|
+
clickAndWait: (request) => checked(ClickRequest, request, "click-and-wait").pipe(Effect.flatMap((value) => controls.clickAndWait(value.selector)), Effect.flatMap(({ url, input }) => action({
|
|
4251
|
+
url,
|
|
4252
|
+
input
|
|
4253
|
+
}))),
|
|
4161
4254
|
ready: controls.readiness.pipe(Effect.mapError((error) => InitializationError.make({
|
|
4162
4255
|
operation: "ready",
|
|
4163
4256
|
step: "session",
|
|
@@ -5136,6 +5229,17 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
5136
5229
|
* Direct operations resolve selection under admission. Retained operations capture selection
|
|
5137
5230
|
* and generation; pinned operations capture generation and their explicit page/frame only.
|
|
5138
5231
|
*/
|
|
5232
|
+
const captureClickAt = (target) => async (dispatch, dispatched) => {
|
|
5233
|
+
const startedMonotonicNanos = clock.monotonicTimeNanosUnsafe();
|
|
5234
|
+
await dispatch();
|
|
5235
|
+
return {
|
|
5236
|
+
...dispatched,
|
|
5237
|
+
target,
|
|
5238
|
+
kind: "click",
|
|
5239
|
+
startedMonotonicNanos,
|
|
5240
|
+
completedMonotonicNanos: clock.monotonicTimeNanosUnsafe()
|
|
5241
|
+
};
|
|
5242
|
+
};
|
|
5139
5243
|
const makeOperations = (retained) => {
|
|
5140
5244
|
const browserTarget = retained?.target;
|
|
5141
5245
|
const check = () => {
|
|
@@ -5321,7 +5425,7 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
5321
5425
|
startNavigation,
|
|
5322
5426
|
navigate: (url, timeoutMillis) => Effect.scoped(startNavigation(url, timeoutMillis).pipe(Effect.flatMap((operation) => operation.completed))),
|
|
5323
5427
|
readText: (selector) => run("read-text", (driver, ticket) => driver.readText(selector, options.maxReturnedBytes, ticket, browserTarget)),
|
|
5324
|
-
click: (target, policy) => run("click", (driver, ticket) => driver.click(target, ticket, policy, browserTarget), true),
|
|
5428
|
+
click: (target, policy) => run("click", (driver, ticket) => driver.click(target, ticket, captureClickAt(operationTarget()), policy, browserTarget), true),
|
|
5325
5429
|
fill: (target, value, policy) => run("fill", (driver, ticket) => driver.fill(target, value, ticket, policy, browserTarget), true),
|
|
5326
5430
|
scroll: (x, y) => run("scroll", (driver, ticket) => driver.scroll(x, y, ticket, browserTarget), true),
|
|
5327
5431
|
pointerMove: (to) => input("pointer-move", (driver, ticket) => driver.pointerMove(to, ticket, browserTarget)),
|
|
@@ -5459,7 +5563,7 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
5459
5563
|
}
|
|
5460
5564
|
});
|
|
5461
5565
|
for (const field of request.fields) {
|
|
5462
|
-
const exit = yield* Effect.exit(nativeOperation("fill-form", (driver, ticket) => driver.formStep(reference(field.elementId), field, ticket, policy, form.settleMillis), {
|
|
5566
|
+
const exit = yield* Effect.exit(nativeOperation("fill-form", (driver, ticket) => driver.formStep(reference(field.elementId), field, ticket, policy, form.settleMillis, captureClickAt(capture.target())), {
|
|
5463
5567
|
mutation: true,
|
|
5464
5568
|
mutationScope: kept
|
|
5465
5569
|
}));
|
|
@@ -5471,7 +5575,8 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
5471
5575
|
const step = exit.value;
|
|
5472
5576
|
fields.push({
|
|
5473
5577
|
elementId: field.elementId,
|
|
5474
|
-
status: step.status
|
|
5578
|
+
status: step.status,
|
|
5579
|
+
...step.input === void 0 ? {} : { input: step.input }
|
|
5475
5580
|
});
|
|
5476
5581
|
states.push(step.state);
|
|
5477
5582
|
url = step.url;
|
|
@@ -5499,14 +5604,17 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
5499
5604
|
}
|
|
5500
5605
|
if (request.submit === void 0) return finish(false);
|
|
5501
5606
|
const submit = request.submit;
|
|
5502
|
-
const exit = yield* Effect.exit(nativeOperation("fill-form", (driver, ticket) => driver.formSubmit(reference(submit), ticket, policy), { mutation: true }));
|
|
5607
|
+
const exit = yield* Effect.exit(nativeOperation("fill-form", (driver, ticket) => driver.formSubmit(reference(submit), ticket, captureClickAt(capture.target()), policy), { mutation: true }));
|
|
5503
5608
|
if (Exit.isFailure(exit)) {
|
|
5504
5609
|
const error = Cause.findErrorOption(exit.cause);
|
|
5505
5610
|
if (Option.isNone(error)) return yield* Effect.failCause(exit.cause);
|
|
5506
5611
|
return stop("submit", error.value, submit);
|
|
5507
5612
|
}
|
|
5508
|
-
url = exit.value;
|
|
5509
|
-
return
|
|
5613
|
+
url = exit.value.url;
|
|
5614
|
+
return {
|
|
5615
|
+
...finish(true),
|
|
5616
|
+
submitInput: exit.value.input
|
|
5617
|
+
};
|
|
5510
5618
|
}).pipe(Effect.ensuring(Effect.sync(() => {
|
|
5511
5619
|
if (pageId !== void 0) owner.invalidate("observation", { pageId });
|
|
5512
5620
|
})));
|
|
@@ -5545,7 +5653,7 @@ const acquireSession = Effect.fnUntraced(function* (limits, options) {
|
|
|
5545
5653
|
}),
|
|
5546
5654
|
waitFor: (selector, state) => wait((driver, ticket, target) => driver.waitFor(selector, state, ticket, target)),
|
|
5547
5655
|
waitForElement: (request) => wait((driver, ticket, target) => driver.waitForElement(request.reference, request.state, ticket, target), request.timeoutMillis),
|
|
5548
|
-
clickAndWait: (target) => nativeOperation("click-and-wait", (driver, ticket) => driver.clickAndWait(target, ticket), { mutation: true }),
|
|
5656
|
+
clickAndWait: (target) => nativeOperation("click-and-wait", (driver, ticket) => driver.clickAndWait(target, ticket, captureClickAt(capture.target())), { mutation: true }),
|
|
5549
5657
|
clickForDownload: (target) => nativeOperation("download-action", (driver, ticket) => driver.clickForDownload(target, ticket), { mutation: true }),
|
|
5550
5658
|
selectFiles: (target, files) => nativeOperation("select-files", (driver, ticket) => driver.selectFiles(target, files, ticket), { mutation: true }),
|
|
5551
5659
|
clickForFileSelection: (target, files) => nativeOperation("file-chooser", (driver, ticket) => driver.clickForFileSelection(target, files, ticket), { mutation: true }),
|
|
@@ -5787,4 +5895,4 @@ const make = Effect.fnUntraced(function* (options) {
|
|
|
5787
5895
|
//#endregion
|
|
5788
5896
|
export { cleanupStep as a, checked as c, randomUuid as i, fromNativeAttempt as l, make as n, noConnection as o, playwright as r, reported as s, DownloadEvent as t, issueBinding as u };
|
|
5789
5897
|
|
|
5790
|
-
//# sourceMappingURL=BrowserRuntime-
|
|
5898
|
+
//# sourceMappingURL=BrowserRuntime-DImn_Oe_.mjs.map
|