screenshot/test_1

This commit is contained in:
ramkumarp
2025-03-27 11:21:02 +00:00
commit 616d466383
470 changed files with 144705 additions and 0 deletions

558
node_modules/playwright/lib/reporters/base.js generated vendored Normal file
View File

@@ -0,0 +1,558 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TerminalReporter = void 0;
exports.fitToWidth = fitToWidth;
exports.formatError = formatError;
exports.formatFailure = formatFailure;
exports.formatResultFailure = formatResultFailure;
exports.formatRetry = formatRetry;
exports.nonTerminalScreen = exports.kOutputSymbol = exports.internalScreen = void 0;
exports.prepareErrorStack = prepareErrorStack;
exports.relativeFilePath = relativeFilePath;
exports.resolveOutputFile = resolveOutputFile;
exports.separator = separator;
exports.stepSuffix = stepSuffix;
exports.terminalScreen = void 0;
var _path = _interopRequireDefault(require("path"));
var _utils = require("playwright-core/lib/utils");
var _utilsBundle = require("playwright-core/lib/utilsBundle");
var _util = require("../util");
var _utilsBundle2 = require("../utilsBundle");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const kOutputSymbol = exports.kOutputSymbol = Symbol('output');
// Output goes to terminal.
const terminalScreen = exports.terminalScreen = (() => {
let isTTY = !!process.stdout.isTTY;
let ttyWidth = process.stdout.columns || 0;
if (process.env.PLAYWRIGHT_FORCE_TTY === 'false' || process.env.PLAYWRIGHT_FORCE_TTY === '0') {
isTTY = false;
ttyWidth = 0;
} else if (process.env.PLAYWRIGHT_FORCE_TTY === 'true' || process.env.PLAYWRIGHT_FORCE_TTY === '1') {
isTTY = true;
ttyWidth = process.stdout.columns || 100;
} else if (process.env.PLAYWRIGHT_FORCE_TTY) {
isTTY = true;
ttyWidth = +process.env.PLAYWRIGHT_FORCE_TTY;
if (isNaN(ttyWidth)) ttyWidth = 100;
}
let useColors = isTTY;
if (process.env.DEBUG_COLORS === '0' || process.env.DEBUG_COLORS === 'false' || process.env.FORCE_COLOR === '0' || process.env.FORCE_COLOR === 'false') useColors = false;else if (process.env.DEBUG_COLORS || process.env.FORCE_COLOR) useColors = true;
const colors = useColors ? _utils.colors : _utils.noColors;
return {
resolveFiles: 'cwd',
isTTY,
ttyWidth,
colors
};
})();
// Output does not go to terminal, but colors are controlled with terminal env vars.
const nonTerminalScreen = exports.nonTerminalScreen = {
colors: terminalScreen.colors,
isTTY: false,
ttyWidth: 0,
resolveFiles: 'rootDir'
};
// Internal output for post-processing, should always contain real colors.
const internalScreen = exports.internalScreen = {
colors: _utils.colors,
isTTY: false,
ttyWidth: 0,
resolveFiles: 'rootDir'
};
class TerminalReporter {
constructor(options = {}) {
this.screen = terminalScreen;
this.config = void 0;
this.suite = void 0;
this.totalTestCount = 0;
this.result = void 0;
this.fileDurations = new Map();
this._omitFailures = void 0;
this._fatalErrors = [];
this._failureCount = 0;
this._omitFailures = options.omitFailures || false;
}
version() {
return 'v2';
}
onConfigure(config) {
this.config = config;
}
onBegin(suite) {
this.suite = suite;
this.totalTestCount = suite.allTests().length;
}
onStdOut(chunk, test, result) {
this._appendOutput({
chunk,
type: 'stdout'
}, result);
}
onStdErr(chunk, test, result) {
this._appendOutput({
chunk,
type: 'stderr'
}, result);
}
_appendOutput(output, result) {
if (!result) return;
result[kOutputSymbol] = result[kOutputSymbol] || [];
result[kOutputSymbol].push(output);
}
onTestEnd(test, result) {
if (result.status !== 'skipped' && result.status !== test.expectedStatus) ++this._failureCount;
const projectName = test.titlePath()[1];
const relativePath = relativeTestPath(this.screen, this.config, test);
const fileAndProject = (projectName ? `[${projectName}] ` : '') + relativePath;
const entry = this.fileDurations.get(fileAndProject) || {
duration: 0,
workers: new Set()
};
entry.duration += result.duration;
entry.workers.add(result.workerIndex);
this.fileDurations.set(fileAndProject, entry);
}
onError(error) {
this._fatalErrors.push(error);
}
async onEnd(result) {
this.result = result;
}
fitToScreen(line, prefix) {
if (!this.screen.ttyWidth) {
// Guard against the case where we cannot determine available width.
return line;
}
return fitToWidth(line, this.screen.ttyWidth, prefix);
}
generateStartingMessage() {
var _this$config$metadata;
const jobs = (_this$config$metadata = this.config.metadata.actualWorkers) !== null && _this$config$metadata !== void 0 ? _this$config$metadata : this.config.workers;
const shardDetails = this.config.shard ? `, shard ${this.config.shard.current} of ${this.config.shard.total}` : '';
if (!this.totalTestCount) return '';
return '\n' + this.screen.colors.dim('Running ') + this.totalTestCount + this.screen.colors.dim(` test${this.totalTestCount !== 1 ? 's' : ''} using `) + jobs + this.screen.colors.dim(` worker${jobs !== 1 ? 's' : ''}${shardDetails}`);
}
getSlowTests() {
if (!this.config.reportSlowTests) return [];
// Only pick durations that were served by single worker.
const fileDurations = [...this.fileDurations.entries()].filter(([key, value]) => value.workers.size === 1).map(([key, value]) => [key, value.duration]);
fileDurations.sort((a, b) => b[1] - a[1]);
const count = Math.min(fileDurations.length, this.config.reportSlowTests.max || Number.POSITIVE_INFINITY);
const threshold = this.config.reportSlowTests.threshold;
return fileDurations.filter(([, duration]) => duration > threshold).slice(0, count);
}
generateSummaryMessage({
didNotRun,
skipped,
expected,
interrupted,
unexpected,
flaky,
fatalErrors
}) {
const tokens = [];
if (unexpected.length) {
tokens.push(this.screen.colors.red(` ${unexpected.length} failed`));
for (const test of unexpected) tokens.push(this.screen.colors.red(this.formatTestHeader(test, {
indent: ' '
})));
}
if (interrupted.length) {
tokens.push(this.screen.colors.yellow(` ${interrupted.length} interrupted`));
for (const test of interrupted) tokens.push(this.screen.colors.yellow(this.formatTestHeader(test, {
indent: ' '
})));
}
if (flaky.length) {
tokens.push(this.screen.colors.yellow(` ${flaky.length} flaky`));
for (const test of flaky) tokens.push(this.screen.colors.yellow(this.formatTestHeader(test, {
indent: ' '
})));
}
if (skipped) tokens.push(this.screen.colors.yellow(` ${skipped} skipped`));
if (didNotRun) tokens.push(this.screen.colors.yellow(` ${didNotRun} did not run`));
if (expected) tokens.push(this.screen.colors.green(` ${expected} passed`) + this.screen.colors.dim(` (${(0, _utilsBundle.ms)(this.result.duration)})`));
if (fatalErrors.length && expected + unexpected.length + interrupted.length + flaky.length > 0) tokens.push(this.screen.colors.red(` ${fatalErrors.length === 1 ? '1 error was not a part of any test' : fatalErrors.length + ' errors were not a part of any test'}, see above for details`));
return tokens.join('\n');
}
generateSummary() {
let didNotRun = 0;
let skipped = 0;
let expected = 0;
const interrupted = [];
const interruptedToPrint = [];
const unexpected = [];
const flaky = [];
this.suite.allTests().forEach(test => {
switch (test.outcome()) {
case 'skipped':
{
if (test.results.some(result => result.status === 'interrupted')) {
if (test.results.some(result => !!result.error)) interruptedToPrint.push(test);
interrupted.push(test);
} else if (!test.results.length || test.expectedStatus !== 'skipped') {
++didNotRun;
} else {
++skipped;
}
break;
}
case 'expected':
++expected;
break;
case 'unexpected':
unexpected.push(test);
break;
case 'flaky':
flaky.push(test);
break;
}
});
const failuresToPrint = [...unexpected, ...flaky, ...interruptedToPrint];
return {
didNotRun,
skipped,
expected,
interrupted,
unexpected,
flaky,
failuresToPrint,
fatalErrors: this._fatalErrors
};
}
epilogue(full) {
const summary = this.generateSummary();
const summaryMessage = this.generateSummaryMessage(summary);
if (full && summary.failuresToPrint.length && !this._omitFailures) this._printFailures(summary.failuresToPrint);
this._printSlowTests();
// TODO: 1.52: Make warning display prettier
// this._printWarnings();
this._printSummary(summaryMessage);
}
_printFailures(failures) {
console.log('');
failures.forEach((test, index) => {
console.log(this.formatFailure(test, index + 1));
});
}
_printSlowTests() {
const slowTests = this.getSlowTests();
slowTests.forEach(([file, duration]) => {
console.log(this.screen.colors.yellow(' Slow test file: ') + file + this.screen.colors.yellow(` (${(0, _utilsBundle.ms)(duration)})`));
});
if (slowTests.length) console.log(this.screen.colors.yellow(' Consider running tests from slow files in parallel, see https://playwright.dev/docs/test-parallel.'));
}
_printWarnings() {
const warningTests = this.suite.allTests().filter(test => test.annotations.some(a => a.type === 'warning'));
const encounteredWarnings = new Map();
for (const test of warningTests) {
for (const annotation of test.annotations) {
if (annotation.type !== 'warning' || annotation.description === undefined) continue;
let tests = encounteredWarnings.get(annotation.description);
if (!tests) {
tests = [];
encounteredWarnings.set(annotation.description, tests);
}
tests.push(test);
}
}
for (const [description, tests] of encounteredWarnings) {
console.log(this.screen.colors.yellow(' Warning: ') + description);
for (const test of tests) console.log(this.formatTestHeader(test, {
indent: ' ',
mode: 'default'
}));
}
}
_printSummary(summary) {
if (summary.trim()) console.log(summary);
}
willRetry(test) {
return test.outcome() === 'unexpected' && test.results.length <= test.retries;
}
formatTestTitle(test, step, omitLocation = false) {
return formatTestTitle(this.screen, this.config, test, step, omitLocation);
}
formatTestHeader(test, options = {}) {
return formatTestHeader(this.screen, this.config, test, options);
}
formatFailure(test, index) {
return formatFailure(this.screen, this.config, test, index);
}
formatError(error) {
return formatError(this.screen, error);
}
}
exports.TerminalReporter = TerminalReporter;
function formatFailure(screen, config, test, index) {
const lines = [];
const header = formatTestHeader(screen, config, test, {
indent: ' ',
index,
mode: 'error'
});
lines.push(screen.colors.red(header));
for (const result of test.results) {
const resultLines = [];
const errors = formatResultFailure(screen, test, result, ' ');
if (!errors.length) continue;
const retryLines = [];
if (result.retry) {
retryLines.push('');
retryLines.push(screen.colors.gray(separator(screen, ` Retry #${result.retry}`)));
}
resultLines.push(...retryLines);
resultLines.push(...errors.map(error => '\n' + error.message));
for (let i = 0; i < result.attachments.length; ++i) {
const attachment = result.attachments[i];
if (attachment.name.startsWith('_')) continue;
const hasPrintableContent = attachment.contentType.startsWith('text/');
if (!attachment.path && !hasPrintableContent) continue;
resultLines.push('');
resultLines.push(screen.colors.cyan(separator(screen, ` attachment #${i + 1}: ${attachment.name} (${attachment.contentType})`)));
if (attachment.path) {
const relativePath = _path.default.relative(process.cwd(), attachment.path);
resultLines.push(screen.colors.cyan(` ${relativePath}`));
// Make this extensible
if (attachment.name === 'trace') {
const packageManagerCommand = (0, _utils.getPackageManagerExecCommand)();
resultLines.push(screen.colors.cyan(` Usage:`));
resultLines.push('');
resultLines.push(screen.colors.cyan(` ${packageManagerCommand} playwright show-trace ${quotePathIfNeeded(relativePath)}`));
resultLines.push('');
}
} else {
if (attachment.contentType.startsWith('text/') && attachment.body) {
let text = attachment.body.toString();
if (text.length > 300) text = text.slice(0, 300) + '...';
for (const line of text.split('\n')) resultLines.push(screen.colors.cyan(` ${line}`));
}
}
resultLines.push(screen.colors.cyan(separator(screen, ' ')));
}
lines.push(...resultLines);
}
lines.push('');
return lines.join('\n');
}
function formatRetry(screen, result) {
const retryLines = [];
if (result.retry) {
retryLines.push('');
retryLines.push(screen.colors.gray(separator(screen, ` Retry #${result.retry}`)));
}
return retryLines;
}
function quotePathIfNeeded(path) {
if (/\s/.test(path)) return `"${path}"`;
return path;
}
function formatResultFailure(screen, test, result, initialIndent) {
const errorDetails = [];
if (result.status === 'passed' && test.expectedStatus === 'failed') {
errorDetails.push({
message: indent(screen.colors.red(`Expected to fail, but passed.`), initialIndent)
});
}
if (result.status === 'interrupted') {
errorDetails.push({
message: indent(screen.colors.red(`Test was interrupted.`), initialIndent)
});
}
for (const error of result.errors) {
const formattedError = formatError(screen, error);
errorDetails.push({
message: indent(formattedError.message, initialIndent),
location: formattedError.location
});
}
return errorDetails;
}
function relativeFilePath(screen, config, file) {
if (screen.resolveFiles === 'cwd') return _path.default.relative(process.cwd(), file);
return _path.default.relative(config.rootDir, file);
}
function relativeTestPath(screen, config, test) {
return relativeFilePath(screen, config, test.location.file);
}
function stepSuffix(step) {
const stepTitles = step ? step.titlePath() : [];
return stepTitles.map(t => t.split('\n')[0]).map(t => ' ' + t).join('');
}
function formatTestTitle(screen, config, test, step, omitLocation = false) {
// root, project, file, ...describes, test
const [, projectName,, ...titles] = test.titlePath();
let location;
if (omitLocation) location = `${relativeTestPath(screen, config, test)}`;else location = `${relativeTestPath(screen, config, test)}:${test.location.line}:${test.location.column}`;
const projectTitle = projectName ? `[${projectName}] ` : '';
const testTitle = `${projectTitle}${location} ${titles.join(' ')}`;
const extraTags = test.tags.filter(t => !testTitle.includes(t));
return `${testTitle}${stepSuffix(step)}${extraTags.length ? ' ' + extraTags.join(' ') : ''}`;
}
function formatTestHeader(screen, config, test, options = {}) {
const title = formatTestTitle(screen, config, test);
const header = `${options.indent || ''}${options.index ? options.index + ') ' : ''}${title}`;
let fullHeader = header;
// Render the path to the deepest failing test.step.
if (options.mode === 'error') {
const stepPaths = new Set();
for (const result of test.results.filter(r => !!r.errors.length)) {
const stepPath = [];
const visit = steps => {
const errors = steps.filter(s => s.error);
if (errors.length > 1) return;
if (errors.length === 1 && errors[0].category === 'test.step') {
stepPath.push(errors[0].title);
visit(errors[0].steps);
}
};
visit(result.steps);
stepPaths.add(['', ...stepPath].join(' '));
}
fullHeader = header + (stepPaths.size === 1 ? stepPaths.values().next().value : '');
}
return separator(screen, fullHeader);
}
function formatError(screen, error) {
const message = error.message || error.value || '';
const stack = error.stack;
if (!stack && !error.location) return {
message
};
const tokens = [];
// Now that we filter out internals from our stack traces, we can safely render
// the helper / original exception locations.
const parsedStack = stack ? prepareErrorStack(stack) : undefined;
tokens.push((parsedStack === null || parsedStack === void 0 ? void 0 : parsedStack.message) || message);
if (error.snippet) {
let snippet = error.snippet;
if (!screen.colors.enabled) snippet = (0, _util.stripAnsiEscapes)(snippet);
tokens.push('');
tokens.push(snippet);
}
if (parsedStack && parsedStack.stackLines.length) tokens.push(screen.colors.dim(parsedStack.stackLines.join('\n')));
let location = error.location;
if (parsedStack && !location) location = parsedStack.location;
if (error.cause) tokens.push(screen.colors.dim('[cause]: ') + formatError(screen, error.cause).message);
return {
location,
message: tokens.join('\n')
};
}
function separator(screen, text = '') {
if (text) text += ' ';
const columns = Math.min(100, screen.ttyWidth || 100);
return text + screen.colors.dim('─'.repeat(Math.max(0, columns - text.length)));
}
function indent(lines, tab) {
return lines.replace(/^(?=.+$)/gm, tab);
}
function prepareErrorStack(stack) {
return (0, _utils.parseErrorStack)(stack, _path.default.sep, !!process.env.PWDEBUGIMPL);
}
function characterWidth(c) {
return _utilsBundle2.getEastAsianWidth.eastAsianWidth(c.codePointAt(0));
}
function stringWidth(v) {
let width = 0;
for (const {
segment
} of new Intl.Segmenter(undefined, {
granularity: 'grapheme'
}).segment(v)) width += characterWidth(segment);
return width;
}
function suffixOfWidth(v, width) {
const segments = [...new Intl.Segmenter(undefined, {
granularity: 'grapheme'
}).segment(v)];
let suffixBegin = v.length;
for (const {
segment,
index
} of segments.reverse()) {
const segmentWidth = stringWidth(segment);
if (segmentWidth > width) break;
width -= segmentWidth;
suffixBegin = index;
}
return v.substring(suffixBegin);
}
// Leaves enough space for the "prefix" to also fit.
function fitToWidth(line, width, prefix) {
const prefixLength = prefix ? (0, _util.stripAnsiEscapes)(prefix).length : 0;
width -= prefixLength;
if (stringWidth(line) <= width) return line;
// Even items are plain text, odd items are control sequences.
const parts = line.split(_util.ansiRegex);
const taken = [];
for (let i = parts.length - 1; i >= 0; i--) {
if (i % 2) {
// Include all control sequences to preserve formatting.
taken.push(parts[i]);
} else {
let part = suffixOfWidth(parts[i], width);
const wasTruncated = part.length < parts[i].length;
if (wasTruncated && parts[i].length > 0) {
// Add ellipsis if we are truncating.
part = '\u2026' + suffixOfWidth(parts[i], width - 1);
}
taken.push(part);
width -= stringWidth(part);
}
}
return taken.reverse().join('');
}
function resolveFromEnv(name) {
const value = process.env[name];
if (value) return _path.default.resolve(process.cwd(), value);
return undefined;
}
// In addition to `outputFile` the function returns `outputDir` which should
// be cleaned up if present by some reporters contract.
function resolveOutputFile(reporterName, options) {
var _ref, _process$env, _options$default;
const name = reporterName.toUpperCase();
let outputFile = resolveFromEnv(`PLAYWRIGHT_${name}_OUTPUT_FILE`);
if (!outputFile && options.outputFile) outputFile = _path.default.resolve(options.configDir, options.outputFile);
if (outputFile) return {
outputFile
};
let outputDir = resolveFromEnv(`PLAYWRIGHT_${name}_OUTPUT_DIR`);
if (!outputDir && options.outputDir) outputDir = _path.default.resolve(options.configDir, options.outputDir);
if (!outputDir && options.default) outputDir = (0, _util.resolveReporterOutputPath)(options.default.outputDir, options.configDir, undefined);
if (!outputDir) outputDir = options.configDir;
const reportName = (_ref = (_process$env = process.env[`PLAYWRIGHT_${name}_OUTPUT_NAME`]) !== null && _process$env !== void 0 ? _process$env : options.fileName) !== null && _ref !== void 0 ? _ref : (_options$default = options.default) === null || _options$default === void 0 ? void 0 : _options$default.fileName;
if (!reportName) return undefined;
outputFile = _path.default.resolve(outputDir, reportName);
return {
outputFile,
outputDir
};
}

