test: cleanup proxy and context tests (#6085)
This commit is contained in:
parent
1a44f68155
commit
63e471ca22
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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}) => {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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([]);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
|
|
|
|||
28
tests/config/contextTest.ts
Normal file
28
tests/config/contextTest.ts
Normal 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>();
|
||||
|
|
@ -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), {});
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
Loading…
Reference in a new issue