test-error-handler.js•7.25 kB
/**
* Test for the fixed error handler to ensure it properly formats error responses
* and handles the 'undefined' error cases that were reported in issue #133
*/
// We can't directly import from TypeScript files, so let's mock the functions
// This test focuses on the logic we implemented, not the actual imported functions
// Mock the ErrorType enum
const ErrorType = {
UNKNOWN_ERROR: 'unknown_error',
VALIDATION_ERROR: 'validation_error',
API_ERROR: 'api_error',
NETWORK_ERROR: 'network_error',
};
// Mock the formatErrorResponse function with our new implementation
function formatErrorResponse(error, type = ErrorType.UNKNOWN_ERROR, details) {
// Ensure we have a valid error object
const normalizedError =
error instanceof Error
? error
: new Error(typeof error === 'string' ? error : 'Unknown error');
// Prevent "undefined" from being returned as an error message
const errorMessage =
normalizedError.message === undefined || normalizedError.message === null
? 'An unknown error occurred'
: normalizedError.message;
// Determine appropriate status code based on error type
const errorCode = type === ErrorType.VALIDATION_ERROR ? 400 : 500;
// Create a safe copy of details
let safeDetails = null;
if (details) {
try {
safeDetails = JSON.parse(JSON.stringify(details));
} catch (err) {
console.error('Error stringifying details:', err);
safeDetails = {
note: 'Error details could not be fully serialized',
error: String(err),
partial:
typeof details === 'object'
? Object.keys(details).reduce((acc, key) => {
try {
const val = details[key];
acc[key] =
typeof val === 'object' ? '[Complex Object]' : String(val);
} catch (e) {
acc[key] = '[Unstringifiable]';
}
return acc;
}, {})
: String(details),
};
}
}
return {
content: [
{
type: 'text',
text: `ERROR [${type}]: ${errorMessage}${
safeDetails
? '\n\nDetails: ' + JSON.stringify(safeDetails, null, 2)
: ''
}`,
},
],
isError: true,
error: {
code: errorCode,
message: errorMessage,
type,
details: safeDetails,
},
};
}
// Mock the createErrorResult function with our new implementation
function createErrorResult(error, url, method, responseData = {}) {
// Ensure we have a valid error object
const normalizedError =
error instanceof Error
? error
: new Error(typeof error === 'string' ? error : 'Unknown error');
console.error(
`[Test] Processing error for ${method} ${url}:`,
normalizedError.message
);
// For our test, we'll just format the normalized error
let errorType = ErrorType.UNKNOWN_ERROR;
// Safe check for includes
const message = normalizedError.message || '';
if (
message &&
(message.includes('network') || message.includes('connection'))
) {
errorType = ErrorType.NETWORK_ERROR;
}
const errorDetails = {
method,
url,
status: responseData.status || 'Unknown',
rawError:
typeof error === 'object'
? (function () {
try {
return JSON.stringify(error);
} catch (e) {
return `[Circular or unstringifiable object: ${e.message}]`;
}
})()
: String(error),
};
return formatErrorResponse(normalizedError, errorType, errorDetails);
}
// Test case 1: Handle undefined error
function testUndefinedError() {
console.error('\n=== Test Case 1: Undefined Error ===');
const error = undefined;
const url = '/api/companies';
const method = 'GET';
try {
const result = createErrorResult(error, url, method);
console.error('Result:', JSON.stringify(result, null, 2));
if (result.error.message === 'Unknown error') {
console.error('✅ Success: Properly handled undefined error');
} else {
console.error('❌ Failed: Did not properly handle undefined error');
}
} catch (e) {
console.error('❌ Test failed with exception:', e);
}
}
// Test case 2: Handle error with no message
function testErrorWithNoMessage() {
console.error('\n=== Test Case 2: Error With No Message ===');
const error = new Error();
error.message = undefined;
const url = '/api/companies';
const method = 'GET';
try {
const result = createErrorResult(error, url, method);
console.error('Result:', JSON.stringify(result, null, 2));
if (result.error.message && result.error.message !== 'undefined') {
console.error('✅ Success: Properly handled error with no message');
} else {
console.error('❌ Failed: Did not properly handle error with no message');
}
} catch (e) {
console.error('❌ Test failed with exception:', e);
}
}
// Test case 3: Handle non-Error object
function testNonErrorObject() {
console.error('\n=== Test Case 3: Non-Error Object ===');
const error = { someProperty: 'someValue' };
const url = '/api/companies';
const method = 'GET';
try {
const result = createErrorResult(error, url, method);
console.error('Result:', JSON.stringify(result, null, 2));
if (result.error.message && result.error.message !== 'undefined') {
console.error('✅ Success: Properly handled non-Error object');
} else {
console.error('❌ Failed: Did not properly handle non-Error object');
}
} catch (e) {
console.error('❌ Test failed with exception:', e);
}
}
// Test case 4: Handle circular references in error objects
function testCircularReferenceError() {
console.error('\n=== Test Case 4: Circular Reference in Error ===');
const circularObj = {};
circularObj.self = circularObj;
const error = new Error('Error with circular reference');
error.details = circularObj;
const url = '/api/companies';
const method = 'GET';
try {
const result = createErrorResult(error, url, method);
console.error('Result:', JSON.stringify(result, null, 2));
if (result.error.message) {
console.error('✅ Success: Properly handled error with circular reference');
// The error message should contain the original message
if (result.error.message.includes('Error with circular reference')) {
console.error(' - Original error message was preserved');
}
// The details should indicate there was a circular reference
if (
result.error.details &&
result.error.details.rawError.includes('Circular')
) {
console.error(' - Circular reference was properly handled in details');
}
} else {
console.error(
'❌ Failed: Did not properly handle error with circular reference'
);
}
} catch (e) {
console.error('❌ Test failed with exception:', e);
}
}
// Run all tests
async function runTests() {
console.error('Starting error handler tests...');
testUndefinedError();
testErrorWithNoMessage();
testNonErrorObject();
testCircularReferenceError();
console.error('\nAll tests completed.');
}
runTests();