133
node_modules/playwright/lib/reporters/blob.js generated vendored Normal file
View File

@@ -0,0 +1,133 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.currentBlobReportVersion = exports.BlobReporter = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _stream = require("stream");
var _utils = require("playwright-core/lib/utils");
var _utilsBundle = require("playwright-core/lib/utilsBundle");
var _zipBundle = require("playwright-core/lib/zipBundle");
var _base = require("./base");
var _teleEmitter = require("./teleEmitter");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const currentBlobReportVersion = exports.currentBlobReportVersion = 2;
class BlobReporter extends _teleEmitter.TeleReporterEmitter {
constructor(options) {
super(message => this._messages.push(message));
this._messages = [];
this._attachments = [];
this._options = void 0;
this._salt = void 0;
this._config = void 0;
this._options = options;
if (this._options.fileName && !this._options.fileName.endsWith('.zip')) throw new Error(`Blob report file name must end with .zip extension: ${this._options.fileName}`);
this._salt = (0, _utils.createGuid)();
}
onConfigure(config) {
var _config$shard;
const metadata = {
version: currentBlobReportVersion,
userAgent: (0, _utils.getUserAgent)(),
name: process.env.PWTEST_BOT_NAME,
shard: (_config$shard = config.shard) !== null && _config$shard !== void 0 ? _config$shard : undefined,
pathSeparator: _path.default.sep
};
this._messages.push({
method: 'onBlobReportMetadata',
params: metadata
});
this._config = config;
super.onConfigure(config);
}
async onEnd(result) {
await super.onEnd(result);
const zipFileName = await this._prepareOutputFile();
const zipFile = new _zipBundle.yazl.ZipFile();
const zipFinishPromise = new _utils.ManualPromise();
const finishPromise = zipFinishPromise.catch(e => {
throw new Error(`Failed to write report ${zipFileName}: ` + e.message);
});
zipFile.on('error', error => zipFinishPromise.reject(error));
zipFile.outputStream.pipe(_fs.default.createWriteStream(zipFileName)).on('close', () => {
zipFinishPromise.resolve(undefined);
}).on('error', error => zipFinishPromise.reject(error));
for (const {
originalPath,
zipEntryPath
} of this._attachments) {
var _fs$statSync;
if (!((_fs$statSync = _fs.default.statSync(originalPath, {
throwIfNoEntry: false
})) !== null && _fs$statSync !== void 0 && _fs$statSync.isFile())) continue;
zipFile.addFile(originalPath, zipEntryPath);
}
const lines = this._messages.map(m => JSON.stringify(m) + '\n');
const content = _stream.Readable.from(lines);
zipFile.addReadStream(content, 'report.jsonl');
zipFile.end();
await finishPromise;
}
async _prepareOutputFile() {
const {
outputFile,
outputDir
} = (0, _base.resolveOutputFile)('BLOB', {
...this._options,
default: {
fileName: this._defaultReportName(this._config),
outputDir: 'blob-report'
}
});
if (!process.env.PWTEST_BLOB_DO_NOT_REMOVE) await (0, _utils.removeFolders)([outputDir]);
await _fs.default.promises.mkdir(_path.default.dirname(outputFile), {
recursive: true
});
return outputFile;
}
_defaultReportName(config) {
let reportName = 'report';
if (this._options._commandHash) reportName += '-' + (0, _utils.sanitizeForFilePath)(this._options._commandHash);
if (config.shard) {
const paddedNumber = `${config.shard.current}`.padStart(`${config.shard.total}`.length, '0');
reportName = `${reportName}-${paddedNumber}`;
}
return `${reportName}.zip`;
}
_serializeAttachments(attachments) {
return super._serializeAttachments(attachments).map(attachment => {
if (!attachment.path) return attachment;
// Add run guid to avoid clashes between shards.
const sha1 = (0, _utils.calculateSha1)(attachment.path + this._salt);
const extension = _utilsBundle.mime.getExtension(attachment.contentType) || 'dat';
const newPath = `resources/${sha1}.${extension}`;
this._attachments.push({
originalPath: attachment.path,
zipEntryPath: newPath
});
return {
...attachment,
path: newPath
};
});
}
}
exports.BlobReporter = BlobReporter;

79
node_modules/playwright/lib/reporters/dot.js generated vendored Normal file
View File

@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _base = require("./base");
/**
* 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.
*/
class DotReporter extends _base.TerminalReporter {
constructor(...args) {
super(...args);
this._counter = 0;
}
onBegin(suite) {
super.onBegin(suite);
console.log(this.generateStartingMessage());
}
onStdOut(chunk, test, result) {
super.onStdOut(chunk, test, result);
if (!this.config.quiet) process.stdout.write(chunk);
}
onStdErr(chunk, test, result) {
super.onStdErr(chunk, test, result);
if (!this.config.quiet) process.stderr.write(chunk);
}
onTestEnd(test, result) {
super.onTestEnd(test, result);
if (this._counter === 80) {
process.stdout.write('\n');
this._counter = 0;
}
++this._counter;
if (result.status === 'skipped') {
process.stdout.write(this.screen.colors.yellow('°'));
return;
}
if (this.willRetry(test)) {
process.stdout.write(this.screen.colors.gray('×'));
return;
}
switch (test.outcome()) {
case 'expected':
process.stdout.write(this.screen.colors.green('·'));
break;
case 'unexpected':
process.stdout.write(this.screen.colors.red(result.status === 'timedOut' ? 'T' : 'F'));
break;
case 'flaky':
process.stdout.write(this.screen.colors.yellow('±'));
break;
}
}
onError(error) {
super.onError(error);
console.log('\n' + this.formatError(error).message);
this._counter = 0;
}
async onEnd(result) {
await super.onEnd(result);
process.stdout.write('\n');
this.epilogue(true);
}
}
var _default = exports.default = DotReporter;

31
node_modules/playwright/lib/reporters/empty.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class EmptyReporter {
version() {
return 'v2';
}
printsToStdio() {
return false;
}
}
var _default = exports.default = EmptyReporter;

121
node_modules/playwright/lib/reporters/github.js generated vendored Normal file
View File

@@ -0,0 +1,121 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.GitHubReporter = void 0;
var _path = _interopRequireDefault(require("path"));
var _utils = require("playwright-core/lib/utils");
var _utilsBundle = require("playwright-core/lib/utilsBundle");
var _base = require("./base");
var _util = require("../util");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*/
class GitHubLogger {
_log(message, type = 'notice', options = {}) {
message = message.replace(/\n/g, '%0A');
const configs = Object.entries(options).map(([key, option]) => `${key}=${option}`).join(',');
console.log((0, _util.stripAnsiEscapes)(`::${type} ${configs}::${message}`));
}
debug(message, options) {
this._log(message, 'debug', options);
}
error(message, options) {
this._log(message, 'error', options);
}
notice(message, options) {
this._log(message, 'notice', options);
}
warning(message, options) {
this._log(message, 'warning', options);
}
}
class GitHubReporter extends _base.TerminalReporter {
constructor(options = {}) {
super(options);
this.githubLogger = new GitHubLogger();
this.screen = {
...this.screen,
colors: _utils.noColors
};
}
printsToStdio() {
return false;
}
async onEnd(result) {
await super.onEnd(result);
this._printAnnotations();
}
onError(error) {
const errorMessage = this.formatError(error).message;
this.githubLogger.error(errorMessage);
}
_printAnnotations() {
const summary = this.generateSummary();
const summaryMessage = this.generateSummaryMessage(summary);
if (summary.failuresToPrint.length) this._printFailureAnnotations(summary.failuresToPrint);
this._printSlowTestAnnotations();
this._printSummaryAnnotation(summaryMessage);
}
_printSlowTestAnnotations() {
this.getSlowTests().forEach(([file, duration]) => {
const filePath = workspaceRelativePath(_path.default.join(process.cwd(), file));
this.githubLogger.warning(`${filePath} took ${(0, _utilsBundle.ms)(duration)}`, {
title: 'Slow Test',
file: filePath
});
});
}
_printSummaryAnnotation(summary) {
this.githubLogger.notice(summary, {
title: '🎭 Playwright Run Summary'
});
}
_printFailureAnnotations(failures) {
failures.forEach((test, index) => {
const title = this.formatTestTitle(test);
const header = this.formatTestHeader(test, {
indent: ' ',
index: index + 1,
mode: 'error'
});
for (const result of test.results) {
const errors = (0, _base.formatResultFailure)(this.screen, test, result, ' ');
for (const error of errors) {
var _error$location;
const options = {
file: workspaceRelativePath(((_error$location = error.location) === null || _error$location === void 0 ? void 0 : _error$location.file) || test.location.file),
title
};
if (error.location) {
options.line = error.location.line;
options.col = error.location.column;
}
const message = [header, ...(0, _base.formatRetry)(this.screen, result), error.message].join('\n');
this.githubLogger.error(message, options);
}
}
});
}
}
exports.GitHubReporter = GitHubReporter;
function workspaceRelativePath(filePath) {
var _process$env$GITHUB_W;
return _path.default.relative((_process$env$GITHUB_W = process.env['GITHUB_WORKSPACE']) !== null && _process$env$GITHUB_W !== void 0 ? _process$env$GITHUB_W : '', filePath);
}
var _default = exports.default = GitHubReporter;

