From 11a8723c7314d2c1491d43511c5f05306fbd7edc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 13 Jan 2025 16:15:13 +0000 Subject: [PATCH] Playwright: get console logs without trace (#28972) * Playwright: get console logs without trace Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add page url to log Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Skip empty logs Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Reset page counter Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- playwright/logger.ts | 63 ++++++++++++++++++++++++++++++ playwright/services.ts | 10 ++--- playwright/testcontainers/utils.ts | 43 -------------------- 3 files changed, 68 insertions(+), 48 deletions(-) create mode 100644 playwright/logger.ts delete mode 100644 playwright/testcontainers/utils.ts diff --git a/playwright/logger.ts b/playwright/logger.ts new file mode 100644 index 0000000000..857faaca69 --- /dev/null +++ b/playwright/logger.ts @@ -0,0 +1,63 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { BrowserContext, Page, TestInfo } from "@playwright/test"; +import { Readable } from "stream"; +import stripAnsi from "strip-ansi"; + +export class Logger { + private pages: Page[] = []; + private logs: Record = {}; + + public getConsumer(container: string) { + this.logs[container] = ""; + return (stream: Readable) => { + stream.on("data", (chunk) => { + this.logs[container] += chunk.toString(); + }); + stream.on("err", (chunk) => { + this.logs[container] += "ERR " + chunk.toString(); + }); + }; + } + + public async onTestStarted(context: BrowserContext) { + this.pages = []; + for (const id in this.logs) { + if (id.startsWith("page-")) { + delete this.logs[id]; + } else { + this.logs[id] = ""; + } + } + + context.on("console", (msg) => { + const page = msg.page(); + let pageIdx = this.pages.indexOf(page); + if (pageIdx === -1) { + this.pages.push(page); + pageIdx = this.pages.length - 1; + this.logs[`page-${pageIdx}`] = `Console logs for page with URL: ${page.url()}\n\n`; + } + const type = msg.type(); + const text = msg.text(); + this.logs[`page-${pageIdx}`] += `${type}: ${text}\n`; + }); + } + + public async onTestFinished(testInfo: TestInfo) { + if (testInfo.status !== "passed") { + for (const id in this.logs) { + if (!this.logs[id]) continue; + await testInfo.attach(id, { + body: stripAnsi(this.logs[id]), + contentType: "text/plain", + }); + } + } + } +} diff --git a/playwright/services.ts b/playwright/services.ts index 5e2679953e..213af7df42 100644 --- a/playwright/services.ts +++ b/playwright/services.ts @@ -11,7 +11,7 @@ import { Network, StartedNetwork } from "testcontainers"; import { PostgreSqlContainer, StartedPostgreSqlContainer } from "@testcontainers/postgresql"; import { SynapseConfigOptions, SynapseContainer } from "./testcontainers/synapse.ts"; -import { ContainerLogger } from "./testcontainers/utils.ts"; +import { Logger } from "./logger.ts"; import { StartedMatrixAuthenticationServiceContainer } from "./testcontainers/mas.ts"; import { HomeserverContainer, StartedHomeserverContainer } from "./testcontainers/HomeserverContainer.ts"; import { MailhogContainer, StartedMailhogContainer } from "./testcontainers/mailhog.ts"; @@ -21,7 +21,7 @@ interface TestFixtures { } export interface Services { - logger: ContainerLogger; + logger: Logger; network: StartedNetwork; postgres: StartedPostgreSqlContainer; @@ -37,7 +37,7 @@ export const test = base.extend({ logger: [ // eslint-disable-next-line no-empty-pattern async ({}, use) => { - const logger = new ContainerLogger(); + const logger = new Logger(); await use(logger); }, { scope: "worker" }, @@ -132,8 +132,8 @@ export const test = base.extend({ context: async ({ logger, context, request, homeserver }, use, testInfo) => { homeserver.setRequest(request); - await logger.testStarted(testInfo); + await logger.onTestStarted(context); await use(context); - await logger.testFinished(testInfo); + await logger.onTestFinished(testInfo); }, }); diff --git a/playwright/testcontainers/utils.ts b/playwright/testcontainers/utils.ts deleted file mode 100644 index 1339e9c2fc..0000000000 --- a/playwright/testcontainers/utils.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -import { TestInfo } from "@playwright/test"; -import { Readable } from "stream"; -import stripAnsi from "strip-ansi"; - -export class ContainerLogger { - private logs: Record = {}; - - public getConsumer(container: string) { - this.logs[container] = ""; - return (stream: Readable) => { - stream.on("data", (chunk) => { - this.logs[container] += chunk.toString(); - }); - stream.on("err", (chunk) => { - this.logs[container] += "ERR " + chunk.toString(); - }); - }; - } - - public async testStarted(testInfo: TestInfo) { - for (const container in this.logs) { - this.logs[container] = ""; - } - } - - public async testFinished(testInfo: TestInfo) { - if (testInfo.status !== "passed") { - for (const container in this.logs) { - await testInfo.attach(container, { - body: stripAnsi(this.logs[container]), - contentType: "text/plain", - }); - } - } - } -}