test: cleanup various testing env variables (#6155)

This commit is contained in:
Dmitry Gozman 2021-04-09 07:59:09 -07:00 committed by GitHub
parent 856ced6e65
commit bd8433ba49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 272 additions and 234 deletions

View File

@ -177,7 +177,7 @@ jobs:
# Enable core dumps in the subshell.
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && npm run ctest"
env:
PWMODE: "${{ matrix.mode }}"
PWTEST_MODE: "${{ matrix.mode }}"
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always() && github.repository == 'microsoft/playwright' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-'))
- uses: actions/upload-artifact@v1
@ -209,7 +209,7 @@ jobs:
# Enable core dumps in the subshell.
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && npm run test -- --tag=${{ matrix.browser }}"
env:
PWVIDEO: 1
PWTEST_VIDEO: 1
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always() && github.repository == 'microsoft/playwright' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-'))
- uses: actions/upload-artifact@v1
@ -272,7 +272,7 @@ jobs:
# Enable core dumps in the subshell.
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && npm run ctest"
env:
PW_CHROMIUM_CHANNEL: "chrome"
PWTEST_CHANNEL: "chrome"
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always() && github.repository == 'microsoft/playwright' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-'))
- uses: actions/upload-artifact@v1
@ -301,7 +301,7 @@ jobs:
- run: npm run ctest
shell: bash
env:
PW_CHROMIUM_CHANNEL: "chrome"
PWTEST_CHANNEL: "chrome"
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always() && github.repository == 'microsoft/playwright' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-'))
shell: bash
@ -327,7 +327,7 @@ jobs:
- run: node lib/cli/cli install ffmpeg
- run: npm run ctest
env:
PW_CHROMIUM_CHANNEL: "chrome"
PWTEST_CHANNEL: "chrome"
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always() && github.repository == 'microsoft/playwright' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-'))
- uses: actions/upload-artifact@v1
@ -356,7 +356,7 @@ jobs:
- run: npm run ctest
shell: bash
env:
PW_CHROMIUM_CHANNEL: "msedge"
PWTEST_CHANNEL: "msedge"
- uses: actions/upload-artifact@v1
if: ${{ always() }}
with:

View File

@ -12,8 +12,8 @@
"ctest": "folio --config=tests/config/default.config.ts --tag=chromium",
"ftest": "folio --config=tests/config/default.config.ts --tag=firefox",
"wtest": "folio --config=tests/config/default.config.ts --tag=webkit",
"atest": "cross-env PW_ANDROID_TESTS=1 folio --config=tests/config/android.config.ts",
"etest": "cross-env PW_ELECTRON_TESTS=1 folio --config=tests/config/electron.config.ts",
"atest": "folio --config=tests/config/android.config.ts",
"etest": "folio --config=tests/config/electron.config.ts",
"test": "folio --config=tests/config/default.config.ts",
"eslint": "[ \"$CI\" = true ] && eslint --quiet -f codeframe --ext js,ts . || eslint --ext js,ts .",
"tsc": "tsc -p .",

View File

@ -453,7 +453,7 @@ function test_playwright_cli_codegen_should_work {
npm install ${PLAYWRIGHT_TGZ}
echo "Running playwright codegen"
OUTPUT=$(PWCLI_EXIT_FOR_TEST=1 xvfb-run --auto-servernum -- bash -c "npx playwright codegen")
OUTPUT=$(PWTEST_CLI_EXIT=1 xvfb-run --auto-servernum -- bash -c "npx playwright codegen")
if [[ "${OUTPUT}" != *"chromium.launch"* ]]; then
echo "ERROR: missing chromium.launch in the output"
exit 1
@ -464,7 +464,7 @@ function test_playwright_cli_codegen_should_work {
fi
echo "Running playwright codegen --target=python"
OUTPUT=$(PWCLI_EXIT_FOR_TEST=1 xvfb-run --auto-servernum -- bash -c "npx playwright codegen --target=python")
OUTPUT=$(PWTEST_CLI_EXIT=1 xvfb-run --auto-servernum -- bash -c "npx playwright codegen --target=python")
if [[ "${OUTPUT}" != *"chromium.launch"* ]]; then
echo "ERROR: missing chromium.launch in the output"
exit 1

View File

@ -348,7 +348,7 @@ async function openPage(context: BrowserContext, url: string | undefined): Promi
}
async function open(options: Options, url: string | undefined, language: string) {
const { context, launchOptions, contextOptions } = await launchContext(options, !!process.env.PWCLI_HEADLESS_FOR_TEST);
const { context, launchOptions, contextOptions } = await launchContext(options, !!process.env.PWTEST_CLI_HEADLESS);
await context._enableRecorder({
language,
launchOptions,
@ -357,12 +357,12 @@ async function open(options: Options, url: string | undefined, language: string)
saveStorage: options.saveStorage,
});
await openPage(context, url);
if (process.env.PWCLI_EXIT_FOR_TEST)
if (process.env.PWTEST_CLI_EXIT)
await Promise.all(context.pages().map(p => p.close()));
}
async function codegen(options: Options, url: string | undefined, language: string, outputFile?: string) {
const { context, launchOptions, contextOptions } = await launchContext(options, !!process.env.PWCLI_HEADLESS_FOR_TEST);
const { context, launchOptions, contextOptions } = await launchContext(options, !!process.env.PWTEST_CLI_HEADLESS);
if (process.env.PWTRACE)
contextOptions._traceDir = path.join(process.cwd(), '.trace');
await context._enableRecorder({
@ -375,7 +375,7 @@ async function codegen(options: Options, url: string | undefined, language: stri
outputFile: outputFile ? path.resolve(outputFile) : undefined
});
await openPage(context, url);
if (process.env.PWCLI_EXIT_FOR_TEST)
if (process.env.PWTEST_CLI_EXIT)
await Promise.all(context.pages().map(p => p.close()));
}

View File

@ -93,7 +93,7 @@ export class FrameExecutionContext extends js.ExecutionContext {
${injectedScriptSource.source}
return new pwExport(
${this.frame._page._delegate.rafCountForStablePosition()},
${!!process.env.PW_USE_TIMEOUT_FOR_RAF},
${!!process.env.PWTEST_USE_TIMEOUT_FOR_RAF},
[${custom.join(',\n')}]
);
})();

View File

@ -99,15 +99,15 @@ export class RecorderApp extends EventEmitter {
'--window-size=600,600',
'--window-position=1280,10',
];
if (process.env.PW_RECORDER_PORT)
args.push(`--remote-debugging-port=${process.env.PW_RECORDER_PORT}`);
if (process.env.PWTEST_RECORDER_PORT)
args.push(`--remote-debugging-port=${process.env.PWTEST_RECORDER_PORT}`);
const context = await recorderPlaywright.chromium.launchPersistentContext(internalCallMetadata(), '', {
channel: inspectedContext._browser.options.channel,
sdkLanguage: inspectedContext._options.sdkLanguage,
args,
noDefaultViewport: true,
headless: !!process.env.PWCLI_HEADLESS_FOR_TEST || (isUnderTest() && !inspectedContext._browser.options.headful),
useWebSocket: !!process.env.PW_RECORDER_PORT
headless: !!process.env.PWTEST_CLI_HEADLESS || (isUnderTest() && !inspectedContext._browser.options.headful),
useWebSocket: !!process.env.PWTEST_RECORDER_PORT
});
const controller = new ProgressController(internalCallMetadata(), context._browser);
await controller.run(async progress => {
@ -145,7 +145,7 @@ export class RecorderApp extends EventEmitter {
// Testing harness for runCLI mode.
{
if (process.env.PWCLI_EXIT_FOR_TEST && sources.length) {
if (process.env.PWTEST_CLI_EXIT && sources.length) {
process.stdout.write('\n-------------8<-------------\n');
process.stdout.write(sources[0].text);
process.stdout.write('\n-------------8<-------------\n');

View File

@ -131,7 +131,7 @@ class TraceViewer {
sdkLanguage: 'javascript',
args,
noDefaultViewport: true,
headless: !!process.env.PWCLI_HEADLESS_FOR_TEST,
headless: !!process.env.PWTEST_CLI_HEADLESS,
useWebSocket: isUnderTest()
});

View File

@ -19,9 +19,9 @@ import { test as it, expect } from './config/pageTest';
import { test as browserTest } from './config/browserTest';
import { verifyViewport } from './config/utils';
it.beforeEach(async () => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'Default viewport is null');
it.skip(!!process.env.PW_ELECTRON_TESTS, 'Default viewport is null');
it.beforeEach(async ({ isElectron, isAndroid }) => {
it.skip(isAndroid, 'Default viewport is null');
it.skip(isElectron, 'Default viewport is null');
});
it('should get the proper default viewport size', async ({page, server}) => {

View File

@ -20,10 +20,10 @@ import { test as playwrightTest } from '../config/playwrightTest';
import http from 'http';
pageTest.describe('chromium', () => {
pageTest.beforeEach(async ({ browserName }) => {
pageTest.beforeEach(async ({ browserName, isElectron, isAndroid }) => {
pageTest.skip(browserName !== 'chromium');
pageTest.skip(!!process.env.PW_ANDROID_TESTS);
pageTest.skip(!!process.env.PW_ELECTRON_TESTS);
pageTest.skip(isAndroid);
pageTest.skip(isElectron);
});
pageTest('should create a worker from a service worker', async ({page, server}) => {

View File

@ -17,9 +17,9 @@
import { test as it, expect } from '../config/pageTest';
it.describe('JS Coverage', () => {
it.beforeEach(async ({ browserName }) => {
it.beforeEach(async ({ browserName, isElectron }) => {
it.skip(browserName !== 'chromium');
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it.fixme(isElectron);
});
it('should work', async function({page, server}) {

View File

@ -41,6 +41,6 @@ if (process.env.CI) {
]);
}
const serverEnv = new ServerEnv();
const serverEnv = new ServerEnv('10.0.2.2');
pageTest.runWith(folio.merge(serverEnv, new AndroidPageEnv()), { tag: 'android' });
androidTest.runWith(folio.merge(serverEnv, new AndroidEnv()), { tag: 'android' });

View File

@ -54,6 +54,8 @@ export class AndroidEnv implements Env<AndroidTestArgs> {
isChromium: true,
isFirefox: false,
isWebKit: false,
isAndroid: true,
isElectron: false,
browserName: 'chromium' as const,
browserChannel: undefined,
isWindows: os.platform() === 'win32',

View File

@ -16,7 +16,6 @@
import type { Env, WorkerInfo, TestInfo } from 'folio';
import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, LaunchOptions } from '../../index';
import { installCoverageHooks } from './coverage';
import { start } from '../../lib/outofprocess';
import { PlaywrightClient } from '../../lib/remote/playwrightClient';
import { removeFolders } from '../../lib/utils/utils';
@ -37,7 +36,6 @@ type TestOptions = {
mode: 'default' | 'driver' | 'service';
video?: boolean;
traceDir?: string;
coverageBrowserName?: string;
};
class DriverMode {
@ -105,7 +103,6 @@ export class PlaywrightEnv implements Env<PlaywrightTestArgs> {
protected _browserOptions: LaunchOptions;
private _playwright: typeof import('../../index');
protected _browserType: BrowserType;
private _coverage: ReturnType<typeof installCoverageHooks> | undefined;
private _userDataDirs: string[] = [];
private _persistentContext: BrowserContext | undefined;
private _remoteServer: RemoteServer | undefined;
@ -121,7 +118,6 @@ export class PlaywrightEnv implements Env<PlaywrightTestArgs> {
}
async beforeAll(workerInfo: WorkerInfo) {
this._coverage = installCoverageHooks(this._options.coverageBrowserName || this._browserName);
require('../../lib/utils/utils').setUnderTest();
this._playwright = await this._mode.setup(workerInfo);
this._browserType = this._playwright[this._browserName];
@ -184,6 +180,8 @@ export class PlaywrightEnv implements Env<PlaywrightTestArgs> {
isChromium: this._browserName === 'chromium',
isFirefox: this._browserName === 'firefox',
isWebKit: this._browserName === 'webkit',
isAndroid: false,
isElectron: false,
isWindows: os.platform() === 'win32',
isMac: os.platform() === 'darwin',
isLinux: os.platform() === 'linux',
@ -213,12 +211,6 @@ export class PlaywrightEnv implements Env<PlaywrightTestArgs> {
async afterAll(workerInfo: WorkerInfo) {
await this._mode.teardown();
const { coverage, uninstall } = this._coverage!;
uninstall();
const coveragePath = path.join(__dirname, '..', 'coverage-report', workerInfo.workerIndex + '.json');
const coverageJSON = Array.from(coverage.keys()).filter(key => coverage.get(key));
await fs.promises.mkdir(path.dirname(coveragePath), { recursive: true });
await fs.promises.writeFile(coveragePath, JSON.stringify(coverageJSON, undefined, 2), 'utf8');
}
}

View File

@ -31,7 +31,7 @@ export class CLIEnv extends PageEnv implements Env<CLITestArgs> {
this._port = 10907 + workerInfo.workerIndex * 2;
this._server = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => this._handler(req, res)).listen(this._port);
process.env.PW_RECORDER_PORT = String(this._port + 1);
process.env.PWTEST_RECORDER_PORT = String(this._port + 1);
}
private _runCLI(args: string[]) {

View File

@ -149,8 +149,8 @@ export class CLIMock {
this.process = spawn('node', nodeArgs, {
env: {
...process.env,
PWCLI_EXIT_FOR_TEST: '1',
PWCLI_HEADLESS_FOR_TEST: headless ? '1' : undefined,
PWTEST_CLI_EXIT: '1',
PWTEST_CLI_HEADLESS: headless ? '1' : undefined,
},
stdio: 'pipe'
});

View File

@ -15,6 +15,9 @@
* limitations under the License.
*/
const path = require('path');
const fs = require('fs');
/**
* @param {Map<string, boolean>} apiCoverage
* @param {Object} events
@ -90,6 +93,35 @@ function installCoverageHooks(browserName) {
return {coverage, uninstall};
}
class CoverageEnv {
/**
* @param {string} browserName
*/
constructor(browserName) {
this.browserName = browserName;
}
/**
* @param {import('folio').WorkerInfo} workerInfo
*/
async beforeAll(workerInfo) {
this.coverage = installCoverageHooks(this.browserName);
}
/**
* @param {import('folio').WorkerInfo} workerInfo
*/
async afterAll(workerInfo) {
const { coverage, uninstall } = this.coverage;
uninstall();
const coveragePath = path.join(__dirname, '..', 'coverage-report', workerInfo.workerIndex + '.json');
const coverageJSON = Array.from(coverage.keys()).filter(key => coverage.get(key));
await fs.promises.mkdir(path.dirname(coveragePath), { recursive: true });
await fs.promises.writeFile(coveragePath, JSON.stringify(coverageJSON, undefined, 2), 'utf8');
}
}
module.exports = {
installCoverageHooks
installCoverageHooks,
CoverageEnv
};

View File

@ -24,11 +24,12 @@ import { test as cliTest } from './cliTest';
import { PlaywrightEnv, BrowserEnv, PageEnv, BrowserName } from './browserEnv';
import { ServerEnv } from './serverEnv';
import { CLIEnv } from './cliEnv';
import { CoverageEnv } from './coverage';
const config: folio.Config = {
testDir: path.join(__dirname, '..'),
outputDir: path.join(__dirname, '..', '..', 'test-results'),
timeout: process.env.PWVIDEO || process.env.PWTRACE ? 60000 : 30000,
timeout: process.env.PWTEST_VIDEO || process.env.PWTRACE ? 60000 : 30000,
globalTimeout: 5400000,
};
if (process.env.CI) {
@ -54,28 +55,27 @@ const getExecutablePath = (browserName: BrowserName) => {
return process.env.WKPATH;
};
const serverEnv = new ServerEnv();
const browsers = ['chromium', 'webkit', 'firefox'] as BrowserName[];
for (const browserName of browsers) {
const executablePath = getExecutablePath(browserName);
if (executablePath && (process.env.FOLIO_WORKER_INDEX === undefined || process.env.FOLIO_WORKER_INDEX === ''))
console.error(`Using executable at ${executablePath}`);
const mode = (process.env.PWMODE || 'default') as ('default' | 'driver' | 'service');
const mode = (process.env.PWTEST_MODE || 'default') as ('default' | 'driver' | 'service');
const options = {
mode,
executablePath,
traceDir: process.env.PWTRACE ? path.join(config.outputDir, 'trace') : undefined,
headless: !process.env.HEADFUL,
channel: process.env.PW_CHROMIUM_CHANNEL as any,
video: !!process.env.PWVIDEO,
channel: process.env.PWTEST_CHANNEL as any,
video: !!process.env.PWTEST_VIDEO,
};
playwrightTest.runWith(folio.merge(serverEnv, new PlaywrightEnv(browserName, options)), { tag: browserName });
playwrightSlowTest.runWith(folio.merge(serverEnv, new PlaywrightEnv(browserName, options)), { timeout: config.timeout * 3, tag: browserName });
browserTest.runWith(folio.merge(serverEnv, new BrowserEnv(browserName, options)), { tag: browserName });
browserSlowTest.runWith(folio.merge(serverEnv, new BrowserEnv(browserName, options)), { timeout: config.timeout * 3, tag: browserName });
pageTest.runWith(folio.merge(serverEnv, new PageEnv(browserName, options)), { tag: browserName });
contextTest.runWith(folio.merge(serverEnv, new PageEnv(browserName, options)), { tag: browserName });
const commonEnv = folio.merge(new CoverageEnv(browserName), new ServerEnv());
playwrightTest.runWith(folio.merge(commonEnv, new PlaywrightEnv(browserName, options)), { tag: browserName });
playwrightSlowTest.runWith(folio.merge(commonEnv, new PlaywrightEnv(browserName, options)), { timeout: config.timeout * 3, tag: browserName });
browserTest.runWith(folio.merge(commonEnv, new BrowserEnv(browserName, options)), { tag: browserName });
browserSlowTest.runWith(folio.merge(commonEnv, new BrowserEnv(browserName, options)), { timeout: config.timeout * 3, tag: browserName });
pageTest.runWith(folio.merge(commonEnv, new PageEnv(browserName, options)), { tag: browserName });
contextTest.runWith(folio.merge(commonEnv, new PageEnv(browserName, options)), { tag: browserName });
if (mode !== 'service')
cliTest.runWith(folio.merge(serverEnv, new CLIEnv(browserName, options)), { tag: browserName });
cliTest.runWith(folio.merge(commonEnv, new CLIEnv(browserName, options)), { tag: browserName });
}

View File

@ -20,6 +20,7 @@ import { test as electronTest } from './electronTest';
import { test as pageTest } from './pageTest';
import { ServerEnv } from './serverEnv';
import { ElectronEnv, ElectronPageEnv } from './electronEnv';
import { CoverageEnv } from './coverage';
const config: folio.Config = {
testDir: path.join(__dirname, '..'),
@ -42,5 +43,6 @@ if (process.env.CI) {
}
const serverEnv = new ServerEnv();
electronTest.runWith(folio.merge(serverEnv, new ElectronEnv()), { tag: 'electron' });
pageTest.runWith(folio.merge(serverEnv, new ElectronPageEnv()), { tag: 'electron' });
const coverageEnv = new CoverageEnv('electron');
electronTest.runWith(folio.merge(coverageEnv, serverEnv, new ElectronEnv()), { tag: 'electron' });
pageTest.runWith(folio.merge(coverageEnv, serverEnv, new ElectronPageEnv()), { tag: 'electron' });

View File

@ -27,7 +27,7 @@ export class ElectronEnv extends PlaywrightEnv implements Env<ElectronTestArgs>
protected _browserVersion: string;
constructor() {
super('chromium', { mode: 'default', coverageBrowserName: 'electron' });
super('chromium', { mode: 'default' });
// This env prevents 'Electron Security Policy' console message.
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
this._browserVersion = require('electron/package.json').version;
@ -62,6 +62,7 @@ export class ElectronEnv extends PlaywrightEnv implements Env<ElectronTestArgs>
};
return {
...result,
isElectron: true,
electronApp: this._electronApp,
newWindow: this._newWindow.bind(this),
};

View File

@ -33,6 +33,8 @@ export type CommonTestArgs = {
isChromium: boolean;
isFirefox: boolean;
isWebKit: boolean;
isAndroid: boolean;
isElectron: boolean;
isWindows: boolean;
isMac: boolean;
isLinux: boolean;

View File

@ -25,17 +25,22 @@ export class ServerEnv implements Env<ServerTestArgs> {
private _httpsServer: TestServer;
private _socksServer: any;
private _socksPort: number;
private _loopback: string | undefined;
constructor(loopback?: string) {
this._loopback = loopback;
}
async beforeAll(workerInfo: WorkerInfo) {
const assetsPath = path.join(__dirname, '..', 'assets');
const cachedPath = path.join(__dirname, '..', 'assets', 'cached');
const port = 8907 + workerInfo.workerIndex * 3;
this._server = await TestServer.create(assetsPath, port);
this._server = await TestServer.create(assetsPath, port, this._loopback);
this._server.enableHTTPCache(cachedPath);
const httpsPort = port + 1;
this._httpsServer = await TestServer.createHTTPS(assetsPath, httpsPort);
this._httpsServer = await TestServer.createHTTPS(assetsPath, httpsPort, this._loopback);
this._httpsServer.enableHTTPCache(cachedPath);
this._socksServer = socks.createServer((info, accept, deny) => {

View File

@ -18,8 +18,8 @@
import { test as it, expect } from './config/pageTest';
import { test as browserTest } from './config/browserTest';
it.beforeEach(async () => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid);
});
it('should work', async ({ page, server, browserName, headful }) => {

View File

@ -73,8 +73,8 @@ it('should work for detached elements', async ({ page, server }) => {
expect(await divHandle.ownerFrame()).toBe(page.mainFrame());
});
it('should work for adopted elements', async ({ page, server }) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it('should work for adopted elements', async ({ page, server, isElectron }) => {
it.fixme(isElectron);
await page.goto(server.EMPTY_PAGE);
const [popup] = await Promise.all([

View File

@ -34,8 +34,8 @@ it('should return null for non-existing element', async ({page, server}) => {
expect(second).toBe(null);
});
it('should work for adopted elements', async ({page,server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it('should work for adopted elements', async ({page, server, isElectron}) => {
it.fixme(isElectron);
await page.goto(server.EMPTY_PAGE);
const [popup] = await Promise.all([

View File

@ -23,9 +23,9 @@ import path from 'path';
import fs from 'fs';
it.describe('element screenshot', () => {
it.beforeEach(async ({ browserName, headful }) => {
it.beforeEach(async ({ browserName, headful, isAndroid }) => {
it.skip(browserName === 'firefox' && headful);
it.skip(!!process.env.PW_ANDROID_TESTS, 'Different dpr. Remove after using 1x scale for screenshots.');
it.skip(isAndroid, 'Different dpr. Remove after using 1x scale for screenshots.');
});
it('should work', async ({page, server}) => {
@ -277,9 +277,9 @@ it.describe('element screenshot', () => {
});
browserTest.describe('element sceenshot', () => {
browserTest.beforeEach(async ({ browserName, headful }) => {
browserTest.beforeEach(async ({ browserName, headful, isAndroid }) => {
browserTest.skip(browserName === 'firefox' && headful);
browserTest.skip(!!process.env.PW_ANDROID_TESTS, 'Different dpr. Remove after using 1x scale for screenshots.');
browserTest.skip(isAndroid, 'Different dpr. Remove after using 1x scale for screenshots.');
});
browserTest('should work with a mobile viewport', async ({browser, server, browserName}) => {

View File

@ -17,8 +17,8 @@
import { test as it, expect } from './config/pageTest';
it('should work', async ({ page, server }) => {
it.fixme(!!process.env.PW_ANDROID_TESTS);
it('should work', async ({ page, server, isAndroid }) => {
it.fixme(isAndroid);
await page.goto(server.PREFIX + '/offscreenbuttons.html');
for (let i = 0; i < 11; ++i) {

View File

@ -23,8 +23,8 @@ it('should think that it is focused by default', async ({page}) => {
expect(await page.evaluate('document.hasFocus()')).toBe(true);
});
it('should think that all pages are focused', async ({page}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'BrowserContext.newPage does not work in Electron');
it('should think that all pages are focused', async ({page, isElectron}) => {
it.fixme(isElectron, 'BrowserContext.newPage does not work in Electron');
const page2 = await page.context().newPage();
expect(await page.evaluate('document.hasFocus()')).toBe(true);
@ -42,8 +42,8 @@ it('should focus popups by default', async ({page, server}) => {
expect(await page.evaluate('document.hasFocus()')).toBe(true);
});
it('should provide target for keyboard events', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'BrowserContext.newPage does not work in Electron');
it('should provide target for keyboard events', async ({page, server, isElectron}) => {
it.fixme(isElectron, 'BrowserContext.newPage does not work in Electron');
const page2 = await page.context().newPage();
await Promise.all([
@ -67,8 +67,8 @@ it('should provide target for keyboard events', async ({page, server}) => {
expect(results).toEqual([text, text2]);
});
it('should not affect mouse event target page', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'BrowserContext.newPage does not work in Electron');
it('should not affect mouse event target page', async ({page, server, isElectron}) => {
it.fixme(isElectron, 'BrowserContext.newPage does not work in Electron');
const page2 = await page.context().newPage();
function clickCounter() {
@ -91,8 +91,8 @@ it('should not affect mouse event target page', async ({page, server}) => {
expect(counters).toEqual([1,1]);
});
it('should change document.activeElement', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'BrowserContext.newPage does not work in Electron');
it('should change document.activeElement', async ({page, server, isElectron}) => {
it.fixme(isElectron, 'BrowserContext.newPage does not work in Electron');
const page2 = await page.context().newPage();
await Promise.all([
@ -110,10 +110,10 @@ it('should change document.activeElement', async ({page, server}) => {
expect(active).toEqual(['INPUT', 'TEXTAREA']);
});
it('should not affect screenshots', async ({page, server, browserName, headful}) => {
it('should not affect screenshots', async ({page, server, browserName, headful, isElectron, isAndroid}) => {
it.skip(browserName === 'firefox' && headful);
it.skip(!!process.env.PW_ANDROID_TESTS);
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'BrowserContext.newPage does not work in Electron');
it.skip(isAndroid);
it.fixme(isElectron, 'BrowserContext.newPage does not work in Electron');
// Firefox headful produces a different image.
const page2 = await page.context().newPage();

View File

@ -96,9 +96,9 @@ it('should allow cross-frame element handles', async ({ page, server }) => {
expect(result.trim()).toBe('<div>Hi, I\'m frame</div>');
});
it('should not allow cross-frame element handles when frames do not script each other', async ({ page, server }) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it('should not allow cross-frame element handles when frames do not script each other', async ({ page, server, isElectron, isAndroid }) => {
it.skip(isAndroid, 'No cross-process on Android');
it.fixme(isElectron);
await page.goto(server.EMPTY_PAGE);
const frame = await attachFrame(page, 'frame1', server.CROSS_PROCESS_PREFIX + '/empty.html');

View File

@ -40,8 +40,8 @@ it('should reject when frame detaches', async ({page, server}) => {
expect(error.message).toContain('frame was detached');
});
it('should continue after client redirect', async ({page, server}) => {
it.fixme(!!process.env.PW_ANDROID_TESTS);
it('should continue after client redirect', async ({page, server, isAndroid}) => {
it.fixme(isAndroid);
server.setRoute('/frames/script.js', () => {});
const url = server.PREFIX + '/frames/child-redirect.html';

View File

@ -35,8 +35,8 @@ function dumpFrames(frame: Frame, indentation: string = ''): string[] {
return result;
}
it('should handle nested frames', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should handle nested frames', async ({page, server, isAndroid}) => {
it.skip(isAndroid, 'No cross-process on Android');
await page.goto(server.PREFIX + '/frames/nested-frames.html');
expect(dumpFrames(page.mainFrame())).toEqual([
@ -154,8 +154,8 @@ it('should report frame from-inside shadow DOM', async ({page, server}) => {
expect(page.frames()[1].url()).toBe(server.EMPTY_PAGE);
});
it('should report frame.name()', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it('should report frame.name()', async ({page, server, isElectron}) => {
it.fixme(isElectron);
await attachFrame(page, 'theFrameId', server.EMPTY_PAGE);
await page.evaluate(url => {
@ -178,8 +178,8 @@ it('should report frame.parent()', async ({page, server}) => {
expect(page.frames()[2].parentFrame()).toBe(page.mainFrame());
});
it('should report different frame instance when frame re-attaches', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it('should report different frame instance when frame re-attaches', async ({page, server, isElectron}) => {
it.fixme(isElectron);
const frame1 = await attachFrame(page, 'frame1', server.EMPTY_PAGE);
await page.evaluate(() => {

View File

@ -44,8 +44,8 @@ browserTest('should work with ignoreHTTPSErrors', async ({browser, httpsServer})
await context.close();
});
it('should intercept after a service worker', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should intercept after a service worker', async ({page, server, isAndroid}) => {
it.skip(isAndroid);
await page.goto(server.PREFIX + '/serviceworkers/fetchdummy/sw.html');
await page.evaluate(() => window['activationPromise']);
@ -90,8 +90,8 @@ it('should work with glob', async () => {
expect(globToRegex('**/*.{png,jpg,jpeg}').test('https://localhost:8080/c.css')).toBeFalsy();
});
it('should intercept network activity from worker', async function({page, server}) {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should intercept network activity from worker', async function({page, server, isAndroid}) {
it.skip(isAndroid);
await page.goto(server.EMPTY_PAGE);
server.setRoute('/data_for_worker', (req, res) => res.end('failed to intercept'));
@ -111,9 +111,9 @@ it('should intercept network activity from worker', async function({page, server
expect(msg.text()).toBe('intercepted');
});
it('should intercept network activity from worker 2', async function({page, server}) {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it('should intercept network activity from worker 2', async function({page, server, isElectron, isAndroid}) {
it.skip(isAndroid);
it.fixme(isElectron);
const url = server.PREFIX + '/worker/worker.js';
await page.route(url, route => {
@ -130,8 +130,8 @@ it('should intercept network activity from worker 2', async function({page, serv
expect(msg.text()).toBe('intercepted');
});
it('should work with regular expression passed from a different context', async ({page, server}) => {
it.skip(!!process.env.PW_ELECTRON_TESTS);
it('should work with regular expression passed from a different context', async ({page, server, isElectron}) => {
it.skip(isElectron);
const ctx = vm.createContext();
const regexp = vm.runInContext('new RegExp("empty\\.html")', ctx);

View File

@ -16,8 +16,8 @@
import { test as it, expect } from './config/pageTest';
it.beforeEach(async () => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.beforeEach(async ({ isAndroid }) => {
it.fixme(isAndroid, 'Post data does not work');
});
it('should return correct postData buffer for utf-8 body', async ({page, server}) => {

View File

@ -98,8 +98,8 @@ it('should throw when added with content to the CSP page', async ({page, server}
expect(error).toBeTruthy();
});
it('should throw when added with URL to the CSP page', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should throw when added with URL to the CSP page', async ({page, server, isAndroid}) => {
it.skip(isAndroid, 'No cross-process on Android');
await page.goto(server.PREFIX + '/csp.html');
let error = null;

View File

@ -76,8 +76,8 @@ it('should throw when added with content to the CSP page', async ({page, server}
expect(error).toBeTruthy();
});
it('should throw when added with URL to the CSP page', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should throw when added with URL to the CSP page', async ({page, server, isAndroid}) => {
it.skip(isAndroid, 'No cross-process on Android');
await page.goto(server.PREFIX + '/csp.html');
let error = null;

View File

@ -28,8 +28,8 @@ function initServer(server: TestServer): string[] {
return messages;
}
it.beforeEach(async () => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'Too flaky on Android');
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid, 'Too flaky on Android');
});
it('should await navigation when clicking anchor', async ({page, server}) => {

View File

@ -32,8 +32,8 @@ it('should set the page close state', async ({page}) => {
expect(page.isClosed()).toBe(true);
});
it('should pass page to close event', async ({page}) => {
it.fixme(!!process.env.PW_ANDROID_TESTS);
it('should pass page to close event', async ({page, isAndroid}) => {
it.fixme(isAndroid);
const [closedPage] = await Promise.all([
page.waitForEvent('close'),
@ -121,8 +121,8 @@ it('should pass self as argument to load event', async ({page}) => {
expect(eventArg).toBe(page);
});
it('should fail with error upon disconnect', async ({page}) => {
it.fixme(!!process.env.PW_ANDROID_TESTS);
it('should fail with error upon disconnect', async ({page, isAndroid}) => {
it.fixme(isAndroid);
let error;
const waitForPromise = page.waitForEvent('download').catch(e => error = e);
@ -131,8 +131,8 @@ it('should fail with error upon disconnect', async ({page}) => {
expect(error.message).toContain('Page closed');
});
it('page.url should work', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it('page.url should work', async ({page, server, isElectron}) => {
it.fixme(isElectron);
expect(page.url()).toBe('about:blank');
await page.goto(server.EMPTY_PAGE);
@ -182,9 +182,9 @@ it('page.frame should respect url', async function({page, server}) {
expect(page.frame({ url: /empty/ }).url()).toBe(server.EMPTY_PAGE);
});
it('should have sane user agent', async ({page, isChromium, isFirefox}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.skip(!!process.env.PW_ELECTRON_TESTS);
it('should have sane user agent', async ({page, isChromium, isFirefox, isElectron, isAndroid}) => {
it.skip(isAndroid);
it.skip(isElectron);
const userAgent = await page.evaluate(() => navigator.userAgent);
const [

View File

@ -16,9 +16,9 @@
import { test as it } from './config/pageTest';
it('should not hit scroll bar', async ({page, server, isWebKit, platform}) => {
it('should not hit scroll bar', async ({page, isAndroid, isWebKit, platform}) => {
it.fixme(isWebKit && platform === 'darwin');
it.skip(!!process.env.PW_ANDROID_TESTS);
it.skip(isAndroid);
await page.setContent(`
<style>

View File

@ -370,8 +370,8 @@ it('should click the button with em border with offset', async ({page, server, i
expect(await page.evaluate('offsetY')).toBe(isWebKit ? 12 * 2 + 10 : 10);
});
it('should click a very large button with offset', async ({page, server, isWebKit}) => {
it.skip(process.env.PWTESTREPORT);
it('should click a very large button with offset', async ({page, server, isWebKit, isAndroid}) => {
it.fixme(isAndroid);
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => button.style.borderWidth = '8px');
@ -383,8 +383,8 @@ it('should click a very large button with offset', async ({page, server, isWebKi
expect(await page.evaluate('offsetY')).toBe(isWebKit ? 1910 + 8 : 1910);
});
it('should click a button in scrolling container with offset', async ({page, server, isWebKit}) => {
it.skip(process.env.PWTESTREPORT);
it('should click a button in scrolling container with offset', async ({page, server, isWebKit, isAndroid}) => {
it.fixme(isAndroid);
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => {

View File

@ -27,8 +27,8 @@ it('should fire', async ({page, server}) => {
await page.evaluate(() => alert('yo'));
});
it('should allow accepting prompts', async ({page}) => {
it.skip(!!process.env.PW_ELECTRON_TESTS, 'prompt() is not a thing in electron');
it('should allow accepting prompts', async ({page, isElectron}) => {
it.skip(isElectron, 'prompt() is not a thing in electron');
page.on('dialog', dialog => {
expect(dialog.type()).toBe('prompt');
@ -40,8 +40,8 @@ it('should allow accepting prompts', async ({page}) => {
expect(result).toBe('answer!');
});
it('should dismiss the prompt', async ({page}) => {
it.skip(!!process.env.PW_ELECTRON_TESTS, 'prompt() is not a thing in electron');
it('should dismiss the prompt', async ({page, isElectron}) => {
it.skip(isElectron, 'prompt() is not a thing in electron');
page.on('dialog', dialog => {
dialog.dismiss();
@ -104,8 +104,8 @@ it('should handle multiple confirms', async ({page}) => {
expect(await page.textContent('p')).toBe('Hello World');
});
it('should auto-dismiss the prompt without listeners', async ({page}) => {
it.skip(!!process.env.PW_ELECTRON_TESTS, 'prompt() is not a thing in electron');
it('should auto-dismiss the prompt without listeners', async ({page, isElectron}) => {
it.skip(isElectron, 'prompt() is not a thing in electron');
const result = await page.evaluate(() => prompt('question?'));
expect(result).toBe(null);

View File

@ -19,8 +19,8 @@ import { test as it, expect } from './config/pageTest';
import { attachFrame } from './config/utils';
it.describe('Drag and drop', () => {
it.beforeEach(async ({ browserName }) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.beforeEach(async ({ browserName, isAndroid }) => {
it.skip(isAndroid);
it.fixme(browserName === 'chromium');
});

View File

@ -19,8 +19,8 @@ import { test as it, expect } from './config/pageTest';
import { test as browserTest } from './config/browserTest';
import { attachFrame } from './config/utils';
it.beforeEach(async () => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid);
});
it('should emulate type', async ({page}) => {

View File

@ -71,8 +71,8 @@ it.describe('', () => {
});
it('should be able to close context when page crashes', async args => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.skip(!!process.env.PW_ELECTRON_TESTS);
it.skip(args.isAndroid);
it.skip(args.isElectron);
const { page } = args;
await page.setContent(`<div>This page should crash</div>`);

View File

@ -68,9 +68,9 @@ it('should handle object', async ({page, isChromium, isFirefox}) => {
expect(error.message).toBe(isChromium ? 'Object' : '[object Object]');
});
it('should handle window', async ({page, isChromium, isFirefox}) => {
it('should handle window', async ({page, isChromium, isFirefox, isElectron}) => {
it.fixme(isFirefox);
it.skip(!!process.env.PW_ELECTRON_TESTS);
it.skip(isElectron);
// Firefox just does not report this error.
const [error] = await Promise.all([

View File

@ -41,8 +41,8 @@ it('should fire for fetches', async ({page, server}) => {
expect(requests.length).toBe(2);
});
it('should report requests and responses handled by service worker', async ({page, server}) => {
it.fixme(!!process.env.PW_ANDROID_TESTS);
it('should report requests and responses handled by service worker', async ({page, server, isAndroid}) => {
it.fixme(isAndroid);
await page.goto(server.PREFIX + '/serviceworkers/fetchdummy/sw.html');
await page.evaluate(() => window['activationPromise']);

View File

@ -222,8 +222,8 @@ it('exposeBindingHandle should throw for multiple arguments', async ({page}) =>
expect(error.message).toContain('exposeBindingHandle supports a single argument, 2 received');
});
it('should not result in unhandled rejection', async ({page}) => {
it.fixme(!!process.env.PW_ANDROID_TESTS);
it('should not result in unhandled rejection', async ({page, isAndroid}) => {
it.fixme(isAndroid);
const closedPromise = page.waitForEvent('close');
await page.exposeFunction('foo', async () => {
@ -238,11 +238,11 @@ it('should not result in unhandled rejection', async ({page}) => {
expect(await page.evaluate('1 + 1').catch(e => e)).toBeInstanceOf(Error);
});
it('should work with internal bindings', async ({page, toImpl, server, mode, browserName}) => {
it('should work with internal bindings', async ({page, toImpl, server, mode, browserName, isElectron, isAndroid}) => {
it.skip(mode !== 'default');
it.skip(browserName !== 'chromium');
it.skip(!!process.env.PW_ANDROID_TESTS);
it.skip(!!process.env.PW_ELECTRON_TESTS);
it.skip(isAndroid);
it.skip(isElectron);
const implPage: import('../src/server/page').Page = toImpl(page);
let foo;

View File

@ -25,8 +25,8 @@ it('should work', async ({page, server}) => {
expect(page.url()).toBe(server.EMPTY_PAGE);
});
it('should work with file URL', async ({page, asset}) => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'No files on Android');
it('should work with file URL', async ({page, asset, isAndroid}) => {
it.skip(isAndroid, 'No files on Android');
const fileurl = url.pathToFileURL(asset('frames/two-frames.html')).href;
await page.goto(fileurl);
@ -34,8 +34,8 @@ it('should work with file URL', async ({page, asset}) => {
expect(page.frames().length).toBe(3);
});
it('should use http for no protocol', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should use http for no protocol', async ({page, server, isAndroid}) => {
it.skip(isAndroid);
await page.goto(server.EMPTY_PAGE.substring('http://'.length));
expect(page.url()).toBe(server.EMPTY_PAGE);
@ -236,8 +236,8 @@ it('should fail when exceeding maximum navigation timeout', async ({page, server
expect(error).toBeInstanceOf(playwright.errors.TimeoutError);
});
it('should fail when exceeding default maximum navigation timeout', async ({page, server, playwright}) => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'No context per test');
it('should fail when exceeding default maximum navigation timeout', async ({page, server, playwright, isAndroid}) => {
it.skip(isAndroid, 'No context per test');
// Hang for request to the empty.html
server.setRoute('/empty.html', (req, res) => { });
@ -250,8 +250,8 @@ it('should fail when exceeding default maximum navigation timeout', async ({page
expect(error).toBeInstanceOf(playwright.errors.TimeoutError);
});
it('should fail when exceeding browser context navigation timeout', async ({page, server, playwright}) => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'No context per test');
it('should fail when exceeding browser context navigation timeout', async ({page, server, playwright, isAndroid}) => {
it.skip(isAndroid, 'No context per test');
// Hang for request to the empty.html
server.setRoute('/empty.html', (req, res) => { });
@ -263,8 +263,8 @@ it('should fail when exceeding browser context navigation timeout', async ({page
expect(error).toBeInstanceOf(playwright.errors.TimeoutError);
});
it('should fail when exceeding default maximum timeout', async ({page, server, playwright}) => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'No context per test');
it('should fail when exceeding default maximum timeout', async ({page, server, playwright, isAndroid}) => {
it.skip(isAndroid, 'No context per test');
// Hang for request to the empty.html
server.setRoute('/empty.html', (req, res) => { });
@ -277,8 +277,8 @@ it('should fail when exceeding default maximum timeout', async ({page, server, p
expect(error).toBeInstanceOf(playwright.errors.TimeoutError);
});
it('should fail when exceeding browser context timeout', async ({page, server, playwright}) => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'No context per test');
it('should fail when exceeding browser context timeout', async ({page, server, playwright, isAndroid}) => {
it.skip(isAndroid, 'No context per test');
// Hang for request to the empty.html
server.setRoute('/empty.html', (req, res) => { });
@ -489,8 +489,8 @@ it('should fail when canceled by another navigation', async ({page, server}) =>
expect(error.message).toBeTruthy();
});
it('should work with lazy loading iframes', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it('should work with lazy loading iframes', async ({page, server, isElectron}) => {
it.fixme(isElectron);
await page.goto(server.PREFIX + '/frames/lazy-frame.html');
expect(page.frames().length).toBe(2);

View File

@ -52,9 +52,9 @@ it('page.goBack should work with HistoryAPI', async ({page, server}) => {
expect(page.url()).toBe(server.PREFIX + '/first.html');
});
it('page.goBack should work for file urls', async ({page, server, asset, browserName, platform}) => {
it('page.goBack should work for file urls', async ({page, server, asset, browserName, platform, isAndroid}) => {
it.fail(browserName === 'webkit' && platform === 'darwin');
it.skip(!!process.env.PW_ANDROID_TESTS, 'No files on Android');
it.skip(isAndroid, 'No files on Android');
// WebKit embedder fails to go back/forward to the file url.
const url1 = url.pathToFileURL(asset('empty.html')).href;

View File

@ -18,8 +18,8 @@
import { test as it, expect } from './config/pageTest';
import { attachFrame } from './config/utils';
it.beforeEach(async () => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid);
});
it('should type into a textarea', async ({page}) => {

View File

@ -143,8 +143,8 @@ it('should set modifier keys on click', async ({page, server, isFirefox, isMac})
}
});
it('should tween mouse movement', async ({page, isWebKit}) => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'Bad rounding');
it('should tween mouse movement', async ({page, isWebKit, isAndroid}) => {
it.skip(isAndroid, 'Bad rounding');
// The test becomes flaky on WebKit without next line.
if (isWebKit)

View File

@ -138,8 +138,8 @@ it('should wait for networkidle from the child frame', async ({page, server}) =>
});
});
it('should wait for networkidle from the popup', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS, 'Too slow');
it('should wait for networkidle from the popup', async ({page, server, isAndroid}) => {
it.skip(isAndroid, 'Too slow');
await page.goto(server.EMPTY_PAGE);
await page.setContent(`

View File

@ -113,8 +113,8 @@ it('should get the same headers as the server CORP', async ({page, server, brows
expect(response.request().headers()).toEqual(serverRequest.headers);
});
it('should return postData', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should return postData', async ({page, server, isAndroid}) => {
it.fixme(isAndroid, 'Post data does not work');
await page.goto(server.EMPTY_PAGE);
server.setRoute('/post', (req, res) => res.end());
@ -125,8 +125,8 @@ it('should return postData', async ({page, server}) => {
expect(request.postData()).toBe('{"foo":"bar"}');
});
it('should work with binary post data', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should work with binary post data', async ({page, server, isAndroid}) => {
it.fixme(isAndroid, 'Post data does not work');
await page.goto(server.EMPTY_PAGE);
server.setRoute('/post', (req, res) => res.end());
@ -142,8 +142,8 @@ it('should work with binary post data', async ({page, server}) => {
expect(buffer[i]).toBe(i);
});
it('should work with binary post data and interception', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should work with binary post data and interception', async ({page, server, isAndroid}) => {
it.fixme(isAndroid, 'Post data does not work');
await page.goto(server.EMPTY_PAGE);
server.setRoute('/post', (req, res) => res.end());
@ -160,8 +160,8 @@ it('should work with binary post data and interception', async ({page, server})
expect(buffer[i]).toBe(i);
});
it('should override post data content type', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should override post data content type', async ({page, server, isAndroid}) => {
it.fixme(isAndroid, 'Post data does not work');
await page.goto(server.EMPTY_PAGE);
let request = null;
@ -184,15 +184,15 @@ it('should override post data content type', async ({page, server}) => {
expect(request.headers['content-type']).toBe('application/x-www-form-urlencoded; charset=UTF-8');
});
it('should be |undefined| when there is no post data', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should be |undefined| when there is no post data', async ({page, server, isAndroid}) => {
it.fixme(isAndroid, 'Post data does not work');
const response = await page.goto(server.EMPTY_PAGE);
expect(response.request().postData()).toBe(null);
});
it('should parse the json post data', async ({ page, server }) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should parse the json post data', async ({ page, server, isAndroid }) => {
it.fixme(isAndroid, 'Post data does not work');
await page.goto(server.EMPTY_PAGE);
server.setRoute('/post', (req, res) => res.end());
@ -203,8 +203,8 @@ it('should parse the json post data', async ({ page, server }) => {
expect(request.postDataJSON()).toEqual({ 'foo': 'bar' });
});
it('should parse the data if content-type is application/x-www-form-urlencoded', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should parse the data if content-type is application/x-www-form-urlencoded', async ({page, server, isAndroid}) => {
it.fixme(isAndroid, 'Post data does not work');
await page.goto(server.EMPTY_PAGE);
server.setRoute('/post', (req, res) => res.end());

View File

@ -97,8 +97,8 @@ it('should amend method on main request', async ({page, server}) => {
});
it.describe('', () => {
it.beforeEach(async () => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.beforeEach(async ({ isAndroid }) => {
it.fixme(isAndroid, 'Post data does not work');
});
it('should amend post data', async ({page, server}) => {

View File

@ -49,9 +49,9 @@ it('should work with status code 422', async ({page, server}) => {
expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!');
});
it('should allow mocking binary responses', async ({page, server, browserName, headful, asset}) => {
it('should allow mocking binary responses', async ({page, server, browserName, headful, asset, isAndroid}) => {
it.skip(browserName === 'firefox' && headful, 'Firefox headful produces a different image.');
it.skip(!!process.env.PW_ANDROID_TESTS);
it.skip(isAndroid);
await page.route('**/*', route => {
const imageBuffer = fs.readFileSync(asset('pptr.png'));
@ -70,9 +70,9 @@ it('should allow mocking binary responses', async ({page, server, browserName, h
expect(await img.screenshot()).toMatchSnapshot('mock-binary-response.png');
});
it('should allow mocking svg with charset', async ({page, server, browserName, headful}) => {
it('should allow mocking svg with charset', async ({page, server, browserName, headful, isAndroid}) => {
it.skip(browserName === 'firefox' && headful, 'Firefox headful produces a different image.');
it.skip(!!process.env.PW_ANDROID_TESTS);
it.skip(isAndroid);
// Firefox headful produces a different image.
await page.route('**/*', route => {
@ -91,8 +91,8 @@ it('should allow mocking svg with charset', async ({page, server, browserName, h
expect(await img.screenshot()).toMatchSnapshot('mock-svg.png');
});
it('should work with file path', async ({page, server, asset}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should work with file path', async ({page, server, asset, isAndroid}) => {
it.skip(isAndroid);
await page.route('**/*', route => route.fulfill({ contentType: 'shouldBeIgnored', path: asset('pptr.png') }));
await page.evaluate(PREFIX => {
@ -159,8 +159,8 @@ it('should not modify the headers sent to the server', async ({page, server}) =>
expect(interceptedRequests[1].headers).toEqual(interceptedRequests[0].headers);
});
it('should include the origin header', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it('should include the origin header', async ({page, server, isAndroid}) => {
it.skip(isAndroid, 'No cross-process on Android');
await page.goto(server.PREFIX + '/empty.html');
let interceptedRequest;

View File

@ -123,9 +123,9 @@ it('should contain referer header', async ({page, server}) => {
expect(requests[1].headers().referer).toContain('/one-style.html');
});
it('should properly return navigation response when URL has cookies', async ({page, server}) => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'error: Browser context management is not supported.');
it('should properly return navigation response when URL has cookies', async ({page, server, isElectron, isAndroid}) => {
it.skip(isAndroid, 'No isolated context');
it.fixme(isElectron, 'error: Browser context management is not supported.');
// Setup cookie.
await page.goto(server.EMPTY_PAGE);
@ -535,8 +535,8 @@ it('should support cors with GET', async ({page, server}) => {
}
});
it('should support cors with POST', async ({page, server, isChromium, browserChannel}) => {
it.fail(isChromium && !browserChannel && !process.env.PW_ANDROID_TESTS && !process.env.PW_ELECTRON_TESTS, 'https://github.com/microsoft/playwright/issues/6016');
it('should support cors with POST', async ({page, server, isChromium, browserChannel, isElectron, isAndroid}) => {
it.fail(isChromium && !browserChannel && !isAndroid && !isElectron, 'https://github.com/microsoft/playwright/issues/6016');
await page.goto(server.EMPTY_PAGE);
await page.route('**/cars', async route => {
@ -559,8 +559,8 @@ it('should support cors with POST', async ({page, server, isChromium, browserCha
expect(resp).toEqual(['electric', 'gas']);
});
it('should support cors with credentials', async ({page, server, isChromium, browserChannel}) => {
it.fail(isChromium && !browserChannel && !process.env.PW_ANDROID_TESTS && !process.env.PW_ELECTRON_TESTS, 'https://github.com/microsoft/playwright/issues/6016');
it('should support cors with credentials', async ({page, server, isChromium, browserChannel, isElectron, isAndroid}) => {
it.fail(isChromium && !browserChannel && !isAndroid && !isElectron, 'https://github.com/microsoft/playwright/issues/6016');
await page.goto(server.EMPTY_PAGE);
await page.route('**/cars', async route => {
@ -619,8 +619,8 @@ it('should reject cors with disallowed credentials', async ({page, server}) => {
expect(error).toBeTruthy();
});
it('should support cors for different methods', async ({page, server, isChromium, browserChannel}) => {
it.fail(isChromium && !browserChannel && !process.env.PW_ANDROID_TESTS && !process.env.PW_ELECTRON_TESTS, 'https://github.com/microsoft/playwright/issues/6016');
it('should support cors for different methods', async ({page, server, isChromium, browserChannel, isElectron, isAndroid}) => {
it.fail(isChromium && !browserChannel && !isAndroid && !isElectron, 'https://github.com/microsoft/playwright/issues/6016');
await page.goto(server.EMPTY_PAGE);
await page.route('**/cars', async (route, request) => {

View File

@ -23,9 +23,9 @@ import fs from 'fs';
import { PNG } from 'pngjs';
it.describe('page screenshot', () => {
it.beforeEach(async ({ browserName, headful }) => {
it.beforeEach(async ({ browserName, headful, isAndroid }) => {
it.skip(browserName === 'firefox' && headful, 'Firefox headful produces a different image.');
it.skip(!!process.env.PW_ANDROID_TESTS, 'Different viewport');
it.skip(isAndroid, 'Different viewport');
});
it('should work', async ({page, server}) => {
@ -145,8 +145,8 @@ it.describe('page screenshot', () => {
expect(screenshot).toMatchSnapshot('transparent.png');
});
it('should render white background on jpeg file', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'omitBackground with jpeg does not work');
it('should render white background on jpeg file', async ({page, server, isElectron}) => {
it.fixme(isElectron, 'omitBackground with jpeg does not work');
await page.setViewportSize({ width: 100, height: 100 });
await page.goto(server.EMPTY_PAGE);
@ -224,8 +224,8 @@ it.describe('page screenshot', () => {
expect(await fs.promises.readFile(outputPath)).toMatchSnapshot('screenshot-sanity.png');
});
it('path option should detect jpeg', async ({page, server}, testInfo) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'omitBackground with jpeg does not work');
it('path option should detect jpeg', async ({page, server, isElectron}, testInfo) => {
it.fixme(isElectron, 'omitBackground with jpeg does not work');
await page.setViewportSize({ width: 100, height: 100 });
await page.goto(server.EMPTY_PAGE);
@ -271,9 +271,9 @@ it.describe('page screenshot', () => {
});
browserTest.describe('page screenshot', () => {
browserTest.beforeEach(async ({ browserName, headful }) => {
browserTest.beforeEach(async ({ browserName, headful, isAndroid }) => {
browserTest.skip(browserName === 'firefox' && headful, 'Firefox headful produces a different image.');
browserTest.skip(!!process.env.PW_ANDROID_TESTS, 'Different viewport');
browserTest.skip(isAndroid, 'Different viewport');
});
browserTest('should run in parallel in multiple pages', async ({server, contextFactory}) => {

View File

@ -226,8 +226,8 @@ it('should accept single file', async ({page, asset}) => {
expect(await page.$eval('input', input => input.files[0].name)).toBe('file-to-upload.txt');
});
it('should detect mime type', async ({page, server, asset}) => {
it.fixme(!!process.env.PW_ANDROID_TESTS);
it('should detect mime type', async ({page, server, asset, isAndroid}) => {
it.fixme(isAndroid);
let files;
server.setRoute('/upload', async (req, res) => {

View File

@ -131,8 +131,8 @@ it('should work with clicking target=_blank', async ({page, server}) => {
expect(await popup.evaluate(() => document.readyState)).toBe('complete');
});
it('should wait for load state of newPage', async ({page, server}) => {
it.fixme(!!process.env.PW_ELECTRON_TESTS, 'BrowserContext.newPage does not work in Electron');
it('should wait for load state of newPage', async ({page, server, isElectron}) => {
it.fixme(isElectron, 'BrowserContext.newPage does not work in Electron');
const [newPage] = await Promise.all([
page.context().waitForEvent('page'),

View File

@ -27,10 +27,10 @@ it('should work for open shadow roots', async ({page, server}) => {
expect(await page.$$(`data-testid:light=foo`)).toEqual([]);
});
it('should click on links in shadow dom', async ({page, server, browserName, browserVersion}) => {
it('should click on links in shadow dom', async ({page, server, browserName, browserVersion, isElectron, isAndroid}) => {
it.fixme(browserName === 'chromium' && Number(browserVersion.split('.')[0]) < 91, 'Remove when crrev.com/864024 gets to the stable channel');
it.fixme(!!process.env.PW_ANDROID_TESTS);
it.fixme(!!process.env.PW_ELECTRON_TESTS);
it.fixme(isAndroid);
it.fixme(isElectron);
await page.goto(server.PREFIX + '/shadow-dom-link.html');
expect(await page.evaluate(() => (window as any).clickCount)).toBe(0);

View File

@ -18,8 +18,8 @@
import { test as it, expect } from './config/pageTest';
import { Server as WebSocketServer } from 'ws';
it.beforeEach(async () => {
it.skip(!!process.env.PW_ANDROID_TESTS);
it.beforeEach(async ({ isAndroid }) => {
it.skip(isAndroid);
});
it('should work', async ({ page, server }) => {

View File

@ -18,8 +18,8 @@ type ServerResponse = import('http').ServerResponse;
type IncomingMessage = import('http').IncomingMessage;
export class TestServer {
static create(dirPath: string, port: number): Promise<TestServer>;
static createHTTPS(dirPath: string, port: number): Promise<TestServer>;
static create(dirPath: string, port: number, loopback?: string): Promise<TestServer>;
static createHTTPS(dirPath: string, port: number, loopback?: string): Promise<TestServer>;
enableHTTPCache(pathPrefix: string);
setAuth(path: string, username: string, password: string);
enableGzip(path: string);

View File

@ -29,17 +29,15 @@ const rejectSymbol = Symbol('reject callback');
const readFileAsync = util.promisify(fs.readFile.bind(fs));
const gzipAsync = util.promisify(zlib.gzip.bind(zlib));
const loopback = process.env.PW_ANDROID_TESTS ? '10.0.2.2' : 'localhost';
const cross_origin_loopback = process.env.PW_ANDROID_TESTS ? '10.0.2.2' : '127.0.0.1';
class TestServer {
/**
* @param {string} dirPath
* @param {number} port
* @param {string=} loopback
* @return {!Promise<TestServer>}
*/
static async create(dirPath, port) {
const server = new TestServer(dirPath, port);
static async create(dirPath, port, loopback) {
const server = new TestServer(dirPath, port, loopback);
await new Promise(x => server._server.once('listening', x));
return server;
}
@ -47,10 +45,11 @@ class TestServer {
/**
* @param {string} dirPath
* @param {number} port
* @param {string=} loopback
* @return {!Promise<TestServer>}
*/
static async createHTTPS(dirPath, port) {
const server = new TestServer(dirPath, port, {
static async createHTTPS(dirPath, port, loopback) {
const server = new TestServer(dirPath, port, loopback, {
key: fs.readFileSync(path.join(__dirname, 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'cert.pem')),
passphrase: 'aaaa',
@ -62,9 +61,10 @@ class TestServer {
/**
* @param {string} dirPath
* @param {number} port
* @param {string=} loopback
* @param {!Object=} sslOptions
*/
constructor(dirPath, port, sslOptions) {
constructor(dirPath, port, loopback, sslOptions) {
if (sslOptions)
this._server = https.createServer(sslOptions, this._onRequest.bind(this));
else
@ -92,11 +92,13 @@ class TestServer {
/** @type {!Map<string, !Promise>} */
this._requestSubscribers = new Map();
const cross_origin = loopback || '127.0.0.1';
const same_origin = loopback || 'localhost';
const protocol = sslOptions ? 'https' : 'http';
this.PORT = port;
this.PREFIX = `${protocol}://${loopback}:${port}`;
this.CROSS_PROCESS_PREFIX = `${protocol}://${cross_origin_loopback}:${port}`;
this.EMPTY_PAGE = `${protocol}://${loopback}:${port}/empty.html`;
this.PREFIX = `${protocol}://${same_origin}:${port}`;
this.CROSS_PROCESS_PREFIX = `${protocol}://${cross_origin}:${port}`;
this.EMPTY_PAGE = `${protocol}://${same_origin}:${port}/empty.html`;
}
_onSocket(socket) {