Files
ccs/tests/unit/services/logging/log-redaction.test.ts
T

104 lines
2.4 KiB
TypeScript

import { describe, expect, it } from 'bun:test';
import { redactContext } from '../../../../src/services/logging/log-redaction';
describe('log redaction', () => {
it('redacts sensitive keys and preserves non-sensitive values', () => {
const redacted = redactContext({
token: 'secret-token',
api_key: 'secret-key',
safe: 'kept',
count: 3,
enabled: true,
});
expect(redacted).toEqual({
token: '[redacted]',
api_key: '[redacted]',
safe: 'kept',
count: 3,
enabled: true,
});
});
it('sanitizes nested objects and arrays recursively', () => {
const redacted = redactContext({
request: {
headers: {
authorization: 'Bearer abc',
cookie: 'session=123',
},
steps: [
{ secret: 'hidden' },
{ label: 'safe-step' },
['nested-array', { password_hash: 'hidden-hash' }],
],
},
});
expect(redacted).toEqual({
request: {
headers: {
authorization: '[redacted]',
cookie: '[redacted]',
},
steps: [
{ secret: '[redacted]' },
{ label: 'safe-step' },
['nested-array', { password_hash: '[redacted]' }],
],
},
});
});
it('caps recursive depth, truncates long strings, and preserves nullish values', () => {
const deeplyNested = {
first: {
second: {
third: {
fourth: {
fifth: {
sixth: 'too-deep',
},
},
},
},
},
};
const longValue = 'a'.repeat(2_500);
const redacted = redactContext({
nested: deeplyNested,
longValue,
nothing: null,
missing: undefined,
});
expect(redacted.nested).toEqual({
first: {
second: {
third: {
fourth: '[max-depth]',
},
},
},
});
expect(redacted.longValue).toBe(`${'a'.repeat(2_000)}...[truncated]`);
expect(redacted.nothing).toBeNull();
expect(redacted.missing).toBeUndefined();
});
it('reduces Error instances to safe name and message fields', () => {
const error = new Error('boom'.repeat(700));
error.name = 'ExplodedError';
const redacted = redactContext({ error });
expect(redacted).toEqual({
error: {
name: 'ExplodedError',
message: `${'boom'.repeat(500)}...[truncated]`,
},
});
});
});