test: cleanup tests and configs after last folio update (#6463)

This commit is contained in:
Dmitry Gozman 2021-05-08 17:45:04 -07:00 committed by GitHub
parent a9523d9d8f
commit 2d4538c23d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 864 additions and 942 deletions

View file

@ -15,7 +15,7 @@
*/ */
import type { AndroidDevice } from '../../index'; import type { AndroidDevice } from '../../index';
import { CommonArgs, baseTest } from './baseTest'; import { CommonArgs, baseTest } from '../config/baseTest';
import * as folio from 'folio'; import * as folio from 'folio';
export { expect } from 'folio'; export { expect } from 'folio';

View file

@ -14,7 +14,7 @@
* limitations under the License. * 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 }) { test('androidDevice.model', async function({ androidDevice }) {
expect(androidDevice.model()).toBe('sdk_gphone_x86_arm'); expect(androidDevice.model()).toBe('sdk_gphone_x86_arm');

View file

@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import { PNG } from 'pngjs'; 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 }) { test('androidDevice.shell', async function({ androidDevice }) {
const output = await androidDevice.shell('echo 123'); const output = await androidDevice.shell('echo 123');

View file

@ -14,7 +14,7 @@
* limitations under the License. * 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 }) { test('androidDevice.webView', async function({ androidDevice }) {
expect(androidDevice.webViews().length).toBe(0); expect(androidDevice.webViews().length).toBe(0);

View file

@ -19,228 +19,222 @@ import { contextTest as test, expect } from '../config/browserTest';
import { playwrightTest } from '../config/browserTest'; import { playwrightTest } from '../config/browserTest';
import http from 'http'; import http from 'http';
test.describe('chromium', () => { test('should create a worker from a service worker', async ({page, server}) => {
test.skip(({ browserName }) => browserName !== 'chromium'); 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(`
<script>
document.write('<script src="${server.CROSS_PROCESS_PREFIX}/intervention.js">' + '</scr' + 'ipt>');
</script>
`));
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([ const [worker] = await Promise.all([
page.context().waitForEvent('serviceworker'), context.waitForEvent('serviceworker'),
page.goto(server.PREFIX + '/serviceworkers/empty/sw.html') page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
]); ]);
expect(await worker.evaluate(() => self.toString())).toBe('[object ServiceWorkerGlobalScope]'); expect(await worker.evaluate(() => self.toString())).toBe('[object ServiceWorkerGlobalScope]');
}); await cdpBrowser1.close();
test('serviceWorkers() should return current workers', async ({page, server}) => { const cdpBrowser2 = await browserType.connectOverCDP({
const context = page.context(); endpointURL: `http://localhost:${port}`,
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(); const context2 = cdpBrowser2.contexts()[0];
}); expect(context2.serviceWorkers().length).toBe(1);
await cdpBrowser2.close();
test('Page.route should work with intervention headers', async ({server, page}) => { } finally {
server.setRoute('/intervention', (req, res) => res.end(` await browserServer.close();
<script> }
document.write('<script src="${server.CROSS_PROCESS_PREFIX}/intervention.js">' + '</scr' + 'ipt>');
</script>
`));
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.describe('chromium', () => { playwrightTest('should connect over a ws endpoint', async ({browserType, browserOptions, server}, testInfo) => {
playwrightTest.skip(({ browserName }) => browserName !== 'chromium'); const port = 9339 + testInfo.workerIndex;
const browserServer = await browserType.launch({
playwrightTest('should close service worker together with the context', async ({browserType, browserOptions, server}) => { ...browserOptions,
const browser = await browserType.launch(browserOptions); args: ['--remote-debugging-port=' + port]
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();
}); });
try {
playwrightTest('should connect to an existing cdp session', async ({ browserType, browserOptions }, testInfo) => { const json = await new Promise<string>((resolve, reject) => {
const port = 9339 + testInfo.workerIndex; http.get(`http://localhost:${port}/json/version/`, resp => {
const browserServer = await browserType.launch({ let data = '';
...browserOptions, resp.on('data', chunk => data += chunk);
args: ['--remote-debugging-port=' + port] resp.on('end', () => resolve(data));
}).on('error', reject);
}); });
try { const cdpBrowser = await browserType.connectOverCDP({
const cdpBrowser = await browserType.connectOverCDP({ endpointURL: JSON.parse(json).webSocketDebuggerUrl,
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 contexts = cdpBrowser.contexts();
const cdpBrowser1 = await browserType.connectOverCDP({ expect(contexts.length).toBe(1);
endpointURL: `http://localhost:${port}/`, await cdpBrowser.close();
});
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(); // also connect with the depercreated wsEndpoint option
expect(contexts2.length).toBe(1); const cdpBrowser2 = await browserType.connectOverCDP({
const [context2] = contexts2; wsEndpoint: JSON.parse(json).webSocketDebuggerUrl,
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 contexts2 = cdpBrowser.contexts();
const cdpBrowser1 = await browserType.connectOverCDP({ expect(contexts2.length).toBe(1);
endpointURL: `http://localhost:${port}`, await cdpBrowser2.close();
}); } finally {
const context = cdpBrowser1.contexts()[0]; await browserServer.close();
const page = await cdpBrowser1.contexts()[0].newPage(); }
const [worker] = await Promise.all([ });
context.waitForEvent('serviceworker'),
page.goto(server.PREFIX + '/serviceworkers/empty/sw.html') playwrightTest('should send extra headers with connect request', async ({browserType, browserOptions, server}, testInfo) => {
]); {
expect(await worker.evaluate(() => self.toString())).toBe('[object ServiceWorkerGlobalScope]'); const [request] = await Promise.all([
await cdpBrowser1.close(); server.waitForWebSocketConnectionRequest(),
browserType.connectOverCDP({
const cdpBrowser2 = await browserType.connectOverCDP({ wsEndpoint: `ws://localhost:${server.PORT}/ws`,
endpointURL: `http://localhost:${port}`, headers: {
}); 'User-Agent': 'Playwright',
const context2 = cdpBrowser2.contexts()[0]; 'foo': 'bar',
expect(context2.serviceWorkers().length).toBe(1); }
await cdpBrowser2.close(); }).catch(() => {})
} finally { ]);
await browserServer.close(); expect(request.headers['user-agent']).toBe('Playwright');
} expect(request.headers['foo']).toBe('bar');
}); }
playwrightTest('should connect over a ws endpoint', async ({browserType, browserOptions, server}, testInfo) => { {
const port = 9339 + testInfo.workerIndex; const [request] = await Promise.all([
const browserServer = await browserType.launch({ server.waitForWebSocketConnectionRequest(),
...browserOptions, browserType.connectOverCDP({
args: ['--remote-debugging-port=' + port] endpointURL: `ws://localhost:${server.PORT}/ws`,
}); headers: {
try { 'User-Agent': 'Playwright',
const json = await new Promise<string>((resolve, reject) => { 'foo': 'bar',
http.get(`http://localhost:${port}/json/version/`, resp => { }
let data = ''; }).catch(() => {})
resp.on('data', chunk => data += chunk); ]);
resp.on('end', () => resolve(data)); expect(request.headers['user-agent']).toBe('Playwright');
}).on('error', reject); expect(request.headers['foo']).toBe('bar');
}); }
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');
}
});
}); });

View file

@ -16,123 +16,119 @@
import { contextTest as it, expect } from '../config/browserTest'; import { contextTest as it, expect } from '../config/browserTest';
it.describe('CSS Coverage', () => { it('should work', async function({page, server}) {
it.skip(({ browserName }) => browserName !== 'chromium'); await page.coverage.startCSSCoverage();
await page.goto(server.PREFIX + '/csscoverage/simple.html');
it('should work', async function({page, server}) { const coverage = await page.coverage.stopCSSCoverage();
await page.coverage.startCSSCoverage(); expect(coverage.length).toBe(1);
await page.goto(server.PREFIX + '/csscoverage/simple.html'); expect(coverage[0].url).toContain('/csscoverage/simple.html');
const coverage = await page.coverage.stopCSSCoverage(); expect(coverage[0].ranges).toEqual([
expect(coverage.length).toBe(1); {start: 1, end: 22}
expect(coverage[0].url).toContain('/csscoverage/simple.html'); ]);
expect(coverage[0].ranges).toEqual([ const range = coverage[0].ranges[0];
{start: 1, end: 22} expect(coverage[0].text.substring(range.start, range.end)).toBe('div { color: green; }');
]); });
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');
it('should report sourceURLs', async function({page, server}) { const coverage = await page.coverage.stopCSSCoverage();
await page.coverage.startCSSCoverage(); expect(coverage.length).toBe(1);
await page.goto(server.PREFIX + '/csscoverage/sourceurl.html'); expect(coverage[0].url).toBe('nicename.css');
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');
it('should report multiple stylesheets', async function({page, server}) { const coverage = await page.coverage.stopCSSCoverage();
await page.coverage.startCSSCoverage(); expect(coverage.length).toBe(2);
await page.goto(server.PREFIX + '/csscoverage/multiple.html'); coverage.sort((a, b) => a.url.localeCompare(b.url));
const coverage = await page.coverage.stopCSSCoverage(); expect(coverage[0].url).toContain('/csscoverage/stylesheet1.css');
expect(coverage.length).toBe(2); expect(coverage[1].url).toContain('/csscoverage/stylesheet2.css');
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');
it('should report stylesheets that have no coverage', async function({page, server}) { const coverage = await page.coverage.stopCSSCoverage();
await page.coverage.startCSSCoverage(); expect(coverage.length).toBe(1);
await page.goto(server.PREFIX + '/csscoverage/unused.html'); expect(coverage[0].url).toBe('unused.css');
const coverage = await page.coverage.stopCSSCoverage(); expect(coverage[0].ranges.length).toBe(0);
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');
it('should work with media queries', async function({page, server}) { const coverage = await page.coverage.stopCSSCoverage();
await page.coverage.startCSSCoverage(); expect(coverage.length).toBe(1);
await page.goto(server.PREFIX + '/csscoverage/media.html'); expect(coverage[0].url).toContain('/csscoverage/media.html');
const coverage = await page.coverage.stopCSSCoverage(); expect(coverage[0].ranges).toEqual([
expect(coverage.length).toBe(1); {start: 17, end: 38}
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');
it('should work with complicated usecases', async function({page, server}) { const coverage: any = await page.coverage.stopCSSCoverage();
await page.coverage.startCSSCoverage(); delete coverage[0].text;
await page.goto(server.PREFIX + '/csscoverage/involved.html'); delete coverage[0].url;
const coverage: any = await page.coverage.stopCSSCoverage(); expect(coverage).toEqual(
delete coverage[0].text; [
delete coverage[0].url; {
expect(coverage).toEqual( 'ranges': [
[ {
{ 'start': 149,
'ranges': [ 'end': 297
{ },
'start': 149, {
'end': 297 'start': 327,
}, 'end': 433
{ }
'start': 327, ]
'end': 433 }
} ]
] );
} });
]
); it('should ignore injected stylesheets', async function({page, server}) {
}); await page.coverage.startCSSCoverage();
await page.addStyleTag({content: 'body { margin: 10px;}'});
it('should ignore injected stylesheets', async function({page, server}) { // trigger style recalc
await page.coverage.startCSSCoverage(); const margin = await page.evaluate(() => window.getComputedStyle(document.body).margin);
await page.addStyleTag({content: 'body { margin: 10px;}'}); expect(margin).toBe('10px');
// trigger style recalc const coverage = await page.coverage.stopCSSCoverage();
const margin = await page.evaluate(() => window.getComputedStyle(document.body).margin); expect(coverage.length).toBe(0);
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');
it('should report stylesheets across navigations', async function({page, server}) { await page.goto(server.EMPTY_PAGE);
await page.coverage.startCSSCoverage({resetOnNavigation: false}); const coverage = await page.coverage.stopCSSCoverage();
await page.goto(server.PREFIX + '/csscoverage/multiple.html'); expect(coverage.length).toBe(2);
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');
it('should NOT report scripts across navigations', async function({page, server}) { await page.goto(server.EMPTY_PAGE);
await page.coverage.startCSSCoverage(); // Enabled by default. const coverage = await page.coverage.stopCSSCoverage();
await page.goto(server.PREFIX + '/csscoverage/multiple.html'); expect(coverage.length).toBe(0);
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 => {
it('should work with a recently loaded stylesheet', async function({page, server}) { document.body.textContent = 'hello, world';
await page.coverage.startCSSCoverage();
await page.evaluate(async url => { const link = document.createElement('link');
document.body.textContent = 'hello, world'; link.rel = 'stylesheet';
link.href = url;
const link = document.createElement('link'); document.head.appendChild(link);
link.rel = 'stylesheet'; await new Promise(x => link.onload = x);
link.href = url; await new Promise(f => requestAnimationFrame(f));
document.head.appendChild(link); }, server.PREFIX + '/csscoverage/stylesheet1.css');
await new Promise(x => link.onload = x); const coverage = await page.coverage.stopCSSCoverage();
await new Promise(f => requestAnimationFrame(f)); expect(coverage.length).toBe(1);
}, server.PREFIX + '/csscoverage/stylesheet1.css');
const coverage = await page.coverage.stopCSSCoverage();
expect(coverage.length).toBe(1);
});
}); });

View file

@ -16,73 +16,69 @@
import { contextTest as it, expect } from '../config/browserTest'; import { contextTest as it, expect } from '../config/browserTest';
it.describe('JS Coverage', () => { it('should work', async function({page, server}) {
it.skip(({ browserName }) => browserName !== 'chromium'); await page.coverage.startJSCoverage();
await page.goto(server.PREFIX + '/jscoverage/simple.html', { waitUntil: 'load' });
it('should work', async function({page, server}) { const coverage = await page.coverage.stopJSCoverage();
await page.coverage.startJSCoverage(); expect(coverage.length).toBe(1);
await page.goto(server.PREFIX + '/jscoverage/simple.html', { waitUntil: 'load' }); expect(coverage[0].url).toContain('/jscoverage/simple.html');
const coverage = await page.coverage.stopJSCoverage(); expect(coverage[0].functions.find(f => f.functionName === 'foo').ranges[0].count).toEqual(1);
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');
it('should report sourceURLs', async function({page, server}) { const coverage = await page.coverage.stopJSCoverage();
await page.coverage.startJSCoverage(); expect(coverage.length).toBe(1);
await page.goto(server.PREFIX + '/jscoverage/sourceurl.html'); expect(coverage[0].url).toBe('nicename.js');
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');
it('should ignore eval() scripts by default', async function({page, server}) { const coverage = await page.coverage.stopJSCoverage();
await page.coverage.startJSCoverage(); expect(coverage.length).toBe(1);
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');
it('shouldn\'t ignore eval() scripts if reportAnonymousScripts is true', async function({page, server}) { const coverage = await page.coverage.stopJSCoverage();
await page.coverage.startJSCoverage({reportAnonymousScripts: true}); expect(coverage.find(entry => entry.url === '').source).toBe('console.log("foo")');
await page.goto(server.PREFIX + '/jscoverage/eval.html'); expect(coverage.length).toBe(2);
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');
it('should report multiple scripts', async function({page, server}) { const coverage = await page.coverage.stopJSCoverage();
await page.coverage.startJSCoverage(); expect(coverage.length).toBe(2);
await page.goto(server.PREFIX + '/jscoverage/multiple.html'); coverage.sort((a, b) => a.url.localeCompare(b.url));
const coverage = await page.coverage.stopJSCoverage(); expect(coverage[0].url).toContain('/jscoverage/script1.js');
expect(coverage.length).toBe(2); expect(coverage[1].url).toContain('/jscoverage/script2.js');
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');
it('should report scripts across navigations when disabled', async function({page, server}) { await page.goto(server.EMPTY_PAGE);
await page.coverage.startJSCoverage({resetOnNavigation: false}); const coverage = await page.coverage.stopJSCoverage();
await page.goto(server.PREFIX + '/jscoverage/multiple.html'); expect(coverage.length).toBe(2);
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');
it('should NOT report scripts across navigations when enabled', async function({page, server}) { await page.goto(server.EMPTY_PAGE);
await page.coverage.startJSCoverage(); // Enabled by default. const coverage = await page.coverage.stopJSCoverage();
await page.goto(server.PREFIX + '/jscoverage/multiple.html'); expect(coverage.length).toBe(0);
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);
it('should not hang when there is a debugger statement', async function({page, server}) { await page.evaluate(() => {
await page.coverage.startJSCoverage(); debugger; // eslint-disable-line no-debugger
await page.goto(server.EMPTY_PAGE); });
await page.evaluate(() => { await page.coverage.stopJSCoverage();
debugger; // eslint-disable-line no-debugger
});
await page.coverage.stopJSCoverage();
});
}); });

View file

@ -16,8 +16,6 @@
import { playwrightTest as it, expect } from '../config/browserTest'; 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('should throw with remote-debugging-pipe argument', async ({browserType, browserOptions, mode}) => {
it.skip(mode !== 'default'); it.skip(mode !== 'default');

View file

@ -14,307 +14,282 @@
* limitations under the License. * limitations under the License.
*/ */
import { playwrightTest, expect } from '../config/browserTest'; import { contextTest as it, expect } from '../config/browserTest';
import type { Page } from '../../index';
const it = playwrightTest.extend({ it.useOptions({ launchOptions: { args: ['--site-per-process'] } });
async beforeAll({ browserType, browserOptions, browserName }) {
const browser = await browserType.launch({ it('should report oopif frames', async function({page, browser, server}) {
...browserOptions, await page.goto(server.PREFIX + '/dynamic-oopif.html');
args: browserName === 'chromium' ? (browserOptions.args || []).concat(['--site-per-process']) : browserOptions.args, expect(await countOOPIFs(browser)).toBe(1);
}); expect(page.frames().length).toBe(2);
this.browser = browser; expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html');
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.describe('oopif', () => { it('should handle oopif detach', async function({page, browser, server}) {
it.skip(({ browserName }) => browserName !== 'chromium'); 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}) { it('should handle remote -> local -> remote transitions', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html'); await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(await countOOPIFs(browser)).toBe(1); expect(page.frames().length).toBe(2);
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'); 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}) { it('should emulate media', async ({page, browser, server}) => {
await page.goto(server.PREFIX + '/dynamic-oopif.html'); await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(await countOOPIFs(browser)).toBe(1); expect(page.frames().length).toBe(2);
expect(page.frames().length).toBe(2); expect(await countOOPIFs(browser)).toBe(1);
const frame = page.frames()[1]; const oopif = page.frames()[1];
expect(await frame.evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html'); expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
const [detachedFrame] = await Promise.all([ await page.emulateMedia({ colorScheme: 'dark' });
page.waitForEvent('framedetached'), expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
page.evaluate(() => document.querySelector('iframe').remove()), });
]);
expect(detachedFrame).toBe(frame); 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 lEst 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}) { it('should take screenshot', async ({page, browser, server}) => {
await page.goto(server.PREFIX + '/dynamic-oopif.html'); await page.setViewportSize({width: 500, height: 500});
expect(page.frames().length).toBe(2); 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'); expect(await countOOPIFs(browser)).toBe(1);
await Promise.all([ expect(await page.screenshot()).toMatchSnapshot('screenshot-oopif.png', { threshold: 0.3 });
page.frames()[1].waitForNavigation(), });
page.evaluate('goLocal()'),
]); it('should load oopif iframes with subresources and route', async function({page, browser, server}) {
expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.PREFIX + '/grid.html'); await page.route('**/*', route => route.continue());
expect(await countOOPIFs(browser)).toBe(0); await page.goto(server.PREFIX + '/dynamic-oopif.html');
await Promise.all([ expect(await countOOPIFs(browser)).toBe(1);
page.frames()[1].waitForNavigation(), });
page.evaluate('goRemote()'),
]); it('should report main requests', async function({page, browser, server}) {
expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html'); const requestFrames = [];
expect(await countOOPIFs(browser)).toBe(1); 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(() => {
it('should get the proper viewport', async ({page, browser, server}) => { const frame = document.createElement('iframe');
it.fixme(); frame.setAttribute('src', 'https://google.com/');
document.body.appendChild(frame);
expect(page.viewportSize()).toEqual({width: 1280, height: 720}); return new Promise(x => frame.onload = x);
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.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}) => { it('ElementHandle.boundingBox() should work', async function({page, browser, server}) {
await page.goto(server.PREFIX + '/dynamic-oopif.html'); await page.goto(server.PREFIX + '/dynamic-oopif.html');
expect(page.frames().length).toBe(2); await page.$eval('iframe', iframe => {
expect(await countOOPIFs(browser)).toBe(1); iframe.style.width = '500px';
const oopif = page.frames()[1]; iframe.style.height = '500px';
await page.exposeFunction('mul', (a, b) => a * b); iframe.style.marginLeft = '42px';
const result = await oopif.evaluate(async function() { iframe.style.marginTop = '17px';
return await window['mul'](9, 4);
});
expect(result).toBe(36);
}); });
await page.frames()[1].goto(page.frames()[1].url());
it('should emulate media', async ({page, browser, server}) => { expect(await countOOPIFs(browser)).toBe(1);
await page.goto(server.PREFIX + '/dynamic-oopif.html'); const handle1 = await page.frames()[1].$('.box:nth-of-type(13)');
expect(page.frames().length).toBe(2); expect(await handle1.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 });
expect(await countOOPIFs(browser)).toBe(1);
const oopif = page.frames()[1]; await Promise.all([
expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false); page.frames()[1].waitForNavigation(),
await page.emulateMedia({ colorScheme: 'dark' }); page.evaluate('goLocal()'),
expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true); ]);
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}) => { expect(await countOOPIFs(browser)).toBe(1);
await page.goto(server.PREFIX + '/dynamic-oopif.html'); const handle1 = await page.frames()[1].$('.box:nth-of-type(13)');
expect(page.frames().length).toBe(2); await handle1.evaluate(div => div.addEventListener('click', () => window['_clicked'] = true, false));
expect(await countOOPIFs(browser)).toBe(1); await handle1.click();
const oopif = page.frames()[1]; expect(await handle1.evaluate(() => window['_clicked'])).toBe(true);
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 lEst 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);
});
}); });
async function countOOPIFs(browser) { async function countOOPIFs(browser) {

View file

@ -17,115 +17,107 @@
import { contextTest as it, expect } from '../config/browserTest'; import { contextTest as it, expect } from '../config/browserTest';
import { browserTest } from '../config/browserTest'; import { browserTest } from '../config/browserTest';
it.describe('session', () => { it('should work', async function({page}) {
it.skip(({ browserName }) => browserName !== 'chromium'); const client = await page.context().newCDPSession(page);
it('should work', async function({page}) { await Promise.all([
const client = await page.context().newCDPSession(page); client.send('Runtime.enable'),
client.send('Runtime.evaluate', { expression: 'window.foo = "bar"' })
await Promise.all([ ]);
client.send('Runtime.enable'), const foo = await page.evaluate(() => window['foo']);
client.send('Runtime.evaluate', { expression: 'window.foo = "bar"' }) expect(foo).toBe('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<void>(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.describe('session', () => { it('should send events', async function({page, server}) {
browserTest.skip(({ browserName }) => browserName !== 'chromium'); const client = await page.context().newCDPSession(page);
await client.send('Network.enable');
browserTest('should not break page.close()', async function({browser}) { const events = [];
const context = await browser.newContext(); client.on('Network.requestWillBeSent', event => events.push(event));
const page = await context.newPage(); await page.goto(server.EMPTY_PAGE);
const session = await page.context().newCDPSession(page); expect(events.length).toBe(1);
await session.detach(); });
await page.close();
await context.close(); 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);
browserTest('should detach when page closes', async function({browser}) { expect(error.message).toContain('page: expected Page');
const context = await browser.newContext(); });
const page = await context.newPage();
const session = await context.newCDPSession(page); it('should enable and disable domains independently', async function({page}) {
await page.close(); const client = await page.context().newCDPSession(page);
let error; await client.send('Runtime.enable');
await session.detach().catch(e => error = e); await client.send('Debugger.enable');
expect(error).toBeTruthy(); // JS coverage enables and then disables Debugger domain.
await context.close(); await page.coverage.startJSCoverage();
}); await page.coverage.stopJSCoverage();
page.on('console', console.log);
browserTest('should work with newBrowserCDPSession', async function({browser}) { // generate a script in page and wait for the event.
const session = await browser.newBrowserCDPSession(); await Promise.all([
new Promise<void>(f => client.on('Debugger.scriptParsed', event => {
const version = await session.send('Browser.getVersion'); if (event.url === 'foo.js')
expect(version.userAgent).toBeTruthy(); f();
})),
let gotEvent = false; page.evaluate('//# sourceURL=foo.js')
session.on('Target.targetCreated', () => gotEvent = true); ]);
await session.send('Target.setDiscoverTargets', { discover: true }); });
expect(gotEvent).toBe(true);
it('should be able to detach session', async function({page}) {
await session.detach(); 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();
}); });

View file

@ -18,79 +18,75 @@ import { browserTest as it, expect } from '../config/browserTest';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
it.describe('tracing', () => { it('should output a trace', async ({browser, server}, testInfo) => {
it.skip(({ browserName }) => browserName !== 'chromium'); const page = await browser.newPage();
const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
it('should output a trace', async ({browser, server}, testInfo) => { await browser.startTracing(page, {screenshots: true, path: outputTraceFile});
const page = await browser.newPage(); await page.goto(server.PREFIX + '/grid.html');
const outputTraceFile = testInfo.outputPath(path.join(`trace.json`)); await browser.stopTracing();
await browser.startTracing(page, {screenshots: true, path: outputTraceFile}); expect(fs.existsSync(outputTraceFile)).toBe(true);
await page.goto(server.PREFIX + '/grid.html'); await page.close();
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'));
it('should create directories as needed', async ({browser, server}, testInfo) => { await browser.startTracing(page, {screenshots: true, path: filePath});
const page = await browser.newPage(); await page.goto(server.PREFIX + '/grid.html');
const filePath = testInfo.outputPath(path.join('these', 'are', 'directories', 'trace.json')); await browser.stopTracing();
await browser.startTracing(page, {screenshots: true, path: filePath}); expect(fs.existsSync(filePath)).toBe(true);
await page.goto(server.PREFIX + '/grid.html'); await page.close();
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`));
it('should run with custom categories if provided', async ({browser}, testInfo) => { await browser.startTracing(page, {path: outputTraceFile, categories: ['disabled-by-default-v8.cpu_profiler.hires']});
const page = await browser.newPage(); await browser.stopTracing();
const outputTraceFile = testInfo.outputPath(path.join(`trace.json`));
await browser.startTracing(page, {path: outputTraceFile, categories: ['disabled-by-default-v8.cpu_profiler.hires']}); const traceJson = JSON.parse(fs.readFileSync(outputTraceFile).toString());
await browser.stopTracing(); expect(traceJson.metadata['trace-config']).toContain('disabled-by-default-v8.cpu_profiler.hires');
await page.close();
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`));
it('should throw if tracing on two pages', async ({browser}, testInfo) => { await browser.startTracing(page, {path: outputTraceFile});
const page = await browser.newPage(); const newPage = await browser.newPage();
const outputTraceFile = testInfo.outputPath(path.join(`trace.json`)); let error = null;
await browser.startTracing(page, {path: outputTraceFile}); await browser.startTracing(newPage, {path: outputTraceFile}).catch(e => error = e);
const newPage = await browser.newPage(); await newPage.close();
let error = null; expect(error).toBeTruthy();
await browser.startTracing(newPage, {path: outputTraceFile}).catch(e => error = e); await browser.stopTracing();
await newPage.close(); await page.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`));
it('should return a buffer', async ({browser, server}, testInfo) => { await browser.startTracing(page, {screenshots: true, path: outputTraceFile});
const page = await browser.newPage(); await page.goto(server.PREFIX + '/grid.html');
const outputTraceFile = testInfo.outputPath(path.join(`trace.json`)); const trace = await browser.stopTracing();
await browser.startTracing(page, {screenshots: true, path: outputTraceFile}); const buf = fs.readFileSync(outputTraceFile);
await page.goto(server.PREFIX + '/grid.html'); expect(trace.toString()).toEqual(buf.toString());
const trace = await browser.stopTracing(); await page.close();
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);
it('should work without options', async ({browser, server}) => { await page.goto(server.PREFIX + '/grid.html');
const page = await browser.newPage(); const trace = await browser.stopTracing();
await browser.startTracing(page); expect(trace).toBeTruthy();
await page.goto(server.PREFIX + '/grid.html'); await page.close();
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});
it('should support a buffer without a path', async ({browser, server}) => { await page.goto(server.PREFIX + '/grid.html');
const page = await browser.newPage(); const trace = await browser.stopTracing();
await browser.startTracing(page, {screenshots: true}); expect(trace.toString()).toContain('screenshot');
await page.goto(server.PREFIX + '/grid.html'); await page.close();
const trace = await browser.stopTracing();
expect(trace.toString()).toContain('screenshot');
await page.close();
});
}); });

View file

@ -17,7 +17,7 @@
import * as folio from 'folio'; import * as folio from 'folio';
import * as path from 'path'; import * as path from 'path';
import { test as pageTest } from '../page/pageTest'; import { test as pageTest } from '../page/pageTest';
import { AndroidEnv } from './androidTest'; import { AndroidEnv } from '../android/androidTest';
import type { BrowserContext } from '../../index'; import type { BrowserContext } from '../../index';
import { PlaywrightEnvOptions } from './browserTest'; import { PlaywrightEnvOptions } from './browserTest';
import { CommonOptions } from './baseTest'; import { CommonOptions } from './baseTest';

View file

@ -95,14 +95,17 @@ const config: folio.Config<AllOptions> = {
projects: [], 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); const executablePath = getExecutablePath(browserName);
if (executablePath && (process.env.FOLIO_WORKER_INDEX === undefined || process.env.FOLIO_WORKER_INDEX === '')) if (executablePath && (process.env.FOLIO_WORKER_INDEX === undefined || process.env.FOLIO_WORKER_INDEX === ''))
console.error(`Using executable at ${executablePath}`); 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({ config.projects.push({
name: browserName, name: browserName,
testDir, testDir,
testIgnore: [/android/, /electron/], testIgnore,
options: { options: {
mode: (process.env.PWTEST_MODE || 'default') as ('default' | 'driver' | 'service'), mode: (process.env.PWTEST_MODE || 'default') as ('default' | 'driver' | 'service'),
browserName, browserName,

View file

@ -16,7 +16,7 @@
import * as folio from 'folio'; import * as folio from 'folio';
import * as path from 'path'; import * as path from 'path';
import { ElectronEnv } from './electronTest'; import { ElectronEnv } from '../electron/electronTest';
import { test as pageTest } from '../page/pageTest'; import { test as pageTest } from '../page/pageTest';
import { PlaywrightEnvOptions } from './browserTest'; import { PlaywrightEnvOptions } from './browserTest';
import { CommonOptions } from './baseTest'; import { CommonOptions } from './baseTest';

View file

@ -16,11 +16,12 @@
import type { BrowserWindow } from 'electron'; import type { BrowserWindow } from 'electron';
import path from 'path'; 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 }) => { baseTest('should fire close event', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({ const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, '..', 'config', 'electron-app.js')], args: [path.join(__dirname, 'electron-app.js')],
}); });
const events = []; const events = [];
electronApp.on('close', () => events.push('application')); electronApp.on('close', () => events.push('application'));
@ -34,7 +35,7 @@ baseTest('should fire close event', async ({ playwright }) => {
test('should script application', async ({ electronApp }) => { test('should script application', async ({ electronApp }) => {
const appPath = await electronApp.evaluate(async ({ app }) => app.getAppPath()); 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 }) => { 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 }) => { test('should test app that opens window fast', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({ 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(); await electronApp.close();
}); });
test('should return browser window', async ({ playwright }) => { test('should return browser window', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({ 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 page = await electronApp.waitForEvent('window');
const bwHandle = await electronApp.browserWindow(page); const bwHandle = await electronApp.browserWindow(page);

View file

@ -14,7 +14,7 @@
* limitations under the License. * 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}) => { test('should click the button', async ({newWindow, server}) => {
const window = await newWindow(); const window = await newWindow();

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { baseTest, CommonArgs } from './baseTest'; import { baseTest, CommonArgs } from '../config/baseTest';
import { ElectronApplication, Page } from '../../index'; import { ElectronApplication, Page } from '../../index';
import * as folio from 'folio'; import * as folio from 'folio';
import * as path from 'path'; import * as path from 'path';
@ -79,5 +79,4 @@ export class ElectronEnv {
} }
} }
export const baseElectronTest = baseTest;
export const electronTest = baseTest.extend(new ElectronEnv()); export const electronTest = baseTest.extend(new ElectronEnv());

View file

@ -17,8 +17,6 @@
import { playwrightTest as it, expect } from '../config/browserTest'; import { playwrightTest as it, expect } from '../config/browserTest';
it('should pass firefox user preferences', async ({browserType, browserOptions, browserName}) => { it('should pass firefox user preferences', async ({browserType, browserOptions, browserName}) => {
it.skip(browserName !== 'firefox');
const browser = await browserType.launch({ const browser = await browserType.launch({
...browserOptions, ...browserOptions,
firefoxUserPrefs: { firefoxUserPrefs: {

View file

@ -14,8 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { cliTest as test, expect } from '../config/cliTest'; import { test, expect } from './inspectorTest';
import * as http from 'http';
test.describe('cli codegen', () => { test.describe('cli codegen', () => {
test.skip(({ mode }) => mode !== 'default'); test.skip(({ mode }) => mode !== 'default');
@ -58,14 +57,14 @@ await page.ClickAsync("text=Submit");`);
expect(message.text()).toBe('click'); 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(); 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.setHeader('Content-Type', 'text/html; charset=utf-8');
res.end(''); res.end('');
}); });
await recorder.setContentAndWait(`<button onclick="console.log('click')">Submit</button>`, httpServer.PREFIX + '/foo.html'); await recorder.setContentAndWait(`<button onclick="console.log('click')">Submit</button>`, server.PREFIX + '/foo.html');
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.evaluate(() => history.pushState({}, '', '/url.html')), page.evaluate(() => history.pushState({}, '', '/url.html')),

View file

@ -14,8 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { cliTest as test, expect } from '../config/cliTest'; import { test, expect } from './inspectorTest';
import * as http from 'http';
import * as url from 'url'; import * as url from 'url';
test.describe('cli codegen', () => { 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(); const recorder = await openRecorder();
httpServer.setHandler((req: http.IncomingMessage, res: http.ServerResponse) => { server.setRoute('/download', (req, res) => {
const pathName = url.parse(req.url!).path; const pathName = url.parse(req.url!).path;
if (pathName === '/download') { if (pathName === '/download') {
res.setHeader('Content-Type', 'application/octet-stream'); res.setHeader('Content-Type', 'application/octet-stream');
@ -243,8 +242,8 @@ await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { });`);
} }
}); });
await recorder.setContentAndWait(` await recorder.setContentAndWait(`
<a href="${httpServer.PREFIX}/download" download>Download</a> <a href="${server.PREFIX}/download" download>Download</a>
`, httpServer.PREFIX); `, server.PREFIX);
await recorder.hoverOverElement('text=Download'); await recorder.hoverOverElement('text=Download');
await Promise.all([ await Promise.all([
page.waitForEvent('download'), 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(); 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(` await recorder.setContentAndWait(`
<script> <script>
let seqNum = 0; let seqNum = 0;
function pushState() { function pushState() {
history.pushState({}, 'title', '${httpServer.PREFIX}/#seqNum=' + (++seqNum)); history.pushState({}, 'title', '${server.PREFIX}/#seqNum=' + (++seqNum));
} }
</script>`, httpServer.PREFIX); </script>`, server.PREFIX);
for (let i = 1; i < 3; ++i) { for (let i = 1; i < 3; ++i) {
await page.evaluate('pushState()'); await page.evaluate('pushState()');
await recorder.waitForOutput('<javascript>', `await page.goto('${httpServer.PREFIX}/#seqNum=${i}');`); await recorder.waitForOutput('<javascript>', `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\");`); 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(); 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.setHeader('Content-Type', 'text/html; charset=utf-8');
res.end('Hello world'); res.end('Hello world');
}); });
await recorder.setContentAndWait(` await recorder.setContentAndWait(`
<script> <script>
function pushState() { function pushState() {
history.pushState({}, 'title', '${httpServer.PREFIX}'); history.pushState({}, 'title', '${server.PREFIX}');
} }
</script>`, httpServer.PREFIX); </script>`, server.PREFIX);
for (let i = 1; i < 3; ++i) for (let i = 1; i < 3; ++i)
await page.evaluate('pushState()'); await page.evaluate('pushState()');
await page.goto(httpServer.PREFIX + '/page2.html'); await page.goto(server.PREFIX + '/page2.html');
await recorder.waitForOutput('<javascript>', `await page.goto('${httpServer.PREFIX}/page2.html');`); await recorder.waitForOutput('<javascript>', `await page.goto('${server.PREFIX}/page2.html');`);
}); });
test('should record slow navigation signal after mouse move', async ({ page, openRecorder, server }) => { test('should record slow navigation signal after mouse move', async ({ page, openRecorder, server }) => {

View file

@ -16,7 +16,7 @@
import path from 'path'; import path from 'path';
import fs from 'fs'; 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 emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
const launchOptions = (channel: string) => { const launchOptions = (channel: string) => {

View file

@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; 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 emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
const launchOptions = (channel: string) => { const launchOptions = (channel: string) => {

View file

@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; 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 emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();

View file

@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; 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 emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
const launchOptions = (channel: string) => { const launchOptions = (channel: string) => {

View file

@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; 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 emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
const launchOptions = (channel: string) => { const launchOptions = (channel: string) => {

View file

@ -14,9 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
import { contextTest } from './browserTest'; import { contextTest } from '../config/browserTest';
import type { Page } from '../../index'; import type { Page } from '../../index';
import * as http from 'http';
import * as path from 'path'; import * as path from 'path';
import type { Source } from '../../src/server/supplements/recorder/recorderTypes'; import type { Source } from '../../src/server/supplements/recorder/recorderTypes';
import { ChildProcess, spawn } from 'child_process'; import { ChildProcess, spawn } from 'child_process';
@ -24,23 +23,15 @@ import { chromium } from '../../index';
import * as folio from 'folio'; import * as folio from 'folio';
export { expect } from 'folio'; export { expect } from 'folio';
interface CLIHTTPServer {
setHandler: (handler: http.RequestListener) => void;
PREFIX: string;
}
type CLITestArgs = { type CLITestArgs = {
httpServer: CLIHTTPServer;
recorderPageGetter: () => Promise<Page>; recorderPageGetter: () => Promise<Page>;
openRecorder: () => Promise<Recorder>; openRecorder: () => Promise<Recorder>;
runCLI: (args: string[]) => CLIMock; runCLI: (args: string[]) => CLIMock;
}; };
export const cliTest = contextTest.extend({ export const test = contextTest.extend({
async beforeAll({}, workerInfo: folio.WorkerInfo) { async beforeAll({}, workerInfo: folio.WorkerInfo) {
this._port = 10907 + workerInfo.workerIndex * 2; process.env.PWTEST_RECORDER_PORT = String(10907 + workerInfo.workerIndex);
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);
}, },
async beforeEach({ page, context, toImpl, browserName, browserChannel, headful, mode }, testInfo: folio.TestInfo): Promise<CLITestArgs> { async beforeEach({ page, context, toImpl, browserName, browserChannel, headful, mode }, testInfo: folio.TestInfo): Promise<CLITestArgs> {
@ -54,10 +45,6 @@ export const cliTest = contextTest.extend({
return c.pages()[0] || await c.waitForEvent('page'); return c.pages()[0] || await c.waitForEvent('page');
}; };
return { return {
httpServer: {
setHandler: newHandler => this._handler = newHandler,
PREFIX: `http://127.0.0.1:${this._port}`,
},
runCLI: (cliArgs: string[]) => { runCLI: (cliArgs: string[]) => {
this._cli = new CLIMock(browserName, browserChannel, !headful, cliArgs); this._cli = new CLIMock(browserName, browserChannel, !headful, cliArgs);
return this._cli; return this._cli;
@ -76,13 +63,6 @@ export const cliTest = contextTest.extend({
this._cli = undefined; this._cli = undefined;
} }
}, },
async afterAll({}, workerInfo: folio.WorkerInfo) {
if (this._server) {
this._server.close();
this._server = undefined;
}
},
}); });
class Recorder { class Recorder {

View file

@ -14,8 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
import { Page } from '../index'; import { Page } from '../../index';
import { cliTest as it, expect } from './config/cliTest'; import { test as it, expect } from './inspectorTest';
it.describe('pause', () => { it.describe('pause', () => {
it.skip(({ mode }) => mode !== 'default'); it.skip(({ mode }) => mode !== 'default');