diff --git a/tests/config/androidTest.ts b/tests/android/androidTest.ts
similarity index 97%
rename from tests/config/androidTest.ts
rename to tests/android/androidTest.ts
index f0125ca86c..fdda9f4cf7 100644
--- a/tests/config/androidTest.ts
+++ b/tests/android/androidTest.ts
@@ -15,7 +15,7 @@
*/
import type { AndroidDevice } from '../../index';
-import { CommonArgs, baseTest } from './baseTest';
+import { CommonArgs, baseTest } from '../config/baseTest';
import * as folio from 'folio';
export { expect } from 'folio';
diff --git a/tests/android/browser.spec.ts b/tests/android/browser.spec.ts
index 5e2f5854d1..e577e6da52 100644
--- a/tests/android/browser.spec.ts
+++ b/tests/android/browser.spec.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { androidTest as test, expect } from '../config/androidTest';
+import { androidTest as test, expect } from './androidTest';
test('androidDevice.model', async function({ androidDevice }) {
expect(androidDevice.model()).toBe('sdk_gphone_x86_arm');
diff --git a/tests/android/device.spec.ts b/tests/android/device.spec.ts
index 62e5977527..242a9896d5 100644
--- a/tests/android/device.spec.ts
+++ b/tests/android/device.spec.ts
@@ -16,7 +16,7 @@
import fs from 'fs';
import { PNG } from 'pngjs';
-import { androidTest as test, expect } from '../config/androidTest';
+import { androidTest as test, expect } from './androidTest';
test('androidDevice.shell', async function({ androidDevice }) {
const output = await androidDevice.shell('echo 123');
diff --git a/tests/android/webview.spec.ts b/tests/android/webview.spec.ts
index e56eac34e7..34a44752c7 100644
--- a/tests/android/webview.spec.ts
+++ b/tests/android/webview.spec.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { androidTest as test, expect } from '../config/androidTest';
+import { androidTest as test, expect } from './androidTest';
test('androidDevice.webView', async function({ androidDevice }) {
expect(androidDevice.webViews().length).toBe(0);
diff --git a/tests/chromium/chromium.spec.ts b/tests/chromium/chromium.spec.ts
index f21326a8ab..67caa90948 100644
--- a/tests/chromium/chromium.spec.ts
+++ b/tests/chromium/chromium.spec.ts
@@ -19,228 +19,222 @@ import { contextTest as test, expect } from '../config/browserTest';
import { playwrightTest } from '../config/browserTest';
import http from 'http';
-test.describe('chromium', () => {
- test.skip(({ browserName }) => browserName !== 'chromium');
+test('should create a worker from a service worker', async ({page, server}) => {
+ const [worker] = await Promise.all([
+ page.context().waitForEvent('serviceworker'),
+ page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
+ ]);
+ expect(await worker.evaluate(() => self.toString())).toBe('[object ServiceWorkerGlobalScope]');
+});
- test('should create a worker from a service worker', async ({page, server}) => {
+test('serviceWorkers() should return current workers', async ({page, server}) => {
+ const context = page.context();
+ const [worker1] = await Promise.all([
+ context.waitForEvent('serviceworker'),
+ page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
+ ]);
+ let workers = context.serviceWorkers();
+ expect(workers.length).toBe(1);
+
+ const [worker2] = await Promise.all([
+ context.waitForEvent('serviceworker'),
+ page.goto(server.CROSS_PROCESS_PREFIX + '/serviceworkers/empty/sw.html')
+ ]);
+ workers = context.serviceWorkers();
+ expect(workers.length).toBe(2);
+ expect(workers).toContain(worker1);
+ expect(workers).toContain(worker2);
+});
+
+test('should not create a worker from a shared worker', async ({page, server}) => {
+ await page.goto(server.EMPTY_PAGE);
+ let serviceWorkerCreated;
+ page.context().once('serviceworker', () => serviceWorkerCreated = true);
+ await page.evaluate(() => {
+ new SharedWorker('data:text/javascript,console.log("hi")');
+ });
+ expect(serviceWorkerCreated).not.toBeTruthy();
+});
+
+test('Page.route should work with intervention headers', async ({server, page}) => {
+ server.setRoute('/intervention', (req, res) => res.end(`
+
+ `));
+ server.setRedirect('/intervention.js', '/redirect.js');
+ let serverRequest = null;
+ server.setRoute('/redirect.js', (req, res) => {
+ serverRequest = req;
+ res.end('console.log(1);');
+ });
+
+ await page.route('*', route => route.continue());
+ await page.goto(server.PREFIX + '/intervention');
+ // Check for feature URL substring rather than https://www.chromestatus.com to
+ // make it work with Edgium.
+ expect(serverRequest.headers.intervention).toContain('feature/5718547946799104');
+});
+
+playwrightTest('should close service worker together with the context', async ({browserType, browserOptions, server}) => {
+ const browser = await browserType.launch(browserOptions);
+ const context = await browser.newContext();
+ const page = await context.newPage();
+ const [worker] = await Promise.all([
+ context.waitForEvent('serviceworker'),
+ page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
+ ]);
+ const messages = [];
+ context.on('close', () => messages.push('context'));
+ worker.on('close', () => messages.push('worker'));
+ await context.close();
+ expect(messages.join('|')).toBe('worker|context');
+ await browser.close();
+});
+
+playwrightTest('should connect to an existing cdp session', async ({ browserType, browserOptions }, testInfo) => {
+ const port = 9339 + testInfo.workerIndex;
+ const browserServer = await browserType.launch({
+ ...browserOptions,
+ args: ['--remote-debugging-port=' + port]
+ });
+ try {
+ const cdpBrowser = await browserType.connectOverCDP({
+ endpointURL: `http://localhost:${port}/`,
+ });
+ const contexts = cdpBrowser.contexts();
+ expect(contexts.length).toBe(1);
+ await cdpBrowser.close();
+ } finally {
+ await browserServer.close();
+ }
+});
+
+playwrightTest('should connect to an existing cdp session twice', async ({ browserType, browserOptions, server }, testInfo) => {
+ const port = 9339 + testInfo.workerIndex;
+ const browserServer = await browserType.launch({
+ ...browserOptions,
+ args: ['--remote-debugging-port=' + port]
+ });
+ try {
+ const cdpBrowser1 = await browserType.connectOverCDP({
+ endpointURL: `http://localhost:${port}/`,
+ });
+ const cdpBrowser2 = await browserType.connectOverCDP({
+ endpointURL: `http://localhost:${port}/`,
+ });
+ const contexts1 = cdpBrowser1.contexts();
+ expect(contexts1.length).toBe(1);
+ const [context1] = contexts1;
+ const page1 = await context1.newPage();
+ await page1.goto(server.EMPTY_PAGE);
+
+ const contexts2 = cdpBrowser2.contexts();
+ expect(contexts2.length).toBe(1);
+ const [context2] = contexts2;
+ const page2 = await context2.newPage();
+ await page2.goto(server.EMPTY_PAGE);
+
+ expect(context1.pages().length).toBe(2);
+ expect(context2.pages().length).toBe(2);
+
+ await cdpBrowser1.close();
+ await cdpBrowser2.close();
+ } finally {
+ await browserServer.close();
+ }
+});
+
+playwrightTest('should connect to existing service workers', async ({browserType, browserOptions, server}, testInfo) => {
+ const port = 9339 + testInfo.workerIndex;
+ const browserServer = await browserType.launch({
+ ...browserOptions,
+ args: ['--remote-debugging-port=' + port]
+ });
+ try {
+ const cdpBrowser1 = await browserType.connectOverCDP({
+ endpointURL: `http://localhost:${port}`,
+ });
+ const context = cdpBrowser1.contexts()[0];
+ const page = await cdpBrowser1.contexts()[0].newPage();
const [worker] = await Promise.all([
- page.context().waitForEvent('serviceworker'),
+ context.waitForEvent('serviceworker'),
page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
]);
expect(await worker.evaluate(() => self.toString())).toBe('[object ServiceWorkerGlobalScope]');
- });
+ await cdpBrowser1.close();
- test('serviceWorkers() should return current workers', async ({page, server}) => {
- const context = page.context();
- const [worker1] = await Promise.all([
- context.waitForEvent('serviceworker'),
- page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
- ]);
- let workers = context.serviceWorkers();
- expect(workers.length).toBe(1);
-
- const [worker2] = await Promise.all([
- context.waitForEvent('serviceworker'),
- page.goto(server.CROSS_PROCESS_PREFIX + '/serviceworkers/empty/sw.html')
- ]);
- workers = context.serviceWorkers();
- expect(workers.length).toBe(2);
- expect(workers).toContain(worker1);
- expect(workers).toContain(worker2);
- });
-
- test('should not create a worker from a shared worker', async ({page, server}) => {
- await page.goto(server.EMPTY_PAGE);
- let serviceWorkerCreated;
- page.context().once('serviceworker', () => serviceWorkerCreated = true);
- await page.evaluate(() => {
- new SharedWorker('data:text/javascript,console.log("hi")');
+ const cdpBrowser2 = await browserType.connectOverCDP({
+ endpointURL: `http://localhost:${port}`,
});
- expect(serviceWorkerCreated).not.toBeTruthy();
- });
-
- test('Page.route should work with intervention headers', async ({server, page}) => {
- server.setRoute('/intervention', (req, res) => res.end(`
-
- `));
- server.setRedirect('/intervention.js', '/redirect.js');
- let serverRequest = null;
- server.setRoute('/redirect.js', (req, res) => {
- serverRequest = req;
- res.end('console.log(1);');
- });
-
- await page.route('*', route => route.continue());
- await page.goto(server.PREFIX + '/intervention');
- // Check for feature URL substring rather than https://www.chromestatus.com to
- // make it work with Edgium.
- expect(serverRequest.headers.intervention).toContain('feature/5718547946799104');
- });
+ const context2 = cdpBrowser2.contexts()[0];
+ expect(context2.serviceWorkers().length).toBe(1);
+ await cdpBrowser2.close();
+ } finally {
+ await browserServer.close();
+ }
});
-playwrightTest.describe('chromium', () => {
- playwrightTest.skip(({ browserName }) => browserName !== 'chromium');
-
- playwrightTest('should close service worker together with the context', async ({browserType, browserOptions, server}) => {
- const browser = await browserType.launch(browserOptions);
- const context = await browser.newContext();
- const page = await context.newPage();
- const [worker] = await Promise.all([
- context.waitForEvent('serviceworker'),
- page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
- ]);
- const messages = [];
- context.on('close', () => messages.push('context'));
- worker.on('close', () => messages.push('worker'));
- await context.close();
- expect(messages.join('|')).toBe('worker|context');
- await browser.close();
+playwrightTest('should connect over a ws endpoint', async ({browserType, browserOptions, server}, testInfo) => {
+ const port = 9339 + testInfo.workerIndex;
+ const browserServer = await browserType.launch({
+ ...browserOptions,
+ args: ['--remote-debugging-port=' + port]
});
-
- playwrightTest('should connect to an existing cdp session', async ({ browserType, browserOptions }, testInfo) => {
- const port = 9339 + testInfo.workerIndex;
- const browserServer = await browserType.launch({
- ...browserOptions,
- args: ['--remote-debugging-port=' + port]
+ try {
+ const json = await new Promise((resolve, reject) => {
+ http.get(`http://localhost:${port}/json/version/`, resp => {
+ let data = '';
+ resp.on('data', chunk => data += chunk);
+ resp.on('end', () => resolve(data));
+ }).on('error', reject);
});
- try {
- const cdpBrowser = await browserType.connectOverCDP({
- endpointURL: `http://localhost:${port}/`,
- });
- const contexts = cdpBrowser.contexts();
- expect(contexts.length).toBe(1);
- await cdpBrowser.close();
- } finally {
- await browserServer.close();
- }
- });
-
- playwrightTest('should connect to an existing cdp session twice', async ({ browserType, browserOptions, server }, testInfo) => {
- const port = 9339 + testInfo.workerIndex;
- const browserServer = await browserType.launch({
- ...browserOptions,
- args: ['--remote-debugging-port=' + port]
+ const cdpBrowser = await browserType.connectOverCDP({
+ endpointURL: JSON.parse(json).webSocketDebuggerUrl,
});
- try {
- const cdpBrowser1 = await browserType.connectOverCDP({
- endpointURL: `http://localhost:${port}/`,
- });
- const cdpBrowser2 = await browserType.connectOverCDP({
- endpointURL: `http://localhost:${port}/`,
- });
- const contexts1 = cdpBrowser1.contexts();
- expect(contexts1.length).toBe(1);
- const [context1] = contexts1;
- const page1 = await context1.newPage();
- await page1.goto(server.EMPTY_PAGE);
+ const contexts = cdpBrowser.contexts();
+ expect(contexts.length).toBe(1);
+ await cdpBrowser.close();
- const contexts2 = cdpBrowser2.contexts();
- expect(contexts2.length).toBe(1);
- const [context2] = contexts2;
- const page2 = await context2.newPage();
- await page2.goto(server.EMPTY_PAGE);
-
- expect(context1.pages().length).toBe(2);
- expect(context2.pages().length).toBe(2);
-
- await cdpBrowser1.close();
- await cdpBrowser2.close();
- } finally {
- await browserServer.close();
- }
- });
-
- playwrightTest('should connect to existing service workers', async ({browserType, browserOptions, server}, testInfo) => {
- const port = 9339 + testInfo.workerIndex;
- const browserServer = await browserType.launch({
- ...browserOptions,
- args: ['--remote-debugging-port=' + port]
+ // also connect with the depercreated wsEndpoint option
+ const cdpBrowser2 = await browserType.connectOverCDP({
+ wsEndpoint: JSON.parse(json).webSocketDebuggerUrl,
});
- try {
- const cdpBrowser1 = await browserType.connectOverCDP({
- endpointURL: `http://localhost:${port}`,
- });
- const context = cdpBrowser1.contexts()[0];
- const page = await cdpBrowser1.contexts()[0].newPage();
- const [worker] = await Promise.all([
- context.waitForEvent('serviceworker'),
- page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
- ]);
- expect(await worker.evaluate(() => self.toString())).toBe('[object ServiceWorkerGlobalScope]');
- await cdpBrowser1.close();
-
- const cdpBrowser2 = await browserType.connectOverCDP({
- endpointURL: `http://localhost:${port}`,
- });
- const context2 = cdpBrowser2.contexts()[0];
- expect(context2.serviceWorkers().length).toBe(1);
- await cdpBrowser2.close();
- } finally {
- await browserServer.close();
- }
- });
- playwrightTest('should connect over a ws endpoint', async ({browserType, browserOptions, server}, testInfo) => {
- const port = 9339 + testInfo.workerIndex;
- const browserServer = await browserType.launch({
- ...browserOptions,
- args: ['--remote-debugging-port=' + port]
- });
- try {
- const json = await new Promise((resolve, reject) => {
- http.get(`http://localhost:${port}/json/version/`, resp => {
- let data = '';
- resp.on('data', chunk => data += chunk);
- resp.on('end', () => resolve(data));
- }).on('error', reject);
- });
- const cdpBrowser = await browserType.connectOverCDP({
- endpointURL: JSON.parse(json).webSocketDebuggerUrl,
- });
- const contexts = cdpBrowser.contexts();
- expect(contexts.length).toBe(1);
- await cdpBrowser.close();
-
- // also connect with the depercreated wsEndpoint option
- const cdpBrowser2 = await browserType.connectOverCDP({
- wsEndpoint: JSON.parse(json).webSocketDebuggerUrl,
- });
- const contexts2 = cdpBrowser.contexts();
- expect(contexts2.length).toBe(1);
- await cdpBrowser2.close();
- } finally {
- await browserServer.close();
- }
- });
- playwrightTest('should send extra headers with connect request', async ({browserType, browserOptions, server}, testInfo) => {
- {
- const [request] = await Promise.all([
- server.waitForWebSocketConnectionRequest(),
- browserType.connectOverCDP({
- wsEndpoint: `ws://localhost:${server.PORT}/ws`,
- headers: {
- 'User-Agent': 'Playwright',
- 'foo': 'bar',
- }
- }).catch(() => {})
- ]);
- expect(request.headers['user-agent']).toBe('Playwright');
- expect(request.headers['foo']).toBe('bar');
- }
- {
- const [request] = await Promise.all([
- server.waitForWebSocketConnectionRequest(),
- browserType.connectOverCDP({
- endpointURL: `ws://localhost:${server.PORT}/ws`,
- headers: {
- 'User-Agent': 'Playwright',
- 'foo': 'bar',
- }
- }).catch(() => {})
- ]);
- expect(request.headers['user-agent']).toBe('Playwright');
- expect(request.headers['foo']).toBe('bar');
- }
- });
+ const contexts2 = cdpBrowser.contexts();
+ expect(contexts2.length).toBe(1);
+ await cdpBrowser2.close();
+ } finally {
+ await browserServer.close();
+ }
+});
+
+playwrightTest('should send extra headers with connect request', async ({browserType, browserOptions, server}, testInfo) => {
+ {
+ const [request] = await Promise.all([
+ server.waitForWebSocketConnectionRequest(),
+ browserType.connectOverCDP({
+ wsEndpoint: `ws://localhost:${server.PORT}/ws`,
+ headers: {
+ 'User-Agent': 'Playwright',
+ 'foo': 'bar',
+ }
+ }).catch(() => {})
+ ]);
+ expect(request.headers['user-agent']).toBe('Playwright');
+ expect(request.headers['foo']).toBe('bar');
+ }
+ {
+ const [request] = await Promise.all([
+ server.waitForWebSocketConnectionRequest(),
+ browserType.connectOverCDP({
+ endpointURL: `ws://localhost:${server.PORT}/ws`,
+ headers: {
+ 'User-Agent': 'Playwright',
+ 'foo': 'bar',
+ }
+ }).catch(() => {})
+ ]);
+ expect(request.headers['user-agent']).toBe('Playwright');
+ expect(request.headers['foo']).toBe('bar');
+ }
});
diff --git a/tests/chromium/css-coverage.spec.ts b/tests/chromium/css-coverage.spec.ts
index a041bdcdb9..5f78a9dd62 100644
--- a/tests/chromium/css-coverage.spec.ts
+++ b/tests/chromium/css-coverage.spec.ts
@@ -16,123 +16,119 @@
import { contextTest as it, expect } from '../config/browserTest';
-it.describe('CSS Coverage', () => {
- it.skip(({ browserName }) => browserName !== 'chromium');
-
- it('should work', async function({page, server}) {
- await page.coverage.startCSSCoverage();
- await page.goto(server.PREFIX + '/csscoverage/simple.html');
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(1);
- expect(coverage[0].url).toContain('/csscoverage/simple.html');
- expect(coverage[0].ranges).toEqual([
- {start: 1, end: 22}
- ]);
- const range = coverage[0].ranges[0];
- expect(coverage[0].text.substring(range.start, range.end)).toBe('div { color: green; }');
- });
-
- it('should report sourceURLs', async function({page, server}) {
- await page.coverage.startCSSCoverage();
- await page.goto(server.PREFIX + '/csscoverage/sourceurl.html');
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(1);
- expect(coverage[0].url).toBe('nicename.css');
- });
-
- it('should report multiple stylesheets', async function({page, server}) {
- await page.coverage.startCSSCoverage();
- await page.goto(server.PREFIX + '/csscoverage/multiple.html');
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(2);
- coverage.sort((a, b) => a.url.localeCompare(b.url));
- expect(coverage[0].url).toContain('/csscoverage/stylesheet1.css');
- expect(coverage[1].url).toContain('/csscoverage/stylesheet2.css');
- });
-
- it('should report stylesheets that have no coverage', async function({page, server}) {
- await page.coverage.startCSSCoverage();
- await page.goto(server.PREFIX + '/csscoverage/unused.html');
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(1);
- expect(coverage[0].url).toBe('unused.css');
- expect(coverage[0].ranges.length).toBe(0);
- });
-
- it('should work with media queries', async function({page, server}) {
- await page.coverage.startCSSCoverage();
- await page.goto(server.PREFIX + '/csscoverage/media.html');
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(1);
- expect(coverage[0].url).toContain('/csscoverage/media.html');
- expect(coverage[0].ranges).toEqual([
- {start: 17, end: 38}
- ]);
- });
-
- it('should work with complicated usecases', async function({page, server}) {
- await page.coverage.startCSSCoverage();
- await page.goto(server.PREFIX + '/csscoverage/involved.html');
- const coverage: any = await page.coverage.stopCSSCoverage();
- delete coverage[0].text;
- delete coverage[0].url;
- expect(coverage).toEqual(
- [
- {
- 'ranges': [
- {
- 'start': 149,
- 'end': 297
- },
- {
- 'start': 327,
- 'end': 433
- }
- ]
- }
- ]
- );
- });
-
- it('should ignore injected stylesheets', async function({page, server}) {
- await page.coverage.startCSSCoverage();
- await page.addStyleTag({content: 'body { margin: 10px;}'});
- // trigger style recalc
- const margin = await page.evaluate(() => window.getComputedStyle(document.body).margin);
- expect(margin).toBe('10px');
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(0);
- });
-
- it('should report stylesheets across navigations', async function({page, server}) {
- await page.coverage.startCSSCoverage({resetOnNavigation: false});
- await page.goto(server.PREFIX + '/csscoverage/multiple.html');
- await page.goto(server.EMPTY_PAGE);
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(2);
- });
-
- it('should NOT report scripts across navigations', async function({page, server}) {
- await page.coverage.startCSSCoverage(); // Enabled by default.
- await page.goto(server.PREFIX + '/csscoverage/multiple.html');
- await page.goto(server.EMPTY_PAGE);
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(0);
- });
-
- it('should work with a recently loaded stylesheet', async function({page, server}) {
- await page.coverage.startCSSCoverage();
- await page.evaluate(async url => {
- document.body.textContent = 'hello, world';
-
- const link = document.createElement('link');
- link.rel = 'stylesheet';
- link.href = url;
- document.head.appendChild(link);
- await new Promise(x => link.onload = x);
- await new Promise(f => requestAnimationFrame(f));
- }, server.PREFIX + '/csscoverage/stylesheet1.css');
- const coverage = await page.coverage.stopCSSCoverage();
- expect(coverage.length).toBe(1);
- });
+it('should work', async function({page, server}) {
+ await page.coverage.startCSSCoverage();
+ await page.goto(server.PREFIX + '/csscoverage/simple.html');
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(1);
+ expect(coverage[0].url).toContain('/csscoverage/simple.html');
+ expect(coverage[0].ranges).toEqual([
+ {start: 1, end: 22}
+ ]);
+ const range = coverage[0].ranges[0];
+ expect(coverage[0].text.substring(range.start, range.end)).toBe('div { color: green; }');
+});
+
+it('should report sourceURLs', async function({page, server}) {
+ await page.coverage.startCSSCoverage();
+ await page.goto(server.PREFIX + '/csscoverage/sourceurl.html');
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(1);
+ expect(coverage[0].url).toBe('nicename.css');
+});
+
+it('should report multiple stylesheets', async function({page, server}) {
+ await page.coverage.startCSSCoverage();
+ await page.goto(server.PREFIX + '/csscoverage/multiple.html');
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(2);
+ coverage.sort((a, b) => a.url.localeCompare(b.url));
+ expect(coverage[0].url).toContain('/csscoverage/stylesheet1.css');
+ expect(coverage[1].url).toContain('/csscoverage/stylesheet2.css');
+});
+
+it('should report stylesheets that have no coverage', async function({page, server}) {
+ await page.coverage.startCSSCoverage();
+ await page.goto(server.PREFIX + '/csscoverage/unused.html');
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(1);
+ expect(coverage[0].url).toBe('unused.css');
+ expect(coverage[0].ranges.length).toBe(0);
+});
+
+it('should work with media queries', async function({page, server}) {
+ await page.coverage.startCSSCoverage();
+ await page.goto(server.PREFIX + '/csscoverage/media.html');
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(1);
+ expect(coverage[0].url).toContain('/csscoverage/media.html');
+ expect(coverage[0].ranges).toEqual([
+ {start: 17, end: 38}
+ ]);
+});
+
+it('should work with complicated usecases', async function({page, server}) {
+ await page.coverage.startCSSCoverage();
+ await page.goto(server.PREFIX + '/csscoverage/involved.html');
+ const coverage: any = await page.coverage.stopCSSCoverage();
+ delete coverage[0].text;
+ delete coverage[0].url;
+ expect(coverage).toEqual(
+ [
+ {
+ 'ranges': [
+ {
+ 'start': 149,
+ 'end': 297
+ },
+ {
+ 'start': 327,
+ 'end': 433
+ }
+ ]
+ }
+ ]
+ );
+});
+
+it('should ignore injected stylesheets', async function({page, server}) {
+ await page.coverage.startCSSCoverage();
+ await page.addStyleTag({content: 'body { margin: 10px;}'});
+ // trigger style recalc
+ const margin = await page.evaluate(() => window.getComputedStyle(document.body).margin);
+ expect(margin).toBe('10px');
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(0);
+});
+
+it('should report stylesheets across navigations', async function({page, server}) {
+ await page.coverage.startCSSCoverage({resetOnNavigation: false});
+ await page.goto(server.PREFIX + '/csscoverage/multiple.html');
+ await page.goto(server.EMPTY_PAGE);
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(2);
+});
+
+it('should NOT report scripts across navigations', async function({page, server}) {
+ await page.coverage.startCSSCoverage(); // Enabled by default.
+ await page.goto(server.PREFIX + '/csscoverage/multiple.html');
+ await page.goto(server.EMPTY_PAGE);
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(0);
+});
+
+it('should work with a recently loaded stylesheet', async function({page, server}) {
+ await page.coverage.startCSSCoverage();
+ await page.evaluate(async url => {
+ document.body.textContent = 'hello, world';
+
+ const link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.href = url;
+ document.head.appendChild(link);
+ await new Promise(x => link.onload = x);
+ await new Promise(f => requestAnimationFrame(f));
+ }, server.PREFIX + '/csscoverage/stylesheet1.css');
+ const coverage = await page.coverage.stopCSSCoverage();
+ expect(coverage.length).toBe(1);
});
diff --git a/tests/chromium/js-coverage.spec.ts b/tests/chromium/js-coverage.spec.ts
index 42d94605bd..5a9bebe0b6 100644
--- a/tests/chromium/js-coverage.spec.ts
+++ b/tests/chromium/js-coverage.spec.ts
@@ -16,73 +16,69 @@
import { contextTest as it, expect } from '../config/browserTest';
-it.describe('JS Coverage', () => {
- it.skip(({ browserName }) => browserName !== 'chromium');
-
- it('should work', async function({page, server}) {
- await page.coverage.startJSCoverage();
- await page.goto(server.PREFIX + '/jscoverage/simple.html', { waitUntil: 'load' });
- const coverage = await page.coverage.stopJSCoverage();
- expect(coverage.length).toBe(1);
- expect(coverage[0].url).toContain('/jscoverage/simple.html');
- expect(coverage[0].functions.find(f => f.functionName === 'foo').ranges[0].count).toEqual(1);
- });
-
- it('should report sourceURLs', async function({page, server}) {
- await page.coverage.startJSCoverage();
- await page.goto(server.PREFIX + '/jscoverage/sourceurl.html');
- const coverage = await page.coverage.stopJSCoverage();
- expect(coverage.length).toBe(1);
- expect(coverage[0].url).toBe('nicename.js');
- });
-
- it('should ignore eval() scripts by default', async function({page, server}) {
- await page.coverage.startJSCoverage();
- await page.goto(server.PREFIX + '/jscoverage/eval.html');
- const coverage = await page.coverage.stopJSCoverage();
- expect(coverage.length).toBe(1);
- });
-
- it('shouldn\'t ignore eval() scripts if reportAnonymousScripts is true', async function({page, server}) {
- await page.coverage.startJSCoverage({reportAnonymousScripts: true});
- await page.goto(server.PREFIX + '/jscoverage/eval.html');
- const coverage = await page.coverage.stopJSCoverage();
- expect(coverage.find(entry => entry.url === '').source).toBe('console.log("foo")');
- expect(coverage.length).toBe(2);
- });
-
- it('should report multiple scripts', async function({page, server}) {
- await page.coverage.startJSCoverage();
- await page.goto(server.PREFIX + '/jscoverage/multiple.html');
- const coverage = await page.coverage.stopJSCoverage();
- expect(coverage.length).toBe(2);
- coverage.sort((a, b) => a.url.localeCompare(b.url));
- expect(coverage[0].url).toContain('/jscoverage/script1.js');
- expect(coverage[1].url).toContain('/jscoverage/script2.js');
- });
-
- it('should report scripts across navigations when disabled', async function({page, server}) {
- await page.coverage.startJSCoverage({resetOnNavigation: false});
- await page.goto(server.PREFIX + '/jscoverage/multiple.html');
- await page.goto(server.EMPTY_PAGE);
- const coverage = await page.coverage.stopJSCoverage();
- expect(coverage.length).toBe(2);
- });
-
- it('should NOT report scripts across navigations when enabled', async function({page, server}) {
- await page.coverage.startJSCoverage(); // Enabled by default.
- await page.goto(server.PREFIX + '/jscoverage/multiple.html');
- await page.goto(server.EMPTY_PAGE);
- const coverage = await page.coverage.stopJSCoverage();
- expect(coverage.length).toBe(0);
- });
-
- it('should not hang when there is a debugger statement', async function({page, server}) {
- await page.coverage.startJSCoverage();
- await page.goto(server.EMPTY_PAGE);
- await page.evaluate(() => {
- debugger; // eslint-disable-line no-debugger
- });
- await page.coverage.stopJSCoverage();
- });
+it('should work', async function({page, server}) {
+ await page.coverage.startJSCoverage();
+ await page.goto(server.PREFIX + '/jscoverage/simple.html', { waitUntil: 'load' });
+ const coverage = await page.coverage.stopJSCoverage();
+ expect(coverage.length).toBe(1);
+ expect(coverage[0].url).toContain('/jscoverage/simple.html');
+ expect(coverage[0].functions.find(f => f.functionName === 'foo').ranges[0].count).toEqual(1);
+});
+
+it('should report sourceURLs', async function({page, server}) {
+ await page.coverage.startJSCoverage();
+ await page.goto(server.PREFIX + '/jscoverage/sourceurl.html');
+ const coverage = await page.coverage.stopJSCoverage();
+ expect(coverage.length).toBe(1);
+ expect(coverage[0].url).toBe('nicename.js');
+});
+
+it('should ignore eval() scripts by default', async function({page, server}) {
+ await page.coverage.startJSCoverage();
+ await page.goto(server.PREFIX + '/jscoverage/eval.html');
+ const coverage = await page.coverage.stopJSCoverage();
+ expect(coverage.length).toBe(1);
+});
+
+it('shouldn\'t ignore eval() scripts if reportAnonymousScripts is true', async function({page, server}) {
+ await page.coverage.startJSCoverage({reportAnonymousScripts: true});
+ await page.goto(server.PREFIX + '/jscoverage/eval.html');
+ const coverage = await page.coverage.stopJSCoverage();
+ expect(coverage.find(entry => entry.url === '').source).toBe('console.log("foo")');
+ expect(coverage.length).toBe(2);
+});
+
+it('should report multiple scripts', async function({page, server}) {
+ await page.coverage.startJSCoverage();
+ await page.goto(server.PREFIX + '/jscoverage/multiple.html');
+ const coverage = await page.coverage.stopJSCoverage();
+ expect(coverage.length).toBe(2);
+ coverage.sort((a, b) => a.url.localeCompare(b.url));
+ expect(coverage[0].url).toContain('/jscoverage/script1.js');
+ expect(coverage[1].url).toContain('/jscoverage/script2.js');
+});
+
+it('should report scripts across navigations when disabled', async function({page, server}) {
+ await page.coverage.startJSCoverage({resetOnNavigation: false});
+ await page.goto(server.PREFIX + '/jscoverage/multiple.html');
+ await page.goto(server.EMPTY_PAGE);
+ const coverage = await page.coverage.stopJSCoverage();
+ expect(coverage.length).toBe(2);
+});
+
+it('should NOT report scripts across navigations when enabled', async function({page, server}) {
+ await page.coverage.startJSCoverage(); // Enabled by default.
+ await page.goto(server.PREFIX + '/jscoverage/multiple.html');
+ await page.goto(server.EMPTY_PAGE);
+ const coverage = await page.coverage.stopJSCoverage();
+ expect(coverage.length).toBe(0);
+});
+
+it('should not hang when there is a debugger statement', async function({page, server}) {
+ await page.coverage.startJSCoverage();
+ await page.goto(server.EMPTY_PAGE);
+ await page.evaluate(() => {
+ debugger; // eslint-disable-line no-debugger
+ });
+ await page.coverage.stopJSCoverage();
});
diff --git a/tests/chromium/launcher.spec.ts b/tests/chromium/launcher.spec.ts
index 8574a822b4..612eb8429d 100644
--- a/tests/chromium/launcher.spec.ts
+++ b/tests/chromium/launcher.spec.ts
@@ -16,8 +16,6 @@
import { playwrightTest as it, expect } from '../config/browserTest';
-it.skip(({ browserName }) => browserName !== 'chromium');
-
it('should throw with remote-debugging-pipe argument', async ({browserType, browserOptions, mode}) => {
it.skip(mode !== 'default');
diff --git a/tests/chromium/oopif.spec.ts b/tests/chromium/oopif.spec.ts
index b5bbef7624..13617edb9d 100644
--- a/tests/chromium/oopif.spec.ts
+++ b/tests/chromium/oopif.spec.ts
@@ -14,307 +14,282 @@
* limitations under the License.
*/
-import { playwrightTest, expect } from '../config/browserTest';
-import type { Page } from '../../index';
+import { contextTest as it, expect } from '../config/browserTest';
-const it = playwrightTest.extend({
- async beforeAll({ browserType, browserOptions, browserName }) {
- const browser = await browserType.launch({
- ...browserOptions,
- args: browserName === 'chromium' ? (browserOptions.args || []).concat(['--site-per-process']) : browserOptions.args,
- });
- this.browser = browser;
- return { browser };
- },
- async beforeEach() {
- const page = await this.browser.newPage() as Page;
- this.page = page;
- return { page };
- },
- async afterEach() {
- await this.page.close();
- },
- async afterAll() {
- await this.browser.close();
- },
+it.useOptions({ launchOptions: { args: ['--site-per-process'] } });
+
+it('should report oopif frames', async function({page, browser, server}) {
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(await countOOPIFs(browser)).toBe(1);
+ expect(page.frames().length).toBe(2);
+ expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
});
-it.describe('oopif', () => {
- it.skip(({ browserName }) => browserName !== 'chromium');
+it('should handle oopif detach', async function({page, browser, server}) {
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(await countOOPIFs(browser)).toBe(1);
+ expect(page.frames().length).toBe(2);
+ const frame = page.frames()[1];
+ expect(await frame.evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
+ const [detachedFrame] = await Promise.all([
+ page.waitForEvent('framedetached'),
+ page.evaluate(() => document.querySelector('iframe').remove()),
+ ]);
+ expect(detachedFrame).toBe(frame);
+});
- it('should report oopif frames', async function({page, browser, server}) {
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(await countOOPIFs(browser)).toBe(1);
- expect(page.frames().length).toBe(2);
- expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
+it('should handle remote -> local -> remote transitions', async function({page, browser, server}) {
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(page.frames().length).toBe(2);
+ expect(await countOOPIFs(browser)).toBe(1);
+ expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
+ await Promise.all([
+ page.frames()[1].waitForNavigation(),
+ page.evaluate('goLocal()'),
+ ]);
+ expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.PREFIX + '/grid.html');
+ expect(await countOOPIFs(browser)).toBe(0);
+ await Promise.all([
+ page.frames()[1].waitForNavigation(),
+ page.evaluate('goRemote()'),
+ ]);
+ expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
+ expect(await countOOPIFs(browser)).toBe(1);
+});
+
+it('should get the proper viewport', async ({page, browser, server}) => {
+ it.fixme();
+
+ expect(page.viewportSize()).toEqual({width: 1280, height: 720});
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(page.frames().length).toBe(2);
+ expect(await countOOPIFs(browser)).toBe(1);
+ const oopif = page.frames()[1];
+ expect(await oopif.evaluate(() => screen.width)).toBe(1280);
+ expect(await oopif.evaluate(() => screen.height)).toBe(720);
+ expect(await oopif.evaluate(() => matchMedia('(device-width: 1280px)').matches)).toBe(true);
+ expect(await oopif.evaluate(() => matchMedia('(device-height: 720px)').matches)).toBe(true);
+ expect(await oopif.evaluate(() => 'ontouchstart' in window)).toBe(false);
+ await page.setViewportSize({width: 123, height: 456});
+ expect(await oopif.evaluate(() => screen.width)).toBe(123);
+ expect(await oopif.evaluate(() => screen.height)).toBe(456);
+ expect(await oopif.evaluate(() => matchMedia('(device-width: 123px)').matches)).toBe(true);
+ expect(await oopif.evaluate(() => matchMedia('(device-height: 456px)').matches)).toBe(true);
+ expect(await oopif.evaluate(() => 'ontouchstart' in window)).toBe(false);
+});
+
+it('should expose function', async ({page, browser, server}) => {
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(page.frames().length).toBe(2);
+ expect(await countOOPIFs(browser)).toBe(1);
+ const oopif = page.frames()[1];
+ await page.exposeFunction('mul', (a, b) => a * b);
+ const result = await oopif.evaluate(async function() {
+ return await window['mul'](9, 4);
});
+ expect(result).toBe(36);
+});
- it('should handle oopif detach', async function({page, browser, server}) {
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(await countOOPIFs(browser)).toBe(1);
- expect(page.frames().length).toBe(2);
- const frame = page.frames()[1];
- expect(await frame.evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
- const [detachedFrame] = await Promise.all([
- page.waitForEvent('framedetached'),
- page.evaluate(() => document.querySelector('iframe').remove()),
- ]);
- expect(detachedFrame).toBe(frame);
+it('should emulate media', async ({page, browser, server}) => {
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(page.frames().length).toBe(2);
+ expect(await countOOPIFs(browser)).toBe(1);
+ const oopif = page.frames()[1];
+ expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
+ await page.emulateMedia({ colorScheme: 'dark' });
+ expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
+});
+
+it('should emulate offline', async ({page, browser, server}) => {
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(page.frames().length).toBe(2);
+ expect(await countOOPIFs(browser)).toBe(1);
+ const oopif = page.frames()[1];
+ expect(await oopif.evaluate(() => navigator.onLine)).toBe(true);
+ await page.context().setOffline(true);
+ expect(await oopif.evaluate(() => navigator.onLine)).toBe(false);
+});
+
+it('should support context options', async ({browser, server, playwright}) => {
+ const iPhone = playwright.devices['iPhone 6'];
+ const context = await browser.newContext({ ...iPhone, timezoneId: 'America/Jamaica', locale: 'fr-CH', userAgent: 'UA' });
+ const page = await context.newPage();
+
+ const [request] = await Promise.all([
+ server.waitForRequest('/grid.html'),
+ page.goto(server.PREFIX + '/dynamic-oopif.html'),
+ ]);
+ expect(page.frames().length).toBe(2);
+ expect(await countOOPIFs(browser)).toBe(1);
+ const oopif = page.frames()[1];
+
+ expect(await oopif.evaluate(() => 'ontouchstart' in window)).toBe(true);
+ expect(await oopif.evaluate(() => new Date(1479579154987).toString())).toBe('Sat Nov 19 2016 13:12:34 GMT-0500 (heure normale de l’Est nord-américain)');
+ expect(await oopif.evaluate(() => navigator.language)).toBe('fr-CH');
+ expect(await oopif.evaluate(() => navigator.userAgent)).toBe('UA');
+ expect(request.headers['user-agent']).toBe('UA');
+
+ await context.close();
+});
+
+it('should respect route', async ({page, browser, server}) => {
+ let intercepted = false;
+ await page.route('**/digits/0.png', route => {
+ intercepted = true;
+ route.continue();
});
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(page.frames().length).toBe(2);
+ expect(await countOOPIFs(browser)).toBe(1);
+ expect(intercepted).toBe(true);
+});
- it('should handle remote -> local -> remote transitions', async function({page, browser, server}) {
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(page.frames().length).toBe(2);
- expect(await countOOPIFs(browser)).toBe(1);
- expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
- await Promise.all([
- page.frames()[1].waitForNavigation(),
- page.evaluate('goLocal()'),
- ]);
- expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.PREFIX + '/grid.html');
- expect(await countOOPIFs(browser)).toBe(0);
- await Promise.all([
- page.frames()[1].waitForNavigation(),
- page.evaluate('goRemote()'),
- ]);
- expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
- expect(await countOOPIFs(browser)).toBe(1);
+it('should take screenshot', async ({page, browser, server}) => {
+ await page.setViewportSize({width: 500, height: 500});
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(page.frames().length).toBe(2);
+ expect(await countOOPIFs(browser)).toBe(1);
+ expect(await page.screenshot()).toMatchSnapshot('screenshot-oopif.png', { threshold: 0.3 });
+});
+
+it('should load oopif iframes with subresources and route', async function({page, browser, server}) {
+ await page.route('**/*', route => route.continue());
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(await countOOPIFs(browser)).toBe(1);
+});
+
+it('should report main requests', async function({page, browser, server}) {
+ const requestFrames = [];
+ page.on('request', r => requestFrames.push(r.frame()));
+ const finishedFrames = [];
+ page.on('requestfinished', r => finishedFrames.push(r.frame()));
+
+ await page.goto(server.PREFIX + '/empty.html');
+ const main = page.mainFrame();
+
+ await main.evaluate(url => {
+ const iframe = document.createElement('iframe');
+ iframe.src = url;
+ document.body.appendChild(iframe);
+ return new Promise(f => iframe.onload = f);
+ }, server.CROSS_PROCESS_PREFIX + '/empty.html');
+ expect(page.frames().length).toBe(2);
+ const child = main.childFrames()[0];
+ await child.waitForLoadState('domcontentloaded');
+
+ await child.evaluate(url => {
+ const iframe = document.createElement('iframe');
+ iframe.src = url;
+ document.body.appendChild(iframe);
+ return new Promise(f => iframe.onload = f);
+ }, server.PREFIX + '/empty.html');
+ expect(page.frames().length).toBe(3);
+ const grandChild = child.childFrames()[0];
+ await grandChild.waitForLoadState('domcontentloaded');
+
+ expect(await countOOPIFs(browser)).toBe(2);
+ expect(requestFrames[0]).toBe(main);
+ expect(finishedFrames[0]).toBe(main);
+ expect(requestFrames[1]).toBe(child);
+ expect(finishedFrames[1]).toBe(child);
+ expect(requestFrames[2]).toBe(grandChild);
+ expect(finishedFrames[2]).toBe(grandChild);
+});
+
+it('should support exposeFunction', async function({page, browser, server}) {
+ await page.context().exposeFunction('dec', a => a - 1);
+ await page.exposeFunction('inc', a => a + 1);
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(await countOOPIFs(browser)).toBe(1);
+ expect(page.frames().length).toBe(2);
+ expect(await page.frames()[0].evaluate(() => window['inc'](3))).toBe(4);
+ expect(await page.frames()[1].evaluate(() => window['inc'](4))).toBe(5);
+ expect(await page.frames()[0].evaluate(() => window['dec'](3))).toBe(2);
+ expect(await page.frames()[1].evaluate(() => window['dec'](4))).toBe(3);
+});
+
+it('should support addInitScript', async function({page, browser, server}) {
+ await page.context().addInitScript(() => window['bar'] = 17);
+ await page.addInitScript(() => window['foo'] = 42);
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ expect(await countOOPIFs(browser)).toBe(1);
+ expect(page.frames().length).toBe(2);
+ expect(await page.frames()[0].evaluate(() => window['foo'])).toBe(42);
+ expect(await page.frames()[1].evaluate(() => window['foo'])).toBe(42);
+ expect(await page.frames()[0].evaluate(() => window['bar'])).toBe(17);
+ expect(await page.frames()[1].evaluate(() => window['bar'])).toBe(17);
+});
+// @see https://github.com/microsoft/playwright/issues/1240
+it('should click a button when it overlays oopif', async function({page, browser, server}) {
+ await page.goto(server.PREFIX + '/button-overlay-oopif.html');
+ expect(await countOOPIFs(browser)).toBe(1);
+ await page.click('button');
+ expect(await page.evaluate(() => window['BUTTON_CLICKED'])).toBe(true);
+});
+
+it('should report google.com frame with headful', async ({browserType, browserOptions, server}) => {
+ // @see https://github.com/GoogleChrome/puppeteer/issues/2548
+ // https://google.com is isolated by default in Chromium embedder.
+ const browser = await browserType.launch({...browserOptions, headless: false});
+ const page = await browser.newPage();
+ await page.goto(server.EMPTY_PAGE);
+ await page.route('**/*', route => {
+ route.fulfill({body: 'YO, GOOGLE.COM'});
});
-
- it('should get the proper viewport', async ({page, browser, server}) => {
- it.fixme();
-
- expect(page.viewportSize()).toEqual({width: 1280, height: 720});
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(page.frames().length).toBe(2);
- expect(await countOOPIFs(browser)).toBe(1);
- const oopif = page.frames()[1];
- expect(await oopif.evaluate(() => screen.width)).toBe(1280);
- expect(await oopif.evaluate(() => screen.height)).toBe(720);
- expect(await oopif.evaluate(() => matchMedia('(device-width: 1280px)').matches)).toBe(true);
- expect(await oopif.evaluate(() => matchMedia('(device-height: 720px)').matches)).toBe(true);
- expect(await oopif.evaluate(() => 'ontouchstart' in window)).toBe(false);
- await page.setViewportSize({width: 123, height: 456});
- expect(await oopif.evaluate(() => screen.width)).toBe(123);
- expect(await oopif.evaluate(() => screen.height)).toBe(456);
- expect(await oopif.evaluate(() => matchMedia('(device-width: 123px)').matches)).toBe(true);
- expect(await oopif.evaluate(() => matchMedia('(device-height: 456px)').matches)).toBe(true);
- expect(await oopif.evaluate(() => 'ontouchstart' in window)).toBe(false);
+ await page.evaluate(() => {
+ const frame = document.createElement('iframe');
+ frame.setAttribute('src', 'https://google.com/');
+ document.body.appendChild(frame);
+ return new Promise(x => frame.onload = x);
});
+ await page.waitForSelector('iframe[src="https://google.com/"]');
+ expect(await countOOPIFs(browser)).toBe(1);
+ const urls = page.frames().map(frame => frame.url());
+ expect(urls).toEqual([
+ server.EMPTY_PAGE,
+ 'https://google.com/'
+ ]);
+ await browser.close();
+});
- it('should expose function', async ({page, browser, server}) => {
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(page.frames().length).toBe(2);
- expect(await countOOPIFs(browser)).toBe(1);
- const oopif = page.frames()[1];
- await page.exposeFunction('mul', (a, b) => a * b);
- const result = await oopif.evaluate(async function() {
- return await window['mul'](9, 4);
- });
- expect(result).toBe(36);
+it('ElementHandle.boundingBox() should work', async function({page, browser, server}) {
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ await page.$eval('iframe', iframe => {
+ iframe.style.width = '500px';
+ iframe.style.height = '500px';
+ iframe.style.marginLeft = '42px';
+ iframe.style.marginTop = '17px';
});
+ await page.frames()[1].goto(page.frames()[1].url());
- it('should emulate media', async ({page, browser, server}) => {
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(page.frames().length).toBe(2);
- expect(await countOOPIFs(browser)).toBe(1);
- const oopif = page.frames()[1];
- expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
- await page.emulateMedia({ colorScheme: 'dark' });
- expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
+ expect(await countOOPIFs(browser)).toBe(1);
+ const handle1 = await page.frames()[1].$('.box:nth-of-type(13)');
+ expect(await handle1.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 });
+
+ await Promise.all([
+ page.frames()[1].waitForNavigation(),
+ page.evaluate('goLocal()'),
+ ]);
+ expect(await countOOPIFs(browser)).toBe(0);
+ const handle2 = await page.frames()[1].$('.box:nth-of-type(13)');
+ expect(await handle2.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 });
+});
+
+it('should click', async function({page, browser, server}) {
+ await page.goto(server.PREFIX + '/dynamic-oopif.html');
+ await page.$eval('iframe', iframe => {
+ iframe.style.width = '500px';
+ iframe.style.height = '500px';
+ iframe.style.marginLeft = '102px';
+ iframe.style.marginTop = '117px';
});
+ await page.frames()[1].goto(page.frames()[1].url());
- it('should emulate offline', async ({page, browser, server}) => {
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(page.frames().length).toBe(2);
- expect(await countOOPIFs(browser)).toBe(1);
- const oopif = page.frames()[1];
- expect(await oopif.evaluate(() => navigator.onLine)).toBe(true);
- await page.context().setOffline(true);
- expect(await oopif.evaluate(() => navigator.onLine)).toBe(false);
- });
-
- it('should support context options', async ({browser, server, playwright}) => {
- const iPhone = playwright.devices['iPhone 6'];
- const context = await browser.newContext({ ...iPhone, timezoneId: 'America/Jamaica', locale: 'fr-CH', userAgent: 'UA' });
- const page = await context.newPage();
-
- const [request] = await Promise.all([
- server.waitForRequest('/grid.html'),
- page.goto(server.PREFIX + '/dynamic-oopif.html'),
- ]);
- expect(page.frames().length).toBe(2);
- expect(await countOOPIFs(browser)).toBe(1);
- const oopif = page.frames()[1];
-
- expect(await oopif.evaluate(() => 'ontouchstart' in window)).toBe(true);
- expect(await oopif.evaluate(() => new Date(1479579154987).toString())).toBe('Sat Nov 19 2016 13:12:34 GMT-0500 (heure normale de l’Est nord-américain)');
- expect(await oopif.evaluate(() => navigator.language)).toBe('fr-CH');
- expect(await oopif.evaluate(() => navigator.userAgent)).toBe('UA');
- expect(request.headers['user-agent']).toBe('UA');
-
- await context.close();
- });
-
- it('should respect route', async ({page, browser, server}) => {
- let intercepted = false;
- await page.route('**/digits/0.png', route => {
- intercepted = true;
- route.continue();
- });
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(page.frames().length).toBe(2);
- expect(await countOOPIFs(browser)).toBe(1);
- expect(intercepted).toBe(true);
- });
-
- it('should take screenshot', async ({page, browser, server}) => {
- await page.setViewportSize({width: 500, height: 500});
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(page.frames().length).toBe(2);
- expect(await countOOPIFs(browser)).toBe(1);
- expect(await page.screenshot()).toMatchSnapshot('screenshot-oopif.png', { threshold: 0.3 });
- });
-
- it('should load oopif iframes with subresources and route', async function({page, browser, server}) {
- await page.route('**/*', route => route.continue());
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(await countOOPIFs(browser)).toBe(1);
- });
-
- it('should report main requests', async function({page, browser, server}) {
- const requestFrames = [];
- page.on('request', r => requestFrames.push(r.frame()));
- const finishedFrames = [];
- page.on('requestfinished', r => finishedFrames.push(r.frame()));
-
- await page.goto(server.PREFIX + '/empty.html');
- const main = page.mainFrame();
-
- await main.evaluate(url => {
- const iframe = document.createElement('iframe');
- iframe.src = url;
- document.body.appendChild(iframe);
- return new Promise(f => iframe.onload = f);
- }, server.CROSS_PROCESS_PREFIX + '/empty.html');
- expect(page.frames().length).toBe(2);
- const child = main.childFrames()[0];
- await child.waitForLoadState('domcontentloaded');
-
- await child.evaluate(url => {
- const iframe = document.createElement('iframe');
- iframe.src = url;
- document.body.appendChild(iframe);
- return new Promise(f => iframe.onload = f);
- }, server.PREFIX + '/empty.html');
- expect(page.frames().length).toBe(3);
- const grandChild = child.childFrames()[0];
- await grandChild.waitForLoadState('domcontentloaded');
-
- expect(await countOOPIFs(browser)).toBe(2);
- expect(requestFrames[0]).toBe(main);
- expect(finishedFrames[0]).toBe(main);
- expect(requestFrames[1]).toBe(child);
- expect(finishedFrames[1]).toBe(child);
- expect(requestFrames[2]).toBe(grandChild);
- expect(finishedFrames[2]).toBe(grandChild);
- });
-
- it('should support exposeFunction', async function({page, browser, server}) {
- await page.context().exposeFunction('dec', a => a - 1);
- await page.exposeFunction('inc', a => a + 1);
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(await countOOPIFs(browser)).toBe(1);
- expect(page.frames().length).toBe(2);
- expect(await page.frames()[0].evaluate(() => window['inc'](3))).toBe(4);
- expect(await page.frames()[1].evaluate(() => window['inc'](4))).toBe(5);
- expect(await page.frames()[0].evaluate(() => window['dec'](3))).toBe(2);
- expect(await page.frames()[1].evaluate(() => window['dec'](4))).toBe(3);
- });
-
- it('should support addInitScript', async function({page, browser, server}) {
- await page.context().addInitScript(() => window['bar'] = 17);
- await page.addInitScript(() => window['foo'] = 42);
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- expect(await countOOPIFs(browser)).toBe(1);
- expect(page.frames().length).toBe(2);
- expect(await page.frames()[0].evaluate(() => window['foo'])).toBe(42);
- expect(await page.frames()[1].evaluate(() => window['foo'])).toBe(42);
- expect(await page.frames()[0].evaluate(() => window['bar'])).toBe(17);
- expect(await page.frames()[1].evaluate(() => window['bar'])).toBe(17);
- });
- // @see https://github.com/microsoft/playwright/issues/1240
- it('should click a button when it overlays oopif', async function({page, browser, server}) {
- await page.goto(server.PREFIX + '/button-overlay-oopif.html');
- expect(await countOOPIFs(browser)).toBe(1);
- await page.click('button');
- expect(await page.evaluate(() => window['BUTTON_CLICKED'])).toBe(true);
- });
-
- it('should report google.com frame with headful', async ({browserType, browserOptions, server}) => {
- // @see https://github.com/GoogleChrome/puppeteer/issues/2548
- // https://google.com is isolated by default in Chromium embedder.
- const browser = await browserType.launch({...browserOptions, headless: false});
- const page = await browser.newPage();
- await page.goto(server.EMPTY_PAGE);
- await page.route('**/*', route => {
- route.fulfill({body: 'YO, GOOGLE.COM'});
- });
- await page.evaluate(() => {
- const frame = document.createElement('iframe');
- frame.setAttribute('src', 'https://google.com/');
- document.body.appendChild(frame);
- return new Promise(x => frame.onload = x);
- });
- await page.waitForSelector('iframe[src="https://google.com/"]');
- expect(await countOOPIFs(browser)).toBe(1);
- const urls = page.frames().map(frame => frame.url());
- expect(urls).toEqual([
- server.EMPTY_PAGE,
- 'https://google.com/'
- ]);
- await browser.close();
- });
-
- it('ElementHandle.boundingBox() should work', async function({page, browser, server}) {
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- await page.$eval('iframe', iframe => {
- iframe.style.width = '500px';
- iframe.style.height = '500px';
- iframe.style.marginLeft = '42px';
- iframe.style.marginTop = '17px';
- });
- await page.frames()[1].goto(page.frames()[1].url());
-
- expect(await countOOPIFs(browser)).toBe(1);
- const handle1 = await page.frames()[1].$('.box:nth-of-type(13)');
- expect(await handle1.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 });
-
- await Promise.all([
- page.frames()[1].waitForNavigation(),
- page.evaluate('goLocal()'),
- ]);
- expect(await countOOPIFs(browser)).toBe(0);
- const handle2 = await page.frames()[1].$('.box:nth-of-type(13)');
- expect(await handle2.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 });
- });
-
- it('should click', async function({page, browser, server}) {
- await page.goto(server.PREFIX + '/dynamic-oopif.html');
- await page.$eval('iframe', iframe => {
- iframe.style.width = '500px';
- iframe.style.height = '500px';
- iframe.style.marginLeft = '102px';
- iframe.style.marginTop = '117px';
- });
- await page.frames()[1].goto(page.frames()[1].url());
-
- expect(await countOOPIFs(browser)).toBe(1);
- const handle1 = await page.frames()[1].$('.box:nth-of-type(13)');
- await handle1.evaluate(div => div.addEventListener('click', () => window['_clicked'] = true, false));
- await handle1.click();
- expect(await handle1.evaluate(() => window['_clicked'])).toBe(true);
- });
+ expect(await countOOPIFs(browser)).toBe(1);
+ const handle1 = await page.frames()[1].$('.box:nth-of-type(13)');
+ await handle1.evaluate(div => div.addEventListener('click', () => window['_clicked'] = true, false));
+ await handle1.click();
+ expect(await handle1.evaluate(() => window['_clicked'])).toBe(true);
});
async function countOOPIFs(browser) {
diff --git a/tests/chromium/session.spec.ts b/tests/chromium/session.spec.ts
index 74e61f8bdf..e9da7cbdc3 100644
--- a/tests/chromium/session.spec.ts
+++ b/tests/chromium/session.spec.ts
@@ -17,115 +17,107 @@
import { contextTest as it, expect } from '../config/browserTest';
import { browserTest } from '../config/browserTest';
-it.describe('session', () => {
- it.skip(({ browserName }) => browserName !== 'chromium');
+it('should work', async function({page}) {
+ const client = await page.context().newCDPSession(page);
- it('should work', async function({page}) {
- const client = await page.context().newCDPSession(page);
-
- await Promise.all([
- client.send('Runtime.enable'),
- client.send('Runtime.evaluate', { expression: 'window.foo = "bar"' })
- ]);
- const foo = await page.evaluate(() => window['foo']);
- expect(foo).toBe('bar');
- });
-
- it('should send events', async function({page, server}) {
- const client = await page.context().newCDPSession(page);
- await client.send('Network.enable');
- const events = [];
- client.on('Network.requestWillBeSent', event => events.push(event));
- await page.goto(server.EMPTY_PAGE);
- expect(events.length).toBe(1);
- });
-
- it('should only accept a page', async function({page}) {
- // @ts-expect-error newCDPSession expects a Page
- const error = await page.context().newCDPSession(page.context()).catch(e => e);
- expect(error.message).toContain('page: expected Page');
- });
-
- it('should enable and disable domains independently', async function({page}) {
- const client = await page.context().newCDPSession(page);
- await client.send('Runtime.enable');
- await client.send('Debugger.enable');
- // JS coverage enables and then disables Debugger domain.
- await page.coverage.startJSCoverage();
- await page.coverage.stopJSCoverage();
- page.on('console', console.log);
- // generate a script in page and wait for the event.
- await Promise.all([
- new Promise(f => client.on('Debugger.scriptParsed', event => {
- if (event.url === 'foo.js')
- f();
- })),
- page.evaluate('//# sourceURL=foo.js')
- ]);
- });
-
- it('should be able to detach session', async function({page}) {
- const client = await page.context().newCDPSession(page);
- await client.send('Runtime.enable');
- const evalResponse = await client.send('Runtime.evaluate', {expression: '1 + 2', returnByValue: true});
- expect(evalResponse.result.value).toBe(3);
- await client.detach();
- let error = null;
- try {
- await client.send('Runtime.evaluate', {expression: '3 + 1', returnByValue: true});
- } catch (e) {
- error = e;
- }
- expect(error.message).toContain('Target page, context or browser has been closed');
- });
-
- it('should throw nice errors', async function({page}) {
- const client = await page.context().newCDPSession(page);
- const error = await theSourceOfTheProblems().catch(error => error);
- expect(error.stack).toContain('theSourceOfTheProblems');
- expect(error.message).toContain('ThisCommand.DoesNotExist');
-
- async function theSourceOfTheProblems() {
- // @ts-expect-error invalid command
- await client.send('ThisCommand.DoesNotExist');
- }
- });
+ await Promise.all([
+ client.send('Runtime.enable'),
+ client.send('Runtime.evaluate', { expression: 'window.foo = "bar"' })
+ ]);
+ const foo = await page.evaluate(() => window['foo']);
+ expect(foo).toBe('bar');
});
-browserTest.describe('session', () => {
- browserTest.skip(({ browserName }) => browserName !== 'chromium');
-
- browserTest('should not break page.close()', async function({browser}) {
- const context = await browser.newContext();
- const page = await context.newPage();
- const session = await page.context().newCDPSession(page);
- await session.detach();
- await page.close();
- await context.close();
- });
-
- browserTest('should detach when page closes', async function({browser}) {
- const context = await browser.newContext();
- const page = await context.newPage();
- const session = await context.newCDPSession(page);
- await page.close();
- let error;
- await session.detach().catch(e => error = e);
- expect(error).toBeTruthy();
- await context.close();
- });
-
- browserTest('should work with newBrowserCDPSession', async function({browser}) {
- const session = await browser.newBrowserCDPSession();
-
- const version = await session.send('Browser.getVersion');
- expect(version.userAgent).toBeTruthy();
-
- let gotEvent = false;
- session.on('Target.targetCreated', () => gotEvent = true);
- await session.send('Target.setDiscoverTargets', { discover: true });
- expect(gotEvent).toBe(true);
-
- await session.detach();
- });
+it('should send events', async function({page, server}) {
+ const client = await page.context().newCDPSession(page);
+ await client.send('Network.enable');
+ const events = [];
+ client.on('Network.requestWillBeSent', event => events.push(event));
+ await page.goto(server.EMPTY_PAGE);
+ expect(events.length).toBe(1);
+});
+
+it('should only accept a page', async function({page}) {
+ // @ts-expect-error newCDPSession expects a Page
+ const error = await page.context().newCDPSession(page.context()).catch(e => e);
+ expect(error.message).toContain('page: expected Page');
+});
+
+it('should enable and disable domains independently', async function({page}) {
+ const client = await page.context().newCDPSession(page);
+ await client.send('Runtime.enable');
+ await client.send('Debugger.enable');
+ // JS coverage enables and then disables Debugger domain.
+ await page.coverage.startJSCoverage();
+ await page.coverage.stopJSCoverage();
+ page.on('console', console.log);
+ // generate a script in page and wait for the event.
+ await Promise.all([
+ new Promise(f => client.on('Debugger.scriptParsed', event => {
+ if (event.url === 'foo.js')
+ f();
+ })),
+ page.evaluate('//# sourceURL=foo.js')
+ ]);
+});
+
+it('should be able to detach session', async function({page}) {
+ const client = await page.context().newCDPSession(page);
+ await client.send('Runtime.enable');
+ const evalResponse = await client.send('Runtime.evaluate', {expression: '1 + 2', returnByValue: true});
+ expect(evalResponse.result.value).toBe(3);
+ await client.detach();
+ let error = null;
+ try {
+ await client.send('Runtime.evaluate', {expression: '3 + 1', returnByValue: true});
+ } catch (e) {
+ error = e;
+ }
+ expect(error.message).toContain('Target page, context or browser has been closed');
+});
+
+it('should throw nice errors', async function({page}) {
+ const client = await page.context().newCDPSession(page);
+ const error = await theSourceOfTheProblems().catch(error => error);
+ expect(error.stack).toContain('theSourceOfTheProblems');
+ expect(error.message).toContain('ThisCommand.DoesNotExist');
+
+ async function theSourceOfTheProblems() {
+ // @ts-expect-error invalid command
+ await client.send('ThisCommand.DoesNotExist');
+ }
+});
+
+browserTest('should not break page.close()', async function({browser}) {
+ const context = await browser.newContext();
+ const page = await context.newPage();
+ const session = await page.context().newCDPSession(page);
+ await session.detach();
+ await page.close();
+ await context.close();
+});
+
+browserTest('should detach when page closes', async function({browser}) {
+ const context = await browser.newContext();
+ const page = await context.newPage();
+ const session = await context.newCDPSession(page);
+ await page.close();
+ let error;
+ await session.detach().catch(e => error = e);
+ expect(error).toBeTruthy();
+ await context.close();
+});
+
+browserTest('should work with newBrowserCDPSession', async function({browser}) {
+ const session = await browser.newBrowserCDPSession();
+
+ const version = await session.send('Browser.getVersion');
+ expect(version.userAgent).toBeTruthy();
+
+ let gotEvent = false;
+ session.on('Target.targetCreated', () => gotEvent = true);
+ await session.send('Target.setDiscoverTargets', { discover: true });
+ expect(gotEvent).toBe(true);
+
+ await session.detach();
});
diff --git a/tests/chromium/tracing.spec.ts b/tests/chromium/tracing.spec.ts
index 3e2bf87de3..85b05c4a1f 100644
--- a/tests/chromium/tracing.spec.ts
+++ b/tests/chromium/tracing.spec.ts
@@ -18,79 +18,75 @@ import { browserTest as it, expect } from '../config/browserTest';
import fs from 'fs';
import path from 'path';
-it.describe('tracing', () => {
- it.skip(({ browserName }) => browserName !== 'chromium');
-
- it('should output a trace', async ({browser, server}, testInfo) => {
- const page = await browser.newPage();
- const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
- await browser.startTracing(page, {screenshots: true, path: outputTraceFile});
- await page.goto(server.PREFIX + '/grid.html');
- await browser.stopTracing();
- expect(fs.existsSync(outputTraceFile)).toBe(true);
- await page.close();
- });
-
- it('should create directories as needed', async ({browser, server}, testInfo) => {
- const page = await browser.newPage();
- const filePath = testInfo.outputPath(path.join('these', 'are', 'directories', 'trace.json'));
- await browser.startTracing(page, {screenshots: true, path: filePath});
- await page.goto(server.PREFIX + '/grid.html');
- await browser.stopTracing();
- expect(fs.existsSync(filePath)).toBe(true);
- await page.close();
- });
-
- it('should run with custom categories if provided', async ({browser}, testInfo) => {
- const page = await browser.newPage();
- const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
- await browser.startTracing(page, {path: outputTraceFile, categories: ['disabled-by-default-v8.cpu_profiler.hires']});
- await browser.stopTracing();
-
- const traceJson = JSON.parse(fs.readFileSync(outputTraceFile).toString());
- expect(traceJson.metadata['trace-config']).toContain('disabled-by-default-v8.cpu_profiler.hires');
- await page.close();
- });
-
- it('should throw if tracing on two pages', async ({browser}, testInfo) => {
- const page = await browser.newPage();
- const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
- await browser.startTracing(page, {path: outputTraceFile});
- const newPage = await browser.newPage();
- let error = null;
- await browser.startTracing(newPage, {path: outputTraceFile}).catch(e => error = e);
- await newPage.close();
- expect(error).toBeTruthy();
- await browser.stopTracing();
- await page.close();
- });
-
- it('should return a buffer', async ({browser, server}, testInfo) => {
- const page = await browser.newPage();
- const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
- await browser.startTracing(page, {screenshots: true, path: outputTraceFile});
- await page.goto(server.PREFIX + '/grid.html');
- const trace = await browser.stopTracing();
- const buf = fs.readFileSync(outputTraceFile);
- expect(trace.toString()).toEqual(buf.toString());
- await page.close();
- });
-
- it('should work without options', async ({browser, server}) => {
- const page = await browser.newPage();
- await browser.startTracing(page);
- await page.goto(server.PREFIX + '/grid.html');
- const trace = await browser.stopTracing();
- expect(trace).toBeTruthy();
- await page.close();
- });
-
- it('should support a buffer without a path', async ({browser, server}) => {
- const page = await browser.newPage();
- await browser.startTracing(page, {screenshots: true});
- await page.goto(server.PREFIX + '/grid.html');
- const trace = await browser.stopTracing();
- expect(trace.toString()).toContain('screenshot');
- await page.close();
- });
+it('should output a trace', async ({browser, server}, testInfo) => {
+ const page = await browser.newPage();
+ const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
+ await browser.startTracing(page, {screenshots: true, path: outputTraceFile});
+ await page.goto(server.PREFIX + '/grid.html');
+ await browser.stopTracing();
+ expect(fs.existsSync(outputTraceFile)).toBe(true);
+ await page.close();
+});
+
+it('should create directories as needed', async ({browser, server}, testInfo) => {
+ const page = await browser.newPage();
+ const filePath = testInfo.outputPath(path.join('these', 'are', 'directories', 'trace.json'));
+ await browser.startTracing(page, {screenshots: true, path: filePath});
+ await page.goto(server.PREFIX + '/grid.html');
+ await browser.stopTracing();
+ expect(fs.existsSync(filePath)).toBe(true);
+ await page.close();
+});
+
+it('should run with custom categories if provided', async ({browser}, testInfo) => {
+ const page = await browser.newPage();
+ const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
+ await browser.startTracing(page, {path: outputTraceFile, categories: ['disabled-by-default-v8.cpu_profiler.hires']});
+ await browser.stopTracing();
+
+ const traceJson = JSON.parse(fs.readFileSync(outputTraceFile).toString());
+ expect(traceJson.metadata['trace-config']).toContain('disabled-by-default-v8.cpu_profiler.hires');
+ await page.close();
+});
+
+it('should throw if tracing on two pages', async ({browser}, testInfo) => {
+ const page = await browser.newPage();
+ const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
+ await browser.startTracing(page, {path: outputTraceFile});
+ const newPage = await browser.newPage();
+ let error = null;
+ await browser.startTracing(newPage, {path: outputTraceFile}).catch(e => error = e);
+ await newPage.close();
+ expect(error).toBeTruthy();
+ await browser.stopTracing();
+ await page.close();
+});
+
+it('should return a buffer', async ({browser, server}, testInfo) => {
+ const page = await browser.newPage();
+ const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
+ await browser.startTracing(page, {screenshots: true, path: outputTraceFile});
+ await page.goto(server.PREFIX + '/grid.html');
+ const trace = await browser.stopTracing();
+ const buf = fs.readFileSync(outputTraceFile);
+ expect(trace.toString()).toEqual(buf.toString());
+ await page.close();
+});
+
+it('should work without options', async ({browser, server}) => {
+ const page = await browser.newPage();
+ await browser.startTracing(page);
+ await page.goto(server.PREFIX + '/grid.html');
+ const trace = await browser.stopTracing();
+ expect(trace).toBeTruthy();
+ await page.close();
+});
+
+it('should support a buffer without a path', async ({browser, server}) => {
+ const page = await browser.newPage();
+ await browser.startTracing(page, {screenshots: true});
+ await page.goto(server.PREFIX + '/grid.html');
+ const trace = await browser.stopTracing();
+ expect(trace.toString()).toContain('screenshot');
+ await page.close();
});
diff --git a/tests/config/android.config.ts b/tests/config/android.config.ts
index f78eed7de4..0fe774bbaf 100644
--- a/tests/config/android.config.ts
+++ b/tests/config/android.config.ts
@@ -17,7 +17,7 @@
import * as folio from 'folio';
import * as path from 'path';
import { test as pageTest } from '../page/pageTest';
-import { AndroidEnv } from './androidTest';
+import { AndroidEnv } from '../android/androidTest';
import type { BrowserContext } from '../../index';
import { PlaywrightEnvOptions } from './browserTest';
import { CommonOptions } from './baseTest';
diff --git a/tests/config/default.config.ts b/tests/config/default.config.ts
index 711715c991..433e5ec34a 100644
--- a/tests/config/default.config.ts
+++ b/tests/config/default.config.ts
@@ -95,14 +95,17 @@ const config: folio.Config = {
projects: [],
};
-for (const browserName of ['chromium', 'webkit', 'firefox'] as BrowserName[]) {
+const browserNames = ['chromium', 'webkit', 'firefox'] as BrowserName[];
+for (const browserName of browserNames) {
const executablePath = getExecutablePath(browserName);
if (executablePath && (process.env.FOLIO_WORKER_INDEX === undefined || process.env.FOLIO_WORKER_INDEX === ''))
console.error(`Using executable at ${executablePath}`);
+ const testIgnore: RegExp[] = browserNames.filter(b => b !== browserName).map(b => new RegExp(b));
+ testIgnore.push(/android/, /electron/);
config.projects.push({
name: browserName,
testDir,
- testIgnore: [/android/, /electron/],
+ testIgnore,
options: {
mode: (process.env.PWTEST_MODE || 'default') as ('default' | 'driver' | 'service'),
browserName,
diff --git a/tests/config/electron.config.ts b/tests/config/electron.config.ts
index 6f5cf32343..3babc06902 100644
--- a/tests/config/electron.config.ts
+++ b/tests/config/electron.config.ts
@@ -16,7 +16,7 @@
import * as folio from 'folio';
import * as path from 'path';
-import { ElectronEnv } from './electronTest';
+import { ElectronEnv } from '../electron/electronTest';
import { test as pageTest } from '../page/pageTest';
import { PlaywrightEnvOptions } from './browserTest';
import { CommonOptions } from './baseTest';
diff --git a/tests/config/electron-app.js b/tests/electron/electron-app.js
similarity index 100%
rename from tests/config/electron-app.js
rename to tests/electron/electron-app.js
diff --git a/tests/electron/electron-app.spec.ts b/tests/electron/electron-app.spec.ts
index 1c07c78d7a..6ceed9f54d 100644
--- a/tests/electron/electron-app.spec.ts
+++ b/tests/electron/electron-app.spec.ts
@@ -16,11 +16,12 @@
import type { BrowserWindow } from 'electron';
import path from 'path';
-import { electronTest as test, baseElectronTest as baseTest, expect } from '../config/electronTest';
+import { electronTest as test, expect } from './electronTest';
+import { baseTest } from '../config/baseTest';
baseTest('should fire close event', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
- args: [path.join(__dirname, '..', 'config', 'electron-app.js')],
+ args: [path.join(__dirname, 'electron-app.js')],
});
const events = [];
electronApp.on('close', () => events.push('application'));
@@ -34,7 +35,7 @@ baseTest('should fire close event', async ({ playwright }) => {
test('should script application', async ({ electronApp }) => {
const appPath = await electronApp.evaluate(async ({ app }) => app.getAppPath());
- expect(appPath).toBe(path.resolve(__dirname, '..', 'config'));
+ expect(appPath).toBe(path.resolve(__dirname));
});
test('should return windows', async ({ electronApp, newWindow }) => {
@@ -92,14 +93,14 @@ test('should have a clipboard instance', async ({ electronApp }) => {
test('should test app that opens window fast', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
- args: [path.join(__dirname, '..', 'config', 'electron-window-app.js')],
+ args: [path.join(__dirname, 'electron-window-app.js')],
});
await electronApp.close();
});
test('should return browser window', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
- args: [path.join(__dirname, '..', 'config', 'electron-window-app.js')],
+ args: [path.join(__dirname, 'electron-window-app.js')],
});
const page = await electronApp.waitForEvent('window');
const bwHandle = await electronApp.browserWindow(page);
diff --git a/tests/config/electron-window-app.js b/tests/electron/electron-window-app.js
similarity index 100%
rename from tests/config/electron-window-app.js
rename to tests/electron/electron-window-app.js
diff --git a/tests/electron/electron-window.spec.ts b/tests/electron/electron-window.spec.ts
index 7fb4982a7a..14b5256335 100644
--- a/tests/electron/electron-window.spec.ts
+++ b/tests/electron/electron-window.spec.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { electronTest as test, expect } from '../config/electronTest';
+import { electronTest as test, expect } from './electronTest';
test('should click the button', async ({newWindow, server}) => {
const window = await newWindow();
diff --git a/tests/config/electronTest.ts b/tests/electron/electronTest.ts
similarity index 96%
rename from tests/config/electronTest.ts
rename to tests/electron/electronTest.ts
index cd749f8827..2bd92e30c0 100644
--- a/tests/config/electronTest.ts
+++ b/tests/electron/electronTest.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { baseTest, CommonArgs } from './baseTest';
+import { baseTest, CommonArgs } from '../config/baseTest';
import { ElectronApplication, Page } from '../../index';
import * as folio from 'folio';
import * as path from 'path';
@@ -79,5 +79,4 @@ export class ElectronEnv {
}
}
-export const baseElectronTest = baseTest;
export const electronTest = baseTest.extend(new ElectronEnv());
diff --git a/tests/firefox/launcher.spec.ts b/tests/firefox/launcher.spec.ts
index adc7741d44..2b53c4c2f3 100644
--- a/tests/firefox/launcher.spec.ts
+++ b/tests/firefox/launcher.spec.ts
@@ -17,8 +17,6 @@
import { playwrightTest as it, expect } from '../config/browserTest';
it('should pass firefox user preferences', async ({browserType, browserOptions, browserName}) => {
- it.skip(browserName !== 'firefox');
-
const browser = await browserType.launch({
...browserOptions,
firefoxUserPrefs: {
diff --git a/tests/cli/cli-codegen-1.spec.ts b/tests/inspector/cli-codegen-1.spec.ts
similarity index 98%
rename from tests/cli/cli-codegen-1.spec.ts
rename to tests/inspector/cli-codegen-1.spec.ts
index 59fb37c1bb..1f46510a0c 100644
--- a/tests/cli/cli-codegen-1.spec.ts
+++ b/tests/inspector/cli-codegen-1.spec.ts
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-import { cliTest as test, expect } from '../config/cliTest';
-import * as http from 'http';
+import { test, expect } from './inspectorTest';
test.describe('cli codegen', () => {
test.skip(({ mode }) => mode !== 'default');
@@ -58,14 +57,14 @@ await page.ClickAsync("text=Submit");`);
expect(message.text()).toBe('click');
});
- test('should click after same-document navigation', async ({ page, openRecorder, httpServer }) => {
+ test('should click after same-document navigation', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
- httpServer.setHandler((req: http.IncomingMessage, res: http.ServerResponse) => {
+ server.setRoute('/foo.html', (req, res) => {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.end('');
});
- await recorder.setContentAndWait(``, httpServer.PREFIX + '/foo.html');
+ await recorder.setContentAndWait(``, server.PREFIX + '/foo.html');
await Promise.all([
page.waitForNavigation(),
page.evaluate(() => history.pushState({}, '', '/url.html')),
diff --git a/tests/cli/cli-codegen-2.spec.ts b/tests/inspector/cli-codegen-2.spec.ts
similarity index 95%
rename from tests/cli/cli-codegen-2.spec.ts
rename to tests/inspector/cli-codegen-2.spec.ts
index f83e3699b9..12f0019133 100644
--- a/tests/cli/cli-codegen-2.spec.ts
+++ b/tests/inspector/cli-codegen-2.spec.ts
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-import { cliTest as test, expect } from '../config/cliTest';
-import * as http from 'http';
+import { test, expect } from './inspectorTest';
import * as url from 'url';
test.describe('cli codegen', () => {
@@ -228,10 +227,10 @@ await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { });`);
});
- test('should download files', async ({ page, openRecorder, httpServer }) => {
+ test('should download files', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
- httpServer.setHandler((req: http.IncomingMessage, res: http.ServerResponse) => {
+ server.setRoute('/download', (req, res) => {
const pathName = url.parse(req.url!).path;
if (pathName === '/download') {
res.setHeader('Content-Type', 'application/octet-stream');
@@ -243,8 +242,8 @@ await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { });`);
}
});
await recorder.setContentAndWait(`
- Download
- `, httpServer.PREFIX);
+ Download
+ `, server.PREFIX);
await recorder.hoverOverElement('text=Download');
await Promise.all([
page.waitForEvent('download'),
@@ -338,23 +337,19 @@ await page.ClickAsync(\"text=click me\");`);
});
- test('should handle history.postData', async ({ page, openRecorder, httpServer }) => {
+ test('should handle history.postData', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
- httpServer.setHandler((req: http.IncomingMessage, res: http.ServerResponse) => {
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
- res.end('Hello world');
- });
await recorder.setContentAndWait(`
`, httpServer.PREFIX);
+ `, server.PREFIX);
for (let i = 1; i < 3; ++i) {
await page.evaluate('pushState()');
- await recorder.waitForOutput('', `await page.goto('${httpServer.PREFIX}/#seqNum=${i}');`);
+ await recorder.waitForOutput('', `await page.goto('${server.PREFIX}/#seqNum=${i}');`);
}
});
@@ -581,23 +576,23 @@ await page.GetFrame(name: \"two\").ClickAsync(\"text=Hi, I'm frame\");`);
await page.GetFrame(url: \"http://localhost:${server.PORT}/frames/frame.html\").ClickAsync(\"text=Hi, I'm frame\");`);
});
- test('should record navigations after identical pushState', async ({ page, openRecorder, httpServer }) => {
+ test('should record navigations after identical pushState', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
- httpServer.setHandler((req: http.IncomingMessage, res: http.ServerResponse) => {
+ server.setRoute('/page2.html', (req, res) => {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.end('Hello world');
});
await recorder.setContentAndWait(`
`, httpServer.PREFIX);
+ `, server.PREFIX);
for (let i = 1; i < 3; ++i)
await page.evaluate('pushState()');
- await page.goto(httpServer.PREFIX + '/page2.html');
- await recorder.waitForOutput('', `await page.goto('${httpServer.PREFIX}/page2.html');`);
+ await page.goto(server.PREFIX + '/page2.html');
+ await recorder.waitForOutput('', `await page.goto('${server.PREFIX}/page2.html');`);
});
test('should record slow navigation signal after mouse move', async ({ page, openRecorder, server }) => {
diff --git a/tests/cli/cli-codegen-csharp.spec.ts b/tests/inspector/cli-codegen-csharp.spec.ts
similarity index 98%
rename from tests/cli/cli-codegen-csharp.spec.ts
rename to tests/inspector/cli-codegen-csharp.spec.ts
index e752de0df3..fbdbef867e 100644
--- a/tests/cli/cli-codegen-csharp.spec.ts
+++ b/tests/inspector/cli-codegen-csharp.spec.ts
@@ -16,7 +16,7 @@
import path from 'path';
import fs from 'fs';
-import { cliTest as test, expect } from '../config/cliTest';
+import { test, expect } from './inspectorTest';
const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
const launchOptions = (channel: string) => {
diff --git a/tests/cli/cli-codegen-java.spec.ts b/tests/inspector/cli-codegen-java.spec.ts
similarity index 98%
rename from tests/cli/cli-codegen-java.spec.ts
rename to tests/inspector/cli-codegen-java.spec.ts
index 75d6cb35a1..2cbb29577a 100644
--- a/tests/cli/cli-codegen-java.spec.ts
+++ b/tests/inspector/cli-codegen-java.spec.ts
@@ -16,7 +16,7 @@
import fs from 'fs';
import path from 'path';
-import { cliTest as test, expect } from '../config/cliTest';
+import { test, expect } from './inspectorTest';
const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
const launchOptions = (channel: string) => {
diff --git a/tests/cli/cli-codegen-javascript.spec.ts b/tests/inspector/cli-codegen-javascript.spec.ts
similarity index 98%
rename from tests/cli/cli-codegen-javascript.spec.ts
rename to tests/inspector/cli-codegen-javascript.spec.ts
index d64ed99c02..acb9f1e8e8 100644
--- a/tests/cli/cli-codegen-javascript.spec.ts
+++ b/tests/inspector/cli-codegen-javascript.spec.ts
@@ -16,7 +16,7 @@
import fs from 'fs';
import path from 'path';
-import { cliTest as test, expect } from '../config/cliTest';
+import { test, expect } from './inspectorTest';
const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
diff --git a/tests/cli/cli-codegen-python-async.spec.ts b/tests/inspector/cli-codegen-python-async.spec.ts
similarity index 98%
rename from tests/cli/cli-codegen-python-async.spec.ts
rename to tests/inspector/cli-codegen-python-async.spec.ts
index d17db779eb..a740130678 100644
--- a/tests/cli/cli-codegen-python-async.spec.ts
+++ b/tests/inspector/cli-codegen-python-async.spec.ts
@@ -16,7 +16,7 @@
import fs from 'fs';
import path from 'path';
-import { cliTest as test, expect } from '../config/cliTest';
+import { test, expect } from './inspectorTest';
const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
const launchOptions = (channel: string) => {
diff --git a/tests/cli/cli-codegen-python.spec.ts b/tests/inspector/cli-codegen-python.spec.ts
similarity index 98%
rename from tests/cli/cli-codegen-python.spec.ts
rename to tests/inspector/cli-codegen-python.spec.ts
index 0fbd53d99c..2ad7cb8b3b 100644
--- a/tests/cli/cli-codegen-python.spec.ts
+++ b/tests/inspector/cli-codegen-python.spec.ts
@@ -16,7 +16,7 @@
import fs from 'fs';
import path from 'path';
-import { cliTest as test, expect } from '../config/cliTest';
+import { test, expect } from './inspectorTest';
const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
const launchOptions = (channel: string) => {
diff --git a/tests/config/cliTest.ts b/tests/inspector/inspectorTest.ts
similarity index 89%
rename from tests/config/cliTest.ts
rename to tests/inspector/inspectorTest.ts
index e9f6877839..33b9284226 100644
--- a/tests/config/cliTest.ts
+++ b/tests/inspector/inspectorTest.ts
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-import { contextTest } from './browserTest';
+import { contextTest } from '../config/browserTest';
import type { Page } from '../../index';
-import * as http from 'http';
import * as path from 'path';
import type { Source } from '../../src/server/supplements/recorder/recorderTypes';
import { ChildProcess, spawn } from 'child_process';
@@ -24,23 +23,15 @@ import { chromium } from '../../index';
import * as folio from 'folio';
export { expect } from 'folio';
-interface CLIHTTPServer {
- setHandler: (handler: http.RequestListener) => void;
- PREFIX: string;
-}
-
type CLITestArgs = {
- httpServer: CLIHTTPServer;
recorderPageGetter: () => Promise;
openRecorder: () => Promise;
runCLI: (args: string[]) => CLIMock;
};
-export const cliTest = contextTest.extend({
+export const test = contextTest.extend({
async beforeAll({}, workerInfo: folio.WorkerInfo) {
- this._port = 10907 + workerInfo.workerIndex * 2;
- this._server = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => this._handler(req, res)).listen(this._port);
- process.env.PWTEST_RECORDER_PORT = String(this._port + 1);
+ process.env.PWTEST_RECORDER_PORT = String(10907 + workerInfo.workerIndex);
},
async beforeEach({ page, context, toImpl, browserName, browserChannel, headful, mode }, testInfo: folio.TestInfo): Promise {
@@ -54,10 +45,6 @@ export const cliTest = contextTest.extend({
return c.pages()[0] || await c.waitForEvent('page');
};
return {
- httpServer: {
- setHandler: newHandler => this._handler = newHandler,
- PREFIX: `http://127.0.0.1:${this._port}`,
- },
runCLI: (cliArgs: string[]) => {
this._cli = new CLIMock(browserName, browserChannel, !headful, cliArgs);
return this._cli;
@@ -76,13 +63,6 @@ export const cliTest = contextTest.extend({
this._cli = undefined;
}
},
-
- async afterAll({}, workerInfo: folio.WorkerInfo) {
- if (this._server) {
- this._server.close();
- this._server = undefined;
- }
- },
});
class Recorder {
diff --git a/tests/pause.spec.ts b/tests/inspector/pause.spec.ts
similarity index 99%
rename from tests/pause.spec.ts
rename to tests/inspector/pause.spec.ts
index df50e17766..9799c4dd5e 100644
--- a/tests/pause.spec.ts
+++ b/tests/inspector/pause.spec.ts
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-import { Page } from '../index';
-import { cliTest as it, expect } from './config/cliTest';
+import { Page } from '../../index';
+import { test as it, expect } from './inspectorTest';
it.describe('pause', () => {
it.skip(({ mode }) => mode !== 'default');