169 lines
5.9 KiB
TypeScript
169 lines
5.9 KiB
TypeScript
import { sanitizeInput, sanitizeHTML, sanitizeURL } from './sanitize';
|
|
import { isAllowedType, validateFileSignature, isDangerousFile } from './upload';
|
|
import { generateCSRFToken, validateCSRFToken } from './csrf';
|
|
import { calculateContrastRatio, meetsWCAGStandard } from './color-contrast';
|
|
import { PerformanceMonitor } from './monitoring';
|
|
|
|
describe('Integration Tests', () => {
|
|
describe('Input Sanitization Flow', () => {
|
|
it('should sanitize user input end-to-end', () => {
|
|
const userInput = '<script>alert("xss")</script>Hello World';
|
|
const sanitized = sanitizeInput(userInput);
|
|
|
|
expect(sanitized).not.toContain('<script>');
|
|
expect(sanitized).toContain('Hello World');
|
|
});
|
|
|
|
it('should sanitize HTML content', () => {
|
|
const htmlContent = '<p onclick="alert(1)">Safe text</p><script>evil()</script>';
|
|
const sanitized = sanitizeHTML(htmlContent);
|
|
|
|
expect(sanitized).not.toContain('onclick');
|
|
expect(sanitized).not.toContain('<script>');
|
|
expect(sanitized).toContain('Safe text');
|
|
});
|
|
|
|
it('should sanitize URLs', () => {
|
|
const maliciousUrl = 'javascript:alert(1)';
|
|
const safeUrl = 'https://example.com';
|
|
|
|
expect(sanitizeURL(maliciousUrl)).toBe('');
|
|
expect(sanitizeURL(safeUrl)).toBe(safeUrl);
|
|
});
|
|
});
|
|
|
|
describe('CSRF Protection Flow', () => {
|
|
it('should generate and validate CSRF tokens', () => {
|
|
const token = generateCSRFToken();
|
|
expect(token).toBeDefined();
|
|
expect(typeof token).toBe('string');
|
|
expect(token.length).toBeGreaterThan(0);
|
|
|
|
const isValid = validateCSRFToken(token, token);
|
|
expect(isValid).toBe(true);
|
|
});
|
|
|
|
it('should reject invalid CSRF tokens', () => {
|
|
const invalidToken = 'invalid-token-123';
|
|
const storedToken = 'different-token';
|
|
const isValid = validateCSRFToken(invalidToken, storedToken);
|
|
expect(isValid).toBe(false);
|
|
});
|
|
|
|
it('should reject empty tokens', () => {
|
|
const isValid = validateCSRFToken('', 'some-token');
|
|
expect(isValid).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('File Validation Flow', () => {
|
|
it('should validate allowed file types', () => {
|
|
const isImageAllowed = isAllowedType('image/jpeg', 'image');
|
|
const isDocAllowed = isAllowedType('application/pdf', 'document');
|
|
|
|
expect(isImageAllowed).toBe(true);
|
|
expect(isDocAllowed).toBe(true);
|
|
});
|
|
|
|
it('should reject dangerous file types', () => {
|
|
const isDangerous = isDangerousFile('malware.exe');
|
|
expect(isDangerous).toBe(true);
|
|
|
|
const isSafe = isDangerousFile('document.pdf');
|
|
expect(isSafe).toBe(false);
|
|
});
|
|
|
|
it('should validate file signatures', async () => {
|
|
const pngSignature = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
const isValid = validateFileSignature(pngSignature, 'image/png');
|
|
expect(isValid).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('Color Contrast Validation Flow', () => {
|
|
it('should validate accessible color combinations', () => {
|
|
const result = meetsWCAGStandard('#000000', '#FFFFFF', 'AA', 'normal');
|
|
expect(result.passes).toBe(true);
|
|
expect(result.ratio).toBeGreaterThan(4.5);
|
|
});
|
|
|
|
it('should reject inaccessible color combinations', () => {
|
|
const result = meetsWCAGStandard('#CCCCCC', '#FFFFFF', 'AA', 'normal');
|
|
expect(result.passes).toBe(false);
|
|
});
|
|
|
|
it('should calculate contrast ratios correctly', () => {
|
|
const blackOnWhite = calculateContrastRatio('#000000', '#FFFFFF');
|
|
const whiteOnBlack = calculateContrastRatio('#FFFFFF', '#000000');
|
|
|
|
expect(blackOnWhite).toBeCloseTo(21, 0);
|
|
expect(whiteOnBlack).toBeCloseTo(21, 0);
|
|
});
|
|
});
|
|
|
|
describe('Performance Monitoring Flow', () => {
|
|
beforeEach(() => {
|
|
PerformanceMonitor['instance'] = null as any;
|
|
});
|
|
|
|
it('should track metrics across operations', () => {
|
|
const monitor = PerformanceMonitor.getInstance();
|
|
|
|
monitor.recordMetric('response_time', 100);
|
|
monitor.recordMetric('response_time', 200);
|
|
monitor.recordMetric('response_time', 150);
|
|
|
|
const stats = monitor.getStats('response_time');
|
|
expect(stats.count).toBe(3);
|
|
expect(stats.avg).toBe(150);
|
|
expect(stats.min).toBe(100);
|
|
expect(stats.max).toBe(200);
|
|
});
|
|
|
|
it('should track multiple metrics independently', () => {
|
|
const monitor = PerformanceMonitor.getInstance();
|
|
|
|
monitor.recordMetric('api_calls', 1);
|
|
monitor.recordMetric('api_calls', 1);
|
|
monitor.recordMetric('db_queries', 5);
|
|
monitor.recordMetric('db_queries', 5);
|
|
|
|
expect(monitor.getCount('api_calls')).toBe(2);
|
|
expect(monitor.getCount('db_queries')).toBe(2);
|
|
expect(monitor.getAverage('api_calls')).toBe(1);
|
|
expect(monitor.getAverage('db_queries')).toBe(5);
|
|
});
|
|
});
|
|
|
|
describe('Combined Security Validation Flow', () => {
|
|
it('should validate and sanitize user input comprehensively', () => {
|
|
const maliciousInput = {
|
|
name: '<script>alert("xss")</script>John',
|
|
email: 'john@example.com',
|
|
website: 'javascript:alert(1)',
|
|
message: '<p onclick="evil()">Hello</p>',
|
|
};
|
|
|
|
const sanitized = {
|
|
name: sanitizeInput(maliciousInput.name),
|
|
email: sanitizeInput(maliciousInput.email),
|
|
website: sanitizeURL(maliciousInput.website),
|
|
message: sanitizeHTML(maliciousInput.message),
|
|
};
|
|
|
|
expect(sanitized.name).not.toContain('<script>');
|
|
expect(sanitized.email).toBe('john@example.com');
|
|
expect(sanitized.website).toBe('');
|
|
expect(sanitized.message).not.toContain('onclick');
|
|
});
|
|
|
|
it('should validate file upload with CSRF protection', () => {
|
|
const csrfToken = generateCSRFToken();
|
|
const isValidCSRF = validateCSRFToken(csrfToken, csrfToken);
|
|
expect(isValidCSRF).toBe(true);
|
|
|
|
const isAllowed = isAllowedType('application/pdf', 'document');
|
|
expect(isAllowed).toBe(true);
|
|
});
|
|
});
|
|
}); |