mirror of https://github.com/zulip/zulip.git
puppeteer_tests: Translate logged traces and errors with source maps.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
da9783fd10
commit
e62b0d6b5f
|
@ -2,8 +2,12 @@ import {strict as assert} from "assert";
|
|||
import "css.escape";
|
||||
import path from "path";
|
||||
|
||||
import ErrorStackParser from "error-stack-parser";
|
||||
import fetch from "node-fetch";
|
||||
import type {Browser, ConsoleMessage, ConsoleMessageLocation, ElementHandle, Page} from "puppeteer";
|
||||
import {launch} from "puppeteer";
|
||||
import StackFrame from "stackframe";
|
||||
import StackTraceGPS from "stacktrace-gps";
|
||||
|
||||
import {test_credentials} from "../../var/puppeteer/test_credentials";
|
||||
|
||||
|
@ -17,6 +21,8 @@ class CommonUtils {
|
|||
screenshot_id = 0;
|
||||
is_firefox = process.env.PUPPETEER_PRODUCT === "firefox";
|
||||
realm_url = "http://zulip.zulipdev.com:9981/";
|
||||
gps = new StackTraceGPS({ajax: async (url) => (await fetch(url)).text()});
|
||||
|
||||
pm_recipient = {
|
||||
async set(page: Page, recipient: string): Promise<void> {
|
||||
// Without using the delay option here there seems to be
|
||||
|
@ -493,51 +499,102 @@ class CommonUtils {
|
|||
const browser = await this.ensure_browser();
|
||||
const page = await this.get_page();
|
||||
|
||||
// Used to keep console messages in order after async source mapping
|
||||
let console_ready = Promise.resolve();
|
||||
|
||||
page.on("console", (message: ConsoleMessage) => {
|
||||
function context({url, lineNumber, columnNumber}: ConsoleMessageLocation): string {
|
||||
const context = async ({
|
||||
url,
|
||||
lineNumber,
|
||||
columnNumber,
|
||||
}: ConsoleMessageLocation): Promise<string> => {
|
||||
if (lineNumber === undefined || columnNumber === undefined) {
|
||||
return `${url}`;
|
||||
}
|
||||
return `${url}:${lineNumber + 1}:${columnNumber + 1}`;
|
||||
}
|
||||
|
||||
console.log(`${context(message.location())}: ${message.type()}: ${message.text()}`);
|
||||
let frame = new StackFrame({
|
||||
fileName: url,
|
||||
lineNumber: lineNumber + 1,
|
||||
columnNumber: columnNumber + 1,
|
||||
});
|
||||
try {
|
||||
frame = await this.gps.getMappedLocation(frame);
|
||||
} catch {
|
||||
// Ignore source mapping errors
|
||||
}
|
||||
return `${frame.fileName}:${frame.lineNumber}:${frame.columnNumber}`;
|
||||
};
|
||||
|
||||
const console_ready1 = console_ready;
|
||||
console_ready = (async () => {
|
||||
let output = `${await context(
|
||||
message.location(),
|
||||
)}: ${message.type()}: ${message.text()}`;
|
||||
if (message.type() === "trace") {
|
||||
for (const frame of message.stackTrace()) {
|
||||
console.log(` at ${context(frame)}`);
|
||||
output += `\n at ${await context(frame)}`;
|
||||
}
|
||||
}
|
||||
await console_ready1;
|
||||
console.log(output);
|
||||
})();
|
||||
});
|
||||
|
||||
let page_errored = false;
|
||||
page.on("pageerror", async (error: Error) => {
|
||||
console.error("Page error:", error);
|
||||
page.on("pageerror", (error: Error) => {
|
||||
page_errored = true;
|
||||
|
||||
// Puppeteer gives us the stack as the message for some reason.
|
||||
const error1 = new Error("dummy");
|
||||
error1.stack = error.message;
|
||||
|
||||
const console_ready1 = console_ready;
|
||||
console_ready = (async () => {
|
||||
const frames = await Promise.all(
|
||||
ErrorStackParser.parse(error1).map(async (frame1) => {
|
||||
let frame = (frame1 as unknown) as StackFrame;
|
||||
try {
|
||||
frame = await this.gps.getMappedLocation(frame);
|
||||
} catch {
|
||||
// Ignore source mapping errors
|
||||
}
|
||||
return `\n at ${frame.functionName} (${frame.fileName}:${frame.lineNumber}:${frame.columnNumber})`;
|
||||
}),
|
||||
);
|
||||
await console_ready1;
|
||||
console.error("Page error:", error.message.split("\n", 1)[0] + frames.join(""));
|
||||
})();
|
||||
|
||||
const console_ready2 = console_ready;
|
||||
console_ready = (async () => {
|
||||
try {
|
||||
// Take a screenshot, and increment the screenshot_id.
|
||||
await this.screenshot(page, `failure-${this.screenshot_id}`);
|
||||
this.screenshot_id += 1;
|
||||
} finally {
|
||||
await console_ready2;
|
||||
console.log("Closing page to stop the test...");
|
||||
await page.close();
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
try {
|
||||
await test_function(page);
|
||||
} catch (error: unknown) {
|
||||
console.log(error);
|
||||
|
||||
if (page_errored) {
|
||||
throw new Error("Page threw an error");
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (!page_errored) {
|
||||
// Take a screenshot, and increment the screenshot_id.
|
||||
await this.screenshot(page, `failure-${this.screenshot_id}`);
|
||||
this.screenshot_id += 1;
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
process.exit(1);
|
||||
throw error;
|
||||
} finally {
|
||||
await console_ready;
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
"@types/jquery": "^3.3.31",
|
||||
"@types/mini-css-extract-plugin": "^1.0.0",
|
||||
"@types/node": "^14.0.11",
|
||||
"@types/node-fetch": "^2.5.8",
|
||||
"@types/optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"@types/terser-webpack-plugin": "^4.1.0",
|
||||
"@types/webpack": "^4.4.32",
|
||||
|
@ -99,6 +100,7 @@
|
|||
"js-yaml": "^4.0.0",
|
||||
"jsdom": "^16.1.0",
|
||||
"mockdate": "^3.0.2",
|
||||
"node-fetch": "^2.6.1",
|
||||
"nyc": "^15.0.0",
|
||||
"openapi-examples-validator": "^4.0.0",
|
||||
"prettier": "^2.0.5",
|
||||
|
|
|
@ -45,4 +45,4 @@ API_FEATURE_LEVEL = 44
|
|||
# historical commits sharing the same major version, in which case a
|
||||
# minor version bump suffices.
|
||||
|
||||
PROVISION_VERSION = "134.0"
|
||||
PROVISION_VERSION = "134.1"
|
||||
|
|
19
yarn.lock
19
yarn.lock
|
@ -1264,6 +1264,14 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"
|
||||
integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
|
||||
|
||||
"@types/node-fetch@^2.5.8":
|
||||
version "2.5.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb"
|
||||
integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
form-data "^3.0.0"
|
||||
|
||||
"@types/node@*", "@types/node@^14.0.11":
|
||||
version "14.14.31"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
|
||||
|
@ -3229,7 +3237,7 @@ colormap@^2.3.1:
|
|||
dependencies:
|
||||
lerp "^1.0.3"
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
|
@ -5347,6 +5355,15 @@ form-data@^2.3.2:
|
|||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
|
||||
integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||
|
|
Loading…
Reference in New Issue