mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 16:11:12 -05:00
Improve error formatting in tests
- Replace [object Object] errors with readable messages by using robust error formatting across test suites - Introduce formatTestError helper and apply it in all catch blocks and error throws - Update approvalPipelineTests and related suites to utilize improved error extraction for better debugging
This commit is contained in:
59
src/lib/integrationTests/formatTestError.ts
Normal file
59
src/lib/integrationTests/formatTestError.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Test Error Formatting Utility
|
||||||
|
*
|
||||||
|
* Provides robust error formatting for test results to avoid "[object Object]" messages
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format error for test result display
|
||||||
|
* Handles Error objects, PostgresError objects, and plain objects
|
||||||
|
*
|
||||||
|
* @param error - Any error value thrown in a test
|
||||||
|
* @returns Formatted, human-readable error string
|
||||||
|
*/
|
||||||
|
export function formatTestError(error: unknown): string {
|
||||||
|
// Standard Error objects
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return error.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object-like errors (PostgresError, custom error objects, etc.)
|
||||||
|
if (typeof error === 'object' && error !== null) {
|
||||||
|
const err = error as any;
|
||||||
|
|
||||||
|
// Try common error message properties
|
||||||
|
if (err.message && typeof err.message === 'string') {
|
||||||
|
return err.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some errors nest the actual error in an 'error' property
|
||||||
|
if (err.error) {
|
||||||
|
return formatTestError(err.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some APIs use 'msg' instead of 'message'
|
||||||
|
if (err.msg && typeof err.msg === 'string') {
|
||||||
|
return err.msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supabase errors might have details
|
||||||
|
if (err.details && typeof err.details === 'string') {
|
||||||
|
return `${err.message || 'Error'}: ${err.details}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last resort: stringify the entire object
|
||||||
|
try {
|
||||||
|
const stringified = JSON.stringify(error, null, 2);
|
||||||
|
// If it's too long, truncate it
|
||||||
|
return stringified.length > 500
|
||||||
|
? stringified.substring(0, 500) + '... (truncated)'
|
||||||
|
: stringified;
|
||||||
|
} catch {
|
||||||
|
// JSON.stringify can fail on circular references
|
||||||
|
return String(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Primitive values (strings, numbers, etc.)
|
||||||
|
return String(error);
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { TestDataTracker } from '../TestDataTracker';
|
import { TestDataTracker } from '../TestDataTracker';
|
||||||
|
import { formatTestError } from '../formatTestError';
|
||||||
import {
|
import {
|
||||||
submitParkCreation,
|
submitParkCreation,
|
||||||
submitRideCreation,
|
submitRideCreation,
|
||||||
@@ -18,6 +19,9 @@ import {
|
|||||||
submitRideModelCreation
|
submitRideModelCreation
|
||||||
} from '@/lib/entitySubmissionHelpers';
|
} from '@/lib/entitySubmissionHelpers';
|
||||||
|
|
||||||
|
// Re-export formatTestError for use in test suites
|
||||||
|
export { formatTestError } from '../formatTestError';
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// AUTHENTICATION
|
// AUTHENTICATION
|
||||||
// ============================================
|
// ============================================
|
||||||
@@ -416,7 +420,7 @@ export async function approveSubmission(
|
|||||||
const duration = performance.now() - startTime;
|
const duration = performance.now() - startTime;
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
duration,
|
duration,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,6 @@
|
|||||||
export { IntegrationTestRunner } from './testRunner';
|
export { IntegrationTestRunner } from './testRunner';
|
||||||
export { allTestSuites } from './suites';
|
export { allTestSuites } from './suites';
|
||||||
export { formatResultsAsMarkdown, formatSingleTestAsMarkdown } from './formatters';
|
export { formatResultsAsMarkdown, formatSingleTestAsMarkdown } from './formatters';
|
||||||
|
export { formatTestError } from './formatTestError';
|
||||||
|
|
||||||
export type { TestResult, Test, TestSuite } from './testRunner';
|
export type { TestResult, Test, TestSuite } from './testRunner';
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import {
|
|||||||
verifySubmissionStatus,
|
verifySubmissionStatus,
|
||||||
createParkDirectly,
|
createParkDirectly,
|
||||||
createRideDirectly,
|
createRideDirectly,
|
||||||
|
formatTestError,
|
||||||
} from '../helpers/approvalTestHelpers';
|
} from '../helpers/approvalTestHelpers';
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
@@ -132,7 +133,7 @@ const parkCreationTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -220,7 +221,7 @@ const rideCreationTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -298,7 +299,7 @@ const companyCreationTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -387,7 +388,7 @@ const rideModelCreationTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -497,7 +498,7 @@ const rideManufacturerCompositeTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -624,7 +625,7 @@ const partialApprovalTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -714,7 +715,7 @@ const idempotencyTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -809,7 +810,7 @@ const parkUpdateTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -897,7 +898,7 @@ const rideUpdateTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -999,7 +1000,7 @@ const rideManufacturerDesignerCompositeTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1097,7 +1098,7 @@ const parkOperatorOwnerCompositeTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1188,7 +1189,7 @@ const lockConflictTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1280,7 +1281,7 @@ const bannedUserTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1373,7 +1374,7 @@ const multipleEditChainTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1478,7 +1479,7 @@ const versionSnapshotIntegrityTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1557,7 +1558,7 @@ const parkPhotoGalleryTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1639,7 +1640,7 @@ const ridePhotoGalleryTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1753,7 +1754,7 @@ const invalidTempRefTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@@ -1852,7 +1853,7 @@ const concurrentEditTest: Test = {
|
|||||||
suite: 'Approval Pipeline',
|
suite: 'Approval Pipeline',
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: formatTestError(error),
|
||||||
stack: error instanceof Error ? error.stack : undefined,
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ export const performanceTestSuite: TestSuite = {
|
|||||||
.select('id')
|
.select('id')
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (parkError) throw parkError;
|
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`);
|
||||||
parkId = park.id;
|
parkId = park.id;
|
||||||
tracker.track('parks', parkId);
|
tracker.track('parks', parkId);
|
||||||
|
|
||||||
@@ -214,7 +214,7 @@ export const performanceTestSuite: TestSuite = {
|
|||||||
|
|
||||||
const modDuration = Date.now() - modStart;
|
const modDuration = Date.now() - modStart;
|
||||||
|
|
||||||
if (modError) throw modError;
|
if (modError) throw new Error(`Moderator check failed: ${modError.message}`);
|
||||||
|
|
||||||
// Test is_user_banned function performance
|
// Test is_user_banned function performance
|
||||||
const banStart = Date.now();
|
const banStart = Date.now();
|
||||||
@@ -225,7 +225,7 @@ export const performanceTestSuite: TestSuite = {
|
|||||||
|
|
||||||
const banDuration = Date.now() - banStart;
|
const banDuration = Date.now() - banStart;
|
||||||
|
|
||||||
if (banError) throw banError;
|
if (banError) throw new Error(`Ban check failed: ${banError.message}`);
|
||||||
|
|
||||||
// Performance threshold: 200ms for simple functions
|
// Performance threshold: 200ms for simple functions
|
||||||
const threshold = 200;
|
const threshold = 200;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export const unitConversionTestSuite: TestSuite = {
|
|||||||
.select('id')
|
.select('id')
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (parkError) throw parkError;
|
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`);
|
||||||
parkId = park.id;
|
parkId = park.id;
|
||||||
tracker.track('parks', parkId);
|
tracker.track('parks', parkId);
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ export const unitConversionTestSuite: TestSuite = {
|
|||||||
.select('id')
|
.select('id')
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (parkError) throw parkError;
|
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`);
|
||||||
parkId = park.id;
|
parkId = park.id;
|
||||||
tracker.track('parks', parkId);
|
tracker.track('parks', parkId);
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ export const unitConversionTestSuite: TestSuite = {
|
|||||||
.select('id')
|
.select('id')
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
if (rideError) throw rideError;
|
if (rideError) throw new Error(`Ride creation failed: ${rideError.message}`);
|
||||||
rideId = ride.id;
|
rideId = ride.id;
|
||||||
tracker.track('rides', rideId);
|
tracker.track('rides', rideId);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user