How to use addPageBinding 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.

expose-function.js

Source: expose-function.js Github

copy
1/* modified exposeFunction from puppeteer/lib/Page.js
2
3*/
4module.exports = function(page) {
5  const _pageBindings = new Map()
6  return function exposeFunctionAgain(name, puppeteerFunction) {
7    const expression = `(${addPageBinding.toString()})("${name}")`;
8    return page.evaluate(expression)
9
10    function addPageBinding(bindingName) {
11      console.log('MY ADDING page binding', bindingName, 'on', document.location.href)
12      const win = window;
13      const binding = win[`${bindingName}`];
14      console.log('binding', binding.toString())
15      win[bindingName] = (...args) => {
16        const me = window[bindingName];
17        let callbacks = me.callbacks;
18        if (!callbacks) {
19          callbacks = new Map();
20          me.callbacks = callbacks;
21        }
22        const seq = (me.lastSeq || 0) + 1;
23        me.lastSeq = seq;
24        const promise = new Promise((resolve, reject) => callbacks.set(seq, { resolve, reject }));
25        binding(JSON.stringify({ name: bindingName, seq, args }));
26        return promise;
27      };
28    }
29  }
30}
31
Full Screen

helper.js

Source: helper.js Github

copy
1/**
2 * Copyright 2017 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import { isNode } from '../environment.js';
17
18import { assert } from './assert.js';
19import { debug } from './Debug.js';
20import { TimeoutError } from './Errors.js';
21
22export const debugError = debug('puppeteer:error');
23function getExceptionMessage(exceptionDetails) {
24    if (exceptionDetails.exception)
25        return (exceptionDetails.exception.description || exceptionDetails.exception.value);
26    let message = exceptionDetails.text;
27    if (exceptionDetails.stackTrace) {
28        for (const callframe of exceptionDetails.stackTrace.callFrames) {
29            const location = callframe.url +
30                ':' +
31                callframe.lineNumber +
32                ':' +
33                callframe.columnNumber;
34            const functionName = callframe.functionName || '<anonymous>';
35            message += `\n    at ${functionName} (${location})`;
36        }
37    }
38    return message;
39}
40function valueFromRemoteObject(remoteObject) {
41    assert(!remoteObject.objectId, 'Cannot extract value when objectId is given');
42    if (remoteObject.unserializableValue) {
43        if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined')
44            return BigInt(remoteObject.unserializableValue.replace('n', ''));
45        switch (remoteObject.unserializableValue) {
46            case '-0':
47                return -0;
48            case 'NaN':
49                return NaN;
50            case 'Infinity':
51                return Infinity;
52            case '-Infinity':
53                return -Infinity;
54            default:
55                throw new Error('Unsupported unserializable value: ' +
56                    remoteObject.unserializableValue);
57        }
58    }
59    return remoteObject.value;
60}
61async function releaseObject(client, remoteObject) {
62    if (!remoteObject.objectId)
63        return;
64    await client
65        .send('Runtime.releaseObject', { objectId: remoteObject.objectId })
66        .catch((error) => {
67        // Exceptions might happen in case of a page been navigated or closed.
68        // Swallow these since they are harmless and we don't leak anything in this case.
69        debugError(error);
70    });
71}
72function addEventListener(emitter, eventName, handler) {
73    emitter.on(eventName, handler);
74    return { emitter, eventName, handler };
75}
76function removeEventListeners(listeners) {
77    for (const listener of listeners)
78        listener.emitter.removeListener(listener.eventName, listener.handler);
79    listeners.length = 0;
80}
81function isString(obj) {
82    return typeof obj === 'string' || obj instanceof String;
83}
84function isNumber(obj) {
85    return typeof obj === 'number' || obj instanceof Number;
86}
87async function waitForEvent(emitter, eventName, predicate, timeout, abortPromise) {
88    let eventTimeout, resolveCallback, rejectCallback;
89    const promise = new Promise((resolve, reject) => {
90        resolveCallback = resolve;
91        rejectCallback = reject;
92    });
93    const listener = addEventListener(emitter, eventName, (event) => {
94        if (!predicate(event))
95            return;
96        resolveCallback(event);
97    });
98    if (timeout) {
99        eventTimeout = setTimeout(() => {
100            rejectCallback(new TimeoutError('Timeout exceeded while waiting for event'));
101        }, timeout);
102    }
103    function cleanup() {
104        removeEventListeners([listener]);
105        clearTimeout(eventTimeout);
106    }
107    const result = await Promise.race([promise, abortPromise]).then((r) => {
108        cleanup();
109        return r;
110    }, (error) => {
111        cleanup();
112        throw error;
113    });
114    if (result instanceof Error)
115        throw result;
116    return result;
117}
118function evaluationString(fun, ...args) {
119    if (isString(fun)) {
120        assert(args.length === 0, 'Cannot evaluate a string with arguments');
121        return fun;
122    }
123    function serializeArgument(arg) {
124        if (Object.is(arg, undefined))
125            return 'undefined';
126        return JSON.stringify(arg);
127    }
128    return `(${fun})(${args.map(serializeArgument).join(',')})`;
129}
130function pageBindingInitString(type, name) {
131    function addPageBinding(type, bindingName) {
132        /* Cast window to any here as we're about to add properties to it
133         * via win[bindingName] which TypeScript doesn't like.
134         */
135        const win = window;
136        const binding = win[bindingName];
137        win[bindingName] = (...args) => {
138            const me = window[bindingName];
139            let callbacks = me.callbacks;
140            if (!callbacks) {
141                callbacks = new Map();
142                me.callbacks = callbacks;
143            }
144            const seq = (me.lastSeq || 0) + 1;
145            me.lastSeq = seq;
146            const promise = new Promise((resolve, reject) => callbacks.set(seq, { resolve, reject }));
147            binding(JSON.stringify({ type, name: bindingName, seq, args }));
148            return promise;
149        };
150    }
151    return evaluationString(addPageBinding, type, name);
152}
153function pageBindingDeliverResultString(name, seq, result) {
154    function deliverResult(name, seq, result) {
155        window[name].callbacks.get(seq).resolve(result);
156        window[name].callbacks.delete(seq);
157    }
158    return evaluationString(deliverResult, name, seq, result);
159}
160function pageBindingDeliverErrorString(name, seq, message, stack) {
161    function deliverError(name, seq, message, stack) {
162        const error = new Error(message);
163        error.stack = stack;
164        window[name].callbacks.get(seq).reject(error);
165        window[name].callbacks.delete(seq);
166    }
167    return evaluationString(deliverError, name, seq, message, stack);
168}
169function pageBindingDeliverErrorValueString(name, seq, value) {
170    function deliverErrorValue(name, seq, value) {
171        window[name].callbacks.get(seq).reject(value);
172        window[name].callbacks.delete(seq);
173    }
174    return evaluationString(deliverErrorValue, name, seq, value);
175}
176function makePredicateString(predicate, predicateQueryHandler) {
177    function checkWaitForOptions(node, waitForVisible, waitForHidden) {
178        if (!node)
179            return waitForHidden;
180        if (!waitForVisible && !waitForHidden)
181            return node;
182        const element = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
183        const style = window.getComputedStyle(element);
184        const isVisible = style && style.visibility !== 'hidden' && hasVisibleBoundingBox();
185        const success = waitForVisible === isVisible || waitForHidden === !isVisible;
186        return success ? node : null;
187        function hasVisibleBoundingBox() {
188            const rect = element.getBoundingClientRect();
189            return !!(rect.top || rect.bottom || rect.width || rect.height);
190        }
191    }
192    const predicateQueryHandlerDef = predicateQueryHandler
193        ? `const predicateQueryHandler = ${predicateQueryHandler};`
194        : '';
195    return `
196    (() => {
197      ${predicateQueryHandlerDef}
198      const checkWaitForOptions = ${checkWaitForOptions};
199      return (${predicate})(...args)
200    })() `;
201}
202async function waitWithTimeout(promise, taskName, timeout) {
203    let reject;
204    const timeoutError = new TimeoutError(`waiting for ${taskName} failed: timeout ${timeout}ms exceeded`);
205    const timeoutPromise = new Promise((resolve, x) => (reject = x));
206    let timeoutTimer = null;
207    if (timeout)
208        timeoutTimer = setTimeout(() => reject(timeoutError), timeout);
209    try {
210        return await Promise.race([promise, timeoutPromise]);
211    }
212    finally {
213        if (timeoutTimer)
214            clearTimeout(timeoutTimer);
215    }
216}
217async function readProtocolStream(client, handle, path) {
218    if (!isNode && path) {
219        throw new Error('Cannot write to a path outside of Node.js environment.');
220    }
221    const fs = isNode ? await importFSModule() : null;
222    let eof = false;
223    let fileHandle;
224    if (path && fs) {
225        fileHandle = await fs.promises.open(path, 'w');
226    }
227    const bufs = [];
228    while (!eof) {
229        const response = await client.send('IO.read', { handle });
230        eof = response.eof;
231        const buf = Buffer.from(response.data, response.base64Encoded ? 'base64' : undefined);
232        bufs.push(buf);
233        if (path && fs) {
234            await fs.promises.writeFile(fileHandle, buf);
235        }
236    }
237    if (path)
238        await fileHandle.close();
239    await client.send('IO.close', { handle });
240    let resultBuffer = null;
241    try {
242        resultBuffer = Buffer.concat(bufs);
243    }
244    finally {
245        return resultBuffer;
246    }
247}
248/**
249 * Loads the Node fs promises API. Needed because on Node 10.17 and below,
250 * fs.promises is experimental, and therefore not marked as enumerable. That
251 * means when TypeScript compiles an `import('fs')`, its helper doesn't spot the
252 * promises declaration and therefore on Node <10.17 you get an error as
253 * fs.promises is undefined in compiled TypeScript land.
254 *
255 * See https://github.com/puppeteer/puppeteer/issues/6548 for more details.
256 *
257 * Once Node 10 is no longer supported (April 2021) we can remove this and use
258 * `(await import('fs')).promises`.
259 */
260async function importFSModule() {
261    if (!isNode) {
262        throw new Error('Cannot load the fs module API outside of Node.');
263    }
264    const fs = await import('fs');
265    if (fs.promises) {
266        return fs;
267    }
268    return fs.default;
269}
270export const helper = {
271    evaluationString,
272    pageBindingInitString,
273    pageBindingDeliverResultString,
274    pageBindingDeliverErrorString,
275    pageBindingDeliverErrorValueString,
276    makePredicateString,
277    readProtocolStream,
278    waitWithTimeout,
279    waitForEvent,
280    isString,
281    isNumber,
282    importFSModule,
283    addEventListener,
284    removeEventListeners,
285    valueFromRemoteObject,
286    getExceptionMessage,
287    releaseObject,
288};
289
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)