mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-30 09:54:02 +08:00
[testing] Write screenshots to disk if rdb is not available
Bug: b:333423685 Change-Id: I7d866814d17860e0704d1fda12f4183d9bfdab56 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5442779 Commit-Queue: Philip Pfaffe <pfaffe@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org> Reviewed-by: Eric Leese <leese@chromium.org>
This commit is contained in:
committed by
Devtools-frontend LUCI CQ
parent
9101ed587a
commit
5823e11eba
@@ -32,16 +32,6 @@ export async function takeScreenshots(): Promise<{target?: string, frontend?: st
|
||||
}
|
||||
}
|
||||
|
||||
async function takeScreenshotsForError(): Promise<{target?: string, frontend?: string}> {
|
||||
if (getEnvVar('LUCI_CONTEXT')) {
|
||||
const screenshots = await takeScreenshots();
|
||||
console.error('Screenshots will be uploaded to luci-milo invocation.');
|
||||
return screenshots;
|
||||
}
|
||||
console.error('Screenshots skipped because we are not running under rdb; did you run `npm run auto-e2etest-rdb`?');
|
||||
return {};
|
||||
}
|
||||
|
||||
function wrapSuiteFunction(fn: (this: Mocha.Suite) => void) {
|
||||
return function(this: Mocha.Suite): void {
|
||||
const hookCreationHook = (hook: Mocha.Hook) => {
|
||||
@@ -144,7 +134,7 @@ async function timeoutHook(this: Mocha.Runnable, done: Mocha.Done|undefined, err
|
||||
}
|
||||
}
|
||||
if (err && !getEnvVar('DEBUG_TEST') && !(err instanceof ScreenshotError)) {
|
||||
const {target, frontend} = await takeScreenshotsForError();
|
||||
const {target, frontend} = await takeScreenshots();
|
||||
err = ScreenshotError.fromBase64Images(err, target, frontend);
|
||||
}
|
||||
if (done) {
|
||||
@@ -227,7 +217,7 @@ function wrapMochaCall(
|
||||
async function onError(this: unknown, err?: unknown) {
|
||||
const isTimeoutError = err instanceof Error && err.message?.includes(TIMEOUT_ERROR_MESSAGE);
|
||||
if (err && !getEnvVar('DEBUG_TEST') && !(err instanceof ScreenshotError) && !isTimeoutError) {
|
||||
const {target, frontend} = await takeScreenshotsForError();
|
||||
const {target, frontend} = await takeScreenshots();
|
||||
err = ScreenshotError.fromBase64Images(err, target, frontend);
|
||||
}
|
||||
done.call(this, err);
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as Mocha from 'mocha';
|
||||
import * as path from 'path';
|
||||
|
||||
import {
|
||||
ScreenshotError,
|
||||
@@ -49,6 +51,12 @@ class ResultsDbReporter extends Mocha.reporters.Spec {
|
||||
// the rest of the HTML formatting (e.g. <pre> and </pre>).
|
||||
static readonly SUMMARY_LENGTH_CUTOFF = 3985;
|
||||
private suitePrefix?: string;
|
||||
htmlResult: fs.WriteStream|undefined;
|
||||
|
||||
localResultsPath() {
|
||||
return !ResultsDb.available() && this.suitePrefix ? path.join(__dirname, '..', this.suitePrefix, 'results.html') :
|
||||
undefined;
|
||||
}
|
||||
|
||||
constructor(runner: Mocha.Runner, options?: Mocha.MochaOptions) {
|
||||
super(runner, options);
|
||||
@@ -56,6 +64,12 @@ class ResultsDbReporter extends Mocha.reporters.Spec {
|
||||
// BUT, every module.exports is forwarded onto the options object.
|
||||
this.suitePrefix = (options as {suiteName: string} | undefined)?.suiteName;
|
||||
|
||||
const localResults = this.localResultsPath();
|
||||
|
||||
if (localResults) {
|
||||
this.htmlResult = fs.createWriteStream(localResults, {});
|
||||
}
|
||||
|
||||
runner.on(EVENT_TEST_PASS, this.onTestPass.bind(this));
|
||||
runner.on(EVENT_TEST_FAIL, this.onTestFail.bind(this));
|
||||
runner.on(EVENT_TEST_RETRY, this.onTestFail.bind(this));
|
||||
@@ -78,6 +92,16 @@ class ResultsDbReporter extends Mocha.reporters.Spec {
|
||||
} else {
|
||||
testResult.summaryHtml = `<pre>${getErrorMessage(error).slice(0, ResultsDbReporter.SUMMARY_LENGTH_CUTOFF)}</pre>`;
|
||||
}
|
||||
if (this.htmlResult) {
|
||||
this.htmlResult.write(testResult.summaryHtml);
|
||||
if (testResult.artifacts) {
|
||||
for (const screenshot in testResult.artifacts) {
|
||||
this.htmlResult.write(`<details><summary>${screenshot} screenshot:</summary><p><img src="${
|
||||
testResult.artifacts[screenshot].filePath}"></img></p></details>`);
|
||||
}
|
||||
}
|
||||
this.htmlResult.write('<hr>');
|
||||
}
|
||||
ResultsDb.sendTestResult(testResult);
|
||||
}
|
||||
|
||||
@@ -98,6 +122,14 @@ class ResultsDbReporter extends Mocha.reporters.Spec {
|
||||
tags: [{key: 'run', 'value': String(testRetry.currentRetry() + 1)}],
|
||||
};
|
||||
}
|
||||
|
||||
override epilogue() {
|
||||
super.epilogue();
|
||||
const localResults = this.localResultsPath();
|
||||
if (this.failures.length > 0 && localResults) {
|
||||
console.error(`Results have been written to file://${localResults}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports = module.exports = ResultsDbReporter;
|
||||
|
||||
@@ -64,6 +64,11 @@ function getSinkData(): SinkData {
|
||||
return resolvedSinkData;
|
||||
}
|
||||
|
||||
export function available() {
|
||||
const sinkData = getSinkData();
|
||||
return sinkData.url !== undefined;
|
||||
}
|
||||
|
||||
// Call at the end of a test suite. Will send all `TestResult`s collected via
|
||||
// `recordTestResult` to the ResultSink endpoint (only if available).
|
||||
export function sendTestResult(results: TestResult): void {
|
||||
|
||||
Reference in New Issue
Block a user