mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:11:13 -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 { TestDataTracker } from '../TestDataTracker';
|
||||
import { formatTestError } from '../formatTestError';
|
||||
import {
|
||||
submitParkCreation,
|
||||
submitRideCreation,
|
||||
@@ -18,6 +19,9 @@ import {
|
||||
submitRideModelCreation
|
||||
} from '@/lib/entitySubmissionHelpers';
|
||||
|
||||
// Re-export formatTestError for use in test suites
|
||||
export { formatTestError } from '../formatTestError';
|
||||
|
||||
// ============================================
|
||||
// AUTHENTICATION
|
||||
// ============================================
|
||||
@@ -416,7 +420,7 @@ export async function approveSubmission(
|
||||
const duration = performance.now() - startTime;
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
duration,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,5 +7,6 @@
|
||||
export { IntegrationTestRunner } from './testRunner';
|
||||
export { allTestSuites } from './suites';
|
||||
export { formatResultsAsMarkdown, formatSingleTestAsMarkdown } from './formatters';
|
||||
export { formatTestError } from './formatTestError';
|
||||
|
||||
export type { TestResult, Test, TestSuite } from './testRunner';
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
verifySubmissionStatus,
|
||||
createParkDirectly,
|
||||
createRideDirectly,
|
||||
formatTestError,
|
||||
} from '../helpers/approvalTestHelpers';
|
||||
|
||||
// ============================================
|
||||
@@ -132,7 +133,7 @@ const parkCreationTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -220,7 +221,7 @@ const rideCreationTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -298,7 +299,7 @@ const companyCreationTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -387,7 +388,7 @@ const rideModelCreationTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -497,7 +498,7 @@ const rideManufacturerCompositeTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -624,7 +625,7 @@ const partialApprovalTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -714,7 +715,7 @@ const idempotencyTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -809,7 +810,7 @@ const parkUpdateTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -897,7 +898,7 @@ const rideUpdateTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -999,7 +1000,7 @@ const rideManufacturerDesignerCompositeTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1097,7 +1098,7 @@ const parkOperatorOwnerCompositeTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1188,7 +1189,7 @@ const lockConflictTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1280,7 +1281,7 @@ const bannedUserTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1373,7 +1374,7 @@ const multipleEditChainTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1478,7 +1479,7 @@ const versionSnapshotIntegrityTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1557,7 +1558,7 @@ const parkPhotoGalleryTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1639,7 +1640,7 @@ const ridePhotoGalleryTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1753,7 +1754,7 @@ const invalidTempRefTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
@@ -1852,7 +1853,7 @@ const concurrentEditTest: Test = {
|
||||
suite: 'Approval Pipeline',
|
||||
status: 'fail',
|
||||
duration: Date.now() - startTime,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
error: formatTestError(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
||||
@@ -126,7 +126,7 @@ export const performanceTestSuite: TestSuite = {
|
||||
.select('id')
|
||||
.single();
|
||||
|
||||
if (parkError) throw parkError;
|
||||
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`);
|
||||
parkId = park.id;
|
||||
tracker.track('parks', parkId);
|
||||
|
||||
@@ -214,7 +214,7 @@ export const performanceTestSuite: TestSuite = {
|
||||
|
||||
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
|
||||
const banStart = Date.now();
|
||||
@@ -225,7 +225,7 @@ export const performanceTestSuite: TestSuite = {
|
||||
|
||||
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
|
||||
const threshold = 200;
|
||||
|
||||
@@ -38,7 +38,7 @@ export const unitConversionTestSuite: TestSuite = {
|
||||
.select('id')
|
||||
.single();
|
||||
|
||||
if (parkError) throw parkError;
|
||||
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`);
|
||||
parkId = park.id;
|
||||
tracker.track('parks', parkId);
|
||||
|
||||
@@ -145,7 +145,7 @@ export const unitConversionTestSuite: TestSuite = {
|
||||
.select('id')
|
||||
.single();
|
||||
|
||||
if (parkError) throw parkError;
|
||||
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`);
|
||||
parkId = park.id;
|
||||
tracker.track('parks', parkId);
|
||||
|
||||
@@ -167,7 +167,7 @@ export const unitConversionTestSuite: TestSuite = {
|
||||
.select('id')
|
||||
.single();
|
||||
|
||||
if (rideError) throw rideError;
|
||||
if (rideError) throw new Error(`Ride creation failed: ${rideError.message}`);
|
||||
rideId = ride.id;
|
||||
tracker.track('rides', rideId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user