mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	puppeteer_tests: Translate logged traces and errors with source maps.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						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"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user