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 "css.escape";
|
||||||
import path from "path";
|
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 type {Browser, ConsoleMessage, ConsoleMessageLocation, ElementHandle, Page} from "puppeteer";
|
||||||
import {launch} from "puppeteer";
|
import {launch} from "puppeteer";
|
||||||
|
import StackFrame from "stackframe";
|
||||||
|
import StackTraceGPS from "stacktrace-gps";
|
||||||
|
|
||||||
import {test_credentials} from "../../var/puppeteer/test_credentials";
|
import {test_credentials} from "../../var/puppeteer/test_credentials";
|
||||||
|
|
||||||
|
@ -17,6 +21,8 @@ class CommonUtils {
|
||||||
screenshot_id = 0;
|
screenshot_id = 0;
|
||||||
is_firefox = process.env.PUPPETEER_PRODUCT === "firefox";
|
is_firefox = process.env.PUPPETEER_PRODUCT === "firefox";
|
||||||
realm_url = "http://zulip.zulipdev.com:9981/";
|
realm_url = "http://zulip.zulipdev.com:9981/";
|
||||||
|
gps = new StackTraceGPS({ajax: async (url) => (await fetch(url)).text()});
|
||||||
|
|
||||||
pm_recipient = {
|
pm_recipient = {
|
||||||
async set(page: Page, recipient: string): Promise<void> {
|
async set(page: Page, recipient: string): Promise<void> {
|
||||||
// Without using the delay option here there seems to be
|
// Without using the delay option here there seems to be
|
||||||
|
@ -493,51 +499,102 @@ class CommonUtils {
|
||||||
const browser = await this.ensure_browser();
|
const browser = await this.ensure_browser();
|
||||||
const page = await this.get_page();
|
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) => {
|
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) {
|
if (lineNumber === undefined || columnNumber === undefined) {
|
||||||
return `${url}`;
|
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") {
|
if (message.type() === "trace") {
|
||||||
for (const frame of message.stackTrace()) {
|
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;
|
let page_errored = false;
|
||||||
page.on("pageerror", async (error: Error) => {
|
page.on("pageerror", (error: Error) => {
|
||||||
console.error("Page error:", error);
|
|
||||||
page_errored = true;
|
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 {
|
try {
|
||||||
// Take a screenshot, and increment the screenshot_id.
|
// Take a screenshot, and increment the screenshot_id.
|
||||||
await this.screenshot(page, `failure-${this.screenshot_id}`);
|
await this.screenshot(page, `failure-${this.screenshot_id}`);
|
||||||
this.screenshot_id += 1;
|
this.screenshot_id += 1;
|
||||||
} finally {
|
} finally {
|
||||||
|
await console_ready2;
|
||||||
console.log("Closing page to stop the test...");
|
console.log("Closing page to stop the test...");
|
||||||
await page.close();
|
await page.close();
|
||||||
}
|
}
|
||||||
|
})();
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await test_function(page);
|
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) {
|
if (!page_errored) {
|
||||||
// Take a screenshot, and increment the screenshot_id.
|
// Take a screenshot, and increment the screenshot_id.
|
||||||
await this.screenshot(page, `failure-${this.screenshot_id}`);
|
await this.screenshot(page, `failure-${this.screenshot_id}`);
|
||||||
this.screenshot_id += 1;
|
this.screenshot_id += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
await browser.close();
|
throw error;
|
||||||
process.exit(1);
|
|
||||||
} finally {
|
} finally {
|
||||||
|
await console_ready;
|
||||||
await browser.close();
|
await browser.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
"@types/jquery": "^3.3.31",
|
"@types/jquery": "^3.3.31",
|
||||||
"@types/mini-css-extract-plugin": "^1.0.0",
|
"@types/mini-css-extract-plugin": "^1.0.0",
|
||||||
"@types/node": "^14.0.11",
|
"@types/node": "^14.0.11",
|
||||||
|
"@types/node-fetch": "^2.5.8",
|
||||||
"@types/optimize-css-assets-webpack-plugin": "^5.0.1",
|
"@types/optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||||
"@types/terser-webpack-plugin": "^4.1.0",
|
"@types/terser-webpack-plugin": "^4.1.0",
|
||||||
"@types/webpack": "^4.4.32",
|
"@types/webpack": "^4.4.32",
|
||||||
|
@ -99,6 +100,7 @@
|
||||||
"js-yaml": "^4.0.0",
|
"js-yaml": "^4.0.0",
|
||||||
"jsdom": "^16.1.0",
|
"jsdom": "^16.1.0",
|
||||||
"mockdate": "^3.0.2",
|
"mockdate": "^3.0.2",
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
"nyc": "^15.0.0",
|
"nyc": "^15.0.0",
|
||||||
"openapi-examples-validator": "^4.0.0",
|
"openapi-examples-validator": "^4.0.0",
|
||||||
"prettier": "^2.0.5",
|
"prettier": "^2.0.5",
|
||||||
|
|
|
@ -45,4 +45,4 @@ API_FEATURE_LEVEL = 44
|
||||||
# historical commits sharing the same major version, in which case a
|
# historical commits sharing the same major version, in which case a
|
||||||
# minor version bump suffices.
|
# 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"
|
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"
|
||||||
integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
|
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":
|
"@types/node@*", "@types/node@^14.0.11":
|
||||||
version "14.14.31"
|
version "14.14.31"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
|
||||||
|
@ -3229,7 +3237,7 @@ colormap@^2.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
lerp "^1.0.3"
|
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"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||||
|
@ -5347,6 +5355,15 @@ form-data@^2.3.2:
|
||||||
combined-stream "^1.0.6"
|
combined-stream "^1.0.6"
|
||||||
mime-types "^2.1.12"
|
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:
|
form-data@~2.3.2:
|
||||||
version "2.3.3"
|
version "2.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||||
|
|
Loading…
Reference in New Issue