How to use formatResultFailure method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

base.js

Source: base.js Github

copy
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4  value: true
5});
6exports.formatFailure = formatFailure;
7exports.formatResultFailure = formatResultFailure;
8exports.formatTestTitle = formatTestTitle;
9exports.stripAnsiEscapes = stripAnsiEscapes;
10exports.BaseReporter = void 0;
11
12var _codeFrame = require("@babel/code-frame");
13
14var _safe = _interopRequireDefault(require("colors/safe"));
15
16var _fs = _interopRequireDefault(require("fs"));
17
18var _ms = _interopRequireDefault(require("ms"));
19
20var _path = _interopRequireDefault(require("path"));
21
22var _stackUtils = _interopRequireDefault(require("stack-utils"));
23
24function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
26/**
27 * Copyright (c) Microsoft Corporation.
28 *
29 * Licensed under the Apache License, Version 2.0 (the "License");
30 * you may not use this file except in compliance with the License.
31 * You may obtain a copy of the License at
32 *
33 * http://www.apache.org/licenses/LICENSE-2.0
34 *
35 * Unless required by applicable law or agreed to in writing, software
36 * distributed under the License is distributed on an "AS IS" BASIS,
37 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
38 * See the License for the specific language governing permissions and
39 * limitations under the License.
40 */
41// @ts-ignore
42const stackUtils = new _stackUtils.default();
43const kOutputSymbol = Symbol('output');
44
45class BaseReporter {
46  constructor() {
47    this.duration = 0;
48    this.config = void 0;
49    this.suite = void 0;
50    this.result = void 0;
51    this.fileDurations = new Map();
52    this.monotonicStartTime = 0;
53    this.printTestOutput = !process.env.PWTEST_SKIP_TEST_OUTPUT;
54  }
55
56  onBegin(config, suite) {
57    this.monotonicStartTime = monotonicTime();
58    this.config = config;
59    this.suite = suite;
60  }
61
62  onStdOut(chunk, test, result) {
63    this._appendOutput({
64      chunk,
65      type: 'stdout'
66    }, result);
67  }
68
69  onStdErr(chunk, test, result) {
70    this._appendOutput({
71      chunk,
72      type: 'stderr'
73    }, result);
74  }
75
76  _appendOutput(output, result) {
77    if (!result) return;
78    result[kOutputSymbol] = result[kOutputSymbol] || [];
79    result[kOutputSymbol].push(output);
80  }
81
82  onTestEnd(test, result) {
83    const projectName = test.titlePath()[1];
84    const relativePath = relativeTestPath(this.config, test);
85    const fileAndProject = (projectName ? `[${projectName}] › ` : '') + relativePath;
86    const duration = this.fileDurations.get(fileAndProject) || 0;
87    this.fileDurations.set(fileAndProject, duration + result.duration);
88  }
89
90  onError(error) {
91    console.log(formatError(error));
92  }
93
94  async onEnd(result) {
95    this.duration = monotonicTime() - this.monotonicStartTime;
96    this.result = result;
97  }
98
99  _printSlowTests() {
100    if (!this.config.reportSlowTests) return;
101    const fileDurations = [...this.fileDurations.entries()];
102    fileDurations.sort((a, b) => b[1] - a[1]);
103    const count = Math.min(fileDurations.length, this.config.reportSlowTests.max || Number.POSITIVE_INFINITY);
104
105    for (let i = 0; i < count; ++i) {
106      const duration = fileDurations[i][1];
107      if (duration <= this.config.reportSlowTests.threshold) break;
108      console.log(_safe.default.yellow('  Slow test: ') + fileDurations[i][0] + _safe.default.yellow(` (${(0, _ms.default)(duration)})`));
109    }
110  }
111
112  epilogue(full) {
113    let skipped = 0;
114    let expected = 0;
115    const skippedWithError = [];
116    const unexpected = [];
117    const flaky = [];
118    this.suite.allTests().forEach(test => {
119      switch (test.outcome()) {
120        case 'skipped':
121          {
122            ++skipped;
123            if (test.results.some(result => !!result.error)) skippedWithError.push(test);
124            break;
125          }
126
127        case 'expected':
128          ++expected;
129          break;
130
131        case 'unexpected':
132          unexpected.push(test);
133          break;
134
135        case 'flaky':
136          flaky.push(test);
137          break;
138      }
139    });
140
141    if (full && (unexpected.length || skippedWithError.length)) {
142      console.log('');
143
144      this._printFailures([...unexpected, ...skippedWithError]);
145    }
146
147    this._printSlowTests();
148
149    console.log('');
150
151    if (unexpected.length) {
152      console.log(_safe.default.red(`  ${unexpected.length} failed`));
153
154      this._printTestHeaders(unexpected);
155    }
156
157    if (flaky.length) {
158      console.log(_safe.default.red(`  ${flaky.length} flaky`));
159
160      this._printTestHeaders(flaky);
161    }
162
163    if (skipped) console.log(_safe.default.yellow(`  ${skipped} skipped`));
164    if (expected) console.log(_safe.default.green(`  ${expected} passed`) + _safe.default.dim(` (${(0, _ms.default)(this.duration)})`));
165    if (this.result.status === 'timedout') console.log(_safe.default.red(`  Timed out waiting ${this.config.globalTimeout / 1000}s for the entire test run`));
166  }
167
168  _printTestHeaders(tests) {
169    tests.forEach(test => {
170      console.log(formatTestHeader(this.config, test, '    '));
171    });
172  }
173
174  _printFailures(failures) {
175    failures.forEach((test, index) => {
176      console.log(formatFailure(this.config, test, index + 1, this.printTestOutput));
177    });
178  }
179
180  willRetry(test, result) {
181    return result.status !== 'passed' && result.status !== test.expectedStatus && test.results.length <= test.retries;
182  }
183
184}
185
186exports.BaseReporter = BaseReporter;
187
188function formatFailure(config, test, index, stdio) {
189  const tokens = [];
190  tokens.push(formatTestHeader(config, test, '  ', index));
191
192  for (const result of test.results) {
193    const resultTokens = formatResultFailure(test, result, '    ');
194    if (!resultTokens.length) continue;
195    const statusSuffix = result.status === 'passed' && test.expectedStatus === 'failed' ? ' -- passed unexpectedly' : '';
196
197    if (result.retry) {
198      tokens.push('');
199      tokens.push(_safe.default.gray(pad(`    Retry #${result.retry}${statusSuffix}`, '-')));
200    }
201
202    tokens.push(...resultTokens);
203    const output = result[kOutputSymbol] || [];
204
205    if (stdio && output.length) {
206      const outputText = output.map(({
207        chunk,
208        type
209      }) => {
210        const text = chunk.toString('utf8');
211        if (type === 'stderr') return _safe.default.red(stripAnsiEscapes(text));
212        return text;
213      }).join('');
214      tokens.push('');
215      tokens.push(_safe.default.gray(pad('--- Test output', '-')) + '\n\n' + outputText + '\n' + pad('', '-'));
216    }
217  }
218
219  tokens.push('');
220  return tokens.join('\n');
221}
222
223function formatResultFailure(test, result, initialIndent) {
224  const resultTokens = [];
225
226  if (result.status === 'timedOut') {
227    resultTokens.push('');
228    resultTokens.push(indent(_safe.default.red(`Timeout of ${test.timeout}ms exceeded.`), initialIndent));
229  }
230
231  if (result.error !== undefined) resultTokens.push(indent(formatError(result.error, test.location.file), initialIndent));
232  return resultTokens;
233}
234
235function relativeTestPath(config, test) {
236  return _path.default.relative(config.rootDir, test.location.file) || _path.default.basename(test.location.file);
237}
238
239function stepSuffix(step) {
240  const stepTitles = step ? step.titlePath() : [];
241  return stepTitles.map(t => ' › ' + t).join('');
242}
243
244function formatTestTitle(config, test, step) {
245  // root, project, file, ...describes, test
246  const [, projectName,, ...titles] = test.titlePath();
247  const location = `${relativeTestPath(config, test)}:${test.location.line}:${test.location.column}`;
248  const projectTitle = projectName ? `[${projectName}] › ` : '';
249  return `${projectTitle}${location} › ${titles.join(' ')}${stepSuffix(step)}`;
250}
251
252function formatTestHeader(config, test, indent, index) {
253  const title = formatTestTitle(config, test);
254  const passedUnexpectedlySuffix = test.results[0].status === 'passed' && test.expectedStatus === 'failed' ? ' -- passed unexpectedly' : '';
255  const header = `${indent}${index ? index + ') ' : ''}${title}${passedUnexpectedlySuffix}`;
256  return _safe.default.red(pad(header, '='));
257}
258
259function formatError(error, file) {
260  const stack = error.stack;
261  const tokens = [];
262
263  if (stack) {
264    tokens.push('');
265    const message = error.message || '';
266    const messageLocation = stack.indexOf(message);
267    const preamble = stack.substring(0, messageLocation + message.length);
268    tokens.push(preamble);
269    const position = file ? positionInFile(stack, file) : null;
270
271    if (position) {
272      const source = _fs.default.readFileSync(file, 'utf8');
273
274      tokens.push('');
275      tokens.push((0, _codeFrame.codeFrameColumns)(source, {
276        start: position
277      }, {
278        highlightCode: _safe.default.enabled
279      }));
280    }
281
282    tokens.push('');
283    tokens.push(_safe.default.dim(preamble.length > 0 ? stack.substring(preamble.length + 1) : stack));
284  } else {
285    tokens.push('');
286    tokens.push(error.value);
287  }
288
289  return tokens.join('\n');
290}
291
292function pad(line, char) {
293  if (line) line += ' ';
294  return line + _safe.default.gray(char.repeat(Math.max(0, 100 - line.length)));
295}
296
297function indent(lines, tab) {
298  return lines.replace(/^(?=.+$)/gm, tab);
299}
300
301function positionInFile(stack, file) {
302  // Stack will have /private/var/folders instead of /var/folders on Mac.
303  file = _fs.default.realpathSync(file);
304
305  for (const line of stack.split('\n')) {
306    const parsed = stackUtils.parseLine(line);
307    if (!parsed || !parsed.file) continue;
308    if (_path.default.resolve(process.cwd(), parsed.file) === file) return {
309      column: parsed.column || 0,
310      line: parsed.line || 0
311    };
312  }
313}
314
315function monotonicTime() {
316  const [seconds, nanoseconds] = process.hrtime();
317  return seconds * 1000 + (nanoseconds / 1000000 | 0);
318}
319
320const asciiRegex = new RegExp('[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))', 'g');
321
322function stripAnsiEscapes(str) {
323  return str.replace(asciiRegex, '');
324}
Full Screen

