@zorilla/playwright-extra 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 berstend <github@berstend.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,361 @@
1
+ # playwright-extra [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/zorillajs/zorilla/test.yml?branch=main&event=push)](https://github.com/zorillajs/zorilla/actions) [![npm](https://img.shields.io/npm/v/playwright-extra.svg)](https://www.npmjs.com/package/playwright-extra)
2
+
3
+ > A modular plugin framework for [playwright](https://github.com/microsoft/playwright) to enable cool [plugins](#plugins) through a clean interface.
4
+
5
+ **Part of the [zorilla](https://github.com/zorillajs/zorilla) monorepo** - a maintained fork of puppeteer-extra with modern tooling and ESM support.
6
+
7
+ ## Requirements
8
+
9
+ - Node.js 18+ (ESM only)
10
+ - Playwright 1.x
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pnpm add playwright playwright-extra
16
+ # - or -
17
+ npm install playwright playwright-extra
18
+ ```
19
+
20
+ After installing, make sure to install the Playwright browsers:
21
+
22
+ ```bash
23
+ pnpm exec playwright install
24
+ # - or -
25
+ npx playwright install
26
+ ```
27
+
28
+ ## Quickstart
29
+
30
+ ```js
31
+ // playwright-extra is a drop-in replacement for playwright,
32
+ // it augments the installed playwright with plugin functionality
33
+ import { chromium } from 'playwright-extra'
34
+
35
+ // Load the stealth plugin and use defaults (all tricks to hide playwright usage)
36
+ // Note: playwright-extra is compatible with most puppeteer-extra plugins
37
+ import StealthPlugin from '@zorilla/puppeteer-extra-plugin-stealth'
38
+
39
+ // Add the plugin to playwright (any number of plugins can be added)
40
+ chromium.use(StealthPlugin())
41
+
42
+ // That's it, the rest is playwright usage as normal 😊
43
+ const browser = await chromium.launch({ headless: true })
44
+ const page = await browser.newPage()
45
+
46
+ console.log('Testing the stealth plugin..')
47
+ await page.goto('https://bot.sannysoft.com', { waitUntil: 'networkidle' })
48
+ await page.screenshot({ path: 'stealth.png', fullPage: true })
49
+
50
+ console.log('All done, check the screenshot. ✨')
51
+ await browser.close()
52
+ ```
53
+
54
+ The above example uses the compatible [`stealth`](https://github.com/zorillajs/zorilla/tree/main/packages/puppeteer-extra-plugin-stealth) plugin, which needs to be installed as well:
55
+
56
+ ```bash
57
+ pnpm add @zorilla/puppeteer-extra-plugin-stealth
58
+ # - or -
59
+ npm install @zorilla/puppeteer-extra-plugin-stealth
60
+ ```
61
+
62
+ If you'd like to see debug output just run your script like so:
63
+
64
+ ```bash
65
+ # macOS/Linux (Bash)
66
+ DEBUG=playwright-extra*,puppeteer-extra-plugin* node myscript.js
67
+
68
+ # Windows (Powershell)
69
+ $env:DEBUG='playwright-extra*,puppeteer-extra-plugin*'; node myscript.js
70
+ ```
71
+
72
+ ### More examples
73
+
74
+ <details>
75
+ <summary><strong>TypeScript usage</strong></summary><br/>
76
+
77
+ `playwright-extra` and most plugins are written in TS, so you get perfect type support out of the box. :)
78
+
79
+ ```ts
80
+ import { chromium } from 'playwright-extra'
81
+ import StealthPlugin from '@zorilla/puppeteer-extra-plugin-stealth'
82
+
83
+ chromium.use(StealthPlugin())
84
+
85
+ const browser = await chromium.launch({ headless: true })
86
+ const page = await browser.newPage()
87
+
88
+ console.log('Testing the stealth plugin..')
89
+ await page.goto('https://bot.sannysoft.com', { waitUntil: 'networkidle' })
90
+ await page.screenshot({ path: 'stealth.png', fullPage: true })
91
+
92
+ console.log('All done, check the screenshot. ✨')
93
+ await browser.close()
94
+ ```
95
+
96
+ New to TypeScript? Here's a quick setup:
97
+
98
+ ```bash
99
+ # Create new package.json if it's a new project
100
+ pnpm init
101
+
102
+ # Add TypeScript and dependencies
103
+ pnpm add -D typescript @types/node tsx
104
+
105
+ # Add dependencies used in the quick start example
106
+ pnpm add playwright playwright-extra @zorilla/puppeteer-extra-plugin-stealth
107
+
108
+ # Create a TypeScript config
109
+ pnpm tsc --init
110
+
111
+ # Create source folder for the .ts files
112
+ mkdir src
113
+
114
+ # Now place the example code above in `src/index.ts`
115
+
116
+ # Run the TypeScript code directly (no compilation needed)
117
+ pnpm tsx src/index.ts
118
+ ```
119
+
120
+ </details>
121
+
122
+ <details>
123
+ <summary><strong>Using different browsers</strong></summary><br/>
124
+
125
+ ```ts
126
+ // Any browser supported by playwright can be used with plugins
127
+ import { chromium, firefox, webkit } from 'playwright-extra'
128
+
129
+ chromium.use(plugin)
130
+ firefox.use(plugin)
131
+ webkit.use(plugin)
132
+ ```
133
+
134
+ </details>
135
+
136
+ <details>
137
+ <summary><strong>Multiple instances with different plugins</strong></summary><br/>
138
+
139
+ Node.js imports are cached, therefore the default `chromium`, `firefox`, `webkit` exports from `playwright-extra` will always return the same playwright instance.
140
+
141
+ ```ts
142
+ // Use `addExtra` to create fresh and independent instances
143
+ import playwright from 'playwright'
144
+ import { addExtra } from 'playwright-extra'
145
+
146
+ const chromium1 = addExtra(playwright.chromium)
147
+ const chromium2 = addExtra(playwright.chromium)
148
+
149
+ chromium1.use(pluginA)
150
+ chromium2.use(pluginB)
151
+ // chromium1 and chromium2 are independent instances
152
+ ```
153
+
154
+ </details>
155
+
156
+ ---
157
+
158
+ ## Plugins
159
+
160
+ The following plugins are compatible with playwright-extra:
161
+
162
+ ### 🔥 [`@zorilla/puppeteer-extra-plugin-stealth`](https://github.com/zorillajs/zorilla/tree/main/packages/puppeteer-extra-plugin-stealth)
163
+
164
+ - Applies various evasion techniques to make detection of automated browsers harder
165
+ - Compatible with Puppeteer & Playwright and chromium-based browsers
166
+
167
+ <details>
168
+ <summary>&nbsp;&nbsp;Example: Using stealth in Playwright with custom options</summary>
169
+
170
+ ```js
171
+ // The stealth plugin is optimized for chromium based browsers
172
+ import { chromium } from 'playwright-extra'
173
+ import StealthPlugin from '@zorilla/puppeteer-extra-plugin-stealth'
174
+
175
+ chromium.use(StealthPlugin())
176
+
177
+ // Customize options for specific evasion techniques
178
+ chromium.plugins.setDependencyDefaults('stealth/evasions/webgl.vendor', {
179
+ vendor: 'Bob',
180
+ renderer: 'Alice'
181
+ })
182
+
183
+ // That's it, the rest is playwright usage as normal 😊
184
+ const browser = await chromium.launch({ headless: true })
185
+ const page = await browser.newPage()
186
+
187
+ console.log('Testing the webgl spoofing feature of the stealth plugin..')
188
+ await page.goto('https://webglreport.com', { waitUntil: 'networkidle' })
189
+ await page.screenshot({ path: 'webgl.png', fullPage: true })
190
+
191
+ console.log('All done, check the screenshot. ✨')
192
+ await browser.close()
193
+ ```
194
+
195
+ </details>
196
+
197
+ ### 🏴 [`puppeteer-extra-plugin-recaptcha`](https://github.com/zorillajs/zorilla/tree/main/packages/puppeteer-extra-plugin-recaptcha)
198
+
199
+ - Solves reCAPTCHAs and hCaptchas automatically, using a single line of code: `page.solveRecaptchas()`
200
+ - Compatible with Puppeteer & Playwright and all browsers (chromium, firefox, webkit)
201
+
202
+ <details>
203
+ <summary>&nbsp;&nbsp;Example: Solving captchas in Playwright & Firefox</summary>
204
+
205
+ ```js
206
+ // Any browser (chromium, webkit, firefox) can be used
207
+ import { firefox } from 'playwright-extra'
208
+ import RecaptchaPlugin from 'puppeteer-extra-plugin-recaptcha'
209
+
210
+ firefox.use(
211
+ RecaptchaPlugin({
212
+ provider: {
213
+ id: '2captcha',
214
+ token: process.env.TWOCAPTCHA_TOKEN || 'YOUR_API_KEY'
215
+ }
216
+ })
217
+ )
218
+
219
+ // Works in headless as well
220
+ const browser = await firefox.launch({ headless: false })
221
+ const context = await browser.newContext()
222
+ const page = await context.newPage()
223
+
224
+ await page.goto('https://www.google.com/recaptcha/api2/demo', {
225
+ waitUntil: 'networkidle'
226
+ })
227
+
228
+ console.log('Solving captchas..')
229
+ await page.solveRecaptchas()
230
+
231
+ await Promise.all([
232
+ page.waitForNavigation({ waitUntil: 'networkidle' }),
233
+ page.click('#recaptcha-demo-submit')
234
+ ])
235
+
236
+ const content = await page.content()
237
+ const isSuccess = content.includes('Verification Success')
238
+ console.log('Done', { isSuccess })
239
+ await browser.close()
240
+ ```
241
+
242
+ </details>
243
+
244
+ ### 📡 [`@zorilla/plugin-proxy-router`](https://github.com/zorillajs/zorilla/tree/main/packages/plugin-proxy-router)
245
+
246
+ - Use multiple proxies dynamically with flexible per-host routing
247
+ - Compatible with Puppeteer & Playwright and all browsers (chromium, firefox, webkit)
248
+
249
+ ### 🔌 [`@zorilla/puppeteer-extra-plugin-anonymize-ua`](https://github.com/zorillajs/zorilla/tree/main/packages/puppeteer-extra-plugin-anonymize-ua)
250
+
251
+ - Anonymizes the user-agent on all pages
252
+ - Compatible with Puppeteer & Playwright
253
+
254
+ **Additional Resources**
255
+
256
+ - For adblocking, consider using [@cliqz/adblocker-playwright](https://www.npmjs.com/package/@cliqz/adblocker-playwright) or [blocking resources natively](https://playwright.dev/docs/network#handle-requests)
257
+ - To write your own plugins, check out the [`@zorilla/puppeteer-extra-plugin`](https://github.com/zorillajs/zorilla/tree/main/packages/puppeteer-extra-plugin) base class
258
+
259
+ ---
260
+
261
+ ## Development
262
+
263
+ This package is part of the [zorilla monorepo](https://github.com/zorillajs/zorilla) and uses:
264
+ - **TypeScript** for type safety (ESM only, no CommonJS support)
265
+ - **Playwright Test** for testing across chromium, firefox, and webkit
266
+ - **c8** for coverage reporting
267
+ - **Biome** for linting and formatting
268
+
269
+ ### Building and Testing
270
+
271
+ ```bash
272
+ # Install dependencies (from monorepo root)
273
+ pnpm install
274
+
275
+ # Build the package
276
+ pnpm build
277
+
278
+ # Run tests (requires Playwright browsers to be installed)
279
+ pnpm test
280
+
281
+ # Run tests with coverage
282
+ pnpm test:coverage
283
+ ```
284
+
285
+ ### Code Quality
286
+
287
+ ```bash
288
+ # Check code formatting and linting
289
+ npx biome check .
290
+
291
+ # Auto-fix formatting issues
292
+ npx biome check --write .
293
+ ```
294
+
295
+ ### Browser Installation
296
+
297
+ Tests require Playwright browsers. Install them with:
298
+
299
+ ```bash
300
+ pnpm exec playwright install
301
+ ```
302
+
303
+ ---
304
+
305
+ ## API
306
+
307
+ ### Default Export
308
+
309
+ The package exports augmented browser launchers that work as drop-in replacements for playwright:
310
+
311
+ ```ts
312
+ import { chromium, firefox, webkit } from 'playwright-extra'
313
+ ```
314
+
315
+ ### `addExtra(launcher)`
316
+
317
+ Create a fresh playwright-extra instance with its own plugin registry:
318
+
319
+ ```ts
320
+ import { addExtra } from 'playwright-extra'
321
+ import playwright from 'playwright'
322
+
323
+ const chromium = addExtra(playwright.chromium)
324
+ ```
325
+
326
+ ### `launcher.use(plugin)`
327
+
328
+ Register a plugin with the browser launcher:
329
+
330
+ ```ts
331
+ chromium.use(StealthPlugin())
332
+ ```
333
+
334
+ ### `launcher.plugins`
335
+
336
+ Access the plugin registry to configure plugins:
337
+
338
+ ```ts
339
+ // Set default options for a plugin dependency
340
+ chromium.plugins.setDependencyDefaults('stealth/evasions/webgl.vendor', {
341
+ vendor: 'Custom',
342
+ renderer: 'Custom'
343
+ })
344
+
345
+ // List registered plugins
346
+ console.log(chromium.plugins.names)
347
+ ```
348
+
349
+ ---
350
+
351
+ ## Contributors
352
+
353
+ <a href="https://github.com/zorillajs/zorilla/graphs/contributors">
354
+ <img src="https://contributors-img.firebaseapp.com/image?repo=zorillajs/zorilla" />
355
+ </a>
356
+
357
+ ---
358
+
359
+ ## License
360
+
361
+ Copyright © 2018 - 2025, [berstend](https://github.com/berstend). Released under the MIT License.
@@ -0,0 +1,54 @@
1
+ import type * as pw from 'playwright-core';
2
+ import { PluginList } from './plugins.js';
3
+ import type { CompatiblePlugin } from './types/index.js';
4
+ type PlaywrightBrowserLauncher = pw.BrowserType;
5
+ /**
6
+ * The Playwright browser launcher APIs we're augmenting
7
+ * @private
8
+ */
9
+ interface AugmentedLauncherAPIs extends Pick<PlaywrightBrowserLauncher, 'launch' | 'launchPersistentContext' | 'connect' | 'connectOverCDP'> {
10
+ }
11
+ /**
12
+ * Modular plugin framework to teach `playwright` new tricks.
13
+ */
14
+ export declare class PlaywrightExtraClass implements AugmentedLauncherAPIs {
15
+ private _launcher?;
16
+ /** Plugin manager */
17
+ readonly plugins: PluginList;
18
+ constructor(_launcher?: Partial<PlaywrightBrowserLauncher> | undefined);
19
+ /**
20
+ * The **main interface** to register plugins.
21
+ *
22
+ * Can be called multiple times to enable multiple plugins.
23
+ *
24
+ * Plugins derived from `PuppeteerExtraPlugin` will be used with a compatiblity layer.
25
+ *
26
+ * @example
27
+ * chromium.use(plugin1).use(plugin2)
28
+ * firefox.use(plugin1).use(plugin2)
29
+ *
30
+ * @see [PuppeteerExtraPlugin]
31
+ *
32
+ * @return The same `PlaywrightExtra` instance (for optional chaining)
33
+ */
34
+ use(plugin: CompatiblePlugin): this;
35
+ launch(...args: Parameters<PlaywrightBrowserLauncher['launch']>): ReturnType<PlaywrightBrowserLauncher['launch']>;
36
+ launchPersistentContext(...args: Parameters<PlaywrightBrowserLauncher['launchPersistentContext']>): ReturnType<PlaywrightBrowserLauncher['launchPersistentContext']>;
37
+ connect(wsEndpointOrOptions: string | (pw.ConnectOptions & {
38
+ wsEndpoint?: string;
39
+ }), wsOptions?: pw.ConnectOptions): ReturnType<PlaywrightBrowserLauncher['connect']>;
40
+ connectOverCDP(wsEndpointOrOptions: string | (pw.ConnectOverCDPOptions & {
41
+ endpointURL?: string;
42
+ }), wsOptions?: pw.ConnectOverCDPOptions): ReturnType<PlaywrightBrowserLauncher['connectOverCDP']>;
43
+ protected _bindBrowserContextEvents(context: pw.BrowserContext, contextOptions?: pw.BrowserContextOptions): Promise<void>;
44
+ protected _bindBrowserEvents(browser: pw.Browser): Promise<void>;
45
+ }
46
+ /**
47
+ * PlaywrightExtra class with additional launcher methods.
48
+ *
49
+ * Augments the class with an instance proxy to pass on methods that are not augmented to the original target.
50
+ *
51
+ */
52
+ export declare const PlaywrightExtra: typeof PlaywrightExtraClass;
53
+ export {};
54
+ //# sourceMappingURL=extra.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extra.d.ts","sourceRoot":"","sources":["../src/extra.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAG3C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAU,MAAM,kBAAkB,CAAC;AAEjE,KAAK,yBAAyB,GAAG,EAAE,CAAC,WAAW,CAAC;AAEhD;;;GAGG;AACH,UAAU,qBACR,SAAQ,IAAI,CACV,yBAAyB,EACzB,QAAQ,GAAG,yBAAyB,GAAG,SAAS,GAAG,gBAAgB,CACpE;CAAG;AAEN;;GAEG;AACH,qBAAa,oBAAqB,YAAW,qBAAqB;IAIpD,OAAO,CAAC,SAAS,CAAC;IAH9B,qBAAqB;IACrB,SAAgB,OAAO,EAAE,UAAU,CAAC;gBAEhB,SAAS,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,YAAA;IAIlE;;;;;;;;;;;;;;OAcG;IACI,GAAG,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IA4B7B,MAAM,CACjB,GAAG,IAAI,EAAE,UAAU,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC,GACvD,UAAU,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IA8BrC,uBAAuB,CAClC,GAAG,IAAI,EAAE,UAAU,CAAC,yBAAyB,CAAC,yBAAyB,CAAC,CAAC,GACxE,UAAU,CAAC,yBAAyB,CAAC,yBAAyB,CAAC,CAAC;IAuB7D,OAAO,CACX,mBAAmB,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC,cAAc,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAC3E,SAAS,GAAE,EAAE,CAAC,cAAmB,GAChC,UAAU,CAAC,yBAAyB,CAAC,SAAS,CAAC,CAAC;IA2C7C,cAAc,CAClB,mBAAmB,EACf,MAAM,GACN,CAAC,EAAE,CAAC,qBAAqB,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EACzD,SAAS,GAAE,EAAE,CAAC,qBAA0B,GACvC,UAAU,CAAC,yBAAyB,CAAC,gBAAgB,CAAC,CAAC;cA2C1C,yBAAyB,CACvC,OAAO,EAAE,EAAE,CAAC,cAAc,EAC1B,cAAc,CAAC,EAAE,EAAE,CAAC,qBAAqB;cA4B3B,kBAAkB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO;CAsBvD;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,6BAc1B,CAAC"}
package/dist/extra.js ADDED
@@ -0,0 +1,231 @@
1
+ import Debug from 'debug';
2
+ const debug = Debug('playwright-extra');
3
+ import { playwrightLoader } from './helper/loader.js';
4
+ import { PluginList } from './plugins.js';
5
+ /**
6
+ * Modular plugin framework to teach `playwright` new tricks.
7
+ */
8
+ export class PlaywrightExtraClass {
9
+ _launcher;
10
+ /** Plugin manager */
11
+ plugins;
12
+ constructor(_launcher) {
13
+ this._launcher = _launcher;
14
+ this.plugins = new PluginList();
15
+ }
16
+ /**
17
+ * The **main interface** to register plugins.
18
+ *
19
+ * Can be called multiple times to enable multiple plugins.
20
+ *
21
+ * Plugins derived from `PuppeteerExtraPlugin` will be used with a compatiblity layer.
22
+ *
23
+ * @example
24
+ * chromium.use(plugin1).use(plugin2)
25
+ * firefox.use(plugin1).use(plugin2)
26
+ *
27
+ * @see [PuppeteerExtraPlugin]
28
+ *
29
+ * @return The same `PlaywrightExtra` instance (for optional chaining)
30
+ */
31
+ use(plugin) {
32
+ const isValid = plugin && 'name' in plugin;
33
+ if (!isValid) {
34
+ throw new Error('A plugin must be provided to .use()');
35
+ }
36
+ if (this.plugins.add(plugin)) {
37
+ debug('Plugin registered', plugin.name);
38
+ }
39
+ return this;
40
+ }
41
+ /**
42
+ * In order to support a default export which will require vanilla playwright automatically,
43
+ * as well as `addExtra` to patch a provided launcher, we need to so some gymnastics here.
44
+ *
45
+ * Otherwise this would throw immediately, even when only using the `addExtra` export with an arbitrary compatible launcher.
46
+ *
47
+ * The solution is to make the vanilla launcher optional and only throw once we try to effectively use and can't find it.
48
+ *
49
+ * @internal
50
+ */
51
+ get launcher() {
52
+ if (!this._launcher) {
53
+ throw playwrightLoader.requireError;
54
+ }
55
+ return this._launcher;
56
+ }
57
+ async launch(...args) {
58
+ if (!this.launcher.launch) {
59
+ throw new Error('Launcher does not support "launch"');
60
+ }
61
+ let [options] = args;
62
+ options = { args: [], ...(options || {}) }; // Initialize args array
63
+ debug('launch', options);
64
+ this.plugins.prepare();
65
+ // Give plugins the chance to modify the options before continuing
66
+ options =
67
+ (await this.plugins.dispatchBlocking('beforeLaunch', options)) || options;
68
+ debug('launch with options', options);
69
+ if ('userDataDir' in options) {
70
+ debug("A plugin defined userDataDir during .launch, which isn't supported by playwright - ignoring");
71
+ const { userDataDir: _, ...optionsWithoutUserDataDir } = options;
72
+ options = optionsWithoutUserDataDir;
73
+ }
74
+ const browser = await this.launcher.launch(options);
75
+ await this.plugins.dispatchBlocking('onBrowser', browser);
76
+ await this._bindBrowserEvents(browser);
77
+ await this.plugins.dispatchBlocking('afterLaunch', browser);
78
+ return browser;
79
+ }
80
+ async launchPersistentContext(...args) {
81
+ if (!this.launcher.launchPersistentContext) {
82
+ throw new Error('Launcher does not support "launchPersistentContext"');
83
+ }
84
+ let [userDataDir, options] = args;
85
+ options = { args: [], ...(options || {}) }; // Initialize args array
86
+ debug('launchPersistentContext', options);
87
+ this.plugins.prepare();
88
+ // Give plugins the chance to modify the options before continuing
89
+ options =
90
+ (await this.plugins.dispatchBlocking('beforeLaunch', options)) || options;
91
+ const context = await this.launcher.launchPersistentContext(userDataDir, options);
92
+ await this.plugins.dispatchBlocking('afterLaunch', context);
93
+ this._bindBrowserContextEvents(context);
94
+ return context;
95
+ }
96
+ async connect(wsEndpointOrOptions, wsOptions = {}) {
97
+ if (!this.launcher.connect) {
98
+ throw new Error('Launcher does not support "connect"');
99
+ }
100
+ this.plugins.prepare();
101
+ // Playwright currently supports two function signatures for .connect
102
+ let options = {};
103
+ let wsEndpointAsString = false;
104
+ if (typeof wsEndpointOrOptions === 'object') {
105
+ options = { ...wsEndpointOrOptions, ...wsOptions };
106
+ }
107
+ else {
108
+ wsEndpointAsString = true;
109
+ options = { wsEndpoint: wsEndpointOrOptions, ...wsOptions };
110
+ }
111
+ debug('connect', options);
112
+ // Give plugins the chance to modify the options before launch/connect
113
+ options =
114
+ (await this.plugins.dispatchBlocking('beforeConnect', options)) ||
115
+ options;
116
+ // Follow call signature of end user
117
+ const args = [];
118
+ const wsEndpoint = options.wsEndpoint;
119
+ if (wsEndpointAsString) {
120
+ delete options.wsEndpoint;
121
+ args.push(wsEndpoint, options);
122
+ }
123
+ else {
124
+ args.push(options);
125
+ }
126
+ const connectFn = this.launcher.connect;
127
+ const browser = await connectFn.call(this.launcher, ...args);
128
+ await this.plugins.dispatchBlocking('onBrowser', browser);
129
+ await this._bindBrowserEvents(browser);
130
+ await this.plugins.dispatchBlocking('afterConnect', browser);
131
+ return browser;
132
+ }
133
+ async connectOverCDP(wsEndpointOrOptions, wsOptions = {}) {
134
+ if (!this.launcher.connectOverCDP) {
135
+ throw new Error(`Launcher does not implement 'connectOverCDP'`);
136
+ }
137
+ this.plugins.prepare();
138
+ // Playwright currently supports two function signatures for .connectOverCDP
139
+ let options = {};
140
+ let wsEndpointAsString = false;
141
+ if (typeof wsEndpointOrOptions === 'object') {
142
+ options = { ...wsEndpointOrOptions, ...wsOptions };
143
+ }
144
+ else {
145
+ wsEndpointAsString = true;
146
+ options = { endpointURL: wsEndpointOrOptions, ...wsOptions };
147
+ }
148
+ debug('connectOverCDP', options);
149
+ // Give plugins the chance to modify the options before launch/connect
150
+ options =
151
+ (await this.plugins.dispatchBlocking('beforeConnect', options)) ||
152
+ options;
153
+ // Follow call signature of end user
154
+ const args = [];
155
+ const endpointURL = options.endpointURL;
156
+ if (wsEndpointAsString) {
157
+ delete options.endpointURL;
158
+ args.push(endpointURL, options);
159
+ }
160
+ else {
161
+ args.push(options);
162
+ }
163
+ const connectOverCDPFn = this.launcher.connectOverCDP;
164
+ const browser = await connectOverCDPFn.call(this.launcher, ...args);
165
+ await this.plugins.dispatchBlocking('onBrowser', browser);
166
+ await this._bindBrowserEvents(browser);
167
+ await this.plugins.dispatchBlocking('afterConnect', browser);
168
+ return browser;
169
+ }
170
+ async _bindBrowserContextEvents(context, contextOptions) {
171
+ debug('_bindBrowserContextEvents');
172
+ this.plugins.dispatch('onContextCreated', context, contextOptions);
173
+ // Make sure things like `addInitScript` show an effect on the very first page as well
174
+ context.newPage = ((originalMethod, ctx) => {
175
+ return async () => {
176
+ const page = await originalMethod.call(ctx);
177
+ await page.goto('about:blank');
178
+ return page;
179
+ };
180
+ })(context.newPage, context);
181
+ context.on('close', () => {
182
+ // When using `launchPersistentContext` context closing is the same as browser closing
183
+ if (!context.browser()) {
184
+ this.plugins.dispatch('onDisconnected');
185
+ }
186
+ });
187
+ context.on('page', page => {
188
+ this.plugins.dispatch('onPageCreated', page);
189
+ page.on('close', () => {
190
+ this.plugins.dispatch('onPageClose', page);
191
+ });
192
+ });
193
+ }
194
+ async _bindBrowserEvents(browser) {
195
+ debug('_bindPlaywrightBrowserEvents');
196
+ browser.on('disconnected', () => {
197
+ this.plugins.dispatch('onDisconnected', browser);
198
+ });
199
+ // Note: `browser.newPage` will implicitly call `browser.newContext` as well
200
+ browser.newContext = ((originalMethod, ctx) => {
201
+ return async (options = {}) => {
202
+ const contextOptions = (await this.plugins.dispatchBlocking('beforeContext', options, browser)) || options;
203
+ const context = await originalMethod.call(ctx, contextOptions);
204
+ this._bindBrowserContextEvents(context, contextOptions);
205
+ return context;
206
+ };
207
+ })(browser.newContext, browser);
208
+ }
209
+ }
210
+ /**
211
+ * PlaywrightExtra class with additional launcher methods.
212
+ *
213
+ * Augments the class with an instance proxy to pass on methods that are not augmented to the original target.
214
+ *
215
+ */
216
+ export const PlaywrightExtra = new Proxy(PlaywrightExtraClass, {
217
+ construct(classTarget, args) {
218
+ debug(`create instance of ${classTarget.name}`);
219
+ const result = Reflect.construct(classTarget, args);
220
+ return new Proxy(result, {
221
+ get(target, prop) {
222
+ if (prop in target) {
223
+ return Reflect.get(target, prop);
224
+ }
225
+ debug('proxying property to original launcher: ', prop);
226
+ return Reflect.get(target.launcher, prop);
227
+ },
228
+ });
229
+ },
230
+ });
231
+ //# sourceMappingURL=extra.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extra.js","sourceRoot":"","sources":["../src/extra.ts"],"names":[],"mappings":"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"}