diff --git a/docs/api.md b/docs/api.md index b8a8bfa99a0c1..cba744f15a401 100644 --- a/docs/api.md +++ b/docs/api.md @@ -25,6 +25,7 @@ - [class: BrowserServer](#class-browserserver) - [class: BrowserType](#class-browsertype) - [class: ChromiumBrowser](#class-chromiumbrowser) +- [class: ChromiumBrowserContext](#class-chromiumbrowsercontext) - [class: ChromiumCoverage](#class-chromiumcoverage) - [class: ChromiumSession](#class-chromiumsession) - [class: ChromiumTarget](#class-chromiumtarget) @@ -3532,15 +3533,9 @@ await browser.stopTracing(); ``` -- [event: 'targetchanged'](#event-targetchanged) -- [event: 'targetcreated'](#event-targetcreated) -- [event: 'targetdestroyed'](#event-targetdestroyed) - [chromiumBrowser.browserTarget()](#chromiumbrowserbrowsertarget) -- [chromiumBrowser.pageTarget(page)](#chromiumbrowserpagetargetpage) - [chromiumBrowser.startTracing(page, [options])](#chromiumbrowserstarttracingpage-options) - [chromiumBrowser.stopTracing()](#chromiumbrowserstoptracing) -- [chromiumBrowser.targets(context)](#chromiumbrowsertargetscontext) -- [chromiumBrowser.waitForTarget(predicate[, options])](#chromiumbrowserwaitfortargetpredicate-options) - [event: 'disconnected'](#event-disconnected) @@ -3551,12 +3546,64 @@ await browser.stopTracing(); - [browser.newPage([options])](#browsernewpageoptions) +#### chromiumBrowser.browserTarget() +- returns: <[ChromiumTarget]> + +Returns browser target. + +#### chromiumBrowser.startTracing(page, [options]) +- `page` <[Page]> Optional, if specified, tracing includes screenshots of the given page. +- `options` <[Object]> + - `path` <[string]> A path to write the trace file to. + - `screenshots` <[boolean]> captures screenshots in the trace. + - `categories` <[Array]<[string]>> specify custom categories to use instead of default. +- returns: <[Promise]> + +Only one trace can be active at a time per browser. + +#### chromiumBrowser.stopTracing() +- returns: <[Promise]<[Buffer]>> Promise which resolves to buffer with trace data. + +### class: ChromiumBrowserContext + +* extends: [BrowserContext] + +Chromium-specific features including targets, service worker support, etc. + +```js +const backroundPageTarget = await context.waitForTarget(target => target.type() === 'background_page'); +const backgroundPage = await backroundPageTarget.page(); +``` + + +- [event: 'targetchanged'](#event-targetchanged) +- [event: 'targetcreated'](#event-targetcreated) +- [event: 'targetdestroyed'](#event-targetdestroyed) +- [chromiumBrowserContext.pageTarget(page)](#chromiumbrowsercontextpagetargetpage) +- [chromiumBrowserContext.targets()](#chromiumbrowsercontexttargets) +- [chromiumBrowserContext.waitForTarget(predicate[, options])](#chromiumbrowsercontextwaitfortargetpredicate-options) + + +- [event: 'close'](#event-close) +- [browserContext.clearCookies()](#browsercontextclearcookies) +- [browserContext.clearPermissions()](#browsercontextclearpermissions) +- [browserContext.close()](#browsercontextclose) +- [browserContext.cookies([...urls])](#browsercontextcookiesurls) +- [browserContext.newPage()](#browsercontextnewpage) +- [browserContext.pages()](#browsercontextpages) +- [browserContext.setCookies(cookies)](#browsercontextsetcookiescookies) +- [browserContext.setDefaultNavigationTimeout(timeout)](#browsercontextsetdefaultnavigationtimeouttimeout) +- [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout) +- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation) +- [browserContext.setPermissions(origin, permissions[])](#browsercontextsetpermissionsorigin-permissions) + + #### event: 'targetchanged' - <[ChromiumTarget]> Emitted when the url of a target changes. -> **NOTE** This includes target changes in incognito browser contexts. +> **NOTE** Only includes targets from this browser context. #### event: 'targetcreated' @@ -3564,56 +3611,36 @@ Emitted when the url of a target changes. Emitted when a target is created, for example when a new page is opened by [`window.open`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) or [`browserContext.newPage`](#browsercontextnewpage). -> **NOTE** This includes target creations in incognito browser contexts. +> **NOTE** Only includes targets from this browser context. #### event: 'targetdestroyed' - <[ChromiumTarget]> Emitted when a target is destroyed, for example when a page is closed. -> **NOTE** This includes target destructions in incognito browser contexts. - -#### chromiumBrowser.browserTarget() -- returns: <[ChromiumTarget]> - -Returns browser target. +> **NOTE** Only includes targets from this browser context. -#### chromiumBrowser.pageTarget(page) +#### chromiumBrowserContext.pageTarget(page) - `page` <[Page]> Page to return target for. - returns: <[ChromiumTarget]> a target given page was created from. -#### chromiumBrowser.startTracing(page, [options]) -- `page` <[Page]> Optional, if specified, tracing includes screenshots of the given page. -- `options` <[Object]> - - `path` <[string]> A path to write the trace file to. - - `screenshots` <[boolean]> captures screenshots in the trace. - - `categories` <[Array]<[string]>> specify custom categories to use instead of default. -- returns: <[Promise]> - -Only one trace can be active at a time per browser. - -#### chromiumBrowser.stopTracing() -- returns: <[Promise]<[Buffer]>> Promise which resolves to buffer with trace data. - -#### chromiumBrowser.targets(context) -- `context` <[BrowserContext]> Optional, if specified, only targets from this context are returned. +#### chromiumBrowserContext.targets() - returns: <[Array]<[ChromiumTarget]>> -An array of all active targets inside the Browser. In case of multiple browser contexts, -the method will return an array with all the targets in all browser contexts. +An array of all active targets inside the browser context. -#### chromiumBrowser.waitForTarget(predicate[, options]) +#### chromiumBrowserContext.waitForTarget(predicate[, options]) - `predicate` <[function]\([ChromiumTarget]\):[boolean]> A function to be run for every target - `options` <[Object]> - `timeout` <[number]> Maximum wait time in milliseconds. Pass `0` to disable the timeout. Defaults to 30 seconds. - returns: <[Promise]<[ChromiumTarget]>> Promise which resolves to the first target found that matches the `predicate` function. -This searches for a target in all browser contexts. +This searches for a target in the browser context. An example of finding a target for a page opened via `window.open`: ```js await page.evaluate(() => window.open('https://www.example.com/')); -const newWindowTarget = await browser.chromium.waitForTarget(target => target.url() === 'https://www.example.com/'); +const newWindowTarget = await page.context().waitForTarget(target => target.url() === 'https://www.example.com/'); ``` ### class: ChromiumCoverage @@ -3875,6 +3902,7 @@ const { chromium } = require('playwright'); [Buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer "Buffer" [ChildProcess]: https://nodejs.org/api/child_process.html "ChildProcess" [ChromiumBrowser]: #class-chromiumbrowser "ChromiumBrowser" +[ChromiumBrowserContext]: #class-chromiumbrowsercontext "ChromiumBrowserContext" [ChromiumSession]: #class-chromiumsession "ChromiumSession" [ChromiumTarget]: #class-chromiumtarget "ChromiumTarget" [ConsoleMessage]: #class-consolemessage "ConsoleMessage" diff --git a/src/api.ts b/src/api.ts index ba45c5c85cf75..694d54394b9fa 100644 --- a/src/api.ts +++ b/src/api.ts @@ -29,6 +29,7 @@ export { FileChooser, Page, Worker } from './page'; export { Selectors } from './selectors'; export { CRBrowser as ChromiumBrowser } from './chromium/crBrowser'; +export { CRBrowserContext as ChromiumBrowserContext } from './chromium/crBrowser'; export { CRCoverage as ChromiumCoverage } from './chromium/crCoverage'; export { CRSession as ChromiumSession } from './chromium/crConnection'; export { CRTarget as ChromiumTarget } from './chromium/crTarget'; diff --git a/src/chromium/crBrowser.ts b/src/chromium/crBrowser.ts index 15d1e6519838c..fae047e520c31 100644 --- a/src/chromium/crBrowser.ts +++ b/src/chromium/crBrowser.ts @@ -35,7 +35,7 @@ import { TimeoutSettings } from '../timeoutSettings'; export class CRBrowser extends platform.EventEmitter implements Browser { _connection: CRConnection; _client: CRSession; - readonly _defaultContext: BrowserContext; + readonly _defaultContext: CRBrowserContext; readonly _contexts = new Map(); _targets = new Map(); @@ -93,7 +93,7 @@ export class CRBrowser extends platform.EventEmitter implements Browser { this._targets.set(event.targetInfo.targetId, target); if (target._isInitialized || await target._initializedPromise) - this.emit(Events.CRBrowser.TargetCreated, target); + context.emit(Events.CRBrowserContext.TargetCreated, target); } async _targetDestroyed(event: { targetId: string; }) { @@ -102,7 +102,7 @@ export class CRBrowser extends platform.EventEmitter implements Browser { this._targets.delete(event.targetId); target._didClose(); if (await target._initializedPromise) - this.emit(Events.CRBrowser.TargetDestroyed, target); + target.context().emit(Events.CRBrowserContext.TargetDestroyed, target); } _targetInfoChanged(event: Protocol.Target.targetInfoChangedPayload) { @@ -112,7 +112,7 @@ export class CRBrowser extends platform.EventEmitter implements Browser { const wasInitialized = target._isInitialized; target._targetInfoChanged(event.targetInfo); if (wasInitialized && previousURL !== target.url()) - this.emit(Events.CRBrowser.TargetChanged, target); + target.context().emit(Events.CRBrowserContext.TargetChanged, target); } async _closePage(page: Page) { @@ -123,32 +123,6 @@ export class CRBrowser extends platform.EventEmitter implements Browser { return Array.from(this._targets.values()).filter(target => target._isInitialized); } - async waitForTarget(predicate: (arg0: CRTarget) => boolean, options: { timeout?: number; } | undefined = {}): Promise { - const { - timeout = 30000 - } = options; - const existingTarget = this._allTargets().find(predicate); - if (existingTarget) - return existingTarget; - let resolve: (target: CRTarget) => void; - const targetPromise = new Promise(x => resolve = x); - this.on(Events.CRBrowser.TargetCreated, check); - this.on(Events.CRBrowser.TargetChanged, check); - try { - if (!timeout) - return await targetPromise; - return await helper.waitWithTimeout(targetPromise, 'target', timeout); - } finally { - this.removeListener(Events.CRBrowser.TargetCreated, check); - this.removeListener(Events.CRBrowser.TargetChanged, check); - } - - function check(target: CRTarget) { - if (predicate(target)) - resolve(target); - } - } - async close() { const disconnected = new Promise(f => this._connection.once(ConnectionEvents.Disconnected, f)); await Promise.all(this.contexts().map(context => context.close())); @@ -199,15 +173,6 @@ export class CRBrowser extends platform.EventEmitter implements Browser { return contentPromise; } - targets(context?: BrowserContext): CRTarget[] { - const targets = this._allTargets(); - return context ? targets.filter(t => t.context() === context) : targets; - } - - pageTarget(page: Page): CRTarget { - return CRTarget.fromPage(page); - } - isConnected(): boolean { return !this._connection._closed; } @@ -339,6 +304,38 @@ export class CRBrowserContext extends platform.EventEmitter implements BrowserCo this.emit(CommonEvents.BrowserContext.Close); } + pageTarget(page: Page): CRTarget { + return CRTarget.fromPage(page); + } + + targets(): CRTarget[] { + return this._browser._allTargets().filter(t => t.context() === this); + } + + async waitForTarget(predicate: (arg0: CRTarget) => boolean, options: { timeout?: number; } = {}): Promise { + const { timeout = 30000 } = options; + const existingTarget = this._browser._allTargets().find(predicate); + if (existingTarget) + return existingTarget; + let resolve: (target: CRTarget) => void; + const targetPromise = new Promise(x => resolve = x); + this.on(Events.CRBrowserContext.TargetCreated, check); + this.on(Events.CRBrowserContext.TargetChanged, check); + try { + if (!timeout) + return await targetPromise; + return await helper.waitWithTimeout(targetPromise, 'target', timeout); + } finally { + this.removeListener(Events.CRBrowserContext.TargetCreated, check); + this.removeListener(Events.CRBrowserContext.TargetChanged, check); + } + + function check(target: CRTarget) { + if (predicate(target)) + resolve(target); + } + } + _browserClosed() { this._closed = true; for (const page of this._existingPages()) diff --git a/src/chromium/crTarget.ts b/src/chromium/crTarget.ts index 8f9a6ccba45bd..a9fd11b76c60b 100644 --- a/src/chromium/crTarget.ts +++ b/src/chromium/crTarget.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { CRBrowser } from './crBrowser'; -import { BrowserContext } from '../browserContext'; +import { CRBrowser, CRBrowserContext } from './crBrowser'; import { CRSession, CRSessionEvents } from './crConnection'; import { Events } from '../events'; import { Page, Worker } from '../page'; @@ -30,7 +29,7 @@ const targetSymbol = Symbol('target'); export class CRTarget { private _targetInfo: Protocol.Target.TargetInfo; private readonly _browser: CRBrowser; - private readonly _browserContext: BrowserContext; + private readonly _browserContext: CRBrowserContext; readonly _targetId: string; private _sessionFactory: () => Promise; private _pagePromise: Promise | null = null; @@ -47,7 +46,7 @@ export class CRTarget { constructor( browser: CRBrowser, targetInfo: Protocol.Target.TargetInfo, - browserContext: BrowserContext, + browserContext: CRBrowserContext, sessionFactory: () => Promise) { this._targetInfo = targetInfo; this._browser = browser; @@ -120,7 +119,7 @@ export class CRTarget { return 'other'; } - context(): BrowserContext { + context(): CRBrowserContext { return this._browserContext; } diff --git a/src/chromium/events.ts b/src/chromium/events.ts index 1b85dfaa6f718..a4b7d8ddceccf 100644 --- a/src/chromium/events.ts +++ b/src/chromium/events.ts @@ -16,7 +16,7 @@ */ export const Events = { - CRBrowser: { + CRBrowserContext: { TargetCreated: 'targetcreated', TargetDestroyed: 'targetdestroyed', TargetChanged: 'targetchanged', diff --git a/src/server/chromium.ts b/src/server/chromium.ts index 0a55ee56ae059..22ab4bdc5f024 100644 --- a/src/server/chromium.ts +++ b/src/server/chromium.ts @@ -68,7 +68,7 @@ export class Chromium implements BrowserType { const { timeout = 30000 } = options || {}; const { browserServer, transport } = await this._launchServer(options, 'persistent', userDataDir); const browser = await CRBrowser.connect(transport!); - await helper.waitWithTimeout(browser.waitForTarget(t => t.type() === 'page'), 'first page', timeout); + await helper.waitWithTimeout(browser._defaultContext.waitForTarget(t => t.type() === 'page'), 'first page', timeout); // Hack: for typical launch scenario, ensure that close waits for actual process termination. const browserContext = browser._defaultContext; browserContext.close = () => browserServer.close(); diff --git a/test/browsercontext.spec.js b/test/browsercontext.spec.js index b10d0cb41b2be..35da41a0402cf 100644 --- a/test/browsercontext.spec.js +++ b/test/browsercontext.spec.js @@ -38,11 +38,11 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE const context = await browser.newContext(); const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); - const [popupTarget] = await Promise.all([ + const [popup] = await Promise.all([ utils.waitEvent(page, 'popup'), page.evaluate(url => window.open(url), server.EMPTY_PAGE) ]); - expect(popupTarget.context()).toBe(context); + expect(popup.context()).toBe(context); await context.close(); }); it('should isolate localStorage and cookies', async function({browser, server}) { diff --git a/test/chromium/chromium.spec.js b/test/chromium/chromium.spec.js index c278f6d39cf0a..9f09f4053f8b7 100644 --- a/test/chromium/chromium.spec.js +++ b/test/chromium/chromium.spec.js @@ -25,28 +25,31 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; describe('Target', function() { - it('Chromium.targets should return all of the targets', async({page, server, browser}) => { - // The pages will be the testing page and the original newtab page - const targets = browser.targets(); - expect(targets.some(target => target.type() === 'page' && - target.url() === 'about:blank')).toBeTruthy('Missing blank page'); - expect(targets.some(target => target.type() === 'browser')).toBeTruthy('Missing browser target'); - }); - it('Browser.pages should return all of the pages', async({page, server, context}) => { - // The pages will be the testing page + it('ChromiumBrowserContext.targets should return all of the targets', async({page, server, browser}) => { + const second = await page.context().newPage(); + await second.goto(server.EMPTY_PAGE); + const targets = page.context().targets(); + // The pages will be the testing page from the harness and the one created here. + expect(targets.length).toBe(2); + expect(targets.some(target => target.type() !== 'page')).toBe(false); + expect(targets.some(target => target.url() === 'about:blank')).toBeTruthy('Missing blank page'); + expect(targets.some(target => target.url() === server.EMPTY_PAGE)).toBeTruthy('Missing new page'); + await second.close(); + }); + it('BrowserContext.pages should return all of the pages', async({page, server, context}) => { + const second = await page.context().newPage(); const allPages = await context.pages(); - expect(allPages.length).toBe(1); + expect(allPages.length).toBe(2); expect(allPages).toContain(page); - expect(allPages[0]).not.toBe(allPages[1]); + expect(allPages).toContain(second); + await second.close(); }); - it('should contain browser target', async({browser}) => { - const targets = browser.targets(); - const browserTarget = targets.find(target => target.type() === 'browser'); - expect(browserTarget).toBe(browser.browserTarget()); + it('should report browser target', async({browser}) => { + expect(browser.browserTarget()).toBeTruthy(); }); it('should report when a new page is created and closed', async({browser, page, server, context}) => { const [otherPage] = await Promise.all([ - browser.waitForTarget(target => target.url() === server.CROSS_PROCESS_PREFIX + '/empty.html').then(target => target.page()), + page.context().waitForTarget(target => target.url() === server.CROSS_PROCESS_PREFIX + '/empty.html').then(target => target.page()), page.evaluate(url => window.open(url), server.CROSS_PROCESS_PREFIX + '/empty.html'), ]); expect(otherPage.url()).toContain(server.CROSS_PROCESS_PREFIX); @@ -57,31 +60,31 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI expect(allPages).toContain(page); expect(allPages).toContain(otherPage); - const closePagePromise = new Promise(fulfill => browser.once('targetdestroyed', target => fulfill(target.page()))); + const closePagePromise = new Promise(fulfill => page.context().once('targetdestroyed', target => fulfill(target.page()))); await otherPage.close(); expect(await closePagePromise).toBe(otherPage); - allPages = await Promise.all(browser.targets().map(target => target.page())); + allPages = await Promise.all(page.context().targets().map(target => target.page())); expect(allPages).toContain(page); expect(allPages).not.toContain(otherPage); }); it('should report when a service worker is created and destroyed', async({browser, page, server, context}) => { await page.goto(server.EMPTY_PAGE); - const createdTarget = new Promise(fulfill => browser.once('targetcreated', target => fulfill(target))); + const createdTarget = new Promise(fulfill => page.context().once('targetcreated', target => fulfill(target))); await page.goto(server.PREFIX + '/serviceworkers/empty/sw.html'); expect((await createdTarget).type()).toBe('service_worker'); expect((await createdTarget).url()).toBe(server.PREFIX + '/serviceworkers/empty/sw.js'); - const destroyedTarget = new Promise(fulfill => browser.once('targetdestroyed', target => fulfill(target))); + const destroyedTarget = new Promise(fulfill => page.context().once('targetdestroyed', target => fulfill(target))); await page.evaluate(() => window.registrationPromise.then(registration => registration.unregister())); expect(await destroyedTarget).toBe(await createdTarget); }); it('should create a worker from a service worker', async({browser, page, server, context}) => { await page.goto(server.PREFIX + '/serviceworkers/empty/sw.html'); - const target = await browser.waitForTarget(target => target.type() === 'service_worker'); + const target = await page.context().waitForTarget(target => target.type() === 'service_worker'); const worker = await target.serviceWorker(); expect(await worker.evaluate(() => self.toString())).toBe('[object ServiceWorkerGlobalScope]'); }); @@ -90,17 +93,17 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI await page.evaluate(() => { new SharedWorker('data:text/javascript,console.log("hi")'); }); - const target = await browser.waitForTarget(target => target.type() === 'shared_worker'); + const target = await page.context().waitForTarget(target => target.type() === 'shared_worker'); const worker = await target.serviceWorker(); expect(worker).toBe(null); }); it('should report when a target url changes', async({browser, page, server, context}) => { await page.goto(server.EMPTY_PAGE); - let changedTarget = new Promise(fulfill => browser.once('targetchanged', target => fulfill(target))); + let changedTarget = new Promise(fulfill => page.context().once('targetchanged', target => fulfill(target))); await page.goto(server.CROSS_PROCESS_PREFIX + '/'); expect((await changedTarget).url()).toBe(server.CROSS_PROCESS_PREFIX + '/'); - changedTarget = new Promise(fulfill => browser.once('targetchanged', target => fulfill(target))); + changedTarget = new Promise(fulfill => page.context().once('targetchanged', target => fulfill(target))); await page.goto(server.EMPTY_PAGE); expect((await changedTarget).url()).toBe(server.EMPTY_PAGE); }); @@ -108,13 +111,13 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI let targetChanged = false; const listener = () => targetChanged = true; browser.on('targetchanged', listener); - const targetPromise = new Promise(fulfill => browser.once('targetcreated', target => fulfill(target))); + const targetPromise = new Promise(fulfill => context.once('targetcreated', target => fulfill(target))); const newPagePromise = context.newPage(); const target = await targetPromise; expect(target.url()).toBe('about:blank'); const newPage = await newPagePromise; - const targetPromise2 = new Promise(fulfill => browser.once('targetcreated', target => fulfill(target))); + const targetPromise2 = new Promise(fulfill => context.once('targetcreated', target => fulfill(target))); const evaluatePromise = newPage.evaluate(() => window.open('about:blank')); const target2 = await targetPromise2; expect(target2.url()).toBe('about:blank'); @@ -132,7 +135,7 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI server.waitForRequest('/one-style.css') ]); // Connect to the opened page. - const target = await browser.waitForTarget(target => target.url().includes('one-style.html')); + const target = await page.context().waitForTarget(target => target.url().includes('one-style.html')); const newPage = await target.page(); // Issue a redirect. serverResponse.writeHead(302, { location: '/injectedstyle.css' }); @@ -145,23 +148,21 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI it('should have an opener', async({browser, page, server, context}) => { await page.goto(server.EMPTY_PAGE); const [createdTarget] = await Promise.all([ - new Promise(fulfill => browser.once('targetcreated', target => fulfill(target))), + new Promise(fulfill => page.context().once('targetcreated', target => fulfill(target))), page.goto(server.PREFIX + '/popup/window-open.html') ]); expect((await createdTarget.page()).url()).toBe(server.PREFIX + '/popup/popup.html'); - expect(createdTarget.opener()).toBe(browser.pageTarget(page)); - expect(browser.pageTarget(page).opener()).toBe(null); + expect(createdTarget.opener()).toBe(page.context().pageTarget(page)); + expect(page.context().pageTarget(page).opener()).toBe(null); }); it('should close all belonging targets once closing context', async function({browser}) { - const targets = async (context) => (await browser.targets()).filter(t => t.type() === 'page' && t.context() === context); - const context = await browser.newContext(); await context.newPage(); - expect((await targets(context)).length).toBe(1); + expect((await context.targets()).length).toBe(1); expect((await context.pages()).length).toBe(1); await context.close(); - expect((await targets(context)).length).toBe(0); + expect((await context.targets()).length).toBe(0); }); }); @@ -169,7 +170,7 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI it('should wait for a target', async function({server, browser}) { const context = await browser.newContext(); let resolved = false; - const targetPromise = browser.waitForTarget(target => target.context() === context && target.url() === server.EMPTY_PAGE); + const targetPromise = context.waitForTarget(target => target.url() === server.EMPTY_PAGE); targetPromise.then(() => resolved = true); const page = await context.newPage(); expect(resolved).toBe(false); @@ -179,26 +180,27 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI await context.close(); }); it('should timeout waiting for a non-existent target', async function({browser, context, server}) { - const error = await browser.waitForTarget(target => target.context() === context && target.url() === server.EMPTY_PAGE, {timeout: 1}).catch(e => e); + const error = await context.waitForTarget(target => target.url() === server.EMPTY_PAGE, {timeout: 1}).catch(e => e); expect(error).toBeInstanceOf(playwright.errors.TimeoutError); }); it('should wait for a target', async function({browser, server}) { + const context = await browser.newContext(); let resolved = false; - const targetPromise = browser.waitForTarget(target => target.url() === server.EMPTY_PAGE); + const targetPromise = context.waitForTarget(target => target.url() === server.EMPTY_PAGE); targetPromise.then(() => resolved = true); - const page = await browser.newPage(); + const page = await context.newPage(); expect(resolved).toBe(false); await page.goto(server.EMPTY_PAGE); const target = await targetPromise; expect(await target.page()).toBe(page); - await page.context().close(); + await context.close(); }); it('should fire target events', async function({browser, server}) { const context = await browser.newContext(); const events = []; - browser.on('targetcreated', target => events.push('CREATED: ' + target.url())); - browser.on('targetchanged', target => events.push('CHANGED: ' + target.url())); - browser.on('targetdestroyed', target => events.push('DESTROYED: ' + target.url())); + context.on('targetcreated', target => events.push('CREATED: ' + target.url())); + context.on('targetchanged', target => events.push('CHANGED: ' + target.url())); + context.on('targetdestroyed', target => events.push('DESTROYED: ' + target.url())); const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); await page.close(); diff --git a/test/chromium/headful.spec.js b/test/chromium/headful.spec.js index a1744665f5bb6..f9ad8f3462f48 100644 --- a/test/chromium/headful.spec.js +++ b/test/chromium/headful.spec.js @@ -51,17 +51,18 @@ module.exports.describe = function({testRunner, expect, playwright, defaultBrows it('background_page target type should be available', async() => { const browserWithExtension = await playwright.launch(extensionOptions); const page = await browserWithExtension.newPage(); - const backgroundPageTarget = await browserWithExtension.waitForTarget(target => target.type() === 'background_page'); + const backgroundPageTarget = await page.context().waitForTarget(target => target.type() === 'background_page'); await page.close(); await browserWithExtension.close(); expect(backgroundPageTarget).toBeTruthy(); }); it('target.page() should return a background_page', async({}) => { const browserWithExtension = await playwright.launch(extensionOptions); - const backgroundPageTarget = await browserWithExtension.waitForTarget(target => target.type() === 'background_page'); - const page = await backgroundPageTarget.page(); - expect(await page.evaluate(() => 2 * 3)).toBe(6); - expect(await page.evaluate(() => window.MAGIC)).toBe(42); + const page = await browserWithExtension.newPage(); + const backgroundPageTarget = await page.context().waitForTarget(target => target.type() === 'background_page'); + const backgroundPage = await backgroundPageTarget.page(); + expect(await backgroundPage.evaluate(() => 2 * 3)).toBe(6); + expect(await backgroundPage.evaluate(() => window.MAGIC)).toBe(42); await browserWithExtension.close(); }); // TODO: Support OOOPIF. @see https://github.com/GoogleChrome/puppeteer/issues/2548 @@ -91,7 +92,7 @@ module.exports.describe = function({testRunner, expect, playwright, defaultBrows const context = await browser.newContext(); await Promise.all([ context.newPage(), - browser.waitForTarget(target => target.context() === context && target.url().includes('devtools://')), + context.waitForTarget(target => target.url().includes('devtools://')), ]); await browser.close(); }); diff --git a/test/chromium/launcher.spec.js b/test/chromium/launcher.spec.js index b1bbc910d8440..feccb79aeb6bc 100644 --- a/test/chromium/launcher.spec.js +++ b/test/chromium/launcher.spec.js @@ -59,9 +59,9 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p const browser = await playwright.launch(defaultBrowserOptions); const context = await browser.newContext(); const events = []; - browser.on('targetcreated', target => target.context() === context && events.push('CREATED')); - browser.on('targetchanged', target => target.context() === context && events.push('CHANGED')); - browser.on('targetdestroyed', target => target.context() === context && events.push('DESTROYED')); + context.on('targetcreated', target => events.push('CREATED')); + context.on('targetchanged', target => events.push('CHANGED')); + context.on('targetdestroyed', target => events.push('DESTROYED')); const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); await page.close(); diff --git a/test/chromium/oopif.spec.js b/test/chromium/oopif.spec.js index 71f66bff40dad..f6504b0ed5ea1 100644 --- a/test/chromium/oopif.spec.js +++ b/test/chromium/oopif.spec.js @@ -43,18 +43,18 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p }); xit('should report oopif frames', async function({browser, page, server, context}) { await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(oopifs(browser).length).toBe(1); + expect(oopifs(page.context()).length).toBe(1); expect(page.frames().length).toBe(2); }); it('should load oopif iframes with subresources and request interception', async function({browser, page, server, context}) { await page.route('*', request => request.continue()); await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(oopifs(browser).length).toBe(1); + expect(oopifs(page.context()).length).toBe(1); }); }); }; -function oopifs(browser) { - return browser.targets().filter(target => target._targetInfo.type === 'iframe'); +function oopifs(context) { + return context.targets().filter(target => target._targetInfo.type === 'iframe'); } diff --git a/test/chromium/session.spec.js b/test/chromium/session.spec.js index 163e30432c7ee..cbce80a4e2660 100644 --- a/test/chromium/session.spec.js +++ b/test/chromium/session.spec.js @@ -26,7 +26,7 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT}) describe('Chromium.createCDPSession', function() { it('should work', async function({page, browser, server}) { - const client = await browser.pageTarget(page).createCDPSession(); + const client = await page.context().pageTarget(page).createCDPSession(); await Promise.all([ client.send('Runtime.enable'), @@ -36,7 +36,7 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT}) expect(foo).toBe('bar'); }); it('should send events', async function({page, browser, server}) { - const client = await browser.pageTarget(page).createCDPSession(); + const client = await page.context().pageTarget(page).createCDPSession(); await client.send('Network.enable'); const events = []; client.on('Network.requestWillBeSent', event => events.push(event)); @@ -44,7 +44,7 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT}) expect(events.length).toBe(1); }); it('should enable and disable domains independently', async function({page, browser, server}) { - const client = await browser.pageTarget(page).createCDPSession(); + const client = await page.context().pageTarget(page).createCDPSession(); await client.send('Runtime.enable'); await client.send('Debugger.enable'); // JS coverage enables and then disables Debugger domain. @@ -59,7 +59,7 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT}) expect(event.url).toBe('foo.js'); }); it('should be able to detach session', async function({page, browser, server}) { - const client = await browser.pageTarget(page).createCDPSession(); + const client = await page.context().pageTarget(page).createCDPSession(); await client.send('Runtime.enable'); const evalResponse = await client.send('Runtime.evaluate', {expression: '1 + 2', returnByValue: true}); expect(evalResponse.result.value).toBe(3); @@ -73,7 +73,7 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT}) expect(error.message).toContain('Session closed.'); }); it('should throw nice errors', async function({page, browser}) { - const client = await browser.pageTarget(page).createCDPSession(); + const client = await page.context().pageTarget(page).createCDPSession(); const error = await theSourceOfTheProblems().catch(error => error); expect(error.stack).toContain('theSourceOfTheProblems'); expect(error.message).toContain('ThisCommand.DoesNotExist');