How to use _onDispatchMessageFromWorker method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

ffPage.js

Source: ffPage.js Github

copy
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4  value: true
5});
6exports.UTILITY_WORLD_NAME = exports.FFPage = void 0;
7
8var dialog = _interopRequireWildcard(require("../dialog"));
9
10var dom = _interopRequireWildcard(require("../dom"));
11
12var _eventsHelper = require("../../utils/eventsHelper");
13
14var _utils = require("../../utils/utils");
15
16var _page = require("../page");
17
18var _ffAccessibility = require("./ffAccessibility");
19
20var _ffConnection = require("./ffConnection");
21
22var _ffExecutionContext = require("./ffExecutionContext");
23
24var _ffInput = require("./ffInput");
25
26var _ffNetworkManager = require("./ffNetworkManager");
27
28var _stackTrace = require("../../utils/stackTrace");
29
30var _debugLogger = require("../../utils/debugLogger");
31
32var _async = require("../../utils/async");
33
34function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
35
36function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
37
38/**
39 * Copyright 2019 Google Inc. All rights reserved.
40 * Modifications copyright (c) Microsoft Corporation.
41 *
42 * Licensed under the Apache License, Version 2.0 (the "License");
43 * you may not use this file except in compliance with the License.
44 * You may obtain a copy of the License at
45 *
46 *     http://www.apache.org/licenses/LICENSE-2.0
47 *
48 * Unless required by applicable law or agreed to in writing, software
49 * distributed under the License is distributed on an "AS IS" BASIS,
50 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
51 * See the License for the specific language governing permissions and
52 * limitations under the License.
53 */
54const UTILITY_WORLD_NAME = '__playwright_utility_world__';
55exports.UTILITY_WORLD_NAME = UTILITY_WORLD_NAME;
56
57class FFPage {
58  constructor(session, browserContext, opener) {
59    this.cspErrorsAsynchronousForInlineScipts = true;
60    this.rawMouse = void 0;
61    this.rawKeyboard = void 0;
62    this.rawTouchscreen = void 0;
63    this._session = void 0;
64    this._page = void 0;
65    this._networkManager = void 0;
66    this._browserContext = void 0;
67    this._pagePromise = new _async.ManualPromise();
68    this._initializedPage = null;
69    this._initializationFailed = false;
70    this._opener = void 0;
71    this._contextIdToContext = void 0;
72    this._eventListeners = void 0;
73    this._workers = new Map();
74    this._screencastId = void 0;
75    this._session = session;
76    this._opener = opener;
77    this.rawKeyboard = new _ffInput.RawKeyboardImpl(session);
78    this.rawMouse = new _ffInput.RawMouseImpl(session);
79    this.rawTouchscreen = new _ffInput.RawTouchscreenImpl(session);
80    this._contextIdToContext = new Map();
81    this._browserContext = browserContext;
82    this._page = new _page.Page(this, browserContext);
83    this.rawMouse.setPage(this._page);
84    this._networkManager = new _ffNetworkManager.FFNetworkManager(session, this._page);
85
86    this._page.on(_page.Page.Events.FrameDetached, frame => this._removeContextsForFrame(frame)); // TODO: remove Page.willOpenNewWindowAsynchronously from the protocol.
87
88
89    this._eventListeners = [_eventsHelper.eventsHelper.addEventListener(this._session, 'Page.eventFired', this._onEventFired.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.frameAttached', this._onFrameAttached.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.frameDetached', this._onFrameDetached.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationAborted', this._onNavigationAborted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationCommitted', this._onNavigationCommitted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationStarted', this._onNavigationStarted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.sameDocumentNavigation', this._onSameDocumentNavigation.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.executionContextCreated', this._onExecutionContextCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.executionContextDestroyed', this._onExecutionContextDestroyed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.linkClicked', event => this._onLinkClicked(event.phase)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.uncaughtError', this._onUncaughtError.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.console', this._onConsole.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.dialogOpened', this._onDialogOpened.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.bindingCalled', this._onBindingCalled.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.fileChooserOpened', this._onFileChooserOpened.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.workerCreated', this._onWorkerCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.workerDestroyed', this._onWorkerDestroyed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.dispatchMessageFromWorker', this._onDispatchMessageFromWorker.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.crashed', this._onCrashed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.videoRecordingStarted', this._onVideoRecordingStarted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketCreated', this._onWebSocketCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketClosed', this._onWebSocketClosed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketFrameReceived', this._onWebSocketFrameReceived.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketFrameSent', this._onWebSocketFrameSent.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.screencastFrame', this._onScreencastFrame.bind(this))];
90    session.once(_ffConnection.FFSessionEvents.Disconnected, () => {
91      this._markAsError(new Error('Page closed'));
92
93      this._page._didDisconnect();
94    });
95
96    this._session.once('Page.ready', async () => {
97      await this._page.initOpener(this._opener);
98      if (this._initializationFailed) return; // Note: it is important to call |reportAsNew| before resolving pageOrError promise,
99      // so that anyone who awaits pageOrError got a ready and reported page.
100
101      this._initializedPage = this._page;
102
103      this._page.reportAsNew();
104
105      this._pagePromise.resolve(this._page);
106    }); // Ideally, we somehow ensure that utility world is created before Page.ready arrives, but currently it is racy.
107    // Therefore, we can end up with an initialized page without utility world, although very unlikely.
108
109
110    this._session.send('Page.addScriptToEvaluateOnNewDocument', {
111      script: '',
112      worldName: UTILITY_WORLD_NAME
113    }).catch(e => this._markAsError(e));
114  }
115
116  async _markAsError(error) {
117    // Same error may be report twice: channer disconnected and session.send fails.
118    if (this._initializationFailed) return;
119    this._initializationFailed = true;
120
121    if (!this._initializedPage) {
122      await this._page.initOpener(this._opener);
123
124      this._page.reportAsNew(error);
125
126      this._pagePromise.resolve(error);
127    }
128  }
129
130  async pageOrError() {
131    return this._pagePromise;
132  }
133
134  _onWebSocketCreated(event) {
135    this._page._frameManager.onWebSocketCreated(webSocketId(event.frameId, event.wsid), event.requestURL);
136
137    this._page._frameManager.onWebSocketRequest(webSocketId(event.frameId, event.wsid));
138  }
139
140  _onWebSocketClosed(event) {
141    if (event.error) this._page._frameManager.webSocketError(webSocketId(event.frameId, event.wsid), event.error);
142
143    this._page._frameManager.webSocketClosed(webSocketId(event.frameId, event.wsid));
144  }
145
146  _onWebSocketFrameReceived(event) {
147    this._page._frameManager.webSocketFrameReceived(webSocketId(event.frameId, event.wsid), event.opcode, event.data);
148  }
149
150  _onWebSocketFrameSent(event) {
151    this._page._frameManager.onWebSocketFrameSent(webSocketId(event.frameId, event.wsid), event.opcode, event.data);
152  }
153
154  _onExecutionContextCreated(payload) {
155    const {
156      executionContextId,
157      auxData
158    } = payload;
159
160    const frame = this._page._frameManager.frame(auxData.frameId);
161
162    if (!frame) return;
163    const delegate = new _ffExecutionContext.FFExecutionContext(this._session, executionContextId);
164    let worldName = null;
165    if (auxData.name === UTILITY_WORLD_NAME) worldName = 'utility';else if (!auxData.name) worldName = 'main';
166    const context = new dom.FrameExecutionContext(delegate, frame, worldName);
167    context[contextDelegateSymbol] = delegate;
168    if (worldName) frame._contextCreated(worldName, context);
169
170    this._contextIdToContext.set(executionContextId, context);
171  }
172
173  _onExecutionContextDestroyed(payload) {
174    const {
175      executionContextId
176    } = payload;
177
178    const context = this._contextIdToContext.get(executionContextId);
179
180    if (!context) return;
181
182    this._contextIdToContext.delete(executionContextId);
183
184    context.frame._contextDestroyed(context);
185  }
186
187  _removeContextsForFrame(frame) {
188    for (const [contextId, context] of this._contextIdToContext) {
189      if (context.frame === frame) this._contextIdToContext.delete(contextId);
190    }
191  }
192
193  _onLinkClicked(phase) {
194    if (phase === 'before') this._page._frameManager.frameWillPotentiallyRequestNavigation();else this._page._frameManager.frameDidPotentiallyRequestNavigation();
195  }
196
197  _onNavigationStarted(params) {
198    this._page._frameManager.frameRequestedNavigation(params.frameId, params.navigationId);
199  }
200
201  _onNavigationAborted(params) {
202    this._page._frameManager.frameAbortedNavigation(params.frameId, params.errorText, params.navigationId);
203  }
204
205  _onNavigationCommitted(params) {
206    for (const [workerId, worker] of this._workers) {
207      if (worker.frameId === params.frameId) this._onWorkerDestroyed({
208        workerId
209      });
210    }
211
212    this._page._frameManager.frameCommittedNewDocumentNavigation(params.frameId, params.url, params.name || '', params.navigationId || '', false);
213  }
214
215  _onSameDocumentNavigation(params) {
216    this._page._frameManager.frameCommittedSameDocumentNavigation(params.frameId, params.url);
217  }
218
219  _onFrameAttached(params) {
220    this._page._frameManager.frameAttached(params.frameId, params.parentFrameId);
221  }
222
223  _onFrameDetached(params) {
224    this._page._frameManager.frameDetached(params.frameId);
225  }
226
227  _onEventFired(payload) {
228    const {
229      frameId,
230      name
231    } = payload;
232    if (name === 'load') this._page._frameManager.frameLifecycleEvent(frameId, 'load');
233    if (name === 'DOMContentLoaded') this._page._frameManager.frameLifecycleEvent(frameId, 'domcontentloaded');
234  }
235
236  _onUncaughtError(params) {
237    const {
238      name,
239      message
240    } = (0, _stackTrace.splitErrorMessage)(params.message);
241    const error = new Error(message);
242    error.stack = params.message + '\n' + params.stack.split('\n').filter(Boolean).map(a => a.replace(/([^@]*)@(.*)/, '    at $1 ($2)')).join('\n');
243    error.name = name;
244
245    this._page.firePageError(error);
246  }
247
248  _onConsole(payload) {
249    const {
250      type,
251      args,
252      executionContextId,
253      location
254    } = payload;
255
256    const context = this._contextIdToContext.get(executionContextId);
257
258    if (!context) return;
259
260    this._page._addConsoleMessage(type, args.map(arg => context.createHandle(arg)), location);
261  }
262
263  _onDialogOpened(params) {
264    this._page.emit(_page.Page.Events.Dialog, new dialog.Dialog(this._page, params.type, params.message, async (accept, promptText) => {
265      await this._session.sendMayFail('Page.handleDialog', {
266        dialogId: params.dialogId,
267        accept,
268        promptText
269      });
270    }, params.defaultValue));
271  }
272
273  async _onBindingCalled(event) {
274    const pageOrError = await this.pageOrError();
275
276    if (!(pageOrError instanceof Error)) {
277      const context = this._contextIdToContext.get(event.executionContextId);
278
279      if (context) await this._page._onBindingCalled(event.payload, context);
280    }
281  }
282
283  async _onFileChooserOpened(payload) {
284    const {
285      executionContextId,
286      element
287    } = payload;
288
289    const context = this._contextIdToContext.get(executionContextId);
290
291    if (!context) return;
292    const handle = context.createHandle(element).asElement();
293    await this._page._onFileChooserOpened(handle);
294  }
295
296  async _onWorkerCreated(event) {
297    const workerId = event.workerId;
298    const worker = new _page.Worker(this._page, event.url);
299    const workerSession = new _ffConnection.FFSession(this._session._connection, workerId, message => {
300      this._session.send('Page.sendMessageToWorker', {
301        frameId: event.frameId,
302        workerId: workerId,
303        message: JSON.stringify(message)
304      }).catch(e => {
305        workerSession.dispatchMessage({
306          id: message.id,
307          method: '',
308          params: {},
309          error: {
310            message: e.message,
311            data: undefined
312          }
313        });
314      });
315    });
316
317    this._workers.set(workerId, {
318      session: workerSession,
319      frameId: event.frameId
320    });
321
322    this._page._addWorker(workerId, worker);
323
324    workerSession.once('Runtime.executionContextCreated', event => {
325      worker._createExecutionContext(new _ffExecutionContext.FFExecutionContext(workerSession, event.executionContextId));
326    });
327    workerSession.on('Runtime.console', event => {
328      const {
329        type,
330        args,
331        location
332      } = event;
333      const context = worker._existingExecutionContext;
334
335      this._page._addConsoleMessage(type, args.map(arg => context.createHandle(arg)), location);
336    }); // Note: we receive worker exceptions directly from the page.
337  }
338
339  _onWorkerDestroyed(event) {
340    const workerId = event.workerId;
341
342    const worker = this._workers.get(workerId);
343
344    if (!worker) return;
345    worker.session.dispose();
346
347    this._workers.delete(workerId);
348
349    this._page._removeWorker(workerId);
350  }
351
352  async _onDispatchMessageFromWorker(event) {
353    const worker = this._workers.get(event.workerId);
354
355    if (!worker) return;
356    worker.session.dispatchMessage(JSON.parse(event.message));
357  }
358
359  async _onCrashed(event) {
360    this._session.markAsCrashed();
361
362    this._page._didCrash();
363  }
364
365  _onVideoRecordingStarted(event) {
366    this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this.pageOrError());
367  }
368
369  async exposeBinding(binding) {
370    await this._session.send('Page.addBinding', {
371      name: binding.name,
372      script: binding.source
373    });
374  }
375
376  didClose() {
377    this._session.dispose();
378
379    _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
380
381    this._networkManager.dispose();
382
383    this._page._didClose();
384  }
385
386  async navigateFrame(frame, url, referer) {
387    const response = await this._session.send('Page.navigate', {
388      url,
389      referer,
390      frameId: frame._id
391    });
392    return {
393      newDocumentId: response.navigationId || undefined
394    };
395  }
396
397  async updateExtraHTTPHeaders() {
398    await this._session.send('Network.setExtraHTTPHeaders', {
399      headers: this._page._state.extraHTTPHeaders || []
400    });
401  }
402
403  async setEmulatedSize(emulatedSize) {
404    (0, _utils.assert)(this._page._state.emulatedSize === emulatedSize);
405    await this._session.send('Page.setViewportSize', {
406      viewportSize: {
407        width: emulatedSize.viewport.width,
408        height: emulatedSize.viewport.height
409      }
410    });
411  }
412
413  async bringToFront() {
414    await this._session.send('Page.bringToFront', {});
415  }
416
417  async updateEmulateMedia() {
418    const colorScheme = this._page._state.colorScheme === null ? undefined : this._page._state.colorScheme;
419    const reducedMotion = this._page._state.reducedMotion === null ? undefined : this._page._state.reducedMotion;
420    const forcedColors = this._page._state.forcedColors === null ? undefined : this._page._state.forcedColors;
421    await this._session.send('Page.setEmulatedMedia', {
422      // Empty string means reset.
423      type: this._page._state.mediaType === null ? '' : this._page._state.mediaType,
424      colorScheme,
425      reducedMotion,
426      forcedColors
427    });
428  }
429
430  async updateRequestInterception() {
431    await this._networkManager.setRequestInterception(this._page._needsRequestInterception());
432  }
433
434  async setFileChooserIntercepted(enabled) {
435    await this._session.send('Page.setInterceptFileChooserDialog', {
436      enabled
437    }).catch(e => {}); // target can be closed.
438  }
439
440  async reload() {
441    await this._session.send('Page.reload', {
442      frameId: this._page.mainFrame()._id
443    });
444  }
445
446  async goBack() {
447    const {
448      success
449    } = await this._session.send('Page.goBack', {
450      frameId: this._page.mainFrame()._id
451    });
452    return success;
453  }
454
455  async goForward() {
456    const {
457      success
458    } = await this._session.send('Page.goForward', {
459      frameId: this._page.mainFrame()._id
460    });
461    return success;
462  }
463
464  async evaluateOnNewDocument(source) {
465    await this._session.send('Page.addScriptToEvaluateOnNewDocument', {
466      script: source
467    });
468  }
469
470  async closePage(runBeforeUnload) {
471    await this._session.send('Page.close', {
472      runBeforeUnload
473    });
474  }
475
476  async setBackgroundColor(color) {
477    if (color) throw new Error('Not implemented');
478  }
479
480  async takeScreenshot(progress, format, documentRect, viewportRect, quality) {
481    if (!documentRect) {
482      const scrollOffset = await this._page.mainFrame().waitForFunctionValueInUtility(progress, () => ({
483        x: window.scrollX,
484        y: window.scrollY
485      }));
486      documentRect = {
487        x: viewportRect.x + scrollOffset.x,
488        y: viewportRect.y + scrollOffset.y,
489        width: viewportRect.width,
490        height: viewportRect.height
491      };
492    } // TODO: remove fullPage option from Page.screenshot.
493    // TODO: remove Page.getBoundingBox method.
494
495
496    progress.throwIfAborted();
497    const {
498      data
499    } = await this._session.send('Page.screenshot', {
500      mimeType: 'image/' + format,
501      clip: documentRect
502    });
503    return Buffer.from(data, 'base64');
504  }
505
506  async getContentFrame(handle) {
507    const {
508      contentFrameId
509    } = await this._session.send('Page.describeNode', {
510      frameId: handle._context.frame._id,
511      objectId: handle._objectId
512    });
513    if (!contentFrameId) return null;
514    return this._page._frameManager.frame(contentFrameId);
515  }
516
517  async getOwnerFrame(handle) {
518    const {
519      ownerFrameId
520    } = await this._session.send('Page.describeNode', {
521      frameId: handle._context.frame._id,
522      objectId: handle._objectId
523    });
524    return ownerFrameId || null;
525  }
526
527  isElementHandle(remoteObject) {
528    return remoteObject.subtype === 'node';
529  }
530
531  async getBoundingBox(handle) {
532    const quads = await this.getContentQuads(handle);
533    if (!quads || !quads.length) return null;
534    let minX = Infinity;
535    let maxX = -Infinity;
536    let minY = Infinity;
537    let maxY = -Infinity;
538
539    for (const quad of quads) {
540      for (const point of quad) {
541        minX = Math.min(minX, point.x);
542        maxX = Math.max(maxX, point.x);
543        minY = Math.min(minY, point.y);
544        maxY = Math.max(maxY, point.y);
545      }
546    }
547
548    return {
549      x: minX,
550      y: minY,
551      width: maxX - minX,
552      height: maxY - minY
553    };
554  }
555
556  async scrollRectIntoViewIfNeeded(handle, rect) {
557    return await this._session.send('Page.scrollIntoViewIfNeeded', {
558      frameId: handle._context.frame._id,
559      objectId: handle._objectId,
560      rect
561    }).then(() => 'done').catch(e => {
562      if (e instanceof Error && e.message.includes('Node is detached from document')) return 'error:notconnected';
563      if (e instanceof Error && e.message.includes('Node does not have a layout object')) return 'error:notvisible';
564      throw e;
565    });
566  }
567
568  async setScreencastOptions(options) {
569    if (options) {
570      const {
571        screencastId
572      } = await this._session.send('Page.startScreencast', options);
573      this._screencastId = screencastId;
574    } else {
575      await this._session.send('Page.stopScreencast');
576    }
577  }
578
579  _onScreencastFrame(event) {
580    if (!this._screencastId) return;
581    const screencastId = this._screencastId;
582
583    this._page.throttleScreencastFrameAck(() => {
584      this._session.send('Page.screencastFrameAck', {
585        screencastId
586      }).catch(e => _debugLogger.debugLogger.log('error', e));
587    });
588
589    const buffer = Buffer.from(event.data, 'base64');
590
591    this._page.emit(_page.Page.Events.ScreencastFrame, {
592      buffer,
593      width: event.deviceWidth,
594      height: event.deviceHeight
595    });
596  }
597
598  rafCountForStablePosition() {
599    return 1;
600  }
601
602  async getContentQuads(handle) {
603    const result = await this._session.sendMayFail('Page.getContentQuads', {
604      frameId: handle._context.frame._id,
605      objectId: handle._objectId
606    });
607    if (!result) return null;
608    return result.quads.map(quad => [quad.p1, quad.p2, quad.p3, quad.p4]);
609  }
610
611  async setInputFiles(handle, files) {
612    await handle.evaluateInUtility(([injected, node, files]) => injected.setInputFiles(node, files), files);
613  }
614
615  async adoptElementHandle(handle, to) {
616    const result = await this._session.send('Page.adoptNode', {
617      frameId: handle._context.frame._id,
618      objectId: handle._objectId,
619      executionContextId: to[contextDelegateSymbol]._executionContextId
620    });
621    if (!result.remoteObject) throw new Error(dom.kUnableToAdoptErrorMessage);
622    return to.createHandle(result.remoteObject);
623  }
624
625  async getAccessibilityTree(needle) {
626    return (0, _ffAccessibility.getAccessibilityTree)(this._session, needle);
627  }
628
629  async inputActionEpilogue() {}
630
631  async getFrameElement(frame) {
632    const parent = frame.parentFrame();
633    if (!parent) throw new Error('Frame has been detached.');
634
635    const info = this._page.parseSelector('frame,iframe');
636
637    const handles = await this._page.selectors._queryAll(parent, info);
638    const items = await Promise.all(handles.map(async handle => {
639      const frame = await handle.contentFrame().catch(e => null);
640      return {
641        handle,
642        frame
643      };
644    }));
645    const result = items.find(item => item.frame === frame);
646    items.map(item => item === result ? Promise.resolve() : item.handle.dispose());
647    if (!result) throw new Error('Frame has been detached.');
648    return result.handle;
649  }
650
651}
652
653exports.FFPage = FFPage;
654
655function webSocketId(frameId, wsid) {
656  return `${frameId}---${wsid}`;
657}
658
659const contextDelegateSymbol = Symbol('delegate');
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)