644
node_modules/playwright/lib/reporters/html.js generated vendored Normal file
View File

@@ -0,0 +1,644 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.showHTMLReport = showHTMLReport;
exports.startHtmlReportServer = startHtmlReportServer;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _stream = require("stream");
var _utils = require("playwright-core/lib/utils");
var _utilsBundle = require("playwright-core/lib/utilsBundle");
var _zipBundle = require("playwright-core/lib/zipBundle");
var _base = require("./base");
var _babelBundle = require("../transform/babelBundle");
var _util = require("../util");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const htmlReportOptions = ['always', 'never', 'on-failure'];
const isHtmlReportOption = type => {
return htmlReportOptions.includes(type);
};
class HtmlReporter {
constructor(options) {
this.config = void 0;
this.suite = void 0;
this._options = void 0;
this._outputFolder = void 0;
this._attachmentsBaseURL = void 0;
this._open = void 0;
this._port = void 0;
this._host = void 0;
this._buildResult = void 0;
this._topLevelErrors = [];
this._options = options;
}
version() {
return 'v2';
}
printsToStdio() {
return false;
}
onConfigure(config) {
this.config = config;
}
onBegin(suite) {
const {
outputFolder,
open,
attachmentsBaseURL,
host,
port
} = this._resolveOptions();
this._outputFolder = outputFolder;
this._open = open;
this._host = host;
this._port = port;
this._attachmentsBaseURL = attachmentsBaseURL;
const reportedWarnings = new Set();
for (const project of this.config.projects) {
if (this._isSubdirectory(outputFolder, project.outputDir) || this._isSubdirectory(project.outputDir, outputFolder)) {
const key = outputFolder + '|' + project.outputDir;
if (reportedWarnings.has(key)) continue;
reportedWarnings.add(key);
console.log(_utils.colors.red(`Configuration Error: HTML reporter output folder clashes with the tests output folder:`));
console.log(`
html reporter folder: ${_utils.colors.bold(outputFolder)}
test results folder: ${_utils.colors.bold(project.outputDir)}`);
console.log('');
console.log(`HTML reporter will clear its output directory prior to being generated, which will lead to the artifact loss.
`);
}
}
this.suite = suite;
}
_resolveOptions() {
var _reportFolderFromEnv;
const outputFolder = (_reportFolderFromEnv = reportFolderFromEnv()) !== null && _reportFolderFromEnv !== void 0 ? _reportFolderFromEnv : (0, _util.resolveReporterOutputPath)('playwright-report', this._options.configDir, this._options.outputFolder);
return {
outputFolder,
open: getHtmlReportOptionProcessEnv() || this._options.open || 'on-failure',
attachmentsBaseURL: process.env.PLAYWRIGHT_HTML_ATTACHMENTS_BASE_URL || this._options.attachmentsBaseURL || 'data/',
host: process.env.PLAYWRIGHT_HTML_HOST || this._options.host,
port: process.env.PLAYWRIGHT_HTML_PORT ? +process.env.PLAYWRIGHT_HTML_PORT : this._options.port
};
}
_isSubdirectory(parentDir, dir) {
const relativePath = _path.default.relative(parentDir, dir);
return !!relativePath && !relativePath.startsWith('..') && !_path.default.isAbsolute(relativePath);
}
onError(error) {
this._topLevelErrors.push(error);
}
async onEnd(result) {
const projectSuites = this.suite.suites;
await (0, _utils.removeFolders)([this._outputFolder]);
const builder = new HtmlBuilder(this.config, this._outputFolder, this._attachmentsBaseURL);
this._buildResult = await builder.build(this.config.metadata, projectSuites, result, this._topLevelErrors);
}
async onExit() {
if (process.env.CI || !this._buildResult) return;
const {
ok,
singleTestId
} = this._buildResult;
const shouldOpen = !this._options._isTestServer && (this._open === 'always' || !ok && this._open === 'on-failure');
if (shouldOpen) {
await showHTMLReport(this._outputFolder, this._host, this._port, singleTestId);
} else if (this._options._mode === 'test' && !this._options._isTestServer) {
const packageManagerCommand = (0, _utils.getPackageManagerExecCommand)();
const relativeReportPath = this._outputFolder === standaloneDefaultFolder() ? '' : ' ' + _path.default.relative(process.cwd(), this._outputFolder);
const hostArg = this._host ? ` --host ${this._host}` : '';
const portArg = this._port ? ` --port ${this._port}` : '';
console.log('');
console.log('To open last HTML report run:');
console.log(_utils.colors.cyan(`
${packageManagerCommand} playwright show-report${relativeReportPath}${hostArg}${portArg}
`));
}
}
}
function reportFolderFromEnv() {
// Note: PLAYWRIGHT_HTML_REPORT is for backwards compatibility.
const envValue = process.env.PLAYWRIGHT_HTML_OUTPUT_DIR || process.env.PLAYWRIGHT_HTML_REPORT;
return envValue ? _path.default.resolve(envValue) : undefined;
}
function getHtmlReportOptionProcessEnv() {
// Note: PW_TEST_HTML_REPORT_OPEN is for backwards compatibility.
const htmlOpenEnv = process.env.PLAYWRIGHT_HTML_OPEN || process.env.PW_TEST_HTML_REPORT_OPEN;
if (!htmlOpenEnv) return undefined;
if (!isHtmlReportOption(htmlOpenEnv)) {
console.log(_utils.colors.red(`Configuration Error: HTML reporter Invalid value for PLAYWRIGHT_HTML_OPEN: ${htmlOpenEnv}. Valid values are: ${htmlReportOptions.join(', ')}`));
return undefined;
}
return htmlOpenEnv;
}
function standaloneDefaultFolder() {
var _reportFolderFromEnv2;
return (_reportFolderFromEnv2 = reportFolderFromEnv()) !== null && _reportFolderFromEnv2 !== void 0 ? _reportFolderFromEnv2 : (0, _util.resolveReporterOutputPath)('playwright-report', process.cwd(), undefined);
}
async function showHTMLReport(reportFolder, host = 'localhost', port, testId) {
const folder = reportFolder !== null && reportFolder !== void 0 ? reportFolder : standaloneDefaultFolder();
try {
(0, _utils.assert)(_fs.default.statSync(folder).isDirectory());
} catch (e) {
console.log(_utils.colors.red(`No report found at "${folder}"`));
(0, _utils.gracefullyProcessExitDoNotHang)(1);
return;
}
const server = startHtmlReportServer(folder);
await server.start({
port,
host,
preferredPort: port ? undefined : 9323
});
let url = server.urlPrefix('human-readable');
console.log('');
console.log(_utils.colors.cyan(` Serving HTML report at ${url}. Press Ctrl+C to quit.`));
if (testId) url += `#?testId=${testId}`;
url = url.replace('0.0.0.0', 'localhost');
await (0, _utilsBundle.open)(url, {
wait: true
}).catch(() => {});
await new Promise(() => {});
}
function startHtmlReportServer(folder) {
const server = new _utils.HttpServer();
server.routePrefix('/', (request, response) => {
let relativePath = new URL('http://localhost' + request.url).pathname;
if (relativePath.startsWith('/trace/file')) {
const url = new URL('http://localhost' + request.url);
try {
return server.serveFile(request, response, url.searchParams.get('path'));
} catch (e) {
return false;
}
}
if (relativePath.endsWith('/stall.js')) return true;
if (relativePath === '/') relativePath = '/index.html';
const absolutePath = _path.default.join(folder, ...relativePath.split('/'));
return server.serveFile(request, response, absolutePath);
});
return server;
}
class HtmlBuilder {
constructor(config, outputDir, attachmentsBaseURL) {
this._config = void 0;
this._reportFolder = void 0;
this._stepsInFile = new _utils.MultiMap();
this._dataZipFile = void 0;
this._hasTraces = false;
this._attachmentsBaseURL = void 0;
this._config = config;
this._reportFolder = outputDir;
_fs.default.mkdirSync(this._reportFolder, {
recursive: true
});
this._dataZipFile = new _zipBundle.yazl.ZipFile();
this._attachmentsBaseURL = attachmentsBaseURL;
}
async build(metadata, projectSuites, result, topLevelErrors) {
const data = new Map();
for (const projectSuite of projectSuites) {
for (const fileSuite of projectSuite.suites) {
const fileName = this._relativeLocation(fileSuite.location).file;
const fileId = (0, _utils.calculateSha1)((0, _utils.toPosixPath)(fileName)).slice(0, 20);
let fileEntry = data.get(fileId);
if (!fileEntry) {
fileEntry = {
testFile: {
fileId,
fileName,
tests: []
},
testFileSummary: {
fileId,
fileName,
tests: [],
stats: emptyStats()
}
};
data.set(fileId, fileEntry);
}
const {
testFile,
testFileSummary
} = fileEntry;
const testEntries = [];
this._processSuite(fileSuite, projectSuite.project().name, [], testEntries);
for (const test of testEntries) {
testFile.tests.push(test.testCase);
testFileSummary.tests.push(test.testCaseSummary);
}
}
}
createSnippets(this._stepsInFile);
let ok = true;
for (const [fileId, {
testFile,
testFileSummary
}] of data) {
const stats = testFileSummary.stats;
for (const test of testFileSummary.tests) {
if (test.outcome === 'expected') ++stats.expected;
if (test.outcome === 'skipped') ++stats.skipped;
if (test.outcome === 'unexpected') ++stats.unexpected;
if (test.outcome === 'flaky') ++stats.flaky;
++stats.total;
}
stats.ok = stats.unexpected + stats.flaky === 0;
if (!stats.ok) ok = false;
const testCaseSummaryComparator = (t1, t2) => {
const w1 = (t1.outcome === 'unexpected' ? 1000 : 0) + (t1.outcome === 'flaky' ? 1 : 0);
const w2 = (t2.outcome === 'unexpected' ? 1000 : 0) + (t2.outcome === 'flaky' ? 1 : 0);
return w2 - w1;
};
testFileSummary.tests.sort(testCaseSummaryComparator);
this._addDataFile(fileId + '.json', testFile);
}
const htmlReport = {
metadata,
startTime: result.startTime.getTime(),
duration: result.duration,
files: [...data.values()].map(e => e.testFileSummary),
projectNames: projectSuites.map(r => r.project().name),
stats: {
...[...data.values()].reduce((a, e) => addStats(a, e.testFileSummary.stats), emptyStats())
},
errors: topLevelErrors.map(error => (0, _base.formatError)(_base.internalScreen, error).message)
};
htmlReport.files.sort((f1, f2) => {
const w1 = f1.stats.unexpected * 1000 + f1.stats.flaky;
const w2 = f2.stats.unexpected * 1000 + f2.stats.flaky;
return w2 - w1;
});
this._addDataFile('report.json', htmlReport);
let singleTestId;
if (htmlReport.stats.total === 1) {
const testFile = data.values().next().value.testFile;
singleTestId = testFile.tests[0].testId;
}
if (process.env.PW_HMR === '1') {
const redirectFile = _path.default.join(this._reportFolder, 'index.html');
await this._writeReportData(redirectFile);
async function redirect() {
const hmrURL = new URL('http://localhost:44224'); // dev server, port is harcoded in build.js
const popup = window.open(hmrURL);
window.addEventListener('message', evt => {
if (evt.source === popup && evt.data === 'ready') {
popup.postMessage(window.playwrightReportBase64, hmrURL.origin);
window.close();
}
}, {
once: true
});
}
_fs.default.appendFileSync(redirectFile, `<script>(${redirect.toString()})()</script>`);
return {
ok,
singleTestId
};
}
// Copy app.
const appFolder = _path.default.join(require.resolve('playwright-core'), '..', 'lib', 'vite', 'htmlReport');
await (0, _utils.copyFileAndMakeWritable)(_path.default.join(appFolder, 'index.html'), _path.default.join(this._reportFolder, 'index.html'));
// Copy trace viewer.
if (this._hasTraces) {
const traceViewerFolder = _path.default.join(require.resolve('playwright-core'), '..', 'lib', 'vite', 'traceViewer');
const traceViewerTargetFolder = _path.default.join(this._reportFolder, 'trace');
const traceViewerAssetsTargetFolder = _path.default.join(traceViewerTargetFolder, 'assets');
_fs.default.mkdirSync(traceViewerAssetsTargetFolder, {
recursive: true
});
for (const file of _fs.default.readdirSync(traceViewerFolder)) {
if (file.endsWith('.map') || file.includes('watch') || file.includes('assets')) continue;
await (0, _utils.copyFileAndMakeWritable)(_path.default.join(traceViewerFolder, file), _path.default.join(traceViewerTargetFolder, file));
}
for (const file of _fs.default.readdirSync(_path.default.join(traceViewerFolder, 'assets'))) {
if (file.endsWith('.map') || file.includes('xtermModule')) continue;
await (0, _utils.copyFileAndMakeWritable)(_path.default.join(traceViewerFolder, 'assets', file), _path.default.join(traceViewerAssetsTargetFolder, file));
}
}
await this._writeReportData(_path.default.join(this._reportFolder, 'index.html'));
return {
ok,
singleTestId
};
}
async _writeReportData(filePath) {
_fs.default.appendFileSync(filePath, '<script>\nwindow.playwrightReportBase64 = "data:application/zip;base64,');
await new Promise(f => {
this._dataZipFile.end(undefined, () => {
this._dataZipFile.outputStream.pipe(new Base64Encoder()).pipe(_fs.default.createWriteStream(filePath, {
flags: 'a'
})).on('close', f);
});
});
_fs.default.appendFileSync(filePath, '";</script>');
}
_addDataFile(fileName, data) {
this._dataZipFile.addBuffer(Buffer.from(JSON.stringify(data)), fileName);
}
_processSuite(suite, projectName, path, outTests) {
const newPath = [...path, suite.title];
suite.entries().forEach(e => {
if (e.type === 'test') outTests.push(this._createTestEntry(e, projectName, newPath));else this._processSuite(e, projectName, newPath, outTests);
});
}
_createTestEntry(test, projectName, path) {
const duration = test.results.reduce((a, r) => a + r.duration, 0);
const location = this._relativeLocation(test.location);
path = path.slice(1).filter(path => path.length > 0);
const results = test.results.map(r => this._createTestResult(test, r));
return {
testCase: {
testId: test.id,
title: test.title,
projectName,
location,
duration,
// Annotations can be pushed directly, with a wrong type.
annotations: test.annotations.map(a => ({
type: a.type,
description: a.description ? String(a.description) : a.description
})),
tags: test.tags,
outcome: test.outcome(),
path,
results,
ok: test.outcome() === 'expected' || test.outcome() === 'flaky'
},
testCaseSummary: {
testId: test.id,
title: test.title,
projectName,
location,
duration,
// Annotations can be pushed directly, with a wrong type.
annotations: test.annotations.map(a => ({
type: a.type,
description: a.description ? String(a.description) : a.description
})),
tags: test.tags,
outcome: test.outcome(),
path,
ok: test.outcome() === 'expected' || test.outcome() === 'flaky',
results: results.map(result => {
return {
attachments: result.attachments.map(a => ({
name: a.name,
contentType: a.contentType,
path: a.path
}))
};
})
}
};
}
_serializeAttachments(attachments) {
let lastAttachment;
return attachments.map(a => {
if (a.name === 'trace') this._hasTraces = true;
if ((a.name === 'stdout' || a.name === 'stderr') && a.contentType === 'text/plain') {
if (lastAttachment && lastAttachment.name === a.name && lastAttachment.contentType === a.contentType) {
lastAttachment.body += (0, _util.stripAnsiEscapes)(a.body);
return null;
}
a.body = (0, _util.stripAnsiEscapes)(a.body);
lastAttachment = a;
return a;
}
if (a.path) {
let fileName = a.path;
try {
const buffer = _fs.default.readFileSync(a.path);
const sha1 = (0, _utils.calculateSha1)(buffer) + _path.default.extname(a.path);
fileName = this._attachmentsBaseURL + sha1;
_fs.default.mkdirSync(_path.default.join(this._reportFolder, 'data'), {
recursive: true
});
_fs.default.writeFileSync(_path.default.join(this._reportFolder, 'data', sha1), buffer);
} catch (e) {}
return {
name: a.name,
contentType: a.contentType,
path: fileName,
body: a.body
};
}
if (a.body instanceof Buffer) {
if (isTextContentType(a.contentType)) {
var _a$contentType$match;
// Content type is like this: "text/html; charset=UTF-8"
const charset = (_a$contentType$match = a.contentType.match(/charset=(.*)/)) === null || _a$contentType$match === void 0 ? void 0 : _a$contentType$match[1];
try {
const body = a.body.toString(charset || 'utf-8');
return {
name: a.name,
contentType: a.contentType,
body
};
} catch (e) {
// Invalid encoding, fall through and save to file.
}
}
_fs.default.mkdirSync(_path.default.join(this._reportFolder, 'data'), {
recursive: true
});
const extension = (0, _utils.sanitizeForFilePath)(_path.default.extname(a.name).replace(/^\./, '')) || _utilsBundle.mime.getExtension(a.contentType) || 'dat';
const sha1 = (0, _utils.calculateSha1)(a.body) + '.' + extension;
_fs.default.writeFileSync(_path.default.join(this._reportFolder, 'data', sha1), a.body);
return {
name: a.name,
contentType: a.contentType,
path: this._attachmentsBaseURL + sha1
};
}
// string
return {
name: a.name,
contentType: a.contentType,
body: a.body
};
}).filter(Boolean);
}
_createTestResult(test, result) {
return {
duration: result.duration,
startTime: result.startTime.toISOString(),
retry: result.retry,
steps: dedupeSteps(result.steps).map(s => this._createTestStep(s, result)),
errors: (0, _base.formatResultFailure)(_base.internalScreen, test, result, '').map(error => error.message),
status: result.status,
attachments: this._serializeAttachments([...result.attachments, ...result.stdout.map(m => stdioAttachment(m, 'stdout')), ...result.stderr.map(m => stdioAttachment(m, 'stderr'))])
};
}
_createTestStep(dedupedStep, result) {
var _dedupedStep$step$ann, _step$error;
const {
step,
duration,
count
} = dedupedStep;
const skipped = (_dedupedStep$step$ann = dedupedStep.step.annotations) === null || _dedupedStep$step$ann === void 0 ? void 0 : _dedupedStep$step$ann.find(a => a.type === 'skip');
let title = step.title;
if (skipped) title = `${title} (skipped${skipped.description ? ': ' + skipped.description : ''})`;
const testStep = {
title,
startTime: step.startTime.toISOString(),
duration,
steps: dedupeSteps(step.steps).map(s => this._createTestStep(s, result)),
attachments: step.attachments.map(s => {
const index = result.attachments.indexOf(s);
if (index === -1) throw new Error('Unexpected, attachment not found');
return index;
}),
location: this._relativeLocation(step.location),
error: (_step$error = step.error) === null || _step$error === void 0 ? void 0 : _step$error.message,
count,
skipped: !!skipped
};
if (step.location) this._stepsInFile.set(step.location.file, testStep);
return testStep;
}
_relativeLocation(location) {
if (!location) return undefined;
const file = (0, _utils.toPosixPath)(_path.default.relative(this._config.rootDir, location.file));
return {
file,
line: location.line,
column: location.column
};
}
}
const emptyStats = () => {
return {
total: 0,
expected: 0,
unexpected: 0,
flaky: 0,
skipped: 0,
ok: true
};
};
const addStats = (stats, delta) => {
stats.total += delta.total;
stats.skipped += delta.skipped;
stats.expected += delta.expected;
stats.unexpected += delta.unexpected;
stats.flaky += delta.flaky;
stats.ok = stats.ok && delta.ok;
return stats;
};
class Base64Encoder extends _stream.Transform {
constructor(...args) {
super(...args);
this._remainder = void 0;
}
_transform(chunk, encoding, callback) {
if (this._remainder) {
chunk = Buffer.concat([this._remainder, chunk]);
this._remainder = undefined;
}
const remaining = chunk.length % 3;
if (remaining) {
this._remainder = chunk.slice(chunk.length - remaining);
chunk = chunk.slice(0, chunk.length - remaining);
}
chunk = chunk.toString('base64');
this.push(Buffer.from(chunk));
callback();
}
_flush(callback) {
if (this._remainder) this.push(Buffer.from(this._remainder.toString('base64')));
callback();
}
}
function isTextContentType(contentType) {
return contentType.startsWith('text/') || contentType.startsWith('application/json');
}
function stdioAttachment(chunk, type) {
return {
name: type,
contentType: 'text/plain',
body: typeof chunk === 'string' ? chunk : chunk.toString('utf-8')
};
}
function dedupeSteps(steps) {
const result = [];
let lastResult = undefined;
for (const step of steps) {
var _step$location, _lastResult, _step$location2, _lastStep$location, _step$location3, _lastStep$location2, _step$location4, _lastStep$location3;
const canDedupe = !step.error && step.duration >= 0 && ((_step$location = step.location) === null || _step$location === void 0 ? void 0 : _step$location.file) && !step.steps.length;
const lastStep = (_lastResult = lastResult) === null || _lastResult === void 0 ? void 0 : _lastResult.step;
if (canDedupe && lastResult && lastStep && step.category === lastStep.category && step.title === lastStep.title && ((_step$location2 = step.location) === null || _step$location2 === void 0 ? void 0 : _step$location2.file) === ((_lastStep$location = lastStep.location) === null || _lastStep$location === void 0 ? void 0 : _lastStep$location.file) && ((_step$location3 = step.location) === null || _step$location3 === void 0 ? void 0 : _step$location3.line) === ((_lastStep$location2 = lastStep.location) === null || _lastStep$location2 === void 0 ? void 0 : _lastStep$location2.line) && ((_step$location4 = step.location) === null || _step$location4 === void 0 ? void 0 : _step$location4.column) === ((_lastStep$location3 = lastStep.location) === null || _lastStep$location3 === void 0 ? void 0 : _lastStep$location3.column)) {
++lastResult.count;
lastResult.duration += step.duration;
continue;
}
lastResult = {
step,
count: 1,
duration: step.duration
};
result.push(lastResult);
if (!canDedupe) lastResult = undefined;
}
return result;
}
function createSnippets(stepsInFile) {
for (const file of stepsInFile.keys()) {
let source;
try {
source = _fs.default.readFileSync(file, 'utf-8') + '\n//';
} catch (e) {
continue;
}
const lines = source.split('\n').length;
const highlighted = (0, _babelBundle.codeFrameColumns)(source, {
start: {
line: lines,
column: 1
}
}, {
highlightCode: true,
linesAbove: lines,
linesBelow: 0
});
const highlightedLines = highlighted.split('\n');
const lineWithArrow = highlightedLines[highlightedLines.length - 1];
for (const step of stepsInFile.get(file)) {
// Don't bother with snippets that have less than 3 lines.
if (step.location.line < 2 || step.location.line >= lines) continue;
// Cut out snippet.
const snippetLines = highlightedLines.slice(step.location.line - 2, step.location.line + 1);
// Relocate arrow.
const index = lineWithArrow.indexOf('^');
const shiftedArrow = lineWithArrow.slice(0, index) + ' '.repeat(step.location.column - 1) + lineWithArrow.slice(index);
// Insert arrow line.
snippetLines.splice(2, 0, shiftedArrow);
step.snippet = snippetLines.join('\n');
}
}
}
var _default = exports.default = HtmlReporter;

