test: cleanup proxy and context tests (#6085)

This commit is contained in:
Dmitry Gozman 2021-04-05 18:48:46 -07:00 committed by GitHub
parent 1a44f68155
commit 63e471ca22
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 138 additions and 176 deletions

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { test as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
it('should close browser with beforeunload page', async ({server, browserType, browserOptions }) => {
const browser = await browserType.launch(browserOptions);
@ -27,18 +27,15 @@ it('should close browser with beforeunload page', async ({server, browserType, b
await browser.close();
});
it('should close browsercontext with beforeunload page', async ({server, contextFactory }) => {
const browserContext = await contextFactory();
const page = await browserContext.newPage();
it('should close browsercontext with beforeunload page', async ({server, page, context }) => {
await page.goto(server.PREFIX + '/beforeunload.html');
// We have to interact with a page so that 'beforeunload' handlers
// fire.
await page.click('body');
await browserContext.close();
await context.close();
});
it('should close page with beforeunload listener', async ({contextFactory, server}) => {
const context = await contextFactory();
it('should close page with beforeunload listener', async ({context, server}) => {
const newPage = await context.newPage();
await newPage.goto(server.PREFIX + '/beforeunload.html');
// We have to interact with a page so that 'beforeunload' handlers
@ -47,8 +44,7 @@ it('should close page with beforeunload listener', async ({contextFactory, serve
await newPage.close();
});
it('should run beforeunload if asked for', async ({contextFactory, server, isChromium, isWebKit}) => {
const context = await contextFactory();
it('should run beforeunload if asked for', async ({context, server, isChromium, isWebKit}) => {
const newPage = await context.newPage();
await newPage.goto(server.PREFIX + '/beforeunload.html');
// We have to interact with a page so that 'beforeunload' handlers
@ -72,9 +68,7 @@ it('should run beforeunload if asked for', async ({contextFactory, server, isChr
]);
});
it('should access page after beforeunload', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should access page after beforeunload', async ({page, server}) => {
await page.goto(server.PREFIX + '/beforeunload.html');
// We have to interact with a page so that 'beforeunload' handlers
// fire.

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { contextTest as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
import { slowTest as playwrightTest } from './config/playwrightTest';
it('should work', async ({context, page, server}) => {

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { contextTest as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
it('should work with browser context scripts', async ({ context, server }) => {
await context.addInitScript(() => window['temp'] = 123);

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { contextTest as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
it('should clear cookies', async ({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { contextTest as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
it('should return no cookies in pristine browser context', async ({context, page, server}) => {
expect(await context.cookies()).toEqual([]);

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { contextTest as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
it('expose binding should work', async ({context}) => {
let bindingSource;

View file

@ -14,7 +14,17 @@
* limitations under the License.
*/
import { proxyTest as it, expect } from './config/browserTest';
import { test as it, expect } from './config/browserTest';
import type { Browser } from '../index';
let browser: Browser;
it.beforeEach(async ({ browserType, browserOptions }) => {
if (!browser)
browser = await browserType.launch({ ...browserOptions, proxy: { server: 'per-context' } });
});
it.afterAll(async () => {
await browser.close();
});
it('should throw for missing global proxy', async ({ browserType, browserOptions, server }) => {
delete browserOptions.proxy;
@ -24,8 +34,8 @@ it('should throw for missing global proxy', async ({ browserType, browserOptions
await browser.close();
});
it('should throw for bad server value', async ({ contextFactory, contextOptions }) => {
const error = await contextFactory({
it('should throw for bad server value', async ({ contextOptions }) => {
const error = await browser.newContext({
...contextOptions,
// @ts-expect-error server must be a string
proxy: { server: 123 }
@ -33,86 +43,86 @@ it('should throw for bad server value', async ({ contextFactory, contextOptions
expect(error.message).toContain('proxy.server: expected string, got number');
});
it('should use proxy', async ({ contextFactory, contextOptions, server }) => {
it('should use proxy', async ({ contextOptions, server }) => {
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
const browser = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `localhost:${server.PORT}` }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://non-existent.com/target.html');
expect(await page.title()).toBe('Served by the proxy');
await browser.close();
await context.close();
});
it('should use proxy twice', async ({ contextFactory, contextOptions, server }) => {
it('should use proxy twice', async ({ contextOptions, server }) => {
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
const browser = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `localhost:${server.PORT}` }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://non-existent.com/target.html');
await page.goto('http://non-existent-2.com/target.html');
expect(await page.title()).toBe('Served by the proxy');
await browser.close();
await context.close();
});
it('should use proxy for second page', async ({contextFactory, contextOptions, server}) => {
it('should use proxy for second page', async ({contextOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
const browser = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `localhost:${server.PORT}` }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://non-existent.com/target.html');
expect(await page.title()).toBe('Served by the proxy');
const page2 = await browser.newPage();
const page2 = await context.newPage();
await page2.goto('http://non-existent.com/target.html');
expect(await page2.title()).toBe('Served by the proxy');
await browser.close();
await context.close();
});
it('should work with IP:PORT notion', async ({contextFactory, contextOptions, server}) => {
it('should work with IP:PORT notion', async ({contextOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
const browser = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `127.0.0.1:${server.PORT}` }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://non-existent.com/target.html');
expect(await page.title()).toBe('Served by the proxy');
await browser.close();
await context.close();
});
it('should throw for socks5 authentication', async ({contextFactory, contextOptions}) => {
const error = await contextFactory({
it('should throw for socks5 authentication', async ({contextOptions}) => {
const error = await browser.newContext({
...contextOptions,
proxy: { server: `socks5://localhost:1234`, username: 'user', password: 'secret' }
}).catch(e => e);
expect(error.message).toContain('Browser does not support socks5 proxy authentication');
});
it('should throw for socks4 authentication', async ({contextFactory, contextOptions}) => {
const error = await contextFactory({
it('should throw for socks4 authentication', async ({contextOptions}) => {
const error = await browser.newContext({
...contextOptions,
proxy: { server: `socks4://localhost:1234`, username: 'user', password: 'secret' }
}).catch(e => e);
expect(error.message).toContain('Socks4 proxy protocol does not support authentication');
});
it('should authenticate', async ({contextFactory, contextOptions, server}) => {
it('should authenticate', async ({contextOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
const auth = req.headers['proxy-authorization'];
if (!auth) {
@ -124,17 +134,17 @@ it('should authenticate', async ({contextFactory, contextOptions, server}) => {
res.end(`<html><title>${auth}</title></html>`);
}
});
const browser = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `localhost:${server.PORT}`, username: 'user', password: 'secret' }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://non-existent.com/target.html');
expect(await page.title()).toBe('Basic ' + Buffer.from('user:secret').toString('base64'));
await browser.close();
await context.close();
});
it('should authenticate with empty password', async ({contextFactory, contextOptions, server}) => {
it('should authenticate with empty password', async ({contextOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
const auth = req.headers['proxy-authorization'];
if (!auth) {
@ -146,18 +156,18 @@ it('should authenticate with empty password', async ({contextFactory, contextOpt
res.end(`<html><title>${auth}</title></html>`);
}
});
const browser = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `localhost:${server.PORT}`, username: 'user', password: '' }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://non-existent.com/target.html');
expect(await page.title()).toBe('Basic ' + Buffer.from('user:').toString('base64'));
await browser.close();
await context.close();
});
it('should isolate proxy credentials between contexts', async ({contextFactory, contextOptions, server, browserName}) => {
it('should isolate proxy credentials between contexts', async ({contextOptions, server, browserName}) => {
it.fixme(browserName === 'firefox', 'Credentials from the first context stick around');
server.setRoute('/target.html', async (req, res) => {
@ -172,7 +182,7 @@ it('should isolate proxy credentials between contexts', async ({contextFactory,
}
});
{
const context = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `localhost:${server.PORT}`, username: 'user1', password: 'secret1' }
});
@ -182,7 +192,7 @@ it('should isolate proxy credentials between contexts', async ({contextFactory,
await context.close();
}
{
const context = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `localhost:${server.PORT}`, username: 'user2', password: 'secret2' }
});
@ -193,7 +203,7 @@ it('should isolate proxy credentials between contexts', async ({contextFactory,
}
});
it('should exclude patterns', async ({contextFactory, contextOptions, server, browserName, headful}) => {
it('should exclude patterns', async ({contextOptions, server, browserName, headful}) => {
it.fixme(browserName === 'chromium' && headful, 'Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.');
server.setRoute('/target.html', async (req, res) => {
@ -203,12 +213,12 @@ it('should exclude patterns', async ({contextFactory, contextOptions, server, br
// that resolves everything to some weird search results page.
//
// @see https://gist.github.com/CollinChaffin/24f6c9652efb3d6d5ef2f5502720ef00
const browser = await contextFactory({
const context = await browser.newContext({
...contextOptions,
proxy: { server: `localhost:${server.PORT}`, bypass: '1.non.existent.domain.for.the.test, 2.non.existent.domain.for.the.test, .another.test' }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://0.non.existent.domain.for.the.test/target.html');
expect(await page.title()).toBe('Served by the proxy');
@ -232,41 +242,41 @@ it('should exclude patterns', async ({contextFactory, contextOptions, server, br
expect(await page.title()).toBe('Served by the proxy');
}
await browser.close();
await context.close();
});
it('should use socks proxy', async ({ contextFactory, contextOptions, socksPort }) => {
const browser = await contextFactory({
it('should use socks proxy', async ({ contextOptions, socksPort }) => {
const context = await browser.newContext({
...contextOptions,
proxy: { server: `socks5://localhost:${socksPort}` }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://non-existent.com');
expect(await page.title()).toBe('Served by the SOCKS proxy');
await browser.close();
await context.close();
});
it('should use socks proxy in second page', async ({ contextFactory, contextOptions, socksPort }) => {
const browser = await contextFactory({
it('should use socks proxy in second page', async ({ contextOptions, socksPort }) => {
const context = await browser.newContext({
...contextOptions,
proxy: { server: `socks5://localhost:${socksPort}` }
});
const page = await browser.newPage();
const page = await context.newPage();
await page.goto('http://non-existent.com');
expect(await page.title()).toBe('Served by the SOCKS proxy');
const page2 = await browser.newPage();
const page2 = await context.newPage();
await page2.goto('http://non-existent.com');
expect(await page2.title()).toBe('Served by the SOCKS proxy');
await browser.close();
await context.close();
});
it('does launch without a port', async ({ contextFactory, contextOptions }) => {
const browser = await contextFactory({
it('does launch without a port', async ({ contextOptions }) => {
const context = await browser.newContext({
...contextOptions,
proxy: { server: 'http://localhost' }
});
await browser.close();
await context.close();
});

View file

@ -16,20 +16,16 @@
import os from 'os';
import url from 'url';
import { test as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
it('Web Assembly should work', async function({contextFactory, server, browserName, platform}) {
it('Web Assembly should work', async function({page, server, browserName, platform}) {
it.fail(browserName === 'webkit' && platform === 'win32');
const context = await contextFactory();
const page = await context.newPage();
await page.goto(server.PREFIX + '/wasm/table2.html');
expect(await page.evaluate('loadTable()')).toBe('42, 83');
});
it('WebSocket should work', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('WebSocket should work', async ({page, server}) => {
const value = await page.evaluate(port => {
let cb;
const result = new Promise(f => cb = f);
@ -41,7 +37,7 @@ it('WebSocket should work', async ({contextFactory, server}) => {
expect(value).toBe('incoming');
});
it('should respect CSP', async ({contextFactory, server}) => {
it('should respect CSP', async ({page, server}) => {
server.setRoute('/empty.html', async (req, res) => {
res.setHeader('Content-Security-Policy', `script-src 'unsafe-inline';`);
res.end(`
@ -51,22 +47,17 @@ it('should respect CSP', async ({contextFactory, server}) => {
</script>`);
});
const context = await contextFactory();
const page = await context.newPage();
await page.goto(server.EMPTY_PAGE);
expect(await page.evaluate(() => window['testStatus'])).toBe('SUCCESS');
});
it('should play video', async ({contextFactory, asset, isWebKit, browserName, platform}) => {
it('should play video', async ({page, asset, isWebKit, browserName, platform}) => {
// TODO: the test passes on Windows locally but fails on GitHub Action bot,
// apparently due to a Media Pack issue in the Windows Server.
// Also the test is very flaky on Linux WebKit.
it.fixme(browserName === 'webkit' && platform !== 'darwin');
it.fixme(browserName === 'webkit' && platform === 'darwin' && parseInt(os.release(), 10) >= 20, 'Does not work on BigSur');
const context = await contextFactory();
const page = await context.newPage();
// Safari only plays mp4 so we test WebKit with an .mp4 clip.
const fileName = isWebKit ? 'video_mp4.html' : 'video.html';
const absolutePath = asset(fileName);
@ -77,11 +68,9 @@ it('should play video', async ({contextFactory, asset, isWebKit, browserName, pl
await page.$eval('video', v => v.pause());
});
it('should support webgl', async ({contextFactory, browserName, headful}) => {
it('should support webgl', async ({page, browserName, headful}) => {
it.fixme(browserName === 'firefox' && !headful);
const context = await contextFactory();
const page = await context.newPage();
const hasWebGL = await page.evaluate(() => {
const canvas = document.createElement('canvas');
return !!canvas.getContext('webgl');
@ -89,13 +78,11 @@ it('should support webgl', async ({contextFactory, browserName, headful}) => {
expect(hasWebGL).toBe(true);
});
it('should support webgl 2', async ({contextFactory, browserName, headful}) => {
it('should support webgl 2', async ({page, browserName, headful}) => {
it.skip(browserName === 'webkit', 'WebKit doesn\'t have webgl2 enabled yet upstream.');
it.fixme(browserName === 'firefox' && !headful);
it.fixme(browserName === 'chromium' && headful, 'chromium doesn\'t like webgl2 when running under xvfb');
const context = await contextFactory();
const page = await context.newPage();
const hasWebGL2 = await page.evaluate(() => {
const canvas = document.createElement('canvas');
return !!canvas.getContext('webgl2');

View file

@ -15,7 +15,7 @@
*/
import { newTestType } from 'folio';
import type { Browser, BrowserContextOptions, BrowserContext, Page } from '../../index';
import type { Browser, BrowserContextOptions, BrowserContext } from '../../index';
import type { PlaywrightTestArgs } from './playwrightTest';
import type { ServerTestArgs } from './serverTest';
export { expect } from 'folio';
@ -28,11 +28,3 @@ export type BrowserTestArgs = PlaywrightTestArgs & {
export const test = newTestType<BrowserTestArgs & ServerTestArgs>();
export const slowTest = newTestType<BrowserTestArgs & ServerTestArgs>();
export const proxyTest = newTestType<BrowserTestArgs & ServerTestArgs>();
// Context test guarantees an isolated context.
export type ContextTestArgs = BrowserTestArgs & {
context: BrowserContext;
page: Page;
};
export const contextTest = newTestType<ContextTestArgs & ServerTestArgs>();

View file

@ -0,0 +1,28 @@
/**
* 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.
*/
import { newTestType } from 'folio';
import type { BrowserContext, Page } from '../../index';
import type { BrowserTestArgs } from './browserTest';
import type { ServerTestArgs } from './serverTest';
export { expect } from 'folio';
// Context test guarantees an isolated context.
export type ContextTestArgs = BrowserTestArgs & {
context: BrowserContext;
page: Page;
};
export const test = newTestType<ContextTestArgs & ServerTestArgs>();

View file

@ -17,7 +17,8 @@
import { setConfig, Config } from 'folio';
import * as path from 'path';
import { test as playwrightTest, slowTest as playwrightSlowTest } from './playwrightTest';
import { test as browserTest, contextTest, proxyTest, slowTest as browserSlowTest } from './browserTest';
import { test as browserTest, slowTest as browserSlowTest } from './browserTest';
import { test as contextTest } from './contextTest';
import { test as pageTest } from './pageTest';
import { test as electronTest } from './electronTest';
import { test as cliTest } from './cliTest';
@ -67,10 +68,7 @@ for (const browserName of browsers) {
playwrightSlowTest.runWith(browserName, serverEnv, new PlaywrightEnv(browserName, options), { timeout: config.timeout * 3 });
browserTest.runWith(browserName, serverEnv, new BrowserEnv(browserName, options), {});
browserSlowTest.runWith(browserName, serverEnv, new BrowserEnv(browserName, options), { timeout: config.timeout * 3 });
// TODO: perhaps export proxyTest from the test file?
proxyTest.runWith(browserName, serverEnv, new BrowserEnv(browserName, { ...options, proxy: { server: 'per-context' } }), {});
pageTest.runWith(browserName, serverEnv, new PageEnv(browserName, options), {});
// TODO: get rid of contextTest if there isn't too many of them.
contextTest.runWith(browserName, serverEnv, new PageEnv(browserName, options), {});
if (mode !== 'service')
cliTest.runWith(browserName, serverEnv, new CLIEnv(browserName, options), {});

View file

@ -15,15 +15,12 @@
* limitations under the License.
*/
import { test as it } from './config/browserTest';
import { test as it } from './config/contextTest';
it('should load svg favicon with prefer-color-scheme', async ({contextFactory, server, browserName, browserChannel, headful, asset}) => {
it('should load svg favicon with prefer-color-scheme', async ({page, server, browserName, browserChannel, headful, asset}) => {
it.skip(!headful && browserName !== 'firefox', 'headless browsers, except firefox, do not request favicons');
it.skip(headful && browserName === 'webkit' && !browserChannel, 'playwright headful webkit does not have a favicon feature');
const context = await contextFactory();
const page = await context.newPage();
// Browsers aggresively cache favicons, so force bust with the
// `d` parameter to make iterating on this test more predictable and isolated.
const favicon = `/favicon.svg?d=${Date.now()}`;
@ -59,6 +56,4 @@ it('should load svg favicon with prefer-color-scheme', async ({contextFactory, s
await page.waitForTimeout(500);
// Text still being around ensures we haven't actually lost our browser to a crash.
await page.waitForSelector('text=favicons');
await page.close();
});

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { test as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
function getPermission(page, name) {
return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name);
@ -26,91 +26,64 @@ it.describe('permissions', () => {
it.skip(browserName === 'webkit', 'Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)');
});
it('should be prompt by default', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should be prompt by default', async ({page, server}) => {
await page.goto(server.EMPTY_PAGE);
expect(await getPermission(page, 'geolocation')).toBe('prompt');
await context.close();
});
it('should deny permission when not listed', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should deny permission when not listed', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.grantPermissions([], { origin: server.EMPTY_PAGE });
expect(await getPermission(page, 'geolocation')).toBe('denied');
await context.close();
});
it('should fail when bad permission is given', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should fail when bad permission is given', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
let error: Error;
await context.grantPermissions(['foo'], { origin: server.EMPTY_PAGE }).catch(e => error = e);
expect(error.message).toContain('Unknown permission: foo');
await context.close();
});
it('should grant geolocation permission when origin is listed', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should grant geolocation permission when origin is listed', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE });
expect(await getPermission(page, 'geolocation')).toBe('granted');
await context.close();
});
it('should prompt for geolocation permission when origin is not listed', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should prompt for geolocation permission when origin is not listed', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE });
await page.goto(server.EMPTY_PAGE.replace('localhost', '127.0.0.1'));
expect(await getPermission(page, 'geolocation')).toBe('prompt');
await context.close();
});
it('should grant notifications permission when listed', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should grant notifications permission when listed', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.grantPermissions(['notifications'], { origin: server.EMPTY_PAGE });
expect(await getPermission(page, 'notifications')).toBe('granted');
await context.close();
});
it('should accumulate when adding', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should accumulate when adding', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.grantPermissions(['geolocation']);
await context.grantPermissions(['notifications']);
expect(await getPermission(page, 'geolocation')).toBe('granted');
expect(await getPermission(page, 'notifications')).toBe('granted');
await context.close();
});
it('should clear permissions', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should clear permissions', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.grantPermissions(['geolocation']);
await context.clearPermissions();
await context.grantPermissions(['notifications']);
expect(await getPermission(page, 'geolocation')).not.toBe('granted');
expect(await getPermission(page, 'notifications')).toBe('granted');
await context.close();
});
it('should grant permission when listed for all domains', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should grant permission when listed for all domains', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.grantPermissions(['geolocation']);
expect(await getPermission(page, 'geolocation')).toBe('granted');
await context.close();
});
it('should grant permission when creating context', async ({server, browser}) => {
@ -121,23 +94,18 @@ it.describe('permissions', () => {
await context.close();
});
it('should reset permissions', async ({contextFactory, server}) => {
const context = await contextFactory();
const page = await context.newPage();
it('should reset permissions', async ({page, context, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE });
expect(await getPermission(page, 'geolocation')).toBe('granted');
await context.clearPermissions();
expect(await getPermission(page, 'geolocation')).toBe('prompt');
await context.close();
});
it('should trigger permission onchange', async ({contextFactory, server, browserName, headful}) => {
it('should trigger permission onchange', async ({page, context, server, browserName, headful}) => {
it.fail(browserName === 'webkit');
it.fail(browserName === 'chromium' && headful);
const context = await contextFactory();
const page = await context.newPage();
await page.goto(server.EMPTY_PAGE);
await page.evaluate(() => {
window['events'] = [];
@ -155,7 +123,6 @@ it.describe('permissions', () => {
expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted']);
await context.clearPermissions();
expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted', 'prompt']);
await context.close();
});
it('should isolate permissions between browser contexts', async ({server, browser}) => {
@ -180,13 +147,11 @@ it.describe('permissions', () => {
await context.close();
});
it('should support clipboard read', async ({contextFactory, server, browserName, headful}) => {
it('should support clipboard read', async ({page, context, server, browserName, headful}) => {
it.fail(browserName === 'webkit');
it.fail(browserName === 'firefox', 'No such permissions (requires flag) in Firefox');
it.fixme(browserName === 'chromium' && headful);
const context = await contextFactory();
const page = await context.newPage();
await page.goto(server.EMPTY_PAGE);
expect(await getPermission(page, 'clipboard-read')).toBe('prompt');
let error;
@ -195,6 +160,5 @@ it.describe('permissions', () => {
await context.grantPermissions(['clipboard-read']);
expect(await getPermission(page, 'clipboard-read')).toBe('granted');
await page.evaluate(() => navigator.clipboard.readText());
await context.close();
});
});

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { contextTest as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
import type { Page, Frame } from '../index';
async function generate(pageOrFrame: Page | Frame, target: string): Promise<string> {

View file

@ -14,45 +14,39 @@
* limitations under the License.
*/
import { test as it, expect } from './config/browserTest';
import { test as it, expect } from './config/contextTest';
import { InMemorySnapshotter } from '../lib/server/snapshot/inMemorySnapshotter';
import { HttpServer } from '../lib/utils/httpServer';
import { SnapshotServer } from '../lib/server/snapshot/snapshotServer';
import type { BrowserContext, Page } from '../index';
it.describe('snapshots', () => {
let context: BrowserContext;
let page: Page;
let snapshotter: any;
let httpServer: any;
let snapshotPort: number;
it.beforeEach(async ({ mode, toImpl, contextFactory }, testInfo) => {
it.beforeEach(async ({ mode, toImpl, context }, testInfo) => {
it.skip(mode !== 'default');
context = await contextFactory();
page = await context.newPage();
snapshotter = new InMemorySnapshotter(toImpl(context));
await snapshotter.initialize();
httpServer = new HttpServer();
new SnapshotServer(httpServer, snapshotter);
snapshotPort = 9700 + testInfo.workerIndex;
snapshotPort = 11000 + testInfo.workerIndex;
httpServer.start(snapshotPort);
});
it.afterEach(async () => {
await snapshotter.dispose();
httpServer.stop();
await context.close();
});
it('should collect snapshot', async ({ toImpl }) => {
it('should collect snapshot', async ({ page, toImpl }) => {
await page.setContent('<button>Hello</button>');
const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'snapshot');
expect(distillSnapshot(snapshot)).toBe('<BUTTON>Hello</BUTTON>');
});
it('should capture resources', async ({ toImpl, server }) => {
it('should capture resources', async ({ page, toImpl, server }) => {
await page.goto(server.EMPTY_PAGE);
await page.route('**/style.css', route => {
route.fulfill({ body: 'button { color: red; }', }).catch(() => {});
@ -64,7 +58,7 @@ it.describe('snapshots', () => {
expect(resources[cssHref]).toBeTruthy();
});
it('should collect multiple', async ({ toImpl }) => {
it('should collect multiple', async ({ page, toImpl }) => {
await page.setContent('<button>Hello</button>');
const snapshots = [];
snapshotter.on('snapshot', snapshot => snapshots.push(snapshot));
@ -73,7 +67,7 @@ it.describe('snapshots', () => {
expect(snapshots.length).toBe(2);
});
it('should only collect on change', async ({}) => {
it('should only collect on change', async ({ page }) => {
await page.setContent('<button>Hello</button>');
const snapshots = [];
snapshotter.on('snapshot', snapshot => snapshots.push(snapshot));
@ -88,7 +82,7 @@ it.describe('snapshots', () => {
expect(snapshots.length).toBe(2);
});
it('should respect inline CSSOM change', async ({}) => {
it('should respect inline CSSOM change', async ({ page }) => {
await page.setContent('<style>button { color: red; }</style><button>Hello</button>');
const snapshots = [];
snapshotter.on('snapshot', snapshot => snapshots.push(snapshot));
@ -107,7 +101,7 @@ it.describe('snapshots', () => {
expect(distillSnapshot(snapshots[1])).toBe('<style>button { color: blue; }</style><BUTTON>Hello</BUTTON>');
});
it('should respect subresource CSSOM change', async ({ server }) => {
it('should respect subresource CSSOM change', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await page.route('**/style.css', route => {
route.fulfill({ body: 'button { color: red; }', }).catch(() => {});
@ -134,7 +128,7 @@ it.describe('snapshots', () => {
expect(snapshotter.resourceContent(sha1).toString()).toBe('button { color: blue; }');
});
it('should capture iframe', async ({ contextFactory, server, toImpl, browserName }) => {
it('should capture iframe', async ({ page, contextFactory, server, toImpl, browserName }) => {
it.skip(browserName === 'firefox');
await page.route('**/empty.html', route => {
@ -175,7 +169,7 @@ it.describe('snapshots', () => {
expect(await button.textContent()).toBe('Hello iframe');
});
it('should capture snapshot target', async ({ toImpl }) => {
it('should capture snapshot target', async ({ page, toImpl }) => {
await page.setContent('<button>Hello</button><button>World</button>');
{
const handle = await page.$('text=Hello');
@ -189,7 +183,7 @@ it.describe('snapshots', () => {
}
});
it('should collect on attribute change', async ({ toImpl }) => {
it('should collect on attribute change', async ({ page, toImpl }) => {
await page.setContent('<button>Hello</button>');
{
const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'snapshot');