116 lines
3.4 KiB
JavaScript
116 lines
3.4 KiB
JavaScript
const { test } = require('node:test')
|
|
const { strict: assert } = require('node:assert')
|
|
const slowRedact = require('../index.js')
|
|
|
|
test('selective cloning shares references for non-redacted paths', () => {
|
|
const sharedObject = { unchanged: 'data' }
|
|
const obj = {
|
|
toRedact: 'secret',
|
|
shared: sharedObject,
|
|
nested: {
|
|
toRedact: 'secret2',
|
|
shared: sharedObject
|
|
}
|
|
}
|
|
|
|
const redact = slowRedact({
|
|
paths: ['toRedact', 'nested.toRedact'],
|
|
serialize: false
|
|
})
|
|
|
|
const result = redact(obj)
|
|
|
|
// Redacted values should be different
|
|
assert.strictEqual(result.toRedact, '[REDACTED]')
|
|
assert.strictEqual(result.nested.toRedact, '[REDACTED]')
|
|
|
|
// Non-redacted references should be shared (same object reference)
|
|
assert.strictEqual(result.shared, obj.shared)
|
|
assert.strictEqual(result.nested.shared, obj.nested.shared)
|
|
|
|
// The shared object should be the exact same reference
|
|
assert.strictEqual(result.shared, sharedObject)
|
|
assert.strictEqual(result.nested.shared, sharedObject)
|
|
})
|
|
|
|
test('selective cloning works with arrays', () => {
|
|
const sharedItem = { unchanged: 'data' }
|
|
const obj = {
|
|
items: [
|
|
{ secret: 'hidden1', shared: sharedItem },
|
|
{ secret: 'hidden2', shared: sharedItem },
|
|
sharedItem
|
|
]
|
|
}
|
|
|
|
const redact = slowRedact({
|
|
paths: ['items.*.secret'],
|
|
serialize: false
|
|
})
|
|
|
|
const result = redact(obj)
|
|
|
|
// Secrets should be redacted
|
|
assert.strictEqual(result.items[0].secret, '[REDACTED]')
|
|
assert.strictEqual(result.items[1].secret, '[REDACTED]')
|
|
|
|
// Shared references should be preserved where possible
|
|
// Note: array items with secrets will be cloned, but their shared properties should still reference the original
|
|
assert.strictEqual(result.items[0].shared, sharedItem)
|
|
assert.strictEqual(result.items[1].shared, sharedItem)
|
|
|
|
// The third item gets cloned due to wildcard, but should have the same content
|
|
assert.deepStrictEqual(result.items[2], sharedItem)
|
|
// Note: Due to wildcard '*', all array items are cloned, even if they don't need redaction
|
|
// This is still a significant optimization for object properties that aren't in wildcard paths
|
|
})
|
|
|
|
test('selective cloning with no paths returns original object', () => {
|
|
const obj = { data: 'unchanged' }
|
|
const redact = slowRedact({
|
|
paths: [],
|
|
serialize: false
|
|
})
|
|
|
|
const result = redact(obj)
|
|
|
|
// Should return the exact same object reference
|
|
assert.strictEqual(result, obj)
|
|
})
|
|
|
|
test('selective cloning performance - large objects with minimal redaction', () => {
|
|
// Create a large object with mostly shared data
|
|
const sharedData = { large: 'data'.repeat(1000) }
|
|
const obj = {
|
|
secret: 'hidden',
|
|
shared1: sharedData,
|
|
shared2: sharedData,
|
|
nested: {
|
|
secret: 'hidden2',
|
|
shared3: sharedData,
|
|
deep: {
|
|
shared4: sharedData,
|
|
moreShared: sharedData
|
|
}
|
|
}
|
|
}
|
|
|
|
const redact = slowRedact({
|
|
paths: ['secret', 'nested.secret'],
|
|
serialize: false
|
|
})
|
|
|
|
const result = redact(obj)
|
|
|
|
// Verify redaction worked
|
|
assert.strictEqual(result.secret, '[REDACTED]')
|
|
assert.strictEqual(result.nested.secret, '[REDACTED]')
|
|
|
|
// Verify shared references are preserved
|
|
assert.strictEqual(result.shared1, sharedData)
|
|
assert.strictEqual(result.shared2, sharedData)
|
|
assert.strictEqual(result.nested.shared3, sharedData)
|
|
assert.strictEqual(result.nested.deep.shared4, sharedData)
|
|
assert.strictEqual(result.nested.deep.moreShared, sharedData)
|
|
})
|