import { test } from 'node:test'; import assert from 'node:assert/strict'; import { maskEmail, redact, redactString } from '../src/logger.js'; test('bearer tokens are redacted', () => { const out = redactString('Authorization: Bearer sk-abc123DEF456ghi', false); assert.ok(!out.includes('sk-abc123DEF456ghi')); assert.match(out, /Bearer \[REDACTED\]/); }); test('WooCommerce consumer keys are redacted', () => { const out = redactString('ck_1234567890abcdef and cs_abcdef1234567890', false); assert.ok(!out.includes('ck_1234567890abcdef')); assert.ok(!out.includes('cs_abcdef1234567890')); }); test('query-string credentials are redacted', () => { const out = redactString( 'https://shop.test/wp-json/wc/v3/orders?consumer_key=ck_secretvalue&consumer_secret=cs_secretvalue', false, ); assert.ok(!out.includes('ck_secretvalue')); assert.ok(!out.includes('cs_secretvalue')); }); test('e-mail addresses are redacted when PII logging is off', () => { const out = redactString('contact jan.kowalski@example.com about order', false); assert.ok(!out.includes('jan.kowalski@example.com')); }); test('secret-looking object keys are always redacted, even with PII logging on', () => { const out = redact( { api_token: 'abc', consumer_secret: 'def', nested: { password: 'ghi' } }, true, ) as Record; assert.equal(out.api_token, '[REDACTED]'); assert.equal(out.consumer_secret, '[REDACTED]'); assert.equal((out.nested as Record).password, '[REDACTED]'); }); test('PII keys are masked when PII logging is off', () => { const out = redact({ email: 'jan@example.com', content: 'treść wiadomości' }, false) as Record< string, unknown >; assert.equal(out.email, 'j***@example.com'); assert.equal(out.content, '[REDACTED_PII]'); }); test('maskEmail keeps only the first character and the domain', () => { assert.equal(maskEmail('jan.kowalski@example.com'), 'j***@example.com'); assert.equal(maskEmail('not-an-email'), '[REDACTED]'); }); test('redact terminates on deeply nested structures', () => { type Nested = { next?: Nested }; let deep: Nested = {}; for (let i = 0; i < 30; i++) deep = { next: deep }; assert.doesNotThrow(() => redact(deep, false)); });