From: Ardis Lu Date: Mon, 7 Sep 2026 06:19:06 +0000 (-0700) Subject: Remove `assertConsole` X-Git-Url: https://git.ardis.lu/?a=commitdiff_plain;h=26c785e469c07410e6c3f74768838f37becd39e3;p=envpass Remove `assertConsole` Since the function no longer calls `console` by default, it does not make sense to test the `console` implementation when there is `MockLogger`. Removing this assertion also reduces flakiness with concurrent tests because the global console mocks no longer fight with each other across tests. --- diff --git a/test/index.test.js b/test/index.test.js index 679f5cd..79aeeae 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -4,7 +4,7 @@ import childProcess from 'node:child_process'; import { encrypt, decrypt } from '#src/index.js'; import { WINDOW_EXPIRATION_DURATION } from '#src/getPrf.js'; -import { setupPlaywright, setupEnv, assertConsole, MockLogger, fileEqual, fileNotEqual } from '#test/setup.js'; +import { setupPlaywright, setupEnv, MockLogger, fileEqual, fileNotEqual } from '#test/setup.js'; /** Standard value of the .env file used for most setups. */ const STD_ENV = 'A=123\nB=456\nC=789\n'; @@ -17,7 +17,6 @@ suite('e2e', () => { test('encrypt and decrypt .env', async (t) => { const { page } = await setupPlaywright(t); const envFile = await setupEnv(t, STD_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await fileEqual(envFile, STD_ENV); await encrypt({ inFile: envFile, getPrfOptions: { onListening: url => page.goto(url) } }); @@ -25,23 +24,9 @@ suite('e2e', () => { await decrypt({ inFile: envFile, getPrfOptions: { onListening: url => page.goto(url) } }); await fileEqual(envFile, STD_ENV); }); - test('console logger works', async (t) => { + test('logger works', async (t) => { const { page } = await setupPlaywright(t); const envFile = await setupEnv(t, STD_ENV); - assertConsole(t, { debug: 24, info: 6, warn: 0, error: 0 }); - - await fileEqual(envFile, STD_ENV); - await encrypt({ inFile: envFile, logger: console, getPrfOptions: { onListening: url => page.goto(url) } }); - await encrypt({ inFile: envFile, logger: console, alreadyEncryptedValue: 'log', getPrfOptions: { onListening: url => page.goto(url) } }); - await fileNotEqual(envFile, STD_ENV); - await decrypt({ inFile: envFile, logger: console, getPrfOptions: { onListening: url => page.goto(url) } }); - await decrypt({ inFile: envFile, logger: console, notEncryptedValue: 'log', getPrfOptions: { onListening: url => page.goto(url) } }); - await fileEqual(envFile, STD_ENV); - }); - test('alternate logger works', async (t) => { - const { page } = await setupPlaywright(t); - const envFile = await setupEnv(t, STD_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); const logger = new MockLogger(); await fileEqual(envFile, STD_ENV); @@ -59,7 +44,6 @@ suite('encrypt', () => { test('does nothing to empty .env file', async (t) => { const { page } = await setupPlaywright(t); const envFile = await setupEnv(t, ''); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await fileEqual(envFile, ''); await encrypt({ inFile: envFile, getPrfOptions: { onListening: url => page.goto(url) } }); @@ -68,15 +52,15 @@ suite('encrypt', () => { test('does nothing to empty .env file (with logs)', async (t) => { const { page } = await setupPlaywright(t); const envFile = await setupEnv(t, ''); - assertConsole(t, { debug: 1, info: 1, warn: 0, error: 0 }); + const logger = new MockLogger(); await fileEqual(envFile, ''); - await encrypt({ inFile: envFile, logger: console, getPrfOptions: { onListening: url => page.goto(url) } }); + await encrypt({ inFile: envFile, logger, getPrfOptions: { onListening: url => page.goto(url) } }); await fileEqual(envFile, ''); + logger.assertCounts({ debug: 1, info: 1, warn: 0, error: 0 }); }); test('does nothing when all variables are already encrypted', async (t) => { const envFile = await setupEnv(t, ENCRYPTED_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await encrypt({ inFile: envFile }); @@ -85,7 +69,6 @@ suite('encrypt', () => { test("encrypts again when alreadyEncryptedValue: 'encrypt'", async (t) => { const { page } = await setupPlaywright(t); const envFile = await setupEnv(t, ENCRYPTED_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await encrypt({ inFile: envFile, alreadyEncryptedValue: 'encrypt', getPrfOptions: { onListening: url => page.goto(url) } }); @@ -93,7 +76,6 @@ suite('encrypt', () => { }); test("throws when alreadyEncryptedValue: 'error'", async (t) => { const envFile = await setupEnv(t, ENCRYPTED_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await rejects(encrypt({ inFile: envFile, alreadyEncryptedValue: 'error' }), /Environment variable ".+" is already encrypted\./); }); @@ -102,7 +84,6 @@ suite('encrypt', () => { const { page, setAutomaticSignIn } = await setupPlaywright(t); await setAutomaticSignIn(false); const envFile = await setupEnv(t, STD_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); const { promise: opened, resolve } = /** @type {PromiseWithResolvers}*/(Promise.withResolvers()); /** @type {(url: string) => Promise} */ const onListening = async url => { @@ -121,7 +102,6 @@ suite('decrypt', () => { test('does nothing to empty .env file', async (t) => { await setupPlaywright(t); const envFile = await setupEnv(t, ''); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await fileEqual(envFile, ''); await decrypt({ inFile: envFile }); @@ -129,15 +109,15 @@ suite('decrypt', () => { }); test('does nothing to empty .env file (with logs)', async (t) => { const envFile = await setupEnv(t, ''); - assertConsole(t, { debug: 1, info: 1, warn: 0, error: 0 }); + const logger = new MockLogger(); await fileEqual(envFile, ''); - await decrypt({ inFile: envFile, logger: console }); + await decrypt({ inFile: envFile, logger }); await fileEqual(envFile, ''); + logger.assertCounts({ debug: 1, info: 1, warn: 0, error: 0 }); }); test('does nothing when all variables are already decrypted', async (t) => { const envFile = await setupEnv(t, STD_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await decrypt({ inFile: envFile }); @@ -145,7 +125,6 @@ suite('decrypt', () => { }); test("throws error when notEncryptedValue='error'", async (t) => { const envFile = await setupEnv(t, STD_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await rejects(decrypt({ inFile: envFile, notEncryptedValue: 'error' }), /Environment variable ".+" is not encrypted\./); }); @@ -155,7 +134,6 @@ suite('decrypt', () => { await setAutomaticSignIn(false); const env = 'A=envpass:v1:AAA\nB=envpass:v1:BBB\nC=envpass:v1:CCC\n'; const envFile = await setupEnv(t, env); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); const { promise: opened, resolve } = /** @type {PromiseWithResolvers}*/(Promise.withResolvers()); /** @type {(url: string) => Promise} */ const onListening = async url => { @@ -170,7 +148,6 @@ suite('decrypt', () => { }); test('injects environment variables', async (t) => { const envFile = await setupEnv(t, INJECTED_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); deepStrictEqual(process.env.INJECTION_TEST, undefined); await decrypt({ inFile: envFile, injectInProcess: true }); @@ -179,17 +156,17 @@ suite('decrypt', () => { }); test('injects environment variables (with logs)', async (t) => { const envFile = await setupEnv(t, INJECTED_ENV); - assertConsole(t, { debug: 3, info: 0, warn: 0, error: 0 }); + const logger = new MockLogger(); deepStrictEqual(process.env.INJECTION_TEST, undefined); - await decrypt({ inFile: envFile, injectInProcess: true, logger: console }); + await decrypt({ inFile: envFile, injectInProcess: true, logger }); deepStrictEqual(process.env.INJECTION_TEST, 'INJECTED'); delete process.env.INJECTION_TEST; + logger.assertCounts({ debug: 3, info: 0, warn: 0, error: 0 }); }); test('passes through excess args to execute', async (t) => { const execMock = t.mock.method(childProcess, 'execSync', () => { }); const envFile = await setupEnv(t, STD_ENV); - assertConsole(t, { debug: 0, info: 0, warn: 0, error: 0 }); await decrypt({ inFile: envFile }, { args: ['test', 'test', 'test'] }); deepStrictEqual(execMock.mock.calls.length, 1); @@ -197,9 +174,10 @@ suite('decrypt', () => { test('passes through excess args to execute (with logs)', async (t) => { const execMock = t.mock.method(childProcess, 'execSync', () => { }); const envFile = await setupEnv(t, STD_ENV); - assertConsole(t, { debug: 4, info: 0, warn: 0, error: 0 }); + const logger = new MockLogger(); - await decrypt({ inFile: envFile, logger: console }, { args: ['test', 'test', 'test'] }); + await decrypt({ inFile: envFile, logger }, { args: ['test', 'test', 'test'] }); deepStrictEqual(execMock.mock.calls.length, 1); + logger.assertCounts({ debug: 4, info: 0, warn: 0, error: 0 }); }); }); diff --git a/test/setup.js b/test/setup.js index 2d66492..fc9b72e 100644 --- a/test/setup.js +++ b/test/setup.js @@ -113,33 +113,14 @@ export async function setupFolder(t, env = '') { } /** - * @typedef AssertConsoleCounts The total number of times `console.debug`, `console.info`, `console.warn`, and - * `console.error` are expected to be called. - * @property {number} [debug] The number of times `console.debug` is expected to be called. The default value is 0. - * @property {number} [info] The number of times `console.info` is expected to be called. The default value is 0. - * @property {number} [warn] The number of times `console.warn` is expected to be called. The default value is 0. - * @property {number} [error] The number of times `console.error` is expected to be called. The default value is 0. + * @typedef AssertLoggerCounts The total number of times `Logger.debug`, `Logger.info`, `Logger.warn`, and + * `Logger.error` are expected to be called. + * @property {number} [debug] The number of times `Logger.debug` is expected to be called. The default value is 0. + * @property {number} [info] The number of times `Logger.info` is expected to be called. The default value is 0. + * @property {number} [warn] The number of times `Logger.warn` is expected to be called. The default value is 0. + * @property {number} [error] The number of times `Logger.error` is expected to be called. The default value is 0. */ -/** - * Silences console functions during a test and asserts a given number of calls were made during the test. - * - * Console will only be silenced AFTER this function is called, and only until the test ends. Call this - * function early in the test to avoid unexpected console calls. - * @param {TestContext} t Test context to mock the `console` functions for. - * @param {AssertConsoleCounts} [expected] Counts for the total number of times console functions are expected - * to be called. - */ -export function assertConsole(t, expected = {}) { - const actual = { debug: 0, info: 0, warn: 0, error: 0 }; - expected = { ...actual, ...expected }; - - for (const m of /** @type {Array} */(Object.keys(actual))) { - t.mock.method(console, m, () => actual[m]++); - t.after(() => deepStrictEqual(actual[m], expected[m], `expected ${expected[m]} console.${m} calls, got ${actual[m]}`)); - } -} - /** @typedef {'debug'|'info'|'warn'|'error'} LoggerMethod A supported logger method. */ /** @typedef {unknown[]} LoggerCall The arguments passed to a single logger method invocation. */ /** @@ -189,7 +170,7 @@ export class MockLogger { /** * Asserts that each logger method was called the expected number of times. - * @param {AssertConsoleCounts} counts + * @param {AssertLoggerCounts} counts */ assertCounts(counts) { for (const method of /** @type {const} */(['debug', 'info', 'warn', 'error'])) {