View File

@@ -0,0 +1,134 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.InternalReporter = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _utils = require("playwright-core/lib/utils");
var _base = require("./base");
var _multiplexer = require("./multiplexer");
var _test = require("../common/test");
var _babelBundle = require("../transform/babelBundle");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*/
class InternalReporter {
constructor(reporters) {
this._reporter = void 0;
this._didBegin = false;
this._config = void 0;
this._startTime = void 0;
this._monotonicStartTime = void 0;
this._reporter = new _multiplexer.Multiplexer(reporters);
}
version() {
return 'v2';
}
onConfigure(config) {
var _this$_reporter$onCon, _this$_reporter;
this._config = config;
this._startTime = new Date();
this._monotonicStartTime = (0, _utils.monotonicTime)();
(_this$_reporter$onCon = (_this$_reporter = this._reporter).onConfigure) === null || _this$_reporter$onCon === void 0 || _this$_reporter$onCon.call(_this$_reporter, config);
}
onBegin(suite) {
var _this$_reporter$onBeg, _this$_reporter2;
this._didBegin = true;
(_this$_reporter$onBeg = (_this$_reporter2 = this._reporter).onBegin) === null || _this$_reporter$onBeg === void 0 || _this$_reporter$onBeg.call(_this$_reporter2, suite);
}
onTestBegin(test, result) {
var _this$_reporter$onTes, _this$_reporter3;
(_this$_reporter$onTes = (_this$_reporter3 = this._reporter).onTestBegin) === null || _this$_reporter$onTes === void 0 || _this$_reporter$onTes.call(_this$_reporter3, test, result);
}
onStdOut(chunk, test, result) {
var _this$_reporter$onStd, _this$_reporter4;
(_this$_reporter$onStd = (_this$_reporter4 = this._reporter).onStdOut) === null || _this$_reporter$onStd === void 0 || _this$_reporter$onStd.call(_this$_reporter4, chunk, test, result);
}
onStdErr(chunk, test, result) {
var _this$_reporter$onStd2, _this$_reporter5;
(_this$_reporter$onStd2 = (_this$_reporter5 = this._reporter).onStdErr) === null || _this$_reporter$onStd2 === void 0 || _this$_reporter$onStd2.call(_this$_reporter5, chunk, test, result);
}
onTestEnd(test, result) {
var _this$_reporter$onTes2, _this$_reporter6;
this._addSnippetToTestErrors(test, result);
(_this$_reporter$onTes2 = (_this$_reporter6 = this._reporter).onTestEnd) === null || _this$_reporter$onTes2 === void 0 || _this$_reporter$onTes2.call(_this$_reporter6, test, result);
}
async onEnd(result) {
var _this$_reporter$onEnd, _this$_reporter7;
if (!this._didBegin) {
// onBegin was not reported, emit it.
this.onBegin(new _test.Suite('', 'root'));
}
return await ((_this$_reporter$onEnd = (_this$_reporter7 = this._reporter).onEnd) === null || _this$_reporter$onEnd === void 0 ? void 0 : _this$_reporter$onEnd.call(_this$_reporter7, {
...result,
startTime: this._startTime,
duration: (0, _utils.monotonicTime)() - this._monotonicStartTime
}));
}
async onExit() {
var _this$_reporter$onExi, _this$_reporter8;
await ((_this$_reporter$onExi = (_this$_reporter8 = this._reporter).onExit) === null || _this$_reporter$onExi === void 0 ? void 0 : _this$_reporter$onExi.call(_this$_reporter8));
}
onError(error) {
var _this$_reporter$onErr, _this$_reporter9;
addLocationAndSnippetToError(this._config, error);
(_this$_reporter$onErr = (_this$_reporter9 = this._reporter).onError) === null || _this$_reporter$onErr === void 0 || _this$_reporter$onErr.call(_this$_reporter9, error);
}
onStepBegin(test, result, step) {
var _this$_reporter$onSte, _this$_reporter10;
(_this$_reporter$onSte = (_this$_reporter10 = this._reporter).onStepBegin) === null || _this$_reporter$onSte === void 0 || _this$_reporter$onSte.call(_this$_reporter10, test, result, step);
}
onStepEnd(test, result, step) {
var _this$_reporter$onSte2, _this$_reporter11;
this._addSnippetToStepError(test, step);
(_this$_reporter$onSte2 = (_this$_reporter11 = this._reporter).onStepEnd) === null || _this$_reporter$onSte2 === void 0 || _this$_reporter$onSte2.call(_this$_reporter11, test, result, step);
}
printsToStdio() {
return this._reporter.printsToStdio ? this._reporter.printsToStdio() : true;
}
_addSnippetToTestErrors(test, result) {
for (const error of result.errors) addLocationAndSnippetToError(this._config, error, test.location.file);
}
_addSnippetToStepError(test, step) {
if (step.error) addLocationAndSnippetToError(this._config, step.error, test.location.file);
}
}
exports.InternalReporter = InternalReporter;
function addLocationAndSnippetToError(config, error, file) {
if (error.stack && !error.location) error.location = (0, _base.prepareErrorStack)(error.stack).location;
const location = error.location;
if (!location) return;
try {
const tokens = [];
const source = _fs.default.readFileSync(location.file, 'utf8');
const codeFrame = (0, _babelBundle.codeFrameColumns)(source, {
start: location
}, {
highlightCode: true
});
// Convert /var/folders to /private/var/folders on Mac.
if (!file || _fs.default.realpathSync(file) !== location.file) {
tokens.push(_base.internalScreen.colors.gray(` at `) + `${(0, _base.relativeFilePath)(_base.internalScreen, config, location.file)}:${location.line}`);
tokens.push('');
}
tokens.push(codeFrame);
error.snippet = tokens.join('\n');
} catch (e) {
// Failed to read the source file - that's ok.
}
}

245
node_modules/playwright/lib/reporters/json.js generated vendored Normal file
View File

