chore: don't write into stdout from the test runner, use reporters instead (#11367)
This commit is contained in:
parent
9285596806
commit
feb7148b3f
16
packages/.eslintrc.js
Normal file
16
packages/.eslintrc.js
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
module.exports = {
|
||||||
|
"extends": "../.eslintrc.js",
|
||||||
|
/**
|
||||||
|
* ESLint rules
|
||||||
|
*
|
||||||
|
* All available rules: http://eslint.org/docs/rules/
|
||||||
|
*
|
||||||
|
* Rules take the following form:
|
||||||
|
* "rule-name", [severity, { opts }]
|
||||||
|
* Severity: 2 == error, 1 == warning, 0 == off.
|
||||||
|
*/
|
||||||
|
"rules": {
|
||||||
|
"no-console": 2,
|
||||||
|
"no-debugger": 2
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
"extends": "../../../.eslintrc.js",
|
|
||||||
/**
|
|
||||||
* ESLint rules
|
|
||||||
*
|
|
||||||
* All available rules: http://eslint.org/docs/rules/
|
|
||||||
*
|
|
||||||
* Rules take the following form:
|
|
||||||
* "rule-name", [severity, { opts }]
|
|
||||||
* Severity: 2 == error, 1 == warning, 0 == off.
|
|
||||||
*/
|
|
||||||
"rules": {
|
|
||||||
"no-console": [2, { "allow": ["warn", "error", "assert", "timeStamp", "time", "timeEnd"] }],
|
|
||||||
"no-debugger": 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -21,14 +21,14 @@ import * as network from './network';
|
||||||
import * as channels from '../protocol/channels';
|
import * as channels from '../protocol/channels';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
import { deprecate, evaluationScript } from './clientHelper';
|
import { evaluationScript } from './clientHelper';
|
||||||
import { Browser } from './browser';
|
import { Browser } from './browser';
|
||||||
import { Worker } from './worker';
|
import { Worker } from './worker';
|
||||||
import { Events } from './events';
|
import { Events } from './events';
|
||||||
import { TimeoutSettings } from '../utils/timeoutSettings';
|
import { TimeoutSettings } from '../utils/timeoutSettings';
|
||||||
import { Waiter } from './waiter';
|
import { Waiter } from './waiter';
|
||||||
import { URLMatch, Headers, WaitForEventOptions, BrowserContextOptions, StorageState, LaunchOptions } from './types';
|
import { URLMatch, Headers, WaitForEventOptions, BrowserContextOptions, StorageState, LaunchOptions } from './types';
|
||||||
import { isUnderTest, headersObjectToArray, mkdirIfNeeded } from '../utils/utils';
|
import { headersObjectToArray, mkdirIfNeeded } from '../utils/utils';
|
||||||
import { isSafeCloseError } from '../utils/errors';
|
import { isSafeCloseError } from '../utils/errors';
|
||||||
import * as api from '../../types/types';
|
import * as api from '../../types/types';
|
||||||
import * as structs from '../../types/structs';
|
import * as structs from '../../types/structs';
|
||||||
|
|
@ -231,8 +231,6 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||||
}
|
}
|
||||||
|
|
||||||
async setHTTPCredentials(httpCredentials: { username: string, password: string } | null): Promise<void> {
|
async setHTTPCredentials(httpCredentials: { username: string, password: string } | null): Promise<void> {
|
||||||
if (!isUnderTest())
|
|
||||||
deprecate(`context.setHTTPCredentials`, `warning: method |context.setHTTPCredentials()| is deprecated. Instead of changing credentials, create another browser context with new credentials.`);
|
|
||||||
await this._channel.setHTTPCredentials({ httpCredentials: httpCredentials || undefined });
|
await this._channel.setHTTPCredentials({ httpCredentials: httpCredentials || undefined });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
|
||||||
connection.markAsRemote();
|
connection.markAsRemote();
|
||||||
connection.on('close', closePipe);
|
connection.on('close', closePipe);
|
||||||
|
|
||||||
|
let closeError: string | undefined;
|
||||||
const onPipeClosed = () => {
|
const onPipeClosed = () => {
|
||||||
// Emulate all pages, contexts and the browser closing upon disconnect.
|
// Emulate all pages, contexts and the browser closing upon disconnect.
|
||||||
for (const context of browser?.contexts() || []) {
|
for (const context of browser?.contexts() || []) {
|
||||||
|
|
@ -142,7 +143,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
|
||||||
context._onClose();
|
context._onClose();
|
||||||
}
|
}
|
||||||
browser?._didClose();
|
browser?._didClose();
|
||||||
connection.close(kBrowserClosedError);
|
connection.close(closeError || kBrowserClosedError);
|
||||||
};
|
};
|
||||||
pipe.on('closed', onPipeClosed);
|
pipe.on('closed', onPipeClosed);
|
||||||
connection.onmessage = message => pipe.send({ message }).catch(onPipeClosed);
|
connection.onmessage = message => pipe.send({ message }).catch(onPipeClosed);
|
||||||
|
|
@ -151,8 +152,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
|
||||||
try {
|
try {
|
||||||
connection!.dispatch(message);
|
connection!.dispatch(message);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Playwright: Connection dispatch error`);
|
closeError = e.toString();
|
||||||
console.error(e);
|
|
||||||
closePipe();
|
closePipe();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,6 @@ import * as types from './types';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { isString, isRegExp, constructURLBasedOnBaseURL } from '../utils/utils';
|
import { isString, isRegExp, constructURLBasedOnBaseURL } from '../utils/utils';
|
||||||
|
|
||||||
const deprecatedHits = new Set();
|
|
||||||
export function deprecate(methodName: string, message: string) {
|
|
||||||
if (deprecatedHits.has(methodName))
|
|
||||||
return;
|
|
||||||
deprecatedHits.add(methodName);
|
|
||||||
console.warn(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function envObjectToArray(env: types.Env): { name: string, value: string }[] {
|
export function envObjectToArray(env: types.Env): { name: string, value: string }[] {
|
||||||
const result: { name: string, value: string }[] = [];
|
const result: { name: string, value: string }[] = [];
|
||||||
for (const name in env) {
|
for (const name in env) {
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,7 @@ export class GridServer {
|
||||||
return { error: undefined };
|
return { error: undefined };
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this._log('failed to launch agent ' + agent.agentId);
|
this._log('failed to launch agent ' + agent.agentId);
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.error(error);
|
console.error(error);
|
||||||
agent.closeAgent(WSErrors.AGENT_CREATION_FAILED);
|
agent.closeAgent(WSErrors.AGENT_CREATION_FAILED);
|
||||||
return { error };
|
return { error };
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,7 @@ export class Firefox extends BrowserType {
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] {
|
_defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] {
|
||||||
const { args = [], devtools, headless } = options;
|
const { args = [], headless } = options;
|
||||||
if (devtools)
|
|
||||||
console.warn('devtools parameter is not supported as a launch argument in Firefox. You can launch the devtools window manually.');
|
|
||||||
const userDataDirArg = args.find(arg => arg.startsWith('-profile') || arg.startsWith('--profile'));
|
const userDataDirArg = args.find(arg => arg.startsWith('-profile') || arg.startsWith('--profile'));
|
||||||
if (userDataDirArg)
|
if (userDataDirArg)
|
||||||
throw new Error('Pass userDataDir parameter to `browserType.launchPersistentContext(userDataDir, ...)` instead of specifying --profile argument');
|
throw new Error('Pass userDataDir parameter to `browserType.launchPersistentContext(userDataDir, ...)` instead of specifying --profile argument');
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export class Recorder {
|
||||||
};
|
};
|
||||||
globalThis._playwrightRefreshOverlay();
|
globalThis._playwrightRefreshOverlay();
|
||||||
if (params.isUnderTest)
|
if (params.isUnderTest)
|
||||||
console.error('Recorder script ready for test');
|
console.error('Recorder script ready for test'); // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
|
|
||||||
private _refreshListenersIfNeeded() {
|
private _refreshListenersIfNeeded() {
|
||||||
|
|
@ -240,7 +240,7 @@ export class Recorder {
|
||||||
const result = activeElement ? generateSelector(this._injectedScript, activeElement) : null;
|
const result = activeElement ? generateSelector(this._injectedScript, activeElement) : null;
|
||||||
this._activeModel = result && result.selector ? result : null;
|
this._activeModel = result && result.selector ? result : null;
|
||||||
if (this._params.isUnderTest)
|
if (this._params.isUnderTest)
|
||||||
console.error('Highlight updated for test: ' + (result ? result.selector : null));
|
console.error('Highlight updated for test: ' + (result ? result.selector : null)); // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updateModelForHoveredElement() {
|
private _updateModelForHoveredElement() {
|
||||||
|
|
@ -256,7 +256,7 @@ export class Recorder {
|
||||||
this._hoveredModel = selector ? { selector, elements } : null;
|
this._hoveredModel = selector ? { selector, elements } : null;
|
||||||
this._updateHighlight();
|
this._updateHighlight();
|
||||||
if (this._params.isUnderTest)
|
if (this._params.isUnderTest)
|
||||||
console.error('Highlight updated for test: ' + selector);
|
console.error('Highlight updated for test: ' + selector); // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updateHighlight() {
|
private _updateHighlight() {
|
||||||
|
|
@ -400,7 +400,7 @@ export class Recorder {
|
||||||
if (this._params.isUnderTest) {
|
if (this._params.isUnderTest) {
|
||||||
// Serialize all to string as we cannot attribute console message to isolated world
|
// Serialize all to string as we cannot attribute console message to isolated world
|
||||||
// in Firefox.
|
// in Firefox.
|
||||||
console.error('Action performed for test: ' + JSON.stringify({
|
console.error('Action performed for test: ' + JSON.stringify({ // eslint-disable-line no-console
|
||||||
hovered: this._hoveredModel ? this._hoveredModel.selector : null,
|
hovered: this._hoveredModel ? this._hoveredModel.selector : null,
|
||||||
active: this._activeModel ? this._activeModel.selector : null,
|
active: this._activeModel ? this._activeModel.selector : null,
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ export class RecorderApp extends EventEmitter {
|
||||||
|
|
||||||
this._page.once('close', () => {
|
this._page.once('close', () => {
|
||||||
this.emit('close');
|
this.emit('close');
|
||||||
this._page.context().close(internalCallMetadata()).catch(e => console.error(e));
|
this._page.context().close(internalCallMetadata()).catch(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
const mainFrame = this._page.mainFrame();
|
const mainFrame = this._page.mainFrame();
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import { ProgressController } from '../../progress';
|
||||||
|
|
||||||
export async function showTraceViewer(traceUrl: string, browserName: string, headless = false, port?: number): Promise<BrowserContext | undefined> {
|
export async function showTraceViewer(traceUrl: string, browserName: string, headless = false, port?: number): Promise<BrowserContext | undefined> {
|
||||||
if (traceUrl && !traceUrl.startsWith('http://') && !traceUrl.startsWith('https://') && !fs.existsSync(traceUrl)) {
|
if (traceUrl && !traceUrl.startsWith('http://') && !traceUrl.startsWith('https://') && !fs.existsSync(traceUrl)) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.error(`Trace file ${traceUrl} does not exist!`);
|
console.error(`Trace file ${traceUrl} does not exist!`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,7 @@ export class WebKit extends BrowserType {
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] {
|
_defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] {
|
||||||
const { args = [], proxy, devtools, headless } = options;
|
const { args = [], proxy, headless } = options;
|
||||||
if (devtools)
|
|
||||||
console.warn('devtools parameter as a launch argument in WebKit is not supported. Also starting Web Inspector manually will terminate the execution in WebKit.');
|
|
||||||
const userDataDirArg = args.find(arg => arg.startsWith('--user-data-dir'));
|
const userDataDirArg = args.find(arg => arg.startsWith('--user-data-dir'));
|
||||||
if (userDataDirArg)
|
if (userDataDirArg)
|
||||||
throw new Error('Pass userDataDir parameter to `browserType.launchPersistentContext(userDataDir, ...)` instead of specifying --user-data-dir argument');
|
throw new Error('Pass userDataDir parameter to `browserType.launchPersistentContext(userDataDir, ...)` instead of specifying --user-data-dir argument');
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,9 @@ export async function validateDependenciesWindows(windowsExeAndDllDirectories: s
|
||||||
if (isSupportedWindowsVersion()) {
|
if (isSupportedWindowsVersion()) {
|
||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
} else {
|
} else {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.warn(`WARNING: running on unsupported windows version!`);
|
console.warn(`WARNING: running on unsupported windows version!`);
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.warn(message);
|
console.warn(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ export class HttpServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async start(port?: number): Promise<string> {
|
async start(port?: number): Promise<string> {
|
||||||
console.assert(!this._urlPrefix, 'server already started');
|
assert(!this._urlPrefix, 'server already started');
|
||||||
this._server.on('connection', socket => {
|
this._server.on('connection', socket => {
|
||||||
this._activeSockets.add(socket);
|
this._activeSockets.add(socket);
|
||||||
socket.once('close', () => this._activeSockets.delete(socket));
|
socket.once('close', () => this._activeSockets.delete(socket));
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ const semver = currentNodeVersion.split('.');
|
||||||
const [major] = [+semver[0]];
|
const [major] = [+semver[0]];
|
||||||
|
|
||||||
if (major < 12) {
|
if (major < 12) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.error(
|
console.error(
|
||||||
'You are running Node.js ' +
|
'You are running Node.js ' +
|
||||||
currentNodeVersion +
|
currentNodeVersion +
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ async function doFetch(event: FetchEvent): Promise<Response> {
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.error(error);
|
console.error(error);
|
||||||
const traceFileName = url.searchParams.get('traceFileName')!;
|
const traceFileName = url.searchParams.get('traceFileName')!;
|
||||||
return new Response(JSON.stringify({
|
return new Response(JSON.stringify({
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||||
process.env.PWDEBUG = '1';
|
process.env.PWDEBUG = '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
const runner = new Runner(overrides, { defaultConfig, printResolvedConfig: process.stdout.isTTY });
|
const runner = new Runner(overrides, { defaultConfig });
|
||||||
|
|
||||||
// When no --config option is passed, let's look for the config file in the current directory.
|
// When no --config option is passed, let's look for the config file in the current directory.
|
||||||
const configFile = opts.config ? path.resolve(process.cwd(), opts.config) : process.cwd();
|
const configFile = opts.config ? path.resolve(process.cwd(), opts.config) : process.cwd();
|
||||||
|
|
|
||||||
|
|
@ -54,24 +54,18 @@ type RunOptions = {
|
||||||
|
|
||||||
export class Runner {
|
export class Runner {
|
||||||
private _loader: Loader;
|
private _loader: Loader;
|
||||||
private _printResolvedConfig: boolean;
|
|
||||||
private _reporter!: Reporter;
|
private _reporter!: Reporter;
|
||||||
private _didBegin = false;
|
private _didBegin = false;
|
||||||
private _internalGlobalSetups: Array<InternalGlobalSetupFunction> = [];
|
private _internalGlobalSetups: Array<InternalGlobalSetupFunction> = [];
|
||||||
|
|
||||||
constructor(configOverrides: Config, options: { defaultConfig?: Config, printResolvedConfig?: boolean } = {}) {
|
constructor(configOverrides: Config, options: { defaultConfig?: Config } = {}) {
|
||||||
this._printResolvedConfig = !!options.printResolvedConfig;
|
|
||||||
this._loader = new Loader(options.defaultConfig || {}, configOverrides);
|
this._loader = new Loader(options.defaultConfig || {}, configOverrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadConfigFromFile(configFileOrDirectory: string): Promise<Config> {
|
async loadConfigFromFile(configFileOrDirectory: string): Promise<Config> {
|
||||||
const loadConfig = async (configFile: string) => {
|
const loadConfig = async (configFile: string) => {
|
||||||
if (fs.existsSync(configFile)) {
|
if (fs.existsSync(configFile))
|
||||||
if (this._printResolvedConfig)
|
return await this._loader.loadConfigFile(configFile);
|
||||||
console.log(`Using config at ` + configFile);
|
|
||||||
const config = await this._loader.loadConfigFile(configFile);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadConfigFromDirectory = async (directory: string) => {
|
const loadConfigFromDirectory = async (directory: string) => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue