test: remove describes (5) (#3294)
This commit is contained in:
parent
1673e62779
commit
4cbfa09c2c
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const utils = require('./utils');
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
|
||||
it('browserType.executablePath should work', async({browserType}) => {
|
||||
const executablePath = browserType.executablePath();
|
||||
expect(fs.existsSync(executablePath)).toBe(true);
|
||||
expect(fs.realpathSync(executablePath)).toBe(executablePath);
|
||||
});
|
||||
|
||||
it('browserType.name should work', async({browserType}) => {
|
||||
if (WEBKIT)
|
||||
expect(browserType.name()).toBe('webkit');
|
||||
else if (FFOX)
|
||||
expect(browserType.name()).toBe('firefox');
|
||||
else if (CHROMIUM)
|
||||
expect(browserType.name()).toBe('chromium');
|
||||
else
|
||||
throw new Error('Unknown browser');
|
||||
});
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const utils = require('./utils');
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
|
||||
it.slow()('should be able to reconnect to a browser', async({browserType, defaultBrowserOptions, server}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
{
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const browserContext = await browser.newContext();
|
||||
const page = await browserContext.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await browser.close();
|
||||
}
|
||||
{
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const browserContext = await browser.newContext();
|
||||
const page = await browserContext.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await browser.close();
|
||||
}
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
|
||||
it.fail(USES_HOOKS || (CHROMIUM && WIN)).slow()('should handle exceptions during connect', async({browserType, defaultBrowserOptions, server}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const __testHookBeforeCreateBrowser = () => { throw new Error('Dummy') };
|
||||
const error = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint(), __testHookBeforeCreateBrowser }).catch(e => e);
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
expect(error.message).toContain('Dummy');
|
||||
});
|
||||
|
||||
it('should set the browser connected state', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
expect(remote.isConnected()).toBe(true);
|
||||
await remote.close();
|
||||
expect(remote.isConnected()).toBe(false);
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
|
||||
it('should throw when used after isConnected returns false', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
await Promise.all([
|
||||
browserServer.close(),
|
||||
new Promise(f => remote.once('disconnected', f)),
|
||||
]);
|
||||
expect(remote.isConnected()).toBe(false);
|
||||
const error = await page.evaluate('1 + 1').catch(e => e);
|
||||
expect(error.message).toContain('has been closed');
|
||||
});
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const utils = require('./utils');
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
|
||||
it('should work', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const browserContext = await browser.newContext();
|
||||
expect(browserContext.pages().length).toBe(0);
|
||||
expect(browserServer.wsEndpoint()).not.toBe(null);
|
||||
const page = await browserContext.newPage();
|
||||
expect(await page.evaluate('11 * 11')).toBe(121);
|
||||
await page.close();
|
||||
await browser.close();
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
|
||||
it('should fire "disconnected" when closing the server', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const disconnectedEventPromise = new Promise(resolve => browser.once('disconnected', resolve));
|
||||
const closedPromise = new Promise(f => browserServer.on('close', f));
|
||||
browserServer.kill();
|
||||
await Promise.all([
|
||||
disconnectedEventPromise,
|
||||
closedPromise,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should fire "close" event during kill', async({browserType, defaultBrowserOptions}) => {
|
||||
const order = [];
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const closedPromise = new Promise(f => browserServer.on('close', () => {
|
||||
order.push('closed');
|
||||
f();
|
||||
}));
|
||||
await Promise.all([
|
||||
browserServer.kill().then(() => order.push('killed')),
|
||||
closedPromise,
|
||||
]);
|
||||
expect(order).toEqual(['closed', 'killed']);
|
||||
});
|
||||
|
||||
it('should return child_process instance', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
expect(browserServer.process().pid).toBeGreaterThan(0);
|
||||
await browserServer.close();
|
||||
});
|
||||
|
||||
it('should fire close event', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const [result] = await Promise.all([
|
||||
new Promise(f => browserServer.on('close', (exitCode, signal) => f({ exitCode, signal }))),
|
||||
browserServer.close(),
|
||||
]);
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.signal).toBe(null);
|
||||
});
|
||||
|
||||
it('should reject navigation when browser closes', async({browserType, defaultBrowserOptions, server}) => {
|
||||
server.setRoute('/one-style.css', () => {});
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
const navigationPromise = page.goto(server.PREFIX + '/one-style.html', {timeout: 60000}).catch(e => e);
|
||||
await server.waitForRequest('/one-style.css');
|
||||
await remote.close();
|
||||
const error = await navigationPromise;
|
||||
expect(error.message).toContain('Navigation failed because page was closed!');
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
|
||||
it('should reject waitForSelector when browser closes', async({browserType, defaultBrowserOptions, server}) => {
|
||||
server.setRoute('/empty.html', () => {});
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
const watchdog = page.waitForSelector('div', { state: 'attached', timeout: 60000 }).catch(e => e);
|
||||
|
||||
// Make sure the previous waitForSelector has time to make it to the browser before we disconnect.
|
||||
await page.waitForSelector('body', { state: 'attached' });
|
||||
|
||||
await remote.close();
|
||||
const error = await watchdog;
|
||||
expect(error.message).toContain('Protocol error');
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
|
||||
it('should throw if used after disconnect', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
await remote.close();
|
||||
const error = await page.evaluate('1 + 1').catch(e => e);
|
||||
expect(error.message).toContain('has been closed');
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
|
||||
it('should emit close events on pages and contexts', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const context = await remote.newContext();
|
||||
const page = await context.newPage();
|
||||
let pageClosed = false;
|
||||
page.on('close', e => pageClosed = true);
|
||||
await Promise.all([
|
||||
new Promise(f => context.on('close', f)),
|
||||
browserServer.close()
|
||||
]);
|
||||
expect(pageClosed).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should terminate network waiters', async({browserType, defaultBrowserOptions, server}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const newPage = await remote.newPage();
|
||||
const results = await Promise.all([
|
||||
newPage.waitForRequest(server.EMPTY_PAGE).catch(e => e),
|
||||
newPage.waitForResponse(server.EMPTY_PAGE).catch(e => e),
|
||||
browserServer.close()
|
||||
]);
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const message = results[i].message;
|
||||
expect(message).toContain('Page closed');
|
||||
expect(message).not.toContain('Timeout');
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const utils = require('./utils');
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
|
||||
it('should reject all promises when browser is closed', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
const page = await (await browser.newContext()).newPage();
|
||||
let error = null;
|
||||
const neverResolves = page.evaluate(() => new Promise(r => {})).catch(e => error = e);
|
||||
await page.evaluate(() => new Promise(f => setTimeout(f, 0)));
|
||||
await browser.close();
|
||||
await neverResolves;
|
||||
expect(error.message).toContain('Protocol error');
|
||||
});
|
||||
|
||||
it('should throw if userDataDir option is passed', async({browserType, defaultBrowserOptions}) => {
|
||||
let waitError = null;
|
||||
const options = Object.assign({}, defaultBrowserOptions, {userDataDir: 'random-path'});
|
||||
await browserType.launch(options).catch(e => waitError = e);
|
||||
expect(waitError.message).toContain('launchPersistentContext');
|
||||
});
|
||||
|
||||
it.skip(FFOX)('should throw if page argument is passed', async({browserType, defaultBrowserOptions}) => {
|
||||
let waitError = null;
|
||||
const options = Object.assign({}, defaultBrowserOptions, { args: ['http://example.com'] });
|
||||
await browserType.launch(options).catch(e => waitError = e);
|
||||
expect(waitError.message).toContain('can not specify page');
|
||||
});
|
||||
|
||||
it.fail(true)('should reject if launched browser fails immediately', async({browserType, defaultBrowserOptions}) => {
|
||||
// I'm getting ENCONRESET on this one.
|
||||
const options = Object.assign({}, defaultBrowserOptions, {executablePath: path.join(__dirname, 'assets', 'dummy_bad_browser_executable.js')});
|
||||
let waitError = null;
|
||||
await browserType.launch(options).catch(e => waitError = e);
|
||||
expect(waitError.message).toContain('== logs ==');
|
||||
});
|
||||
|
||||
it('should reject if executable path is invalid', async({browserType, defaultBrowserOptions}) => {
|
||||
let waitError = null;
|
||||
const options = Object.assign({}, defaultBrowserOptions, {executablePath: 'random-invalid-path'});
|
||||
await browserType.launch(options).catch(e => waitError = e);
|
||||
expect(waitError.message).toContain('Failed to launch');
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should handle timeout', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
expect(error.message).toContain(`browserType.launch: Timeout 5000ms exceeded.`);
|
||||
expect(error.message).toContain(`[browser] <launching>`);
|
||||
expect(error.message).toContain(`[browser] <launched> pid=`);
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should handle exception', async({browserType, defaultBrowserOptions}) => {
|
||||
const e = new Error('Dummy');
|
||||
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
expect(error.message).toContain('Dummy');
|
||||
});
|
||||
|
||||
it.skip(USES_HOOKS)('should report launch log', async({browserType, defaultBrowserOptions}) => {
|
||||
const e = new Error('Dummy');
|
||||
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
expect(error.message).toContain('<launching>');
|
||||
});
|
||||
|
||||
it.slow()('should accept objects as options', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch({ ...defaultBrowserOptions, process });
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should fire close event for all contexts', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
const context = await browser.newContext();
|
||||
let closed = false;
|
||||
context.on('close', () => closed = true);
|
||||
await browser.close();
|
||||
expect(closed).toBe(true);
|
||||
});
|
||||
|
||||
it('should be callable twice', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
await Promise.all([
|
||||
browser.close(),
|
||||
browser.close(),
|
||||
]);
|
||||
await browser.close();
|
||||
});
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
/**
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
|
||||
describe.skip(!CHROMIUM)('Service Worker', function() {
|
||||
it('should create a worker from a service worker', async({page, server, context}) => {
|
||||
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]');
|
||||
});
|
||||
it('serviceWorkers() should return current workers', async({page, server, 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);
|
||||
});
|
||||
it('should not create a worker from a shared worker', async({page, server, context}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
let serviceWorkerCreated;
|
||||
context.once('serviceworker', () => serviceWorkerCreated = true);
|
||||
await page.evaluate(() => {
|
||||
new SharedWorker('data:text/javascript,console.log("hi")');
|
||||
});
|
||||
expect(serviceWorkerCreated).not.toBeTruthy();
|
||||
});
|
||||
it('should close service worker together with the context', async({browser, server}) => {
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip(!CHROMIUM)('Chromium-Specific Page Tests', function() {
|
||||
it('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');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
|
||||
it.skip(!CHROMIUM)('should create a worker from a service worker', async({page, server, context}) => {
|
||||
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]');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('serviceWorkers() should return current workers', async({page, server, 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);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should not create a worker from a shared worker', async({page, server, context}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
let serviceWorkerCreated;
|
||||
context.once('serviceworker', () => serviceWorkerCreated = true);
|
||||
await page.evaluate(() => {
|
||||
new SharedWorker('data:text/javascript,console.log("hi")');
|
||||
});
|
||||
expect(serviceWorkerCreated).not.toBeTruthy();
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should close service worker together with the context', async({browser, server}) => {
|
||||
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');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('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');
|
||||
});
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const utils = require('../utils');
|
||||
const {makeUserDataDir, removeUserDataDir} = utils;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = testOptions;
|
||||
|
||||
describe.skip(!CHROMIUM)('launcher', function() {
|
||||
it('should throw with remote-debugging-pipe argument', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = Object.assign({}, defaultBrowserOptions);
|
||||
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
|
||||
const error = await browserType.launchServer(options).catch(e => e);
|
||||
expect(error.message).toContain('Playwright manages remote debugging connection itself');
|
||||
});
|
||||
it('should not throw with remote-debugging-port argument', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = Object.assign({}, defaultBrowserOptions);
|
||||
options.args = ['--remote-debugging-port=0'].concat(options.args || []);
|
||||
const browser = await browserType.launchServer(options);
|
||||
await browser.close();
|
||||
});
|
||||
it.fail(USES_HOOKS || WIN)('should open devtools when "devtools: true" option is given', async({browserType, defaultBrowserOptions}) => {
|
||||
let devtoolsCallback;
|
||||
const devtoolsPromise = new Promise(f => devtoolsCallback = f);
|
||||
const __testHookForDevTools = devtools => devtools.__testHookOnBinding = parsed => {
|
||||
if (parsed.method === 'getPreferences')
|
||||
devtoolsCallback();
|
||||
};
|
||||
const browser = await browserType.launch({...defaultBrowserOptions, headless: false, devtools: true, __testHookForDevTools});
|
||||
const context = await browser.newContext();
|
||||
await Promise.all([
|
||||
devtoolsPromise,
|
||||
context.newPage()
|
||||
]);
|
||||
await browser.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip(!CHROMIUM)('extensions', () => {
|
||||
it('should return background pages', async({browserType, defaultBrowserOptions}) => {
|
||||
const userDataDir = await makeUserDataDir();
|
||||
const extensionPath = path.join(__dirname, '..', 'assets', 'simple-extension');
|
||||
const extensionOptions = {...defaultBrowserOptions,
|
||||
headless: false,
|
||||
args: [
|
||||
`--disable-extensions-except=${extensionPath}`,
|
||||
`--load-extension=${extensionPath}`,
|
||||
],
|
||||
};
|
||||
const context = await browserType.launchPersistentContext(userDataDir, extensionOptions);
|
||||
const backgroundPages = context.backgroundPages();
|
||||
let backgroundPage = backgroundPages.length
|
||||
? backgroundPages[0]
|
||||
: await context.waitForEvent('backgroundpage');
|
||||
expect(backgroundPage).toBeTruthy();
|
||||
expect(context.backgroundPages()).toContain(backgroundPage);
|
||||
expect(context.pages()).not.toContain(backgroundPage);
|
||||
await context.close();
|
||||
await removeUserDataDir(userDataDir);
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip(!CHROMIUM)('BrowserContext', function() {
|
||||
it('should not create pages automatically', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
const browserSession = await browser.newBrowserCDPSession();
|
||||
const targets = [];
|
||||
browserSession.on('Target.targetCreated', async ({targetInfo}) => {
|
||||
if (targetInfo.type !== 'browser')
|
||||
targets.push(targetInfo);
|
||||
});
|
||||
await browserSession.send('Target.setDiscoverTargets', { discover: true });
|
||||
await browser.newContext();
|
||||
await browser.close();
|
||||
expect(targets.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const utils = require('../utils');
|
||||
const {makeUserDataDir, removeUserDataDir} = utils;
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = testOptions;
|
||||
|
||||
it.skip(!CHROMIUM)('should throw with remote-debugging-pipe argument', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = Object.assign({}, defaultBrowserOptions);
|
||||
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
|
||||
const error = await browserType.launchServer(options).catch(e => e);
|
||||
expect(error.message).toContain('Playwright manages remote debugging connection itself');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should not throw with remote-debugging-port argument', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = Object.assign({}, defaultBrowserOptions);
|
||||
options.args = ['--remote-debugging-port=0'].concat(options.args || []);
|
||||
const browser = await browserType.launchServer(options);
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM || USES_HOOKS || WIN)('should open devtools when "devtools: true" option is given', async({browserType, defaultBrowserOptions}) => {
|
||||
let devtoolsCallback;
|
||||
const devtoolsPromise = new Promise(f => devtoolsCallback = f);
|
||||
const __testHookForDevTools = devtools => devtools.__testHookOnBinding = parsed => {
|
||||
if (parsed.method === 'getPreferences')
|
||||
devtoolsCallback();
|
||||
};
|
||||
const browser = await browserType.launch({...defaultBrowserOptions, headless: false, devtools: true, __testHookForDevTools});
|
||||
const context = await browser.newContext();
|
||||
await Promise.all([
|
||||
devtoolsPromise,
|
||||
context.newPage()
|
||||
]);
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should return background pages', async({browserType, defaultBrowserOptions}) => {
|
||||
const userDataDir = await makeUserDataDir();
|
||||
const extensionPath = path.join(__dirname, '..', 'assets', 'simple-extension');
|
||||
const extensionOptions = {...defaultBrowserOptions,
|
||||
headless: false,
|
||||
args: [
|
||||
`--disable-extensions-except=${extensionPath}`,
|
||||
`--load-extension=${extensionPath}`,
|
||||
],
|
||||
};
|
||||
const context = await browserType.launchPersistentContext(userDataDir, extensionOptions);
|
||||
const backgroundPages = context.backgroundPages();
|
||||
let backgroundPage = backgroundPages.length
|
||||
? backgroundPages[0]
|
||||
: await context.waitForEvent('backgroundpage');
|
||||
expect(backgroundPage).toBeTruthy();
|
||||
expect(context.backgroundPages()).toContain(backgroundPage);
|
||||
expect(context.pages()).not.toContain(backgroundPage);
|
||||
await context.close();
|
||||
await removeUserDataDir(userDataDir);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should not create pages automatically', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
const browserSession = await browser.newBrowserCDPSession();
|
||||
const targets = [];
|
||||
browserSession.on('Target.targetCreated', async ({targetInfo}) => {
|
||||
if (targetInfo.type !== 'browser')
|
||||
targets.push(targetInfo);
|
||||
});
|
||||
await browserSession.send('Target.setDiscoverTargets', { discover: true });
|
||||
await browser.newContext();
|
||||
await browser.close();
|
||||
expect(targets.length).toBe(0);
|
||||
});
|
||||
|
|
@ -1,350 +0,0 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
|
||||
registerFixture('sppBrowser', async ({browserType, defaultBrowserOptions}, test) => {
|
||||
const browser = await browserType.launch({
|
||||
...defaultBrowserOptions,
|
||||
args: (defaultBrowserOptions.args || []).concat(['--site-per-process'])
|
||||
});
|
||||
try {
|
||||
await test(browser);
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
});
|
||||
|
||||
registerFixture('sppContext', async ({sppBrowser}, test) => {
|
||||
const context = await sppBrowser.newContext();
|
||||
try {
|
||||
await test(context);
|
||||
} finally {
|
||||
await context.close();
|
||||
}
|
||||
});
|
||||
|
||||
registerFixture('sppPage', async ({sppContext}, test) => {
|
||||
const page = await sppContext.newPage();
|
||||
await test(page);
|
||||
});
|
||||
|
||||
|
||||
describe.skip(!CHROMIUM)('OOPIF', function() {
|
||||
it('should report oopif frames', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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 oopif detach', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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 handle remote -> local -> remote transitions', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.fail(true)('should get the proper viewport', async({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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 mul(9, 4);
|
||||
});
|
||||
expect(result).toBe(36);
|
||||
});
|
||||
it('should emulate media', async({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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({sppBrowser, sppPage, sppContext, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const context = sppContext;
|
||||
const page = sppPage;
|
||||
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 context.setOffline(true);
|
||||
expect(await oopif.evaluate(() => navigator.onLine)).toBe(false);
|
||||
});
|
||||
it('should support context options', async({sppBrowser, server, playwright}) => {
|
||||
const browser = sppBrowser;
|
||||
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({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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()).toBeGolden('screenshot-oopif.png');
|
||||
});
|
||||
it('should load oopif iframes with subresources and request interception', async function({sppBrowser, sppPage, server, context}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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({sppBrowser, sppContext, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const context = sppContext;
|
||||
const page = sppPage;
|
||||
await 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(() => inc(3))).toBe(4);
|
||||
expect(await page.frames()[1].evaluate(() => inc(4))).toBe(5);
|
||||
expect(await page.frames()[0].evaluate(() => dec(3))).toBe(2);
|
||||
expect(await page.frames()[1].evaluate(() => dec(4))).toBe(3);
|
||||
});
|
||||
it('should support addInitScript', async function({sppBrowser, sppContext, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const context = sppContext;
|
||||
const page = sppPage;
|
||||
await 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({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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, defaultBrowserOptions, server}) => {
|
||||
// @see https://github.com/GoogleChrome/puppeteer/issues/2548
|
||||
// https://google.com is isolated by default in Chromium embedder.
|
||||
const browser = await browserType.launch({...defaultBrowserOptions, 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({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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) {
|
||||
const browserSession = await browser.newBrowserCDPSession();
|
||||
const oopifs = [];
|
||||
browserSession.on('Target.targetCreated', async ({targetInfo}) => {
|
||||
if (targetInfo.type === 'iframe')
|
||||
oopifs.push(targetInfo);
|
||||
});
|
||||
await browserSession.send('Target.setDiscoverTargets', { discover: true });
|
||||
await browserSession.detach();
|
||||
return oopifs.length;
|
||||
}
|
||||
|
|
@ -0,0 +1,364 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = testOptions;
|
||||
|
||||
registerFixture('sppBrowser', async ({browserType, defaultBrowserOptions}, test) => {
|
||||
const browser = await browserType.launch({
|
||||
...defaultBrowserOptions,
|
||||
args: (defaultBrowserOptions.args || []).concat(['--site-per-process'])
|
||||
});
|
||||
try {
|
||||
await test(browser);
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
});
|
||||
|
||||
registerFixture('sppContext', async ({sppBrowser}, test) => {
|
||||
const context = await sppBrowser.newContext();
|
||||
try {
|
||||
await test(context);
|
||||
} finally {
|
||||
await context.close();
|
||||
}
|
||||
});
|
||||
|
||||
registerFixture('sppPage', async ({sppContext}, test) => {
|
||||
const page = await sppContext.newPage();
|
||||
await test(page);
|
||||
});
|
||||
|
||||
|
||||
it.skip(!CHROMIUM)('should report oopif frames', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.skip(!CHROMIUM)('should handle oopif detach', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.skip(!CHROMIUM)('should handle remote -> local -> remote transitions', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.fail(true)('should get the proper viewport', async({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.skip(!CHROMIUM)('should expose function', async({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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 mul(9, 4);
|
||||
});
|
||||
expect(result).toBe(36);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should emulate media', async({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.skip(!CHROMIUM)('should emulate offline', async({sppBrowser, sppPage, sppContext, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const context = sppContext;
|
||||
const page = sppPage;
|
||||
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 context.setOffline(true);
|
||||
expect(await oopif.evaluate(() => navigator.onLine)).toBe(false);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should support context options', async({sppBrowser, server, playwright}) => {
|
||||
const browser = sppBrowser;
|
||||
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.skip(!CHROMIUM)('should respect route', async({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.skip(!CHROMIUM)('should take screenshot', async({sppBrowser, sppPage, server}) => {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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()).toBeGolden('screenshot-oopif.png');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should load oopif iframes with subresources and request interception', async function({sppBrowser, sppPage, server, context}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
await page.route('**/*', route => route.continue());
|
||||
await page.goto(server.PREFIX + '/dynamic-oopif.html');
|
||||
expect(await countOOPIFs(browser)).toBe(1);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should report main requests', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.skip(!CHROMIUM)('should support exposeFunction', async function({sppBrowser, sppContext, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const context = sppContext;
|
||||
const page = sppPage;
|
||||
await 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(() => inc(3))).toBe(4);
|
||||
expect(await page.frames()[1].evaluate(() => inc(4))).toBe(5);
|
||||
expect(await page.frames()[0].evaluate(() => dec(3))).toBe(2);
|
||||
expect(await page.frames()[1].evaluate(() => dec(4))).toBe(3);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should support addInitScript', async function({sppBrowser, sppContext, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const context = sppContext;
|
||||
const page = sppPage;
|
||||
await 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.skip(!CHROMIUM)('should click a button when it overlays oopif', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.skip(!CHROMIUM)('should report google.com frame with headful', async({browserType, defaultBrowserOptions, server}) => {
|
||||
// @see https://github.com/GoogleChrome/puppeteer/issues/2548
|
||||
// https://google.com is isolated by default in Chromium embedder.
|
||||
const browser = await browserType.launch({...defaultBrowserOptions, 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.skip(!CHROMIUM)('ElementHandle.boundingBox() should work', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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.skip(!CHROMIUM)('should click', async function({sppBrowser, sppPage, server}) {
|
||||
const browser = sppBrowser;
|
||||
const page = sppPage;
|
||||
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) {
|
||||
const browserSession = await browser.newBrowserCDPSession();
|
||||
const oopifs = [];
|
||||
browserSession.on('Target.targetCreated', async ({targetInfo}) => {
|
||||
if (targetInfo.type === 'iframe')
|
||||
oopifs.push(targetInfo);
|
||||
});
|
||||
await browserSession.send('Target.setDiscoverTargets', { discover: true });
|
||||
await browserSession.detach();
|
||||
return oopifs.length;
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
/**
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
|
||||
describe.skip(!CHROMIUM)('ChromiumBrowserContext.createSession', function() {
|
||||
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 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(CHANNEL ? 'Target browser or context has been closed' : 'Session 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() {
|
||||
await client.send('ThisCommand.DoesNotExist');
|
||||
}
|
||||
});
|
||||
it('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();
|
||||
});
|
||||
it('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();
|
||||
});
|
||||
});
|
||||
describe.skip(!CHROMIUM)('ChromiumBrowser.newBrowserCDPSession', function() {
|
||||
it('should work', 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();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const {FFOX, CHROMIUM, WEBKIT, CHANNEL, USES_HOOKS} = testOptions;
|
||||
|
||||
it.skip(!CHROMIUM)('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.skip(!CHROMIUM)('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.skip(!CHROMIUM)('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.skip(!CHROMIUM)('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(CHANNEL ? 'Target browser or context has been closed' : 'Session closed.');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('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() {
|
||||
await client.send('ThisCommand.DoesNotExist');
|
||||
}
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('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();
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('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();
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should work', 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();
|
||||
});
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const {FFOX, CHROMIUM, WEBKIT, OUTPUT_DIR, CHANNEL} = testOptions;
|
||||
|
||||
registerFixture('outputFile', async ({parallelIndex}, test) => {
|
||||
const outputFile = path.join(OUTPUT_DIR, `trace-${parallelIndex}.json`);
|
||||
await test(outputFile);
|
||||
if (fs.existsSync(outputFile))
|
||||
fs.unlinkSync(outputFile);
|
||||
});
|
||||
|
||||
describe.skip(!CHROMIUM)('Chromium.startTracing', function() {
|
||||
it('should output a trace', async({browser, page, server, outputFile}) => {
|
||||
await browser.startTracing(page, {screenshots: true, path: outputFile});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
await browser.stopTracing();
|
||||
expect(fs.existsSync(outputFile)).toBe(true);
|
||||
});
|
||||
it('should run with custom categories if provided', async({browser, page, outputFile}) => {
|
||||
await browser.startTracing(page, {path: outputFile, categories: ['disabled-by-default-v8.cpu_profiler.hires']});
|
||||
await browser.stopTracing();
|
||||
|
||||
const traceJson = JSON.parse(fs.readFileSync(outputFile).toString());
|
||||
expect(traceJson.metadata['trace-config']).toContain('disabled-by-default-v8.cpu_profiler.hires', 'Does not contain expected category');
|
||||
});
|
||||
it('should throw if tracing on two pages', async({browser, page, outputFile}) => {
|
||||
await browser.startTracing(page, {path: outputFile});
|
||||
const newPage = await browser.newPage();
|
||||
let error = null;
|
||||
await browser.startTracing(newPage, {path: outputFile}).catch(e => error = e);
|
||||
await newPage.close();
|
||||
expect(error).toBeTruthy();
|
||||
await browser.stopTracing();
|
||||
});
|
||||
it('should return a buffer', async({browser, page, server, outputFile}) => {
|
||||
await browser.startTracing(page, {screenshots: true, path: outputFile});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const trace = await browser.stopTracing();
|
||||
const buf = fs.readFileSync(outputFile);
|
||||
expect(trace.toString()).toEqual(buf.toString(), 'Tracing buffer mismatch');
|
||||
});
|
||||
it('should work without options', async({browser, page, server}) => {
|
||||
await browser.startTracing(page);
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const trace = await browser.stopTracing();
|
||||
expect(trace).toBeTruthy();
|
||||
});
|
||||
it('should support a buffer without a path', async({browser, page, server}) => {
|
||||
await browser.startTracing(page, {screenshots: true});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const trace = await browser.stopTracing();
|
||||
expect(trace.toString()).toContain('screenshot', 'Does not contain screenshot');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const {FFOX, CHROMIUM, WEBKIT, OUTPUT_DIR, CHANNEL} = testOptions;
|
||||
|
||||
registerFixture('outputFile', async ({parallelIndex}, test) => {
|
||||
const outputFile = path.join(OUTPUT_DIR, `trace-${parallelIndex}.json`);
|
||||
await test(outputFile);
|
||||
if (fs.existsSync(outputFile))
|
||||
fs.unlinkSync(outputFile);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should output a trace', async({browser, page, server, outputFile}) => {
|
||||
await browser.startTracing(page, {screenshots: true, path: outputFile});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
await browser.stopTracing();
|
||||
expect(fs.existsSync(outputFile)).toBe(true);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should run with custom categories if provided', async({browser, page, outputFile}) => {
|
||||
await browser.startTracing(page, {path: outputFile, categories: ['disabled-by-default-v8.cpu_profiler.hires']});
|
||||
await browser.stopTracing();
|
||||
|
||||
const traceJson = JSON.parse(fs.readFileSync(outputFile).toString());
|
||||
expect(traceJson.metadata['trace-config']).toContain('disabled-by-default-v8.cpu_profiler.hires', 'Does not contain expected category');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should throw if tracing on two pages', async({browser, page, outputFile}) => {
|
||||
await browser.startTracing(page, {path: outputFile});
|
||||
const newPage = await browser.newPage();
|
||||
let error = null;
|
||||
await browser.startTracing(newPage, {path: outputFile}).catch(e => error = e);
|
||||
await newPage.close();
|
||||
expect(error).toBeTruthy();
|
||||
await browser.stopTracing();
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should return a buffer', async({browser, page, server, outputFile}) => {
|
||||
await browser.startTracing(page, {screenshots: true, path: outputFile});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const trace = await browser.stopTracing();
|
||||
const buf = fs.readFileSync(outputFile);
|
||||
expect(trace.toString()).toEqual(buf.toString(), 'Tracing buffer mismatch');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should work without options', async({browser, page, server}) => {
|
||||
await browser.startTracing(page);
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const trace = await browser.stopTracing();
|
||||
expect(trace).toBeTruthy();
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should support a buffer without a path', async({browser, page, server}) => {
|
||||
await browser.startTracing(page, {screenshots: true});
|
||||
await page.goto(server.PREFIX + '/grid.html');
|
||||
const trace = await browser.stopTracing();
|
||||
expect(trace.toString()).toContain('screenshot', 'Does not contain screenshot');
|
||||
});
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const electronName = process.platform === 'win32' ? 'electron.cmd' : 'electron';
|
||||
|
||||
const { CHROMIUM } = testOptions;
|
||||
|
||||
registerFixture('application', async ({playwright}, test) => {
|
||||
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);
|
||||
const application = await playwright.electron.launch(electronPath, {
|
||||
args: [path.join(__dirname, 'testApp.js')],
|
||||
});
|
||||
try {
|
||||
await test(application);
|
||||
} finally {
|
||||
await application.close();
|
||||
}
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should fire close event', async ({ playwright }) => {
|
||||
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);
|
||||
const application = await playwright.electron.launch(electronPath, {
|
||||
args: [path.join(__dirname, 'testApp.js')],
|
||||
});
|
||||
const events = [];
|
||||
application.on('close', () => events.push('application'));
|
||||
application.context().on('close', () => events.push('context'));
|
||||
await application.close();
|
||||
expect(events.join('|')).toBe('context|application');
|
||||
// Give it some time to fire more events - there should not be any.
|
||||
await new Promise(f => setTimeout(f, 1000));
|
||||
expect(events.join('|')).toBe('context|application');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should script application', async ({ application }) => {
|
||||
const appPath = await application.evaluate(async ({ app }) => app.getAppPath());
|
||||
expect(appPath).toContain('electron');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should create window', async ({ application }) => {
|
||||
const [ page ] = await Promise.all([
|
||||
application.waitForEvent('window'),
|
||||
application.evaluate(({ BrowserWindow }) => {
|
||||
const window = new BrowserWindow({ width: 800, height: 600 });
|
||||
window.loadURL('data:text/html,<title>Hello World 1</title>');
|
||||
})
|
||||
]);
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
expect(await page.title()).toBe('Hello World 1');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should create window 2', async ({ application }) => {
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await page.goto('data:text/html,<title>Hello World 2</title>');
|
||||
expect(await page.title()).toBe('Hello World 2');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should create multiple windows', async ({ application }) => {
|
||||
const createPage = async ordinal => {
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.browserWindow.evaluate((window, ordinal) => window.loadURL(`data:text/html,<title>Hello World ${ordinal}</title>`), ordinal)
|
||||
]);
|
||||
return page;
|
||||
};
|
||||
|
||||
const page1 = await createPage(1);
|
||||
const page2 = await createPage(2);
|
||||
const page3 = await createPage(3);
|
||||
await page1.close();
|
||||
const page4 = await createPage(4);
|
||||
const titles = [];
|
||||
for (const window of application.windows())
|
||||
titles.push(await window.title());
|
||||
expect(titles).toEqual(['Hello World 2', 'Hello World 3', 'Hello World 4']);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should route network', async ({ application }) => {
|
||||
await application.context().route('**/empty.html', (route, request) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'text/html',
|
||||
body: '<title>Hello World</title>',
|
||||
})
|
||||
});
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await page.goto('https://localhost:1000/empty.html');
|
||||
expect(await page.title()).toBe('Hello World');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should support init script', async ({ application }) => {
|
||||
await application.context().addInitScript('window.magic = 42;')
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await page.goto('data:text/html,<script>window.copy = magic</script>');
|
||||
expect(await page.evaluate(() => copy)).toBe(42);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should expose function', async ({ application }) => {
|
||||
const result = new Promise(f => callback = f);
|
||||
const t = Date.now();
|
||||
await application.context().exposeFunction('add', (a, b) => a + b);
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await page.goto('data:text/html,<script>window.result = add(20, 22);</script>');
|
||||
expect(await page.evaluate(() => result)).toBe(42);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should wait for first window', async ({ application }) => {
|
||||
application.evaluate(({ BrowserWindow }) => {
|
||||
const window = new BrowserWindow({ width: 800, height: 600 });
|
||||
window.loadURL('data:text/html,<title>Hello World!</title>');
|
||||
});
|
||||
const window = await application.firstWindow();
|
||||
expect(await window.title()).toBe('Hello World!');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should have a clipboard instance', async ({ application }) => {
|
||||
const clipboardContentToWrite = 'Hello from Playwright';
|
||||
await application.evaluate(async ({clipboard}, text) => clipboard.writeText(text), clipboardContentToWrite);
|
||||
const clipboardContentRead = await application.evaluate(async ({clipboard}) => clipboard.readText());
|
||||
await expect(clipboardContentRead).toEqual(clipboardContentToWrite);
|
||||
});
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const electronName = process.platform === 'win32' ? 'electron.cmd' : 'electron';
|
||||
|
||||
const { CHROMIUM } = testOptions;
|
||||
|
||||
registerFixture('application', async ({playwright}, test) => {
|
||||
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);
|
||||
const application = await playwright.electron.launch(electronPath, {
|
||||
args: [path.join(__dirname, 'testApp.js')],
|
||||
});
|
||||
try {
|
||||
await test(application);
|
||||
} finally {
|
||||
await application.close();
|
||||
}
|
||||
});
|
||||
|
||||
registerFixture('window', async ({application}, test) => {
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
try {
|
||||
await test(page);
|
||||
} finally {
|
||||
await page.close();
|
||||
}
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should click the button', async({window, server}) => {
|
||||
await window.goto(server.PREFIX + '/input/button.html');
|
||||
await window.click('button');
|
||||
expect(await window.evaluate(() => result)).toBe('Clicked');
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should check the box', async({window}) => {
|
||||
await window.setContent(`<input id='checkbox' type='checkbox'></input>`);
|
||||
await window.check('input');
|
||||
expect(await window.evaluate(() => checkbox.checked)).toBe(true);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should not check the checked box', async({window}) => {
|
||||
await window.setContent(`<input id='checkbox' type='checkbox' checked></input>`);
|
||||
await window.check('input');
|
||||
expect(await window.evaluate(() => checkbox.checked)).toBe(true);
|
||||
});
|
||||
|
||||
it.skip(!CHROMIUM)('should type into a textarea', async({window, server}) => {
|
||||
await window.evaluate(() => {
|
||||
const textarea = document.createElement('textarea');
|
||||
document.body.appendChild(textarea);
|
||||
textarea.focus();
|
||||
});
|
||||
const text = 'Hello world. I am the text that was typed!';
|
||||
await window.keyboard.type(text);
|
||||
expect(await window.evaluate(() => document.querySelector('textarea').value)).toBe(text);
|
||||
});
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const electronName = process.platform === 'win32' ? 'electron.cmd' : 'electron';
|
||||
|
||||
const { CHROMIUM } = testOptions;
|
||||
|
||||
registerFixture('application', async ({playwright}, test) => {
|
||||
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);
|
||||
const application = await playwright.electron.launch(electronPath, {
|
||||
args: [path.join(__dirname, 'testApp.js')],
|
||||
});
|
||||
try {
|
||||
await test(application);
|
||||
} finally {
|
||||
await application.close();
|
||||
}
|
||||
});
|
||||
|
||||
registerFixture('window', async ({application}, test) => {
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
try {
|
||||
await test(page);
|
||||
} finally {
|
||||
await page.close();
|
||||
}
|
||||
});
|
||||
|
||||
describe.skip(!CHROMIUM)('Electron', function() {
|
||||
it('should fire close event', async ({ playwright }) => {
|
||||
const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName);
|
||||
const application = await playwright.electron.launch(electronPath, {
|
||||
args: [path.join(__dirname, 'testApp.js')],
|
||||
});
|
||||
const events = [];
|
||||
application.on('close', () => events.push('application'));
|
||||
application.context().on('close', () => events.push('context'));
|
||||
await application.close();
|
||||
expect(events.join('|')).toBe('context|application');
|
||||
// Give it some time to fire more events - there should not be any.
|
||||
await new Promise(f => setTimeout(f, 1000));
|
||||
expect(events.join('|')).toBe('context|application');
|
||||
});
|
||||
it('should script application', async ({ application }) => {
|
||||
const appPath = await application.evaluate(async ({ app }) => app.getAppPath());
|
||||
expect(appPath).toContain('electron');
|
||||
});
|
||||
it('should create window', async ({ application }) => {
|
||||
const [ page ] = await Promise.all([
|
||||
application.waitForEvent('window'),
|
||||
application.evaluate(({ BrowserWindow }) => {
|
||||
const window = new BrowserWindow({ width: 800, height: 600 });
|
||||
window.loadURL('data:text/html,<title>Hello World 1</title>');
|
||||
})
|
||||
]);
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
expect(await page.title()).toBe('Hello World 1');
|
||||
});
|
||||
it('should create window 2', async ({ application }) => {
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await page.goto('data:text/html,<title>Hello World 2</title>');
|
||||
expect(await page.title()).toBe('Hello World 2');
|
||||
});
|
||||
it('should create multiple windows', async ({ application }) => {
|
||||
const createPage = async ordinal => {
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.browserWindow.evaluate((window, ordinal) => window.loadURL(`data:text/html,<title>Hello World ${ordinal}</title>`), ordinal)
|
||||
]);
|
||||
return page;
|
||||
};
|
||||
|
||||
const page1 = await createPage(1);
|
||||
const page2 = await createPage(2);
|
||||
const page3 = await createPage(3);
|
||||
await page1.close();
|
||||
const page4 = await createPage(4);
|
||||
const titles = [];
|
||||
for (const window of application.windows())
|
||||
titles.push(await window.title());
|
||||
expect(titles).toEqual(['Hello World 2', 'Hello World 3', 'Hello World 4']);
|
||||
});
|
||||
it('should route network', async ({ application }) => {
|
||||
await application.context().route('**/empty.html', (route, request) => {
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'text/html',
|
||||
body: '<title>Hello World</title>',
|
||||
})
|
||||
});
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await page.goto('https://localhost:1000/empty.html');
|
||||
expect(await page.title()).toBe('Hello World');
|
||||
});
|
||||
it('should support init script', async ({ application }) => {
|
||||
await application.context().addInitScript('window.magic = 42;')
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await page.goto('data:text/html,<script>window.copy = magic</script>');
|
||||
expect(await page.evaluate(() => copy)).toBe(42);
|
||||
});
|
||||
it('should expose function', async ({ application }) => {
|
||||
const result = new Promise(f => callback = f);
|
||||
const t = Date.now();
|
||||
await application.context().exposeFunction('add', (a, b) => a + b);
|
||||
const page = await application.newBrowserWindow({ width: 800, height: 600 });
|
||||
await page.goto('data:text/html,<script>window.result = add(20, 22);</script>');
|
||||
expect(await page.evaluate(() => result)).toBe(42);
|
||||
});
|
||||
it('should wait for first window', async ({ application }) => {
|
||||
application.evaluate(({ BrowserWindow }) => {
|
||||
const window = new BrowserWindow({ width: 800, height: 600 });
|
||||
window.loadURL('data:text/html,<title>Hello World!</title>');
|
||||
});
|
||||
const window = await application.firstWindow();
|
||||
expect(await window.title()).toBe('Hello World!');
|
||||
});
|
||||
it('should have a clipboard instance', async ({ application }) => {
|
||||
const clipboardContentToWrite = 'Hello from Playwright';
|
||||
await application.evaluate(async ({clipboard}, text) => clipboard.writeText(text), clipboardContentToWrite);
|
||||
const clipboardContentRead = await application.evaluate(async ({clipboard}) => clipboard.readText());
|
||||
await expect(clipboardContentRead).toEqual(clipboardContentToWrite);
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip(!CHROMIUM)('Electron per window', function() {
|
||||
it('should click the button', async({window, server}) => {
|
||||
await window.goto(server.PREFIX + '/input/button.html');
|
||||
await window.click('button');
|
||||
expect(await window.evaluate(() => result)).toBe('Clicked');
|
||||
});
|
||||
it('should check the box', async({window}) => {
|
||||
await window.setContent(`<input id='checkbox' type='checkbox'></input>`);
|
||||
await window.check('input');
|
||||
expect(await window.evaluate(() => checkbox.checked)).toBe(true);
|
||||
});
|
||||
it('should not check the checked box', async({window}) => {
|
||||
await window.setContent(`<input id='checkbox' type='checkbox' checked></input>`);
|
||||
await window.check('input');
|
||||
expect(await window.evaluate(() => checkbox.checked)).toBe(true);
|
||||
});
|
||||
it('should type into a textarea', async({window, server}) => {
|
||||
await window.evaluate(() => {
|
||||
const textarea = document.createElement('textarea');
|
||||
document.body.appendChild(textarea);
|
||||
textarea.focus();
|
||||
});
|
||||
const text = 'Hello world. I am the text that was typed!';
|
||||
await window.keyboard.type(text);
|
||||
expect(await window.evaluate(() => document.querySelector('textarea').value)).toBe(text);
|
||||
});
|
||||
});
|
||||
|
|
@ -16,19 +16,17 @@
|
|||
|
||||
const { FFOX } = testOptions;
|
||||
|
||||
describe.skip(!FFOX)('launcher', function() {
|
||||
it('should pass firefox user preferences', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch({
|
||||
...defaultBrowserOptions,
|
||||
firefoxUserPrefs: {
|
||||
'network.proxy.type': 1,
|
||||
'network.proxy.http': '127.0.0.1',
|
||||
'network.proxy.http_port': 3333,
|
||||
}
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
const error = await page.goto('http://example.com').catch(e => e);
|
||||
expect(error.message).toContain('NS_ERROR_PROXY_CONNECTION_REFUSED');
|
||||
await browser.close();
|
||||
it.skip(!FFOX)('should pass firefox user preferences', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch({
|
||||
...defaultBrowserOptions,
|
||||
firefoxUserPrefs: {
|
||||
'network.proxy.type': 1,
|
||||
'network.proxy.http': '127.0.0.1',
|
||||
'network.proxy.http_port': 3333,
|
||||
}
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
const error = await page.goto('http://example.com').catch(e => e);
|
||||
expect(error.message).toContain('NS_ERROR_PROXY_CONNECTION_REFUSED');
|
||||
await browser.close();
|
||||
});
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
/**
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const {spawn, execSync} = require('child_process');
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, LINUX, HEADLESS} = testOptions;
|
||||
|
||||
const playwrightPath = path.join(__dirname, '..');
|
||||
|
||||
class Wrapper {
|
||||
constructor(browserType, defaultBrowserOptions, extraOptions) {
|
||||
this._output = new Map();
|
||||
this._outputCallback = new Map();
|
||||
|
||||
this._browserType = browserType;
|
||||
const launchOptions = {...defaultBrowserOptions,
|
||||
handleSIGINT: true,
|
||||
handleSIGTERM: true,
|
||||
handleSIGHUP: true,
|
||||
executablePath: browserType.executablePath(),
|
||||
logger: undefined,
|
||||
};
|
||||
const options = {
|
||||
playwrightPath,
|
||||
browserTypeName: browserType.name(),
|
||||
launchOptions,
|
||||
...extraOptions,
|
||||
};
|
||||
this._child = spawn('node', [path.join(__dirname, 'fixtures', 'closeme.js'), JSON.stringify(options)]);
|
||||
this._child.on('error', (...args) => console.log("ERROR", ...args));
|
||||
this._exitPromise = new Promise(resolve => this._child.on('exit', resolve));
|
||||
|
||||
let outputString = '';
|
||||
this._child.stdout.on('data', data => {
|
||||
outputString += data.toString();
|
||||
// Uncomment to debug.
|
||||
// console.log(data.toString());
|
||||
let match;
|
||||
while (match = outputString.match(/\(([^()]+)=>([^()]+)\)/)) {
|
||||
const key = match[1];
|
||||
const value = match[2];
|
||||
this._addOutput(key, value);
|
||||
outputString = outputString.substring(match.index + match[0].length);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_addOutput(key, value) {
|
||||
this._output.set(key, value);
|
||||
const cb = this._outputCallback.get(key);
|
||||
this._outputCallback.delete(key);
|
||||
if (cb)
|
||||
cb();
|
||||
}
|
||||
|
||||
async out(key) {
|
||||
if (!this._output.has(key))
|
||||
await new Promise(f => this._outputCallback.set(key, f));
|
||||
return this._output.get(key);
|
||||
}
|
||||
|
||||
async connect() {
|
||||
const wsEndpoint = await this.out('wsEndpoint');
|
||||
const browser = await this._browserType.connect({ wsEndpoint });
|
||||
this._exitAndDisconnectPromise = Promise.all([
|
||||
this._exitPromise,
|
||||
new Promise(resolve => browser.once('disconnected', resolve)),
|
||||
]).then(([exitCode]) => exitCode);
|
||||
}
|
||||
|
||||
child() {
|
||||
return this._child;
|
||||
}
|
||||
|
||||
async childExitCode() {
|
||||
return await this._exitAndDisconnectPromise;
|
||||
}
|
||||
}
|
||||
|
||||
registerFixture('wrapper', async ({browserType, defaultBrowserOptions}, test) => {
|
||||
const wrapper = new Wrapper(browserType, defaultBrowserOptions);
|
||||
await wrapper.connect();
|
||||
await test(wrapper);
|
||||
});
|
||||
|
||||
registerFixture('stallingWrapper', async ({browserType, defaultBrowserOptions}, test) => {
|
||||
const wrapper = new Wrapper(browserType, defaultBrowserOptions, { stallOnClose: true });
|
||||
await wrapper.connect();
|
||||
await test(wrapper);
|
||||
});
|
||||
|
||||
describe('Fixtures', function() {
|
||||
it.slow()('should close the browser when the node process closes', async ({wrapper}) => {
|
||||
if (WIN)
|
||||
execSync(`taskkill /pid ${wrapper.child().pid} /T /F`);
|
||||
else
|
||||
process.kill(wrapper.child().pid);
|
||||
expect(await wrapper.childExitCode()).toBe(WIN ? 1 : 0);
|
||||
// We might not get browser exitCode in time when killing the parent node process,
|
||||
// so we don't check it here.
|
||||
});
|
||||
|
||||
describe.skip(WIN || !HEADLESS)('signals', () => {
|
||||
// Cannot reliably send signals on Windows.
|
||||
it.slow()('should report browser close signal', async ({wrapper}) => {
|
||||
const pid = await wrapper.out('pid');
|
||||
process.kill(-pid, 'SIGTERM');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGTERM');
|
||||
process.kill(wrapper.child().pid);
|
||||
await wrapper.childExitCode();
|
||||
});
|
||||
it.slow()('should report browser close signal 2', async ({wrapper}) => {
|
||||
const pid = await wrapper.out('pid');
|
||||
process.kill(-pid, 'SIGKILL');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGKILL');
|
||||
process.kill(wrapper.child().pid);
|
||||
await wrapper.childExitCode();
|
||||
});
|
||||
it.slow()('should close the browser on SIGINT', async ({wrapper}) => {
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
expect(await wrapper.out('exitCode')).toBe('0');
|
||||
expect(await wrapper.out('signal')).toBe('null');
|
||||
expect(await wrapper.childExitCode()).toBe(130);
|
||||
});
|
||||
it.slow()('should close the browser on SIGTERM', async ({wrapper}) => {
|
||||
process.kill(wrapper.child().pid, 'SIGTERM');
|
||||
expect(await wrapper.out('exitCode')).toBe('0');
|
||||
expect(await wrapper.out('signal')).toBe('null');
|
||||
expect(await wrapper.childExitCode()).toBe(0);
|
||||
});
|
||||
it.slow()('should close the browser on SIGHUP', async ({wrapper}) => {
|
||||
process.kill(wrapper.child().pid, 'SIGHUP');
|
||||
expect(await wrapper.out('exitCode')).toBe('0');
|
||||
expect(await wrapper.out('signal')).toBe('null');
|
||||
expect(await wrapper.childExitCode()).toBe(0);
|
||||
});
|
||||
it.slow()('should kill the browser on double SIGINT', async ({stallingWrapper}) => {
|
||||
const wrapper = stallingWrapper;
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
await wrapper.out('stalled');
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGKILL');
|
||||
expect(await wrapper.childExitCode()).toBe(130);
|
||||
});
|
||||
it.slow()('should kill the browser on SIGINT + SIGTERM', async ({stallingWrapper}) => {
|
||||
const wrapper = stallingWrapper;
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
await wrapper.out('stalled');
|
||||
process.kill(wrapper.child().pid, 'SIGTERM');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGKILL');
|
||||
expect(await wrapper.childExitCode()).toBe(0);
|
||||
});
|
||||
it.slow()('should kill the browser on SIGTERM + SIGINT', async ({stallingWrapper}) => {
|
||||
const wrapper = stallingWrapper;
|
||||
process.kill(wrapper.child().pid, 'SIGTERM');
|
||||
await wrapper.out('stalled');
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGKILL');
|
||||
expect(await wrapper.childExitCode()).toBe(130);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('StackTrace', () => {
|
||||
it('caller file path', async ({}) => {
|
||||
const stackTrace = require(path.join(playwrightPath, 'lib', 'utils', 'stackTrace'));
|
||||
const callme = require('./fixtures/callback');
|
||||
const filePath = callme(() => {
|
||||
return stackTrace.getCallerFilePath(path.join(__dirname, 'fixtures') + path.sep);
|
||||
});
|
||||
expect(filePath).toBe(__filename);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
/**
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const {spawn, execSync} = require('child_process');
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, LINUX, HEADLESS} = testOptions;
|
||||
|
||||
const playwrightPath = path.join(__dirname, '..');
|
||||
|
||||
class Wrapper {
|
||||
constructor(browserType, defaultBrowserOptions, extraOptions) {
|
||||
this._output = new Map();
|
||||
this._outputCallback = new Map();
|
||||
|
||||
this._browserType = browserType;
|
||||
const launchOptions = {...defaultBrowserOptions,
|
||||
handleSIGINT: true,
|
||||
handleSIGTERM: true,
|
||||
handleSIGHUP: true,
|
||||
executablePath: browserType.executablePath(),
|
||||
logger: undefined,
|
||||
};
|
||||
const options = {
|
||||
playwrightPath,
|
||||
browserTypeName: browserType.name(),
|
||||
launchOptions,
|
||||
...extraOptions,
|
||||
};
|
||||
this._child = spawn('node', [path.join(__dirname, 'fixtures', 'closeme.js'), JSON.stringify(options)]);
|
||||
this._child.on('error', (...args) => console.log("ERROR", ...args));
|
||||
this._exitPromise = new Promise(resolve => this._child.on('exit', resolve));
|
||||
|
||||
let outputString = '';
|
||||
this._child.stdout.on('data', data => {
|
||||
outputString += data.toString();
|
||||
// Uncomment to debug.
|
||||
// console.log(data.toString());
|
||||
let match;
|
||||
while (match = outputString.match(/\(([^()]+)=>([^()]+)\)/)) {
|
||||
const key = match[1];
|
||||
const value = match[2];
|
||||
this._addOutput(key, value);
|
||||
outputString = outputString.substring(match.index + match[0].length);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_addOutput(key, value) {
|
||||
this._output.set(key, value);
|
||||
const cb = this._outputCallback.get(key);
|
||||
this._outputCallback.delete(key);
|
||||
if (cb)
|
||||
cb();
|
||||
}
|
||||
|
||||
async out(key) {
|
||||
if (!this._output.has(key))
|
||||
await new Promise(f => this._outputCallback.set(key, f));
|
||||
return this._output.get(key);
|
||||
}
|
||||
|
||||
async connect() {
|
||||
const wsEndpoint = await this.out('wsEndpoint');
|
||||
const browser = await this._browserType.connect({ wsEndpoint });
|
||||
this._exitAndDisconnectPromise = Promise.all([
|
||||
this._exitPromise,
|
||||
new Promise(resolve => browser.once('disconnected', resolve)),
|
||||
]).then(([exitCode]) => exitCode);
|
||||
}
|
||||
|
||||
child() {
|
||||
return this._child;
|
||||
}
|
||||
|
||||
async childExitCode() {
|
||||
return await this._exitAndDisconnectPromise;
|
||||
}
|
||||
}
|
||||
|
||||
registerFixture('wrapper', async ({browserType, defaultBrowserOptions}, test) => {
|
||||
const wrapper = new Wrapper(browserType, defaultBrowserOptions);
|
||||
await wrapper.connect();
|
||||
await test(wrapper);
|
||||
});
|
||||
|
||||
registerFixture('stallingWrapper', async ({browserType, defaultBrowserOptions}, test) => {
|
||||
const wrapper = new Wrapper(browserType, defaultBrowserOptions, { stallOnClose: true });
|
||||
await wrapper.connect();
|
||||
await test(wrapper);
|
||||
});
|
||||
|
||||
it.slow()('should close the browser when the node process closes', async ({wrapper}) => {
|
||||
if (WIN)
|
||||
execSync(`taskkill /pid ${wrapper.child().pid} /T /F`);
|
||||
else
|
||||
process.kill(wrapper.child().pid);
|
||||
expect(await wrapper.childExitCode()).toBe(WIN ? 1 : 0);
|
||||
// We might not get browser exitCode in time when killing the parent node process,
|
||||
// so we don't check it here.
|
||||
});
|
||||
|
||||
// Cannot reliably send signals on Windows.
|
||||
it.skip(WIN || !HEADLESS).slow()('should report browser close signal', async ({wrapper}) => {
|
||||
const pid = await wrapper.out('pid');
|
||||
process.kill(-pid, 'SIGTERM');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGTERM');
|
||||
process.kill(wrapper.child().pid);
|
||||
await wrapper.childExitCode();
|
||||
});
|
||||
|
||||
it.skip(WIN || !HEADLESS).slow()('should report browser close signal 2', async ({wrapper}) => {
|
||||
const pid = await wrapper.out('pid');
|
||||
process.kill(-pid, 'SIGKILL');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGKILL');
|
||||
process.kill(wrapper.child().pid);
|
||||
await wrapper.childExitCode();
|
||||
});
|
||||
|
||||
it.skip(WIN || !HEADLESS).slow()('should close the browser on SIGINT', async ({wrapper}) => {
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
expect(await wrapper.out('exitCode')).toBe('0');
|
||||
expect(await wrapper.out('signal')).toBe('null');
|
||||
expect(await wrapper.childExitCode()).toBe(130);
|
||||
});
|
||||
|
||||
it.skip(WIN || !HEADLESS).slow()('should close the browser on SIGTERM', async ({wrapper}) => {
|
||||
process.kill(wrapper.child().pid, 'SIGTERM');
|
||||
expect(await wrapper.out('exitCode')).toBe('0');
|
||||
expect(await wrapper.out('signal')).toBe('null');
|
||||
expect(await wrapper.childExitCode()).toBe(0);
|
||||
});
|
||||
|
||||
it.skip(WIN || !HEADLESS).slow()('should close the browser on SIGHUP', async ({wrapper}) => {
|
||||
process.kill(wrapper.child().pid, 'SIGHUP');
|
||||
expect(await wrapper.out('exitCode')).toBe('0');
|
||||
expect(await wrapper.out('signal')).toBe('null');
|
||||
expect(await wrapper.childExitCode()).toBe(0);
|
||||
});
|
||||
|
||||
it.skip(WIN || !HEADLESS).slow()('should kill the browser on double SIGINT', async ({stallingWrapper}) => {
|
||||
const wrapper = stallingWrapper;
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
await wrapper.out('stalled');
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGKILL');
|
||||
expect(await wrapper.childExitCode()).toBe(130);
|
||||
});
|
||||
|
||||
it.skip(WIN || !HEADLESS).slow()('should kill the browser on SIGINT + SIGTERM', async ({stallingWrapper}) => {
|
||||
const wrapper = stallingWrapper;
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
await wrapper.out('stalled');
|
||||
process.kill(wrapper.child().pid, 'SIGTERM');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGKILL');
|
||||
expect(await wrapper.childExitCode()).toBe(0);
|
||||
});
|
||||
|
||||
it.skip(WIN || !HEADLESS).slow()('should kill the browser on SIGTERM + SIGINT', async ({stallingWrapper}) => {
|
||||
const wrapper = stallingWrapper;
|
||||
process.kill(wrapper.child().pid, 'SIGTERM');
|
||||
await wrapper.out('stalled');
|
||||
process.kill(wrapper.child().pid, 'SIGINT');
|
||||
expect(await wrapper.out('exitCode')).toBe('null');
|
||||
expect(await wrapper.out('signal')).toBe('SIGKILL');
|
||||
expect(await wrapper.childExitCode()).toBe(130);
|
||||
});
|
||||
|
||||
it('caller file path', async ({}) => {
|
||||
const stackTrace = require(path.join(playwrightPath, 'lib', 'utils', 'stackTrace'));
|
||||
const callme = require('./fixtures/callback');
|
||||
const filePath = callme(() => {
|
||||
return stackTrace.getCallerFilePath(path.join(__dirname, 'fixtures') + path.sep);
|
||||
});
|
||||
expect(filePath).toBe(__filename);
|
||||
});
|
||||
|
|
@ -1,314 +0,0 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const utils = require('./utils');
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
|
||||
describe('Playwright', function() {
|
||||
describe('browserType.launch', function() {
|
||||
it('should reject all promises when browser is closed', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
const page = await (await browser.newContext()).newPage();
|
||||
let error = null;
|
||||
const neverResolves = page.evaluate(() => new Promise(r => {})).catch(e => error = e);
|
||||
await page.evaluate(() => new Promise(f => setTimeout(f, 0)));
|
||||
await browser.close();
|
||||
await neverResolves;
|
||||
expect(error.message).toContain('Protocol error');
|
||||
});
|
||||
it('should throw if userDataDir option is passed', async({browserType, defaultBrowserOptions}) => {
|
||||
let waitError = null;
|
||||
const options = Object.assign({}, defaultBrowserOptions, {userDataDir: 'random-path'});
|
||||
await browserType.launch(options).catch(e => waitError = e);
|
||||
expect(waitError.message).toContain('launchPersistentContext');
|
||||
});
|
||||
it.skip(FFOX)('should throw if page argument is passed', async({browserType, defaultBrowserOptions}) => {
|
||||
let waitError = null;
|
||||
const options = Object.assign({}, defaultBrowserOptions, { args: ['http://example.com'] });
|
||||
await browserType.launch(options).catch(e => waitError = e);
|
||||
expect(waitError.message).toContain('can not specify page');
|
||||
});
|
||||
it.fail(true)('should reject if launched browser fails immediately', async({browserType, defaultBrowserOptions}) => {
|
||||
// I'm getting ENCONRESET on this one.
|
||||
const options = Object.assign({}, defaultBrowserOptions, {executablePath: path.join(__dirname, 'assets', 'dummy_bad_browser_executable.js')});
|
||||
let waitError = null;
|
||||
await browserType.launch(options).catch(e => waitError = e);
|
||||
expect(waitError.message).toContain('== logs ==');
|
||||
});
|
||||
it('should reject if executable path is invalid', async({browserType, defaultBrowserOptions}) => {
|
||||
let waitError = null;
|
||||
const options = Object.assign({}, defaultBrowserOptions, {executablePath: 'random-invalid-path'});
|
||||
await browserType.launch(options).catch(e => waitError = e);
|
||||
expect(waitError.message).toContain('Failed to launch');
|
||||
});
|
||||
it.skip(USES_HOOKS)('should handle timeout', async({browserType, defaultBrowserOptions}) => {
|
||||
const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
expect(error.message).toContain(`browserType.launch: Timeout 5000ms exceeded.`);
|
||||
expect(error.message).toContain(`[browser] <launching>`);
|
||||
expect(error.message).toContain(`[browser] <launched> pid=`);
|
||||
});
|
||||
it.skip(USES_HOOKS)('should handle exception', async({browserType, defaultBrowserOptions}) => {
|
||||
const e = new Error('Dummy');
|
||||
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
expect(error.message).toContain('Dummy');
|
||||
});
|
||||
it.skip(USES_HOOKS)('should report launch log', async({browserType, defaultBrowserOptions}) => {
|
||||
const e = new Error('Dummy');
|
||||
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
|
||||
const error = await browserType.launch(options).catch(e => e);
|
||||
expect(error.message).toContain('<launching>');
|
||||
});
|
||||
it.slow()('should accept objects as options', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch({ ...defaultBrowserOptions, process });
|
||||
await browser.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('browserType.executablePath', function() {
|
||||
it('should work', async({browserType}) => {
|
||||
const executablePath = browserType.executablePath();
|
||||
expect(fs.existsSync(executablePath)).toBe(true);
|
||||
expect(fs.realpathSync(executablePath)).toBe(executablePath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('browserType.name', function() {
|
||||
it('should work', async({browserType}) => {
|
||||
if (WEBKIT)
|
||||
expect(browserType.name()).toBe('webkit');
|
||||
else if (FFOX)
|
||||
expect(browserType.name()).toBe('firefox');
|
||||
else if (CHROMIUM)
|
||||
expect(browserType.name()).toBe('chromium');
|
||||
else
|
||||
throw new Error('Unknown browser');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Top-level requires', function() {
|
||||
it('should require top-level Errors', async({playwright}) => {
|
||||
const Errors = require(path.join(utils.projectRoot(), '/lib/errors.js'));
|
||||
expect(String(Errors.TimeoutError)).toContain('TimeoutError');
|
||||
});
|
||||
it('should require top-level DeviceDescriptors', async({playwright}) => {
|
||||
const Devices = require(path.join(utils.projectRoot(), '/lib/deviceDescriptors.js')).DeviceDescriptors;
|
||||
expect(Devices['iPhone 6']).toBeTruthy();
|
||||
expect(Devices['iPhone 6']).toEqual(playwright.devices['iPhone 6']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Browser.isConnected', () => {
|
||||
it('should set the browser connected state', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
expect(remote.isConnected()).toBe(true);
|
||||
await remote.close();
|
||||
expect(remote.isConnected()).toBe(false);
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
it('should throw when used after isConnected returns false', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
await Promise.all([
|
||||
browserServer.close(),
|
||||
new Promise(f => remote.once('disconnected', f)),
|
||||
]);
|
||||
expect(remote.isConnected()).toBe(false);
|
||||
const error = await page.evaluate('1 + 1').catch(e => e);
|
||||
expect(error.message).toContain('has been closed');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Browser.disconnect', function() {
|
||||
it('should reject navigation when browser closes', async({browserType, defaultBrowserOptions, server}) => {
|
||||
server.setRoute('/one-style.css', () => {});
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
const navigationPromise = page.goto(server.PREFIX + '/one-style.html', {timeout: 60000}).catch(e => e);
|
||||
await server.waitForRequest('/one-style.css');
|
||||
await remote.close();
|
||||
const error = await navigationPromise;
|
||||
expect(error.message).toContain('Navigation failed because page was closed!');
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
it('should reject waitForSelector when browser closes', async({browserType, defaultBrowserOptions, server}) => {
|
||||
server.setRoute('/empty.html', () => {});
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
const watchdog = page.waitForSelector('div', { state: 'attached', timeout: 60000 }).catch(e => e);
|
||||
|
||||
// Make sure the previous waitForSelector has time to make it to the browser before we disconnect.
|
||||
await page.waitForSelector('body', { state: 'attached' });
|
||||
|
||||
await remote.close();
|
||||
const error = await watchdog;
|
||||
expect(error.message).toContain('Protocol error');
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
it('should throw if used after disconnect', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const page = await remote.newPage();
|
||||
await remote.close();
|
||||
const error = await page.evaluate('1 + 1').catch(e => e);
|
||||
expect(error.message).toContain('has been closed');
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
it('should emit close events on pages and contexts', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const context = await remote.newContext();
|
||||
const page = await context.newPage();
|
||||
let pageClosed = false;
|
||||
page.on('close', e => pageClosed = true);
|
||||
await Promise.all([
|
||||
new Promise(f => context.on('close', f)),
|
||||
browserServer.close()
|
||||
]);
|
||||
expect(pageClosed).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Browser.close', function() {
|
||||
it('should terminate network waiters', async({browserType, defaultBrowserOptions, server}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const newPage = await remote.newPage();
|
||||
const results = await Promise.all([
|
||||
newPage.waitForRequest(server.EMPTY_PAGE).catch(e => e),
|
||||
newPage.waitForResponse(server.EMPTY_PAGE).catch(e => e),
|
||||
browserServer.close()
|
||||
]);
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const message = results[i].message;
|
||||
expect(message).toContain('Page closed');
|
||||
expect(message).not.toContain('Timeout');
|
||||
}
|
||||
});
|
||||
it('should fire close event for all contexts', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
const context = await browser.newContext();
|
||||
let closed = false;
|
||||
context.on('close', () => closed = true);
|
||||
await browser.close();
|
||||
expect(closed).toBe(true);
|
||||
});
|
||||
it('should be callable twice', async({browserType, defaultBrowserOptions}) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
await Promise.all([
|
||||
browser.close(),
|
||||
browser.close(),
|
||||
]);
|
||||
await browser.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('browserType.launchServer', function() {
|
||||
it('should work', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const browserContext = await browser.newContext();
|
||||
expect(browserContext.pages().length).toBe(0);
|
||||
expect(browserServer.wsEndpoint()).not.toBe(null);
|
||||
const page = await browserContext.newPage();
|
||||
expect(await page.evaluate('11 * 11')).toBe(121);
|
||||
await page.close();
|
||||
await browser.close();
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
it('should fire "disconnected" when closing the server', async({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const disconnectedEventPromise = new Promise(resolve => browser.once('disconnected', resolve));
|
||||
const closedPromise = new Promise(f => browserServer.on('close', f));
|
||||
browserServer.kill();
|
||||
await Promise.all([
|
||||
disconnectedEventPromise,
|
||||
closedPromise,
|
||||
]);
|
||||
});
|
||||
it('should fire "close" event during kill', async({browserType, defaultBrowserOptions}) => {
|
||||
const order = [];
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const closedPromise = new Promise(f => browserServer.on('close', () => {
|
||||
order.push('closed');
|
||||
f();
|
||||
}));
|
||||
await Promise.all([
|
||||
browserServer.kill().then(() => order.push('killed')),
|
||||
closedPromise,
|
||||
]);
|
||||
expect(order).toEqual(['closed', 'killed']);
|
||||
});
|
||||
it('should return child_process instance', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
expect(browserServer.process().pid).toBeGreaterThan(0);
|
||||
await browserServer.close();
|
||||
});
|
||||
it('should fire close event', async ({browserType, defaultBrowserOptions}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const [result] = await Promise.all([
|
||||
new Promise(f => browserServer.on('close', (exitCode, signal) => f({ exitCode, signal }))),
|
||||
browserServer.close(),
|
||||
]);
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.signal).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('browserType.connect', function() {
|
||||
it.slow()('should be able to reconnect to a browser', async({browserType, defaultBrowserOptions, server}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
{
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const browserContext = await browser.newContext();
|
||||
const page = await browserContext.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await browser.close();
|
||||
}
|
||||
{
|
||||
const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() });
|
||||
const browserContext = await browser.newContext();
|
||||
const page = await browserContext.newPage();
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await browser.close();
|
||||
}
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
});
|
||||
it.fail(USES_HOOKS || (CHROMIUM && WIN)).slow()('should handle exceptions during connect', async({browserType, defaultBrowserOptions, server}) => {
|
||||
const browserServer = await browserType.launchServer(defaultBrowserOptions);
|
||||
const __testHookBeforeCreateBrowser = () => { throw new Error('Dummy') };
|
||||
const error = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint(), __testHookBeforeCreateBrowser }).catch(e => e);
|
||||
await browserServer._checkLeaks();
|
||||
await browserServer.close();
|
||||
expect(error.message).toContain('Dummy');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const utils = require('./utils');
|
||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS, CHANNEL} = testOptions;
|
||||
|
||||
it('should require top-level Errors', async({playwright}) => {
|
||||
const Errors = require(path.join(utils.projectRoot(), '/lib/errors.js'));
|
||||
expect(String(Errors.TimeoutError)).toContain('TimeoutError');
|
||||
});
|
||||
|
||||
it('should require top-level DeviceDescriptors', async({playwright}) => {
|
||||
const Devices = require(path.join(utils.projectRoot(), '/lib/deviceDescriptors.js')).DeviceDescriptors;
|
||||
expect(Devices['iPhone 6']).toBeTruthy();
|
||||
expect(Devices['iPhone 6']).toEqual(playwright.devices['iPhone 6']);
|
||||
});
|
||||
|
|
@ -98,7 +98,7 @@ it('should trigger correct Log', async({page, server}) => {
|
|||
expect(message.type()).toEqual('error');
|
||||
});
|
||||
|
||||
it.only('should have location for console API calls', async({page, server}) => {
|
||||
it('should have location for console API calls', async({page, server}) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
const [message] = await Promise.all([
|
||||
page.waitForEvent('console', m => m.text() === 'yellow' ),
|
||||
|
|
|
|||
Loading…
Reference in New Issue