@@ -0,0 +1,245 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.serializePatterns = serializePatterns;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _utils = require("playwright-core/lib/utils");
var _base = require("./base");
var _config = require("../common/config");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*/
class JSONReporter {
constructor(options) {
var _resolveOutputFile;
this.config = void 0;
this.suite = void 0;
this._errors = [];
this._resolvedOutputFile = void 0;
this._resolvedOutputFile = (_resolveOutputFile = (0, _base.resolveOutputFile)('JSON', options)) === null || _resolveOutputFile === void 0 ? void 0 : _resolveOutputFile.outputFile;
}
version() {
return 'v2';
}
printsToStdio() {
return !this._resolvedOutputFile;
}
onConfigure(config) {
this.config = config;
}
onBegin(suite) {
this.suite = suite;
}
onError(error) {
this._errors.push(error);
}
async onEnd(result) {
await outputReport(this._serializeReport(result), this._resolvedOutputFile);
}
_serializeReport(result) {
const report = {
config: {
...removePrivateFields(this.config),
rootDir: (0, _utils.toPosixPath)(this.config.rootDir),
projects: this.config.projects.map(project => {
return {
outputDir: (0, _utils.toPosixPath)(project.outputDir),
repeatEach: project.repeatEach,
retries: project.retries,
metadata: project.metadata,
id: (0, _config.getProjectId)(project),
name: project.name,
testDir: (0, _utils.toPosixPath)(project.testDir),
testIgnore: serializePatterns(project.testIgnore),
testMatch: serializePatterns(project.testMatch),
timeout: project.timeout
};
})
},
suites: this._mergeSuites(this.suite.suites),
errors: this._errors,
stats: {
startTime: result.startTime.toISOString(),
duration: result.duration,
expected: 0,
skipped: 0,
unexpected: 0,
flaky: 0
}
};
for (const test of this.suite.allTests()) ++report.stats[test.outcome()];
return report;
}
_mergeSuites(suites) {
const fileSuites = new _utils.MultiMap();
for (const projectSuite of suites) {
const projectId = (0, _config.getProjectId)(projectSuite.project());
const projectName = projectSuite.project().name;
for (const fileSuite of projectSuite.suites) {
const file = fileSuite.location.file;
const serialized = this._serializeSuite(projectId, projectName, fileSuite);
if (serialized) fileSuites.set(file, serialized);
}
}
const results = [];
for (const [, suites] of fileSuites) {
const result = {
title: suites[0].title,
file: suites[0].file,
column: 0,
line: 0,
specs: []
};
for (const suite of suites) this._mergeTestsFromSuite(result, suite);
results.push(result);
}
return results;
}
_relativeLocation(location) {
if (!location) return {
file: '',
line: 0,
column: 0
};
return {
file: (0, _utils.toPosixPath)(_path.default.relative(this.config.rootDir, location.file)),
line: location.line,
column: location.column
};
}
_locationMatches(s1, s2) {
return s1.file === s2.file && s1.line === s2.line && s1.column === s2.column;
}
_mergeTestsFromSuite(to, from) {
for (const fromSuite of from.suites || []) {
const toSuite = (to.suites || []).find(s => s.title === fromSuite.title && this._locationMatches(s, fromSuite));
if (toSuite) {
this._mergeTestsFromSuite(toSuite, fromSuite);
} else {
if (!to.suites) to.suites = [];
to.suites.push(fromSuite);
}
}
for (const spec of from.specs || []) {
const toSpec = to.specs.find(s => s.title === spec.title && s.file === (0, _utils.toPosixPath)(_path.default.relative(this.config.rootDir, spec.file)) && s.line === spec.line && s.column === spec.column);
if (toSpec) toSpec.tests.push(...spec.tests);else to.specs.push(spec);
}
}
_serializeSuite(projectId, projectName, suite) {
if (!suite.allTests().length) return null;
const suites = suite.suites.map(suite => this._serializeSuite(projectId, projectName, suite)).filter(s => s);
return {
title: suite.title,
...this._relativeLocation(suite.location),
specs: suite.tests.map(test => this._serializeTestSpec(projectId, projectName, test)),
suites: suites.length ? suites : undefined
};
}
_serializeTestSpec(projectId, projectName, test) {
return {
title: test.title,
ok: test.ok(),
tags: test.tags.map(tag => tag.substring(1)),
// Strip '@'.
tests: [this._serializeTest(projectId, projectName, test)],
id: test.id,
...this._relativeLocation(test.location)
};
}
_serializeTest(projectId, projectName, test) {
return {
timeout: test.timeout,
annotations: test.annotations,
expectedStatus: test.expectedStatus,
projectId,
projectName,
results: test.results.map(r => this._serializeTestResult(r, test)),
status: test.outcome()
};
}
_serializeTestResult(result, test) {
var _result$error;
const steps = result.steps.filter(s => s.category === 'test.step');
const jsonResult = {
workerIndex: result.workerIndex,
parallelIndex: result.parallelIndex,
status: result.status,
duration: result.duration,
error: result.error,
errors: result.errors.map(e => this._serializeError(e)),
stdout: result.stdout.map(s => stdioEntry(s)),
stderr: result.stderr.map(s => stdioEntry(s)),
retry: result.retry,
steps: steps.length ? steps.map(s => this._serializeTestStep(s)) : undefined,
startTime: result.startTime.toISOString(),
attachments: result.attachments.map(a => {
var _a$body;
return {
name: a.name,
contentType: a.contentType,
path: a.path,
body: (_a$body = a.body) === null || _a$body === void 0 ? void 0 : _a$body.toString('base64')
};
})
};
if ((_result$error = result.error) !== null && _result$error !== void 0 && _result$error.stack) jsonResult.errorLocation = (0, _base.prepareErrorStack)(result.error.stack).location;
return jsonResult;
}
_serializeError(error) {
return (0, _base.formatError)(_base.nonTerminalScreen, error);
}
_serializeTestStep(step) {
const steps = step.steps.filter(s => s.category === 'test.step');
return {
title: step.title,
duration: step.duration,
error: step.error,
steps: steps.length ? steps.map(s => this._serializeTestStep(s)) : undefined
};
}
}
async function outputReport(report, resolvedOutputFile) {
const reportString = JSON.stringify(report, undefined, 2);
if (resolvedOutputFile) {
await _fs.default.promises.mkdir(_path.default.dirname(resolvedOutputFile), {
recursive: true
});
await _fs.default.promises.writeFile(resolvedOutputFile, reportString);
} else {
console.log(reportString);
}
}
function stdioEntry(s) {
if (typeof s === 'string') return {
text: s
};
return {
buffer: s.toString('base64')
};
}
function removePrivateFields(config) {
return Object.fromEntries(Object.entries(config).filter(([name, value]) => !name.startsWith('_')));
}
function serializePatterns(patterns) {
if (!Array.isArray(patterns)) patterns = [patterns];
return patterns.map(s => s.toString());
}
var _default = exports.default = JSONReporter;

235
node_modules/playwright/lib/reporters/junit.js generated vendored Normal file
View File

