rwadurian/backend/services/backup-service/test/unit/shared/audit-log.interceptor.spec.ts

193 lines
5.6 KiB
TypeScript

import { ExecutionContext, CallHandler } from '@nestjs/common';
import { of, throwError } from 'rxjs';
import { AuditLogInterceptor } from '../../../src/shared/interceptors/audit-log.interceptor';
describe('AuditLogInterceptor', () => {
let interceptor: AuditLogInterceptor;
const createMockContext = (
method: string = 'POST',
url: string = '/backup-share/store',
body: any = {},
sourceService: string = 'identity-service',
sourceIp: string = '127.0.0.1',
): ExecutionContext => {
return {
switchToHttp: () => ({
getRequest: () => ({
method,
url,
body,
sourceService,
sourceIp,
}),
}),
} as ExecutionContext;
};
const createMockCallHandler = (response: any = {}): CallHandler => ({
handle: () => of(response),
});
const createErrorCallHandler = (error: Error): CallHandler => ({
handle: () => throwError(() => error),
});
beforeEach(() => {
interceptor = new AuditLogInterceptor();
});
describe('intercept', () => {
it('should allow request to proceed', (done) => {
const context = createMockContext();
const handler = createMockCallHandler({ success: true });
interceptor.intercept(context, handler).subscribe({
next: (response) => {
expect(response).toEqual({ success: true });
done();
},
});
});
it('should not modify the response', (done) => {
const context = createMockContext();
const originalResponse = { shareId: '123', success: true };
const handler = createMockCallHandler(originalResponse);
interceptor.intercept(context, handler).subscribe({
next: (response) => {
expect(response).toEqual(originalResponse);
done();
},
});
});
it('should propagate errors', (done) => {
const context = createMockContext();
const error = new Error('Test error');
const handler = createErrorCallHandler(error);
interceptor.intercept(context, handler).subscribe({
error: (err) => {
expect(err).toBe(error);
done();
},
});
});
it('should sanitize sensitive fields in body', () => {
const sensitiveBody = {
userId: '12345',
encryptedShareData: 'secret-data',
recoveryToken: 'secret-token',
password: 'secret-password',
publicKey: '02abc...',
};
// Access the private method through prototype
const sanitized = (interceptor as any).sanitizeBody(sensitiveBody);
expect(sanitized.userId).toBe('12345');
expect(sanitized.publicKey).toBe('02abc...');
expect(sanitized.encryptedShareData).toBe('[REDACTED]');
expect(sanitized.recoveryToken).toBe('[REDACTED]');
expect(sanitized.password).toBe('[REDACTED]');
});
it('should handle null body', () => {
const sanitized = (interceptor as any).sanitizeBody(null);
expect(sanitized).toBeNull();
});
it('should handle undefined body', () => {
const sanitized = (interceptor as any).sanitizeBody(undefined);
expect(sanitized).toBeUndefined();
});
it('should handle empty body', () => {
const sanitized = (interceptor as any).sanitizeBody({});
expect(sanitized).toEqual({});
});
it('should not modify original body object', () => {
const originalBody = {
userId: '12345',
encryptedShareData: 'secret-data',
};
const bodyCopy = { ...originalBody };
(interceptor as any).sanitizeBody(originalBody);
expect(originalBody).toEqual(bodyCopy);
});
});
describe('logging behavior', () => {
it('should handle different HTTP methods', (done) => {
const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'];
let completed = 0;
methods.forEach((method) => {
const context = createMockContext(method, '/test');
const handler = createMockCallHandler();
interceptor.intercept(context, handler).subscribe({
complete: () => {
completed++;
if (completed === methods.length) {
done();
}
},
});
});
});
it('should handle different URL paths', (done) => {
const paths = [
'/backup-share/store',
'/backup-share/retrieve',
'/backup-share/revoke',
'/health',
];
let completed = 0;
paths.forEach((url) => {
const context = createMockContext('GET', url);
const handler = createMockCallHandler();
interceptor.intercept(context, handler).subscribe({
complete: () => {
completed++;
if (completed === paths.length) {
done();
}
},
});
});
});
it('should handle unknown source service', (done) => {
const context = createMockContext('POST', '/test', {}, undefined, '127.0.0.1');
const handler = createMockCallHandler();
interceptor.intercept(context, handler).subscribe({
complete: () => {
done();
},
});
});
it('should handle unknown source IP', (done) => {
const context = createMockContext('POST', '/test', {}, 'identity-service', undefined);
const handler = createMockCallHandler();
interceptor.intercept(context, handler).subscribe({
complete: () => {
done();
},
});
});
});
});