diff --git a/jest.config.js b/jest.config.js index 7ab50e6a5e..8dfa6facda 100644 --- a/jest.config.js +++ b/jest.config.js @@ -32,7 +32,6 @@ module.exports = { `./packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai-json-object.test.ts`, `./packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/openapi/openapi-validation.test.ts`, `./packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/openapi/openapi-validation-no-keychain.test.ts`, - `./packages/cactus-common/src/test/typescript/unit/logging/logger.test.ts`, `./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/v21-sign-transaction-endpoint.test.ts`, `./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/cactus-keychain-vault-server.test.ts`, `./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/plugin-keychain-vault.test.ts`, diff --git a/packages/cactus-common/src/test/typescript/unit/logging/logger.test.ts b/packages/cactus-common/src/test/typescript/unit/logging/logger.test.ts index 0cc680ccec..c834a14511 100644 --- a/packages/cactus-common/src/test/typescript/unit/logging/logger.test.ts +++ b/packages/cactus-common/src/test/typescript/unit/logging/logger.test.ts @@ -2,12 +2,7 @@ import test, { Test } from "tape"; import { v4 as uuidv4 } from "uuid"; import { LoggerProvider } from "../../../../main/typescript/public-api"; -// FIXME(2020-11-12) this does not work because for some reason the stdout -// stream does not emit 'data' events with anything even though it should. -// Suspecting that the test runner library does some internal magic with -// piping the stream somewhere else or similar foul play at hand. -// Until we can fix this, marked the test to be skipped. -test.skip("Logger#debug/error writes to stdout/stderr", async (t: Test) => { +test("Logger#debug/error writes to stdout/stderr", async (t: Test) => { const log = LoggerProvider.getOrCreate({ level: "TRACE", label: "logger-test", @@ -15,52 +10,40 @@ test.skip("Logger#debug/error writes to stdout/stderr", async (t: Test) => { // generate random UUID v4 to guarantee we don't mistake something else as the marker const marker = uuidv4(); - interface DataHandler { - (data: Buffer): void; - } - // wait for the marker to appear on stdout OR crash with timeout if it never comes - let aggregateStdOut = ""; - let stdOutDataHandler: undefined | DataHandler; - let didNotThrow: boolean; - - try { - // hook up to the stdout data stream and wrap it in a promise that can be awaited - // for when the marker does appear on stdout (which would be a passing test) - // or when it times out (which would mean the test is failing). - // Certain issues could happen here if the stream is chunking data and then you never - // actually get the complete marker string at once but instead different parts of it - // but I did not consider this because the uuid is only a few dozen bytes when stored as a hex string - // so I'm pretty confident it wouldn't get chunked (probably not impossible either though so - // if you are paranoid about that happening (which would make the test flaky) then you can - // bake in some stream data aggregation instead where you collect and continually append - // the incoming data chunks and test for marker presence in the aggregate variable not the chunk - // that is provided in the 'data' event handler callback. - await new Promise((resolve, reject) => { - const timeoutMsg = "Timed out waiting for marker to appear on stdout"; - const timerId = setTimeout(() => reject(new Error(timeoutMsg)), 5000); - const stdOutDataHandler: DataHandler = (data: Buffer) => { - const msg = data.toString("utf-8"); - aggregateStdOut = aggregateStdOut.concat(msg); - if (msg.includes(marker)) { - clearInterval(timerId); - resolve(); - } - }; + // Capture original stdout write method + const originalWrite = process.stdout.write; + let outputData = ""; + + // Mock process.stdout.write to capture output + process.stdout.write = function ( + chunk: any, + encoding?: any, + callback?: any, + ): boolean { + outputData += chunk.toString(); + if (callback) callback(); + return true; + }; - process.stdout.on("data", stdOutDataHandler); - - // send the log now that we have hooked into the stream waiting for the marker to appear - log.info(marker); - }); - didNotThrow = true; - } catch (ex) { - didNotThrow = false; + try { + log.info(marker); + + // Delay to ensure log output is flushed + await new Promise((resolve) => setImmediate(resolve)); + + // Restore original stdout.write + process.stdout.write = originalWrite; + + // Check if the marker appeared in the captured output + t.true( + outputData.includes(marker), + `Marker (${marker}) appeared in stdout OK`, + ); + } catch (error) { + process.stdout.write = originalWrite; // Ensure restoration in case of errors + throw error; } - process.stdout.off("data", stdOutDataHandler as DataHandler); - t.comment(`Aggregate std out messages: ${aggregateStdOut}`); - t.true(didNotThrow, "Marker appeared on stdout on time OK"); - t.end(); });