@@ -0,0 +1,235 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _utils = require("playwright-core/lib/utils");
var _base = require("./base");
var _util = require("../util");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*/
class JUnitReporter {
constructor(options) {
var _resolveOutputFile;
this.config = void 0;
this.configDir = void 0;
this.suite = void 0;
this.timestamp = void 0;
this.totalTests = 0;
this.totalFailures = 0;
this.totalSkipped = 0;
this.resolvedOutputFile = void 0;
this.stripANSIControlSequences = false;
this.includeProjectInTestName = false;
this.stripANSIControlSequences = (0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_JUNIT_STRIP_ANSI', !!options.stripANSIControlSequences);
this.includeProjectInTestName = (0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_JUNIT_INCLUDE_PROJECT_IN_TEST_NAME', !!options.includeProjectInTestName);
this.configDir = options.configDir;
this.resolvedOutputFile = (_resolveOutputFile = (0, _base.resolveOutputFile)('JUNIT', options)) === null || _resolveOutputFile === void 0 ? void 0 : _resolveOutputFile.outputFile;
}
version() {
return 'v2';
}
printsToStdio() {
return !this.resolvedOutputFile;
}
onConfigure(config) {
this.config = config;
}
onBegin(suite) {
this.suite = suite;
this.timestamp = new Date();
}
async onEnd(result) {
const children = [];
for (const projectSuite of this.suite.suites) {
for (const fileSuite of projectSuite.suites) children.push(await this._buildTestSuite(projectSuite.title, fileSuite));
}
const tokens = [];
const self = this;
const root = {
name: 'testsuites',
attributes: {
id: process.env[`PLAYWRIGHT_JUNIT_SUITE_ID`] || '',
name: process.env[`PLAYWRIGHT_JUNIT_SUITE_NAME`] || '',
tests: self.totalTests,
failures: self.totalFailures,
skipped: self.totalSkipped,
errors: 0,
time: result.duration / 1000
},
children
};
serializeXML(root, tokens, this.stripANSIControlSequences);
const reportString = tokens.join('\n');
if (this.resolvedOutputFile) {
await _fs.default.promises.mkdir(_path.default.dirname(this.resolvedOutputFile), {
recursive: true
});
await _fs.default.promises.writeFile(this.resolvedOutputFile, reportString);
} else {
console.log(reportString);
}
}
async _buildTestSuite(projectName, suite) {
let tests = 0;
let skipped = 0;
let failures = 0;
let duration = 0;
const children = [];
const testCaseNamePrefix = projectName && this.includeProjectInTestName ? `[${projectName}] ` : '';
for (const test of suite.allTests()) {
++tests;
if (test.outcome() === 'skipped') ++skipped;
if (!test.ok()) ++failures;
for (const result of test.results) duration += result.duration;
await this._addTestCase(suite.title, testCaseNamePrefix, test, children);
}
this.totalTests += tests;
this.totalSkipped += skipped;
this.totalFailures += failures;
const entry = {
name: 'testsuite',
attributes: {
name: suite.title,
timestamp: this.timestamp.toISOString(),
hostname: projectName,
tests,
failures,
skipped,
time: duration / 1000,
errors: 0
},
children
};
return entry;
}
async _addTestCase(suiteName, namePrefix, test, entries) {
var _properties$children2;
const entry = {
name: 'testcase',
attributes: {
// Skip root, project, file
name: namePrefix + test.titlePath().slice(3).join(' '),
// filename
classname: suiteName,
time: test.results.reduce((acc, value) => acc + value.duration, 0) / 1000
},
children: []
};
entries.push(entry);
// Xray Test Management supports testcase level properties, where additional metadata may be provided
// some annotations are encoded as value attributes, other as cdata content; this implementation supports
// Xray JUnit extensions but it also agnostic, so other tools can also take advantage of this format
const properties = {
name: 'properties',
children: []
};
for (const annotation of test.annotations) {
var _properties$children;
const property = {
name: 'property',
attributes: {
name: annotation.type,
value: annotation !== null && annotation !== void 0 && annotation.description ? annotation.description : ''
}
};
(_properties$children = properties.children) === null || _properties$children === void 0 || _properties$children.push(property);
}
if ((_properties$children2 = properties.children) !== null && _properties$children2 !== void 0 && _properties$children2.length) entry.children.push(properties);
if (test.outcome() === 'skipped') {
entry.children.push({
name: 'skipped'
});
return;
}
if (!test.ok()) {
entry.children.push({
name: 'failure',
attributes: {
message: `${_path.default.basename(test.location.file)}:${test.location.line}:${test.location.column} ${test.title}`,
type: 'FAILURE'
},
text: (0, _util.stripAnsiEscapes)((0, _base.formatFailure)(_base.nonTerminalScreen, this.config, test))
});
}
const systemOut = [];
const systemErr = [];
for (const result of test.results) {
systemOut.push(...result.stdout.map(item => item.toString()));
systemErr.push(...result.stderr.map(item => item.toString()));
for (const attachment of result.attachments) {
if (!attachment.path) continue;
let attachmentPath = _path.default.relative(this.configDir, attachment.path);
try {
if (this.resolvedOutputFile) attachmentPath = _path.default.relative(_path.default.dirname(this.resolvedOutputFile), attachment.path);
} catch {
systemOut.push(`\nWarning: Unable to make attachment path ${attachment.path} relative to report output file ${this.resolvedOutputFile}`);
}
try {
await _fs.default.promises.access(attachment.path);
systemOut.push(`\n[[ATTACHMENT|${attachmentPath}]]\n`);
} catch {
systemErr.push(`\nWarning: attachment ${attachmentPath} is missing`);
}
}
}
// Note: it is important to only produce a single system-out/system-err entry
// so that parsers in the wild understand it.
if (systemOut.length) entry.children.push({
name: 'system-out',
text: systemOut.join('')
});
if (systemErr.length) entry.children.push({
name: 'system-err',
text: systemErr.join('')
});
}
}
function serializeXML(entry, tokens, stripANSIControlSequences) {
const attrs = [];
for (const [name, value] of Object.entries(entry.attributes || {})) attrs.push(`${name}="${escape(String(value), stripANSIControlSequences, false)}"`);
tokens.push(`<${entry.name}${attrs.length ? ' ' : ''}${attrs.join(' ')}>`);
for (const child of entry.children || []) serializeXML(child, tokens, stripANSIControlSequences);
if (entry.text) tokens.push(escape(entry.text, stripANSIControlSequences, true));
tokens.push(`</${entry.name}>`);
}
// See https://en.wikipedia.org/wiki/Valid_characters_in_XML
const discouragedXMLCharacters = /[\u0000-\u0008\u000b-\u000c\u000e-\u001f\u007f-\u0084\u0086-\u009f]/g;
function escape(text, stripANSIControlSequences, isCharacterData) {
if (stripANSIControlSequences) text = (0, _util.stripAnsiEscapes)(text);
if (isCharacterData) {
text = '<![CDATA[' + text.replace(/]]>/g, ']]&gt;') + ']]>';
} else {
const escapeRe = /[&"'<>]/g;
text = text.replace(escapeRe, c => ({
'&': '&amp;',
'"': '&quot;',
"'": '&apos;',
'<': '&lt;',
'>': '&gt;'
})[c]);
}
text = text.replace(discouragedXMLCharacters, '');
return text;
}
var _default = exports.default = JUnitReporter;

100
node_modules/playwright/lib/reporters/line.js generated vendored Normal file
View File

@@ -0,0 +1,100 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _base = require("./base");
/**
* 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.
*/
class LineReporter extends _base.TerminalReporter {
constructor(...args) {
super(...args);
this._current = 0;
this._failures = 0;
this._lastTest = void 0;
this._didBegin = false;
}
onBegin(suite) {
super.onBegin(suite);
const startingMessage = this.generateStartingMessage();
if (startingMessage) {
console.log(startingMessage);
console.log();
}
this._didBegin = true;
}
onStdOut(chunk, test, result) {
super.onStdOut(chunk, test, result);
this._dumpToStdio(test, chunk, process.stdout);
}
onStdErr(chunk, test, result) {
super.onStdErr(chunk, test, result);
this._dumpToStdio(test, chunk, process.stderr);
}
_dumpToStdio(test, chunk, stream) {
if (this.config.quiet) return;
if (!process.env.PW_TEST_DEBUG_REPORTERS) stream.write(`\u001B[1A\u001B[2K`);
if (test && this._lastTest !== test) {
// Write new header for the output.
const title = this.screen.colors.dim(this.formatTestTitle(test));
stream.write(this.fitToScreen(title) + `\n`);
this._lastTest = test;
}
stream.write(chunk);
if (chunk[chunk.length - 1] !== '\n') console.log();
console.log();
}
onTestBegin(test, result) {
++this._current;
this._updateLine(test, result, undefined);
}
onStepBegin(test, result, step) {
if (this.screen.isTTY && step.category === 'test.step') this._updateLine(test, result, step);
}
onStepEnd(test, result, step) {
if (this.screen.isTTY && step.category === 'test.step') this._updateLine(test, result, step.parent);
}
onTestEnd(test, result) {
super.onTestEnd(test, result);
if (!this.willRetry(test) && (test.outcome() === 'flaky' || test.outcome() === 'unexpected' || result.status === 'interrupted')) {
if (!process.env.PW_TEST_DEBUG_REPORTERS) process.stdout.write(`\u001B[1A\u001B[2K`);
console.log(this.formatFailure(test, ++this._failures));
console.log();
}
}
_updateLine(test, result, step) {
const retriesPrefix = this.totalTestCount < this._current ? ` (retries)` : ``;
const prefix = `[${this._current}/${this.totalTestCount}]${retriesPrefix} `;
const currentRetrySuffix = result.retry ? this.screen.colors.yellow(` (retry #${result.retry})`) : '';
const title = this.formatTestTitle(test, step) + currentRetrySuffix;
if (process.env.PW_TEST_DEBUG_REPORTERS) process.stdout.write(`${prefix + title}\n`);else process.stdout.write(`\u001B[1A\u001B[2K${prefix + this.fitToScreen(title, prefix)}\n`);
}
onError(error) {
super.onError(error);
const message = this.formatError(error).message + '\n';
if (!process.env.PW_TEST_DEBUG_REPORTERS && this._didBegin) process.stdout.write(`\u001B[1A\u001B[2K`);
process.stdout.write(message);
console.log();
}
async onEnd(result) {
if (!process.env.PW_TEST_DEBUG_REPORTERS && this._didBegin) process.stdout.write(`\u001B[1A\u001B[2K`);
await super.onEnd(result);
this.epilogue(false);
}
}
var _default = exports.default = LineReporter;

220
node_modules/playwright/lib/reporters/list.js generated vendored Normal file
View File

@@ -0,0 +1,220 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _utils = require("playwright-core/lib/utils");
var _utilsBundle = require("playwright-core/lib/utilsBundle");
var _base = require("./base");
var _util = require("../util");
/**
* 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.
*/
// Allow it in the Visual Studio Code Terminal and the new Windows Terminal
const DOES_NOT_SUPPORT_UTF8_IN_TERMINAL = process.platform === 'win32' && process.env.TERM_PROGRAM !== 'vscode' && !process.env.WT_SESSION;
const POSITIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? 'ok' : '✓';
const NEGATIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? 'x' : '✘';
class ListReporter extends _base.TerminalReporter {
constructor(options = {}) {
super();
this._lastRow = 0;
this._lastColumn = 0;
this._testRows = new Map();
this._stepRows = new Map();
this._resultIndex = new Map();
this._stepIndex = new Map();
this._needNewLine = false;
this._printSteps = void 0;
this._printSteps = (0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_LIST_PRINT_STEPS', options.printSteps);
}
onBegin(suite) {
super.onBegin(suite);
const startingMessage = this.generateStartingMessage();
if (startingMessage) {
console.log(startingMessage);
console.log();
}
}
onTestBegin(test, result) {
const index = String(this._resultIndex.size + 1);
this._resultIndex.set(result, index);
if (!this.screen.isTTY) return;
this._maybeWriteNewLine();
this._testRows.set(test, this._lastRow);
const prefix = this._testPrefix(index, '');
const line = this.screen.colors.dim(this.formatTestTitle(test)) + this._retrySuffix(result);
this._appendLine(line, prefix);
}
onStdOut(chunk, test, result) {
super.onStdOut(chunk, test, result);
this._dumpToStdio(test, chunk, process.stdout);
}
onStdErr(chunk, test, result) {
super.onStdErr(chunk, test, result);
this._dumpToStdio(test, chunk, process.stderr);
}
getStepIndex(testIndex, result, step) {
if (this._stepIndex.has(step)) return this._stepIndex.get(step);
const ordinal = (result[lastStepOrdinalSymbol] || 0) + 1;
result[lastStepOrdinalSymbol] = ordinal;
const stepIndex = `${testIndex}.${ordinal}`;
this._stepIndex.set(step, stepIndex);
return stepIndex;
}
onStepBegin(test, result, step) {
if (step.category !== 'test.step') return;
const testIndex = this._resultIndex.get(result) || '';
if (!this.screen.isTTY) return;
if (this._printSteps) {
this._maybeWriteNewLine();
this._stepRows.set(step, this._lastRow);
const prefix = this._testPrefix(this.getStepIndex(testIndex, result, step), '');
const line = test.title + this.screen.colors.dim((0, _base.stepSuffix)(step));
this._appendLine(line, prefix);
} else {
this._updateLine(this._testRows.get(test), this.screen.colors.dim(this.formatTestTitle(test, step)) + this._retrySuffix(result), this._testPrefix(testIndex, ''));
}
}
onStepEnd(test, result, step) {
if (step.category !== 'test.step') return;
const testIndex = this._resultIndex.get(result) || '';
if (!this._printSteps) {
if (this.screen.isTTY) this._updateLine(this._testRows.get(test), this.screen.colors.dim(this.formatTestTitle(test, step.parent)) + this._retrySuffix(result), this._testPrefix(testIndex, ''));
return;
}
const index = this.getStepIndex(testIndex, result, step);
const title = this.screen.isTTY ? test.title + this.screen.colors.dim((0, _base.stepSuffix)(step)) : this.formatTestTitle(test, step);
const prefix = this._testPrefix(index, '');
let text = '';
if (step.error) text = this.screen.colors.red(title);else text = title;
text += this.screen.colors.dim(` (${(0, _utilsBundle.ms)(step.duration)})`);
this._updateOrAppendLine(this._stepRows.get(step), text, prefix);
}
_maybeWriteNewLine() {
if (this._needNewLine) {
this._needNewLine = false;
process.stdout.write('\n');
++this._lastRow;
this._lastColumn = 0;
}
}
_updateLineCountAndNewLineFlagForOutput(text) {
this._needNewLine = text[text.length - 1] !== '\n';
if (!this.screen.ttyWidth) return;
for (const ch of text) {
if (ch === '\n') {
this._lastColumn = 0;
++this._lastRow;
continue;
}
++this._lastColumn;
if (this._lastColumn > this.screen.ttyWidth) {
this._lastColumn = 0;
++this._lastRow;
}
}
}
_dumpToStdio(test, chunk, stream) {
if (this.config.quiet) return;
const text = chunk.toString('utf-8');
this._updateLineCountAndNewLineFlagForOutput(text);
stream.write(chunk);
}
onTestEnd(test, result) {
super.onTestEnd(test, result);
const title = this.formatTestTitle(test);
let prefix = '';
let text = '';
// In TTY mode test index is incremented in onTestStart
// and in non-TTY mode it is incremented onTestEnd.
let index = this._resultIndex.get(result);
if (!index) {
index = String(this._resultIndex.size + 1);
this._resultIndex.set(result, index);
}
if (result.status === 'skipped') {
prefix = this._testPrefix(index, this.screen.colors.green('-'));
// Do not show duration for skipped.
text = this.screen.colors.cyan(title) + this._retrySuffix(result);
} else {
const statusMark = result.status === 'passed' ? POSITIVE_STATUS_MARK : NEGATIVE_STATUS_MARK;
if (result.status === test.expectedStatus) {
prefix = this._testPrefix(index, this.screen.colors.green(statusMark));
text = title;
} else {
prefix = this._testPrefix(index, this.screen.colors.red(statusMark));
text = this.screen.colors.red(title);
}
text += this._retrySuffix(result) + this.screen.colors.dim(` (${(0, _utilsBundle.ms)(result.duration)})`);
}
this._updateOrAppendLine(this._testRows.get(test), text, prefix);
}
_updateOrAppendLine(row, text, prefix) {
if (this.screen.isTTY) {
this._updateLine(row, text, prefix);
} else {
this._maybeWriteNewLine();
this._appendLine(text, prefix);
}
}
_appendLine(text, prefix) {
const line = prefix + this.fitToScreen(text, prefix);
if (process.env.PW_TEST_DEBUG_REPORTERS) {
process.stdout.write('#' + this._lastRow + ' : ' + line + '\n');
} else {
process.stdout.write(line);
process.stdout.write('\n');
}
++this._lastRow;
this._lastColumn = 0;
}
_updateLine(row, text, prefix) {
const line = prefix + this.fitToScreen(text, prefix);
if (process.env.PW_TEST_DEBUG_REPORTERS) process.stdout.write('#' + row + ' : ' + line + '\n');else this._updateLineForTTY(row, line);
}
_updateLineForTTY(row, line) {
// Go up if needed
if (row !== this._lastRow) process.stdout.write(`\u001B[${this._lastRow - row}A`);
// Erase line, go to the start
process.stdout.write('\u001B[2K\u001B[0G');
process.stdout.write(line);
// Go down if needed.
if (row !== this._lastRow) process.stdout.write(`\u001B[${this._lastRow - row}E`);
}
_testPrefix(index, statusMark) {
const statusMarkLength = (0, _util.stripAnsiEscapes)(statusMark).length;
return ' ' + statusMark + ' '.repeat(3 - statusMarkLength) + this.screen.colors.dim(index + ' ');
}
_retrySuffix(result) {
return result.retry ? this.screen.colors.yellow(` (retry #${result.retry})`) : '';
}
onError(error) {
super.onError(error);
this._maybeWriteNewLine();
const message = this.formatError(error).message + '\n';
this._updateLineCountAndNewLineFlagForOutput(message);
process.stdout.write(message);
}
async onEnd(result) {
await super.onEnd(result);
process.stdout.write('\n');
this.epilogue(true);
}
}
const lastStepOrdinalSymbol = Symbol('lastStepOrdinal');
var _default = exports.default = ListReporter;

76
node_modules/playwright/lib/reporters/markdown.js generated vendored Normal file
View File

@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _util = require("../util");
var _base = require("./base");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*/
class MarkdownReporter extends _base.TerminalReporter {
constructor(options) {
super();
this._options = void 0;
this._options = options;
}
printsToStdio() {
return false;
}
async onEnd(result) {
await super.onEnd(result);
const summary = this.generateSummary();
const lines = [];
if (summary.fatalErrors.length) lines.push(`**${summary.fatalErrors.length} fatal errors, not part of any test**`);
if (summary.unexpected.length) {
lines.push(`**${summary.unexpected.length} failed**`);
this._printTestList(':x:', summary.unexpected, lines);
}
if (summary.flaky.length) {
lines.push(`<details>`);
lines.push(`<summary><b>${summary.flaky.length} flaky</b></summary>`);
this._printTestList(':warning:', summary.flaky, lines, ' <br/>');
lines.push(`</details>`);
lines.push(``);
}
if (summary.interrupted.length) {
lines.push(`<details>`);
lines.push(`<summary><b>${summary.interrupted.length} interrupted</b></summary>`);
this._printTestList(':warning:', summary.interrupted, lines, ' <br/>');
lines.push(`</details>`);
lines.push(``);
}
const skipped = summary.skipped ? `, ${summary.skipped} skipped` : '';
const didNotRun = summary.didNotRun ? `, ${summary.didNotRun} did not run` : '';
lines.push(`**${summary.expected} passed${skipped}${didNotRun}**`);
lines.push(`:heavy_check_mark::heavy_check_mark::heavy_check_mark:`);
lines.push(``);
const reportFile = (0, _util.resolveReporterOutputPath)('report.md', this._options.configDir, this._options.outputFile);
await _fs.default.promises.mkdir(_path.default.dirname(reportFile), {
recursive: true
});
await _fs.default.promises.writeFile(reportFile, lines.join('\n'));
}
_printTestList(prefix, tests, lines, suffix) {
for (const test of tests) lines.push(`${prefix} ${this.formatTestTitle(test)}${suffix || ''}`);
lines.push(``);
}
}
var _default = exports.default = MarkdownReporter;

488
node_modules/playwright/lib/reporters/merge.js generated vendored Normal file
View File

@@ -0,0 +1,488 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createMergedReport = createMergedReport;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _utils = require("playwright-core/lib/utils");
var _blob = require("./blob");
var _multiplexer = require("./multiplexer");
var _stringInternPool = require("../isomorphic/stringInternPool");
var _teleReceiver = require("../isomorphic/teleReceiver");
var _reporters = require("../runner/reporters");
var _util = require("../util");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*/
async function createMergedReport(config, dir, reporterDescriptions, rootDirOverride) {
var _eventData$pathSepara;
const reporters = await (0, _reporters.createReporters)(config, 'merge', false, reporterDescriptions);
const multiplexer = new _multiplexer.Multiplexer(reporters);
const stringPool = new _stringInternPool.StringInternPool();
let printStatus = () => {};
if (!multiplexer.printsToStdio()) {
printStatus = printStatusToStdout;
printStatus(`merging reports from ${dir}`);
}
const shardFiles = await sortedShardFiles(dir);
if (shardFiles.length === 0) throw new Error(`No report files found in ${dir}`);
const eventData = await mergeEvents(dir, shardFiles, stringPool, printStatus, rootDirOverride);
// If explicit config is provided, use platform path separator, otherwise use the one from the report (if any).
const pathSeparator = rootDirOverride ? _path.default.sep : (_eventData$pathSepara = eventData.pathSeparatorFromMetadata) !== null && _eventData$pathSepara !== void 0 ? _eventData$pathSepara : _path.default.sep;
const receiver = new _teleReceiver.TeleReporterReceiver(multiplexer, {
mergeProjects: false,
mergeTestCases: false,
resolvePath: (rootDir, relativePath) => stringPool.internString(rootDir + pathSeparator + relativePath),
configOverrides: config.config
});
printStatus(`processing test events`);
const dispatchEvents = async events => {
for (const event of events) {
if (event.method === 'onEnd') printStatus(`building final report`);
await receiver.dispatch(event);
if (event.method === 'onEnd') printStatus(`finished building report`);
}
};
await dispatchEvents(eventData.prologue);
for (const {
reportFile,
eventPatchers,
metadata
} of eventData.reports) {
const reportJsonl = await _fs.default.promises.readFile(reportFile);
const events = parseTestEvents(reportJsonl);
new _stringInternPool.JsonStringInternalizer(stringPool).traverse(events);
eventPatchers.patchers.push(new AttachmentPathPatcher(dir));
if (metadata.name) eventPatchers.patchers.push(new GlobalErrorPatcher(metadata.name));
eventPatchers.patchEvents(events);
await dispatchEvents(events);
}
await dispatchEvents(eventData.epilogue);
}
const commonEventNames = ['onBlobReportMetadata', 'onConfigure', 'onProject', 'onBegin', 'onEnd'];
const commonEvents = new Set(commonEventNames);
const commonEventRegex = new RegExp(`${commonEventNames.join('|')}`);
function parseCommonEvents(reportJsonl) {
return splitBufferLines(reportJsonl).map(line => line.toString('utf8')).filter(line => commonEventRegex.test(line)) // quick filter
.map(line => JSON.parse(line)).filter(event => commonEvents.has(event.method));
}
function parseTestEvents(reportJsonl) {
return splitBufferLines(reportJsonl).map(line => line.toString('utf8')).filter(line => line.length).map(line => JSON.parse(line)).filter(event => !commonEvents.has(event.method));
}
function splitBufferLines(buffer) {
const lines = [];
let start = 0;
while (start < buffer.length) {
// 0x0A is the byte for '\n'
const end = buffer.indexOf(0x0A, start);
if (end === -1) {
lines.push(buffer.slice(start));
break;
}
lines.push(buffer.slice(start, end));
start = end + 1;
}
return lines;
}
async function extractAndParseReports(dir, shardFiles, internalizer, printStatus) {
const shardEvents = [];
await _fs.default.promises.mkdir(_path.default.join(dir, 'resources'), {
recursive: true
});
const reportNames = new UniqueFileNameGenerator();
for (const file of shardFiles) {
const absolutePath = _path.default.join(dir, file);
printStatus(`extracting: ${(0, _util.relativeFilePath)(absolutePath)}`);
const zipFile = new _utils.ZipFile(absolutePath);
const entryNames = await zipFile.entries();
for (const entryName of entryNames.sort()) {
let fileName = _path.default.join(dir, entryName);
const content = await zipFile.read(entryName);
if (entryName.endsWith('.jsonl')) {
fileName = reportNames.makeUnique(fileName);
let parsedEvents = parseCommonEvents(content);
// Passing reviver to JSON.parse doesn't work, as the original strings
// keep being used. To work around that we traverse the parsed events
// as a post-processing step.
internalizer.traverse(parsedEvents);
const metadata = findMetadata(parsedEvents, file);
parsedEvents = modernizer.modernize(metadata.version, parsedEvents);
shardEvents.push({
file,
localPath: fileName,
metadata,
parsedEvents
});
}
await _fs.default.promises.writeFile(fileName, content);
}
zipFile.close();
}
return shardEvents;
}
function findMetadata(events, file) {
var _events$;
if (((_events$ = events[0]) === null || _events$ === void 0 ? void 0 : _events$.method) !== 'onBlobReportMetadata') throw new Error(`No metadata event found in ${file}`);
const metadata = events[0].params;
if (metadata.version > _blob.currentBlobReportVersion) throw new Error(`Blob report ${file} was created with a newer version of Playwright.`);
return metadata;
}
async function mergeEvents(dir, shardReportFiles, stringPool, printStatus, rootDirOverride) {
var _blobs$;
const internalizer = new _stringInternPool.JsonStringInternalizer(stringPool);
const configureEvents = [];
const projectEvents = [];
const endEvents = [];
const blobs = await extractAndParseReports(dir, shardReportFiles, internalizer, printStatus);
// Sort by (report name; shard; file name), so that salt generation below is deterministic when:
// - report names are unique;
// - report names are missing;
// - report names are clashing between shards.
blobs.sort((a, b) => {
var _a$metadata$name, _b$metadata$name, _a$metadata$shard$cur, _a$metadata$shard, _b$metadata$shard$cur, _b$metadata$shard;
const nameA = (_a$metadata$name = a.metadata.name) !== null && _a$metadata$name !== void 0 ? _a$metadata$name : '';
const nameB = (_b$metadata$name = b.metadata.name) !== null && _b$metadata$name !== void 0 ? _b$metadata$name : '';
if (nameA !== nameB) return nameA.localeCompare(nameB);
const shardA = (_a$metadata$shard$cur = (_a$metadata$shard = a.metadata.shard) === null || _a$metadata$shard === void 0 ? void 0 : _a$metadata$shard.current) !== null && _a$metadata$shard$cur !== void 0 ? _a$metadata$shard$cur : 0;
const shardB = (_b$metadata$shard$cur = (_b$metadata$shard = b.metadata.shard) === null || _b$metadata$shard === void 0 ? void 0 : _b$metadata$shard.current) !== null && _b$metadata$shard$cur !== void 0 ? _b$metadata$shard$cur : 0;
if (shardA !== shardB) return shardA - shardB;
return a.file.localeCompare(b.file);
});
printStatus(`merging events`);
const reports = [];
const globalTestIdSet = new Set();
for (let i = 0; i < blobs.length; ++i) {
// Generate unique salt for each blob.
const {
parsedEvents,
metadata,
localPath
} = blobs[i];
const eventPatchers = new JsonEventPatchers();
eventPatchers.patchers.push(new IdsPatcher(stringPool, metadata.name, String(i), globalTestIdSet));
// Only patch path separators if we are merging reports with explicit config.
if (rootDirOverride) eventPatchers.patchers.push(new PathSeparatorPatcher(metadata.pathSeparator));
eventPatchers.patchEvents(parsedEvents);
for (const event of parsedEvents) {
if (event.method === 'onConfigure') configureEvents.push(event);else if (event.method === 'onProject') projectEvents.push(event);else if (event.method === 'onEnd') endEvents.push(event);
}
// Save information about the reports to stream their test events later.
reports.push({
eventPatchers,
reportFile: localPath,
metadata
});
}
return {
prologue: [mergeConfigureEvents(configureEvents, rootDirOverride), ...projectEvents, {
method: 'onBegin',
params: undefined
}],
reports,
epilogue: [mergeEndEvents(endEvents), {
method: 'onExit',
params: undefined
}],
pathSeparatorFromMetadata: (_blobs$ = blobs[0]) === null || _blobs$ === void 0 ? void 0 : _blobs$.metadata.pathSeparator
};
}
function mergeConfigureEvents(configureEvents, rootDirOverride) {
if (!configureEvents.length) throw new Error('No configure events found');
let config = {
configFile: undefined,
globalTimeout: 0,
maxFailures: 0,
metadata: {},
rootDir: '',
version: '',
workers: 0
};
for (const event of configureEvents) config = mergeConfigs(config, event.params.config);
if (rootDirOverride) {
config.rootDir = rootDirOverride;
} else {
const rootDirs = new Set(configureEvents.map(e => e.params.config.rootDir));
if (rootDirs.size > 1) {
throw new Error([`Blob reports being merged were recorded with different test directories, and`, `merging cannot proceed. This may happen if you are merging reports from`, `machines with different environments, like different operating systems or`, `if the tests ran with different playwright configs.`, ``, `You can force merge by specifying a merge config file with "-c" option. If`, `you'd like all test paths to be correct, make sure 'testDir' in the merge config`, `file points to the actual tests location.`, ``, `Found directories:`, ...rootDirs].join('\n'));
}
}
return {
method: 'onConfigure',
params: {
config
}
};
}
function mergeConfigs(to, from) {
return {
...to,
...from,
metadata: {
...to.metadata,
...from.metadata,
actualWorkers: (to.metadata.actualWorkers || 0) + (from.metadata.actualWorkers || 0)
},
workers: to.workers + from.workers
};
}
function mergeEndEvents(endEvents) {
let startTime = endEvents.length ? 10000000000000 : Date.now();
let status = 'passed';
let duration = 0;
for (const event of endEvents) {
const shardResult = event.params.result;
if (shardResult.status === 'failed') status = 'failed';else if (shardResult.status === 'timedout' && status !== 'failed') status = 'timedout';else if (shardResult.status === 'interrupted' && status !== 'failed' && status !== 'timedout') status = 'interrupted';
startTime = Math.min(startTime, shardResult.startTime);
duration = Math.max(duration, shardResult.duration);
}
const result = {
status,
startTime,
duration
};
return {
method: 'onEnd',
params: {
result
}
};
}
async function sortedShardFiles(dir) {
const files = await _fs.default.promises.readdir(dir);
return files.filter(file => file.endsWith('.zip')).sort();
}
function printStatusToStdout(message) {
process.stdout.write(`${message}\n`);
}
class UniqueFileNameGenerator {
constructor() {
this._usedNames = new Set();
}
makeUnique(name) {
if (!this._usedNames.has(name)) {
this._usedNames.add(name);
return name;
}
const extension = _path.default.extname(name);
name = name.substring(0, name.length - extension.length);
let index = 0;
while (true) {
const candidate = `${name}-${++index}${extension}`;
if (!this._usedNames.has(candidate)) {
this._usedNames.add(candidate);
return candidate;
}
}
}
}
class IdsPatcher {
constructor(stringPool, botName, salt, globalTestIdSet) {
this._stringPool = void 0;
this._botName = void 0;
this._salt = void 0;
this._testIdsMap = void 0;
this._globalTestIdSet = void 0;
this._stringPool = stringPool;
this._botName = botName;
this._salt = salt;
this._testIdsMap = new Map();
this._globalTestIdSet = globalTestIdSet;
}
patchEvent(event) {
const {
method,
params
} = event;
switch (method) {
case 'onProject':
this._onProject(params.project);
return;
case 'onTestBegin':
case 'onStepBegin':
case 'onStepEnd':
case 'onStdIO':
params.testId = this._mapTestId(params.testId);
return;
case 'onTestEnd':
params.test.testId = this._mapTestId(params.test.testId);
return;
}
}
_onProject(project) {
var _project$metadata;
(_project$metadata = project.metadata) !== null && _project$metadata !== void 0 ? _project$metadata : project.metadata = {};
project.suites.forEach(suite => this._updateTestIds(suite));
}
_updateTestIds(suite) {
suite.entries.forEach(entry => {
if ('testId' in entry) this._updateTestId(entry);else this._updateTestIds(entry);
});
}
_updateTestId(test) {
test.testId = this._mapTestId(test.testId);
if (this._botName) {
test.tags = test.tags || [];
test.tags.unshift('@' + this._botName);
}
}
_mapTestId(testId) {
const t1 = this._stringPool.internString(testId);
if (this._testIdsMap.has(t1))
// already mapped
return this._testIdsMap.get(t1);
if (this._globalTestIdSet.has(t1)) {
// test id is used in another blob, so we need to salt it.
const t2 = this._stringPool.internString(testId + this._salt);
this._globalTestIdSet.add(t2);
this._testIdsMap.set(t1, t2);
return t2;
}
this._globalTestIdSet.add(t1);
this._testIdsMap.set(t1, t1);
return t1;
}
}
class AttachmentPathPatcher {
constructor(_resourceDir) {
this._resourceDir = _resourceDir;
}
patchEvent(event) {
if (event.method !== 'onTestEnd') return;
for (const attachment of event.params.result.attachments) {
if (!attachment.path) continue;
attachment.path = _path.default.join(this._resourceDir, attachment.path);
}
}
}
class PathSeparatorPatcher {
constructor(from) {
this._from = void 0;
this._to = void 0;
this._from = from !== null && from !== void 0 ? from : _path.default.sep === '/' ? '\\' : '/';
this._to = _path.default.sep;
}
patchEvent(jsonEvent) {
if (this._from === this._to) return;
if (jsonEvent.method === 'onProject') {
this._updateProject(jsonEvent.params.project);
return;
}
if (jsonEvent.method === 'onTestEnd') {
const testResult = jsonEvent.params.result;
testResult.errors.forEach(error => this._updateErrorLocations(error));
testResult.attachments.forEach(attachment => {
if (attachment.path) attachment.path = this._updatePath(attachment.path);
});
return;
}
if (jsonEvent.method === 'onStepBegin') {
const step = jsonEvent.params.step;
this._updateLocation(step.location);
return;
}
if (jsonEvent.method === 'onStepEnd') {
const step = jsonEvent.params.step;
this._updateErrorLocations(step.error);
return;
}
}
_updateProject(project) {
project.outputDir = this._updatePath(project.outputDir);
project.testDir = this._updatePath(project.testDir);
project.snapshotDir = this._updatePath(project.snapshotDir);
project.suites.forEach(suite => this._updateSuite(suite, true));
}
_updateSuite(suite, isFileSuite = false) {
this._updateLocation(suite.location);
if (isFileSuite) suite.title = this._updatePath(suite.title);
for (const entry of suite.entries) {
if ('testId' in entry) this._updateLocation(entry.location);else this._updateSuite(entry);
}
}
_updateErrorLocations(error) {
while (error) {
this._updateLocation(error.location);
error = error.cause;
}
}
_updateLocation(location) {
if (location) location.file = this._updatePath(location.file);
}
_updatePath(text) {
return text.split(this._from).join(this._to);
}
}
class GlobalErrorPatcher {
constructor(botName) {
this._prefix = void 0;
this._prefix = `(${botName}) `;
}
patchEvent(event) {
if (event.method !== 'onError') return;
const error = event.params.error;
if (error.message !== undefined) error.message = this._prefix + error.message;
if (error.stack !== undefined) error.stack = this._prefix + error.stack;
}
}
class JsonEventPatchers {
constructor() {
this.patchers = [];
}
patchEvents(events) {
for (const event of events) {
for (const patcher of this.patchers) patcher.patchEvent(event);
}
}
}
class BlobModernizer {
modernize(fromVersion, events) {
const result = [];
for (const event of events) result.push(...this._modernize(fromVersion, event));
return result;
}
_modernize(fromVersion, event) {
let events = [event];
for (let version = fromVersion; version < _blob.currentBlobReportVersion; ++version) events = this[`_modernize_${version}_to_${version + 1}`].call(this, events);
return events;
}
_modernize_1_to_2(events) {
return events.map(event => {
if (event.method === 'onProject') {
const modernizeSuite = suite => {
const newSuites = suite.suites.map(modernizeSuite);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const {
suites,
tests,
...remainder
} = suite;
return {
entries: [...newSuites, ...tests],
...remainder
};
};
const project = event.params.project;
project.suites = project.suites.map(modernizeSuite);
}
return event;
});
}
}
const modernizer = new BlobModernizer();

123
node_modules/playwright/lib/reporters/multiplexer.js generated vendored Normal file
View File

@@ -0,0 +1,123 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Multiplexer = void 0;
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class Multiplexer {
constructor(reporters) {
this._reporters = void 0;
this._reporters = reporters;
}
version() {
return 'v2';
}
onConfigure(config) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onConfigure;
return (_reporter$onConfigure = reporter.onConfigure) === null || _reporter$onConfigure === void 0 ? void 0 : _reporter$onConfigure.call(reporter, config);
});
}
onBegin(suite) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onBegin;
return (_reporter$onBegin = reporter.onBegin) === null || _reporter$onBegin === void 0 ? void 0 : _reporter$onBegin.call(reporter, suite);
});
}
onTestBegin(test, result) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onTestBegin;
return (_reporter$onTestBegin = reporter.onTestBegin) === null || _reporter$onTestBegin === void 0 ? void 0 : _reporter$onTestBegin.call(reporter, test, result);
});
}
onStdOut(chunk, test, result) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onStdOut;
return (_reporter$onStdOut = reporter.onStdOut) === null || _reporter$onStdOut === void 0 ? void 0 : _reporter$onStdOut.call(reporter, chunk, test, result);
});
}
onStdErr(chunk, test, result) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onStdErr;
return (_reporter$onStdErr = reporter.onStdErr) === null || _reporter$onStdErr === void 0 ? void 0 : _reporter$onStdErr.call(reporter, chunk, test, result);
});
}
onTestEnd(test, result) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onTestEnd;
return (_reporter$onTestEnd = reporter.onTestEnd) === null || _reporter$onTestEnd === void 0 ? void 0 : _reporter$onTestEnd.call(reporter, test, result);
});
}
async onEnd(result) {
for (const reporter of this._reporters) {
const outResult = await wrapAsync(() => {
var _reporter$onEnd;
return (_reporter$onEnd = reporter.onEnd) === null || _reporter$onEnd === void 0 ? void 0 : _reporter$onEnd.call(reporter, result);
});
if (outResult !== null && outResult !== void 0 && outResult.status) result.status = outResult.status;
}
return result;
}
async onExit() {
for (const reporter of this._reporters) await wrapAsync(() => {
var _reporter$onExit;
return (_reporter$onExit = reporter.onExit) === null || _reporter$onExit === void 0 ? void 0 : _reporter$onExit.call(reporter);
});
}
onError(error) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onError;
return (_reporter$onError = reporter.onError) === null || _reporter$onError === void 0 ? void 0 : _reporter$onError.call(reporter, error);
});
}
onStepBegin(test, result, step) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onStepBegin;
return (_reporter$onStepBegin = reporter.onStepBegin) === null || _reporter$onStepBegin === void 0 ? void 0 : _reporter$onStepBegin.call(reporter, test, result, step);
});
}
onStepEnd(test, result, step) {
for (const reporter of this._reporters) wrap(() => {
var _reporter$onStepEnd;
return (_reporter$onStepEnd = reporter.onStepEnd) === null || _reporter$onStepEnd === void 0 ? void 0 : _reporter$onStepEnd.call(reporter, test, result, step);
});
}
printsToStdio() {
return this._reporters.some(r => {
let prints = false;
wrap(() => prints = r.printsToStdio ? r.printsToStdio() : true);
return prints;
});
}
}
exports.Multiplexer = Multiplexer;
async function wrapAsync(callback) {
try {
return await callback();
} catch (e) {
console.error('Error in reporter', e);
}
}
function wrap(callback) {
try {
callback();
} catch (e) {
console.error('Error in reporter', e);
}
}