playwright-formatters.js

Source: playwright-formatters.js Github

copy
1// copied from @playwright/test/lib/reporters/base
2const { relative, resolve } = require("path");
3const { gray, red, cyan, enabled, dim } = require("colors/safe");
4var _codeFrame = require("@babel/code-frame");
5const fs = require("fs");
6const StackUtils = require("stack-utils");
7
8const stackUtils = new StackUtils();
9const kOutputSymbol = Symbol('output');
10
11function prepareErrorStack(stack, file) {
12    const lines = stack.split("\n");
13    let firstStackLine = lines.findIndex((line) => line.startsWith("    at "));
14    if (firstStackLine === -1) firstStackLine = lines.length;
15    const message = lines.slice(0, firstStackLine).join("\n");
16    const stackLines = lines.slice(firstStackLine);
17    const position = file ? positionInFile(stackLines, file) : undefined;
18    return {
19        message,
20        stackLines,
21        position,
22    };
23}
24
25function formatError(error, highlightCode, file) {
26    const stack = error.stack;
27    const tokens = [""];
28    let positionInFile;
29
30    if (stack) {
31        const { message, stackLines, position } = prepareErrorStack(stack, file);
32        positionInFile = position;
33        tokens.push(message);
34        const codeFrame = generateCodeFrame(
35            {
36                highlightCode,
37            },
38            file,
39            position
40        );
41
42        if (codeFrame) {
43            tokens.push("");
44            tokens.push(codeFrame);
45        }
46
47        tokens.push("");
48        tokens.push(dim(stackLines.join("\n")));
49    } else if (error.message) {
50        tokens.push(error.message);
51    } else if (error.value) {
52        tokens.push(error.value);
53    }
54
55    return {
56        position: positionInFile,
57        message: tokens.join("\n"),
58    };
59}
60
61function generateCodeFrame(options, file, position) {
62    if (!position || !file) return;
63
64    const source = fs.readFileSync(file, "utf8");
65
66    const codeFrame = (0, _codeFrame.codeFrameColumns)(
67        source,
68        {
69            start: position,
70        },
71        options
72    );
73    return codeFrame;
74}
75
76function prepareErrorStack(stack, file) {
77    const lines = stack.split("\n");
78    let firstStackLine = lines.findIndex((line) => line.startsWith("    at "));
79    if (firstStackLine === -1) firstStackLine = lines.length;
80    const message = lines.slice(0, firstStackLine).join("\n");
81    const stackLines = lines.slice(firstStackLine);
82    const position = file ? positionInFile(stackLines, file) : undefined;
83    return {
84        message,
85        stackLines,
86        position,
87    };
88}
89
90function positionInFile(stackLines, file) {
91    // Stack will have /private/var/folders instead of /var/folders on Mac.
92    file = fs.realpathSync(file);
93
94    for (const line of stackLines) {
95        const parsed = stackUtils.parseLine(line);
96        if (!parsed || !parsed.file) continue;
97        if (resolve(process.cwd(), parsed.file) === file)
98            return {
99                column: parsed.column || 0,
100                line: parsed.line || 0,
101            };
102    }
103}
104
105function indent(lines, tab) {
106    return lines.replace(/^(?=.+$)/gm, tab);
107}
108
109function stripAnsiEscapes(str) {
110    return str.replace(asciiRegex, "");
111}
112
113function pad(line, char) {
114    if (line) line += " ";
115    return line + gray(char.repeat(Math.max(0, 100 - line.length)));
116}
117
118function formatTestHeader(config, test, indent, index) {
119    const title = formatTestTitle(config, test);
120    const header = `${indent}${index ? index + ") " : ""}${title}`;
121    return pad(header, "=");
122}
123
124function stepSuffix(step) {
125    const stepTitles = step ? step.titlePath() : [];
126    return stepTitles.map((t) => " › " + t).join("");
127}
128
129function relativeTestPath(config, test) {
130    return relative(config.rootDir, test.location.file) || _path.default.basename(test.location.file);
131}
132
133function formatResultFailure(test, result, initialIndent, highlightCode) {
134    var _error;
135
136    const resultTokens = [];
137
138    if (result.status === "timedOut") {
139        resultTokens.push("");
140        resultTokens.push(indent(red(`Timeout of ${test.timeout}ms exceeded.`), initialIndent));
141    }
142
143    if (result.status === "passed" && test.expectedStatus === "failed") {
144        resultTokens.push("");
145        resultTokens.push(indent(red(`Expected to fail, but passed.`), initialIndent));
146    }
147
148    let error = undefined;
149
150    if (result.error !== undefined) {
151        error = formatError(result.error, highlightCode, test.location.file);
152        resultTokens.push(indent(error.message, initialIndent));
153    }
154
155    return {
156        tokens: resultTokens,
157        position: (_error = error) === null || _error === void 0 ? void 0 : _error.position,
158    };
159}
160
161function formatTestTitle(config, test, step) {
162    // root, project, file, ...describes, test
163    const [, projectName, , ...titles] = test.titlePath();
164    const location = `${relativeTestPath(config, test)}:${test.location.line}:${test.location.column}`;
165    const projectTitle = projectName ? `[${projectName}] › ` : "";
166    return `${projectTitle}${location} › ${titles.join(" › ")}${stepSuffix(step)}`;
167}
168
169function formatFailure(config, test, options = {}) {
170    const { index, includeStdio, includeAttachments = true, filePath } = options;
171    const lines = [];
172    const title = formatTestTitle(config, test);
173    const annotations = [];
174    const header = formatTestHeader(config, test, "  ", index);
175    lines.push(red(header));
176
177    for (const result of test.results) {
178        const resultLines = [];
179        const { tokens: resultTokens, position } = formatResultFailure(test, result, "    ", enabled);
180        if (!resultTokens.length) continue;
181
182        if (result.retry) {
183            resultLines.push("");
184            resultLines.push(gray(pad(`    Retry #${result.retry}`, "-")));
185        }
186
187        resultLines.push(...resultTokens);
188
189        if (includeAttachments) {
190            for (let i = 0; i < result.attachments.length; ++i) {
191                const attachment = result.attachments[i];
192                resultLines.push("");
193                resultLines.push(cyan(pad(`    attachment #${i + 1}: ${attachment.name} (${attachment.contentType})`, "-")));
194
195                if (attachment.path) {
196                    const relativePath = relative(process.cwd(), attachment.path);
197
198                    resultLines.push(cyan(`    ${relativePath}`)); // Make this extensible
199
200                    if (attachment.name === "trace") {
201                        resultLines.push(cyan(`    Usage:`));
202                        resultLines.push("");
203                        resultLines.push(cyan(`        npx playwright show-trace ${relativePath}`));
204                        resultLines.push("");
205                    }
206                } else {
207                    if (attachment.contentType.startsWith("text/")) {
208                        let text = attachment.body.toString();
209                        if (text.length > 300) text = text.slice(0, 300) + "...";
210                        resultLines.push(cyan(`    ${text}`));
211                    }
212                }
213
214                resultLines.push(cyan(pad("   ", "-")));
215            }
216        }
217
218        const output = result[kOutputSymbol] || [];
219
220        if (includeStdio && output.length) {
221            const outputText = output
222                .map(({ chunk, type }) => {
223                    const text = chunk.toString("utf8");
224                    if (type === "stderr") return red(stripAnsiEscapes(text));
225                    return text;
226                })
227                .join("");
228            resultLines.push("");
229            resultLines.push(gray(pad("--- Test output", "-")) + "\n\n" + outputText + "\n" + pad("", "-"));
230        }
231
232        if (filePath) {
233            annotations.push({
234                filePath,
235                position,
236                title,
237                message: [header, ...resultLines].join("\n"),
238            });
239        }
240
241        lines.push(...resultLines);
242    }
243
244    lines.push("");
245    return {
246        message: lines.join("\n"),
247        annotations,
248    };
249}
250
251module.exports = {
252    formatFailure,
253    formatTestTitle,
254};
255
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)