UNPKG

qgenutils

Version:

A security-first Node.js utility library providing authentication, HTTP operations, URL processing, validation, datetime formatting, and template rendering. Designed as a lightweight alternative to heavy npm packages with comprehensive error handling and

243 lines (199 loc) 9.28 kB
// Integration tests validating error recovery across modules. These tests // simulate multiple failure scenarios to ensure utilities cooperate under // error conditions without crashing the process. const utils = require('../../index'); describe('Error Handling Integration Tests', () => { // verifies utilities interact safely under failure describe('Cascading Error Scenarios', () => { // simulates multiple failures at once // verifies should handle multiple module failures gracefully test('should handle multiple module failures gracefully', () => { const mockRes = { status: jest.fn().mockReturnThis(), json: jest.fn().mockReturnThis(), render: jest.fn(), send: jest.fn().mockReturnThis() }; // Test invalid URL processing const invalidUrl = null; expect(utils.ensureProtocol(invalidUrl)).toBeNull(); // invalid URL returns null expect(utils.normalizeUrlOrigin(invalidUrl)).toBeNull(); // normalization also null expect(utils.parseUrlParts(invalidUrl)).toBeNull(); // parsing fails gracefully // Test invalid date processing const invalidDate = 'not-a-date'; expect(utils.formatDateTime(invalidDate)).toBe('N/A'); // invalid date yields N/A // Test invalid duration calculation should throw expect(() => utils.formatDuration(invalidDate)).toThrow(); // invalid duration throws // Test validation with malformed object expect(utils.requireFields(null, ['field'], mockRes)).toBe(false); // (reordered parameters to match obj, fields, res) expect(mockRes.status).toHaveBeenCalledWith(500); // validation error results in server error // Test auth with malformed request expect(utils.checkPassportAuth(null)).toBe(false); // malformed req fails auth }); // verifies should handle error propagation in API workflow test('should handle error propagation in API workflow', () => { const mockRes = { status: jest.fn().mockReturnThis(), json: jest.fn().mockReturnThis() }; // Simulate malformed request object const malformedReq = { headers: null, // This will cause issues body: undefined, // This will cause validation issues isAuthenticated: null // This will cause auth issues }; // Each utility should handle the malformed data gracefully expect(utils.checkPassportAuth(malformedReq)).toBe(false); // auth fails with bad object // Header processing would have failed but that module was removed expect(utils.requireFields(malformedReq.body, ['field'], mockRes)).toBe(false); // validation fails on body }); }); describe('View Rendering Error Recovery', () => { // ensures rendering issues propagate correctly // verifies should handle template rendering failures across multiple views test('should handle template rendering failures across multiple views', () => { const mockRes = { render: jest.fn().mockImplementation(() => { throw new Error('Template engine error'); }), status: jest.fn().mockReturnThis(), send: jest.fn().mockReturnThis() }; const views = ['dashboard', 'profile', 'admin']; views.forEach(view => { utils.renderView(mockRes, view, `${view} Error`); expect(mockRes.status).toHaveBeenCalledWith(500); expect(mockRes.send).toHaveBeenCalledWith( expect.stringContaining(`${view} Error`) ); // send error page for each view }); // Should have attempted to render each view expect(mockRes.render).toHaveBeenCalledTimes(3); // attempted rendering each view // Should have sent error pages for each failure expect(mockRes.send).toHaveBeenCalledTimes(3); // error page sent each time }); // verifies should handle route registration with missing global app test('should handle route registration with missing global app', () => { const originalApp = global.app; try { global.app = undefined; // Should not throw even with missing app expect(() => { utils.registerViewRoute('/test', 'test', 'Test Error'); }).not.toThrow(); // should not crash when app undefined global.app = null; expect(() => { utils.registerViewRoute('/test2', 'test2', 'Test Error 2'); }).not.toThrow(); // handle null app as well } finally { global.app = originalApp; } }); }); describe('Authentication Error Scenarios', () => { // tests auth faults across modules // verifies should handle passport strategy detection with broken global state test('should handle passport strategy detection with broken global state', () => { const originalPassport = global.passport; try { // Test with completely broken passport object global.passport = { get _strategies() { throw new Error('Strategies access failed'); } }; expect(utils.hasGithubStrategy()).toBe(false); // Test with circular reference const circular = {}; circular.self = circular; global.passport = circular; expect(utils.hasGithubStrategy()).toBe(false); } finally { global.passport = originalPassport; } }); // verifies should handle authentication with various request object states test('should handle authentication with various request object states', () => { const testCases = [ null, undefined, {}, { isAuthenticated: null }, { isAuthenticated: undefined }, { isAuthenticated: 'not-a-function' }, { isAuthenticated: () => { throw new Error('Auth error'); } } ]; testCases.forEach(testReq => { expect(utils.checkPassportAuth(testReq)).toBe(false); }); }); }); describe('URL Processing Error Recovery', () => { // validates robust URL handling // verifies should handle malformed URLs throughout processing pipeline test('should handle malformed URLs throughout processing pipeline', () => { const malformedUrls = [ '', null, undefined, 123, {}, '://invalid', 'ftp://unsupported-protocol.com' ]; malformedUrls.forEach(url => { // ensureProtocol should return null for invalid inputs const withProtocol = utils.ensureProtocol(url); if (withProtocol === null) { expect(utils.normalizeUrlOrigin(url)).toBeNull(); // invalid URL remains null expect(utils.parseUrlParts(url)).toBeNull(); // parsing returns null } }); }); // verifies should handle URL processing with partial failures test('should handle URL processing with partial failures', () => { // Valid URL that might cause issues in some contexts const edgeCaseUrls = [ 'localhost', '127.0.0.1', 'example.com:99999', // Very high port 'sub.domain.example.com/very/long/path/with/many/segments?lots=of&query=params&more=data' ]; edgeCaseUrls.forEach(url => { const withProtocol = utils.ensureProtocol(url); expect(withProtocol).toContain('https://'); // protocol enforced const normalized = utils.normalizeUrlOrigin(url); if (normalized) { expect(normalized).toContain('https://'); // normalization adds protocol } else { expect(normalized).toBeNull(); // invalid normalization results null } const parsed = utils.parseUrlParts(url); if (parsed) { expect(parsed).toHaveProperty('baseUrl'); // object must contain baseUrl expect(parsed).toHaveProperty('endpoint'); // object must contain endpoint } else { expect(parsed).toBeNull(); // invalid parsing results null } }); }); }); describe('Data Validation Error Recovery', () => { // confirms input validation fails gracefully // verifies should handle validation with various malformed objects test('should handle validation with various malformed objects', () => { const mockRes = { status: jest.fn().mockReturnThis(), json: jest.fn().mockReturnThis() }; const testCases = [ [null, ['field'], 500], // Null object [undefined, ['field'], 500], // Undefined object ['not-an-object', ['field'], 500], // String instead of object [[], ['field'], 500], // Array instead of object [42, ['field'], 500] // Number instead of object ]; testCases.forEach(([obj, fields, expectedStatus]) => { mockRes.status.mockClear(); mockRes.json.mockClear(); const result = utils.requireFields(obj, fields, mockRes); // (reordered parameters to match obj, fields, res) expect(result).toBe(false); // validation fails as expected expect(mockRes.status).toHaveBeenCalledWith(expectedStatus); // status matches table }); }); }); });