118
node_modules/playwright/lib/reporters/reporterV2.js generated vendored Normal file
View File

@@ -0,0 +1,118 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.wrapReporterAsV2 = wrapReporterAsV2;
/**
* 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.
*/
function wrapReporterAsV2(reporter) {
try {
if ('version' in reporter && reporter.version() === 'v2') return reporter;
} catch (e) {}
return new ReporterV2Wrapper(reporter);
}
class ReporterV2Wrapper {
constructor(reporter) {
this._reporter = void 0;
this._deferred = [];
this._config = void 0;
this._reporter = reporter;
}
version() {
return 'v2';
}
onConfigure(config) {
this._config = config;
}
onBegin(suite) {
var _this$_reporter$onBeg, _this$_reporter;
(_this$_reporter$onBeg = (_this$_reporter = this._reporter).onBegin) === null || _this$_reporter$onBeg === void 0 || _this$_reporter$onBeg.call(_this$_reporter, this._config, suite);
const deferred = this._deferred;
this._deferred = null;
for (const item of deferred) {
if (item.error) this.onError(item.error);
if (item.stdout) this.onStdOut(item.stdout.chunk, item.stdout.test, item.stdout.result);
if (item.stderr) this.onStdErr(item.stderr.chunk, item.stderr.test, item.stderr.result);
}
}
onTestBegin(test, result) {
var _this$_reporter$onTes, _this$_reporter2;
(_this$_reporter$onTes = (_this$_reporter2 = this._reporter).onTestBegin) === null || _this$_reporter$onTes === void 0 || _this$_reporter$onTes.call(_this$_reporter2, test, result);
}
onStdOut(chunk, test, result) {
var _this$_reporter$onStd, _this$_reporter3;
if (this._deferred) {
this._deferred.push({
stdout: {
chunk,
test,
result
}
});
return;
}
(_this$_reporter$onStd = (_this$_reporter3 = this._reporter).onStdOut) === null || _this$_reporter$onStd === void 0 || _this$_reporter$onStd.call(_this$_reporter3, chunk, test, result);
}
onStdErr(chunk, test, result) {
var _this$_reporter$onStd2, _this$_reporter4;
if (this._deferred) {
this._deferred.push({
stderr: {
chunk,
test,
result
}
});
return;
}
(_this$_reporter$onStd2 = (_this$_reporter4 = this._reporter).onStdErr) === null || _this$_reporter$onStd2 === void 0 || _this$_reporter$onStd2.call(_this$_reporter4, chunk, test, result);
}
onTestEnd(test, result) {
var _this$_reporter$onTes2, _this$_reporter5;
(_this$_reporter$onTes2 = (_this$_reporter5 = this._reporter).onTestEnd) === null || _this$_reporter$onTes2 === void 0 || _this$_reporter$onTes2.call(_this$_reporter5, test, result);
}
async onEnd(result) {
var _this$_reporter$onEnd, _this$_reporter6;
return await ((_this$_reporter$onEnd = (_this$_reporter6 = this._reporter).onEnd) === null || _this$_reporter$onEnd === void 0 ? void 0 : _this$_reporter$onEnd.call(_this$_reporter6, result));
}
async onExit() {
var _this$_reporter$onExi, _this$_reporter7;
await ((_this$_reporter$onExi = (_this$_reporter7 = this._reporter).onExit) === null || _this$_reporter$onExi === void 0 ? void 0 : _this$_reporter$onExi.call(_this$_reporter7));
}
onError(error) {
var _this$_reporter$onErr, _this$_reporter8;
if (this._deferred) {
this._deferred.push({
error
});
return;
}
(_this$_reporter$onErr = (_this$_reporter8 = this._reporter).onError) === null || _this$_reporter$onErr === void 0 || _this$_reporter$onErr.call(_this$_reporter8, error);
}
onStepBegin(test, result, step) {
var _this$_reporter$onSte, _this$_reporter9;
(_this$_reporter$onSte = (_this$_reporter9 = this._reporter).onStepBegin) === null || _this$_reporter$onSte === void 0 || _this$_reporter$onSte.call(_this$_reporter9, test, result, step);
}
onStepEnd(test, result, step) {
var _this$_reporter$onSte2, _this$_reporter10;
(_this$_reporter$onSte2 = (_this$_reporter10 = this._reporter).onStepEnd) === null || _this$_reporter$onSte2 === void 0 || _this$_reporter$onSte2.call(_this$_reporter10, test, result, step);
}
printsToStdio() {
return this._reporter.printsToStdio ? this._reporter.printsToStdio() : true;
}
}

