UNPKG

guardz-event

Version:

Type-safe event handling with runtime validation using guardz for unsafe data from 3rd parties

254 lines 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /// <reference types="jest" /> const safe_event_never_throws_1 = require("../utils/safe-event-never-throws"); // Mock type guards for testing const isUserMessage = (data) => { return (typeof data === 'object' && data !== null && typeof data.id === 'number' && typeof data.name === 'string' && typeof data.email === 'string' && typeof data.isActive === 'boolean'); }; const isStockUpdate = (data) => { return (typeof data === 'object' && data !== null && typeof data.symbol === 'string' && typeof data.price === 'number' && typeof data.change === 'number'); }; const isClickData = (data) => { return (typeof data === 'object' && data !== null && typeof data.clientX === 'number' && typeof data.clientY === 'number' && typeof data.button === 'number'); }; describe('Legacy API', () => { describe('safePostMessage', () => { it('should return success result for valid message', () => { const handler = (0, safe_event_never_throws_1.safePostMessage)({ guard: isUserMessage, allowedOrigins: ['https://trusted-domain.com'], }); const validEvent = new MessageEvent('message', { origin: 'https://trusted-domain.com', data: { id: 1, name: 'John', email: 'john@example.com', isActive: true, }, }); const result = handler(validEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.SUCCESS); if (result.status === safe_event_never_throws_1.Status.SUCCESS) { expect(result.data).toEqual({ id: 1, name: 'John', email: 'john@example.com', isActive: true, }); } }); it('should return error result for untrusted origin', () => { const handler = (0, safe_event_never_throws_1.safePostMessage)({ guard: isUserMessage, allowedOrigins: ['https://trusted-domain.com'], }); const maliciousEvent = new MessageEvent('message', { origin: 'https://malicious-site.com', data: { id: 1, name: 'Hacker', email: 'hack@evil.com', isActive: true }, }); const result = handler(maliciousEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.ERROR); if (result.status === safe_event_never_throws_1.Status.ERROR) { expect(result.code).toBe(403); expect(result.message).toContain('not allowed'); } }); it('should return error result for invalid data', () => { const handler = (0, safe_event_never_throws_1.safePostMessage)({ guard: isUserMessage, allowedOrigins: ['https://trusted-domain.com'], }); const invalidEvent = new MessageEvent('message', { origin: 'https://trusted-domain.com', data: { id: 'not-a-number', name: 'John', email: 'john@example.com', isActive: true, }, }); const result = handler(invalidEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.ERROR); if (result.status === safe_event_never_throws_1.Status.ERROR) { expect(result.code).toBe(500); expect(result.message).toContain('Validation failed'); } }); }); describe('safeWebSocket', () => { it('should return success result for valid WebSocket message', () => { const handler = (0, safe_event_never_throws_1.safeWebSocket)({ guard: isStockUpdate, }); const validEvent = new MessageEvent('message', { data: { symbol: 'AAPL', price: 150.25, change: 2.5 }, }); const result = handler(validEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.SUCCESS); if (result.status === safe_event_never_throws_1.Status.SUCCESS) { expect(result.data).toEqual({ symbol: 'AAPL', price: 150.25, change: 2.5, }); } }); it('should return error result for invalid WebSocket data', () => { const handler = (0, safe_event_never_throws_1.safeWebSocket)({ guard: isStockUpdate, }); const invalidEvent = new MessageEvent('message', { data: { symbol: 'AAPL', price: 'not-a-number', change: 2.5 }, }); const result = handler(invalidEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.ERROR); if (result.status === safe_event_never_throws_1.Status.ERROR) { expect(result.code).toBe(500); expect(result.message).toContain('Validation failed'); } }); }); describe('safeDOMEvent', () => { it('should return success result for valid DOM event', () => { const handler = (0, safe_event_never_throws_1.safeDOMEvent)({ guard: isClickData, }); const validEvent = new MouseEvent('click', { clientX: 100, clientY: 200, button: 0, }); const result = handler(validEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.SUCCESS); if (result.status === safe_event_never_throws_1.Status.SUCCESS) { expect(result.data).toEqual({ clientX: 100, clientY: 200, button: 0 }); } }); it('should return error result for invalid DOM event data', () => { const handler = (0, safe_event_never_throws_1.safeDOMEvent)({ guard: isClickData, }); const invalidEvent = new Event('click'); const result = handler(invalidEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.ERROR); if (result.status === safe_event_never_throws_1.Status.ERROR) { expect(result.code).toBe(500); expect(result.message).toContain('Validation failed'); } }); }); describe('safeEventSource', () => { it('should return success result for valid EventSource message', () => { const handler = (0, safe_event_never_throws_1.safeEventSource)({ guard: isStockUpdate, }); const validEvent = new MessageEvent('message', { data: { symbol: 'AAPL', price: 150.25, change: 2.5 }, }); const result = handler(validEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.SUCCESS); if (result.status === safe_event_never_throws_1.Status.SUCCESS) { expect(result.data).toEqual({ symbol: 'AAPL', price: 150.25, change: 2.5, }); } }); }); describe('safeCustomEvent', () => { it('should return success result for valid custom event', () => { const handler = (0, safe_event_never_throws_1.safeCustomEvent)({ guard: isStockUpdate, }); const validEvent = new CustomEvent('stock-update', { detail: { symbol: 'AAPL', price: 150.25, change: 2.5 }, }); const result = handler(validEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.SUCCESS); if (result.status === safe_event_never_throws_1.Status.SUCCESS) { expect(result.data).toEqual({ symbol: 'AAPL', price: 150.25, change: 2.5, }); } }); }); describe('safeStorageEvent', () => { it('should return success result for valid storage event', () => { const handler = (0, safe_event_never_throws_1.safeStorageEvent)({ guard: (data) => { return (typeof data === 'object' && data !== null && typeof data.key === 'string' && typeof data.url === 'string'); }, }); const validEvent = new StorageEvent('storage', { key: 'user_preferences', oldValue: 'old_value', newValue: 'new_value', url: 'https://example.com', }); const result = handler(validEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.SUCCESS); if (result.status === safe_event_never_throws_1.Status.SUCCESS) { expect(result.data).toEqual({ key: 'user_preferences', oldValue: 'old_value', newValue: 'new_value', url: 'https://example.com', }); } }); }); describe('Tolerance Mode', () => { it('should handle tolerance mode correctly', () => { const onError = jest.fn(); const handler = (0, safe_event_never_throws_1.safeWebSocket)({ guard: isStockUpdate, tolerance: true, onError, }); const partialEvent = new MessageEvent('message', { data: { symbol: 'AAPL', price: 150.25, change: 'not-a-number' }, }); const result = handler(partialEvent); // In tolerance mode, it should still return success but with warnings expect(result.status).toBe(safe_event_never_throws_1.Status.SUCCESS); expect(onError).toHaveBeenCalled(); }); }); describe('Error Handling', () => { it('should handle null events gracefully', () => { const handler = (0, safe_event_never_throws_1.safePostMessage)({ guard: isUserMessage, allowedOrigins: ['https://trusted-domain.com'], }); const nullEvent = null; const result = handler(nullEvent); expect(result.status).toBe(safe_event_never_throws_1.Status.ERROR); if (result.status === safe_event_never_throws_1.Status.ERROR) { expect(result.code).toBe(500); expect(result.message).toContain('Invalid event'); } }); }); }); //# sourceMappingURL=legacy-api.test.js.map