275
node_modules/playwright/lib/reporters/teleEmitter.js generated vendored Normal file
View File

@@ -0,0 +1,275 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TeleReporterEmitter = void 0;
var _path = _interopRequireDefault(require("path"));
var _utils = require("playwright-core/lib/utils");
var _teleReceiver = require("../isomorphic/teleReceiver");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* 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.
*/
class TeleReporterEmitter {
constructor(messageSink, options = {}) {
this._messageSink = void 0;
this._rootDir = void 0;
this._emitterOptions = void 0;
// In case there is blob reporter and UI mode, make sure one does override
// the id assigned by the other.
this._idSymbol = Symbol('id');
this._messageSink = messageSink;
this._emitterOptions = options;
}
version() {
return 'v2';
}
onConfigure(config) {
this._rootDir = config.rootDir;
this._messageSink({
method: 'onConfigure',
params: {
config: this._serializeConfig(config)
}
});
}
onBegin(suite) {
const projects = suite.suites.map(projectSuite => this._serializeProject(projectSuite));
for (const project of projects) this._messageSink({
method: 'onProject',
params: {
project
}
});
this._messageSink({
method: 'onBegin',
params: undefined
});
}
onTestBegin(test, result) {
result[this._idSymbol] = (0, _utils.createGuid)();
this._messageSink({
method: 'onTestBegin',
params: {
testId: test.id,
result: this._serializeResultStart(result)
}
});
}
onTestEnd(test, result) {
const testEnd = {
testId: test.id,
expectedStatus: test.expectedStatus,
annotations: test.annotations,
timeout: test.timeout
};
this._messageSink({
method: 'onTestEnd',
params: {
test: testEnd,
result: this._serializeResultEnd(result)
}
});
}
onStepBegin(test, result, step) {
step[this._idSymbol] = (0, _utils.createGuid)();
this._messageSink({
method: 'onStepBegin',
params: {
testId: test.id,
resultId: result[this._idSymbol],
step: this._serializeStepStart(step)
}
});
}
onStepEnd(test, result, step) {
this._messageSink({
method: 'onStepEnd',
params: {
testId: test.id,
resultId: result[this._idSymbol],
step: this._serializeStepEnd(step, result)
}
});
}
onError(error) {
this._messageSink({
method: 'onError',
params: {
error
}
});
}
onStdOut(chunk, test, result) {
this._onStdIO('stdout', chunk, test, result);
}
onStdErr(chunk, test, result) {
this._onStdIO('stderr', chunk, test, result);
}
_onStdIO(type, chunk, test, result) {
if (this._emitterOptions.omitOutput) return;
const isBase64 = typeof chunk !== 'string';
const data = isBase64 ? chunk.toString('base64') : chunk;
this._messageSink({
method: 'onStdIO',
params: {
testId: test === null || test === void 0 ? void 0 : test.id,
resultId: result ? result[this._idSymbol] : undefined,
type,
data,
isBase64
}
});
}
async onEnd(result) {
const resultPayload = {
status: result.status,
startTime: result.startTime.getTime(),
duration: result.duration
};
this._messageSink({
method: 'onEnd',
params: {
result: resultPayload
}
});
}
printsToStdio() {
return false;
}
_serializeConfig(config) {
return {
configFile: this._relativePath(config.configFile),
globalTimeout: config.globalTimeout,
maxFailures: config.maxFailures,
metadata: config.metadata,
rootDir: config.rootDir,
version: config.version,
workers: config.workers
};
}
_serializeProject(suite) {
const project = suite.project();
const report = {
metadata: project.metadata,
name: project.name,
outputDir: this._relativePath(project.outputDir),
repeatEach: project.repeatEach,
retries: project.retries,
testDir: this._relativePath(project.testDir),
testIgnore: (0, _teleReceiver.serializeRegexPatterns)(project.testIgnore),
testMatch: (0, _teleReceiver.serializeRegexPatterns)(project.testMatch),
timeout: project.timeout,
suites: suite.suites.map(fileSuite => {
return this._serializeSuite(fileSuite);
}),
grep: (0, _teleReceiver.serializeRegexPatterns)(project.grep),
grepInvert: (0, _teleReceiver.serializeRegexPatterns)(project.grepInvert || []),
dependencies: project.dependencies,
snapshotDir: this._relativePath(project.snapshotDir),
teardown: project.teardown,
use: this._serializeProjectUseOptions(project.use)
};
return report;
}
_serializeProjectUseOptions(use) {
return {
testIdAttribute: use.testIdAttribute
};
}
_serializeSuite(suite) {
const result = {
title: suite.title,
location: this._relativeLocation(suite.location),
entries: suite.entries().map(e => {
if (e.type === 'test') return this._serializeTest(e);
return this._serializeSuite(e);
})
};
return result;
}
_serializeTest(test) {
return {
testId: test.id,
title: test.title,
location: this._relativeLocation(test.location),
retries: test.retries,
tags: test.tags,
repeatEachIndex: test.repeatEachIndex,
annotations: test.annotations
};
}
_serializeResultStart(result) {
return {
id: result[this._idSymbol],
retry: result.retry,
workerIndex: result.workerIndex,
parallelIndex: result.parallelIndex,
startTime: +result.startTime
};
}
_serializeResultEnd(result) {
return {
id: result[this._idSymbol],
duration: result.duration,
status: result.status,
errors: result.errors,
attachments: this._serializeAttachments(result.attachments)
};
}
_serializeAttachments(attachments) {
return attachments.map(a => {
return {
...a,
// There is no Buffer in the browser, so there is no point in sending the data there.
base64: a.body && !this._emitterOptions.omitBuffers ? a.body.toString('base64') : undefined
};
});
}
_serializeStepStart(step) {
var _step$parent;
return {
id: step[this._idSymbol],
parentStepId: (_step$parent = step.parent) === null || _step$parent === void 0 ? void 0 : _step$parent[this._idSymbol],
title: step.title,
category: step.category,
startTime: +step.startTime,
location: this._relativeLocation(step.location)
};
}
_serializeStepEnd(step, result) {
return {
id: step[this._idSymbol],
duration: step.duration,
error: step.error,
attachments: step.attachments.length ? step.attachments.map(a => result.attachments.indexOf(a)) : undefined,
annotations: step.annotations.length ? step.annotations : undefined
};
}
_relativeLocation(location) {
if (!location) return location;
return {
...location,
file: this._relativePath(location.file)
};
}
_relativePath(absolutePath) {
if (!absolutePath) return absolutePath;
return _path.default.relative(this._rootDir, absolutePath);
}
}
exports.TeleReporterEmitter = TeleReporterEmitter;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});