Connect to Lovable Cloud

Apply quick wins and pipeline fixes for integration tests:
- Remove is_test_data flag from location inserts
- Increase test delay from 2.5s to 5s and add delays between suites to curb rate limiting
- Replace [object Object] error formatting with formatTestError across 10 test suites (31 edits) and add import
- Refactor unit/conversion tests and performance tests to use the approval pipeline
- Extend edge function handling by ensuring item_ids are included in idempotency key inserts (edge function fix)
- Update auth, data integrity, edgeFunction, moderation, performance, submission, unitConversion, and versioning test files accordingly
This commit is contained in:
gpt-engineer-app[bot]
2025-11-10 18:20:22 +00:00
parent 2d65f13b85
commit c5d40d07df
14 changed files with 233 additions and 129 deletions

View File

@@ -550,7 +550,6 @@ export async function createParkDirectly(
country: data.location.country, country: data.location.country,
latitude: data.location.latitude, latitude: data.location.latitude,
longitude: data.location.longitude, longitude: data.location.longitude,
is_test_data: true,
}) })
.select() .select()
.single(); .single();

View File

@@ -6,6 +6,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { formatTestError } from '../formatTestError';
export const authTestSuite: TestSuite = { export const authTestSuite: TestSuite = {
id: 'auth', id: 'auth',
@@ -64,7 +65,7 @@ export const authTestSuite: TestSuite = {
suite: 'Authentication & Authorization', suite: 'Authentication & Authorization',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -137,7 +138,7 @@ export const authTestSuite: TestSuite = {
suite: 'Authentication & Authorization', suite: 'Authentication & Authorization',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -187,7 +188,7 @@ export const authTestSuite: TestSuite = {
suite: 'Authentication & Authorization', suite: 'Authentication & Authorization',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -248,7 +249,7 @@ export const authTestSuite: TestSuite = {
suite: 'Authentication & Authorization', suite: 'Authentication & Authorization',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };

View File

@@ -7,6 +7,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { TestDataTracker } from '../TestDataTracker'; import { TestDataTracker } from '../TestDataTracker';
import { formatTestError } from '../formatTestError';
export const dataIntegrityTestSuite: TestSuite = { export const dataIntegrityTestSuite: TestSuite = {
id: 'data-integrity', id: 'data-integrity',
@@ -77,7 +78,7 @@ export const dataIntegrityTestSuite: TestSuite = {
suite: 'Data Integrity & Constraints', suite: 'Data Integrity & Constraints',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -139,7 +140,7 @@ export const dataIntegrityTestSuite: TestSuite = {
suite: 'Data Integrity & Constraints', suite: 'Data Integrity & Constraints',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -239,7 +240,7 @@ export const dataIntegrityTestSuite: TestSuite = {
suite: 'Data Integrity & Constraints', suite: 'Data Integrity & Constraints',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -305,7 +306,7 @@ export const dataIntegrityTestSuite: TestSuite = {
suite: 'Data Integrity & Constraints', suite: 'Data Integrity & Constraints',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };

View File

@@ -6,6 +6,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { formatTestError } from '../formatTestError';
export const edgeFunctionTestSuite: TestSuite = { export const edgeFunctionTestSuite: TestSuite = {
id: 'edge-functions', id: 'edge-functions',
@@ -68,7 +69,7 @@ export const edgeFunctionTestSuite: TestSuite = {
suite: 'Edge Function Tests', suite: 'Edge Function Tests',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }
@@ -121,7 +122,7 @@ export const edgeFunctionTestSuite: TestSuite = {
suite: 'Edge Function Tests', suite: 'Edge Function Tests',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }
@@ -187,7 +188,7 @@ export const edgeFunctionTestSuite: TestSuite = {
suite: 'Edge Function Tests', suite: 'Edge Function Tests',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }

View File

@@ -6,6 +6,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { formatTestError } from '../formatTestError';
export const moderationDependencyTestSuite: TestSuite = { export const moderationDependencyTestSuite: TestSuite = {
id: 'moderation-dependencies', id: 'moderation-dependencies',
@@ -102,7 +103,7 @@ export const moderationDependencyTestSuite: TestSuite = {
suite: 'Multi-Item Dependency Resolution', suite: 'Multi-Item Dependency Resolution',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }
@@ -144,7 +145,7 @@ export const moderationDependencyTestSuite: TestSuite = {
suite: 'Multi-Item Dependency Resolution', suite: 'Multi-Item Dependency Resolution',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }

View File

@@ -6,6 +6,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { formatTestError } from '../formatTestError';
export const moderationLockTestSuite: TestSuite = { export const moderationLockTestSuite: TestSuite = {
id: 'moderation-locks', id: 'moderation-locks',
@@ -97,7 +98,7 @@ export const moderationLockTestSuite: TestSuite = {
suite: 'Moderation Lock Management', suite: 'Moderation Lock Management',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }
@@ -183,7 +184,7 @@ export const moderationLockTestSuite: TestSuite = {
suite: 'Moderation Lock Management', suite: 'Moderation Lock Management',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }
@@ -284,7 +285,7 @@ export const moderationLockTestSuite: TestSuite = {
suite: 'Moderation Lock Management', suite: 'Moderation Lock Management',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }

View File

@@ -6,6 +6,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { formatTestError } from '../formatTestError';
export const moderationTestSuite: TestSuite = { export const moderationTestSuite: TestSuite = {
id: 'moderation', id: 'moderation',
@@ -53,7 +54,7 @@ export const moderationTestSuite: TestSuite = {
suite: 'Moderation Queue & Workflow', suite: 'Moderation Queue & Workflow',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }

View File

@@ -7,6 +7,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { TestDataTracker } from '../TestDataTracker'; import { TestDataTracker } from '../TestDataTracker';
import { formatTestError } from '../formatTestError';
export const performanceTestSuite: TestSuite = { export const performanceTestSuite: TestSuite = {
id: 'performance', id: 'performance',
@@ -96,7 +97,7 @@ export const performanceTestSuite: TestSuite = {
suite: 'Performance & Scalability', suite: 'Performance & Scalability',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }
@@ -112,22 +113,36 @@ export const performanceTestSuite: TestSuite = {
let parkId: string | null = null; let parkId: string | null = null;
try { try {
// Create test park // Import helpers and create park via pipeline
const parkSlug = `test-park-perf-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const {
const { data: park, error: parkError } = await supabase getCurrentUserId,
.from('parks') getAuthToken,
.insert({ generateUniqueParkData,
name: 'Test Park Performance', createTestParkSubmission,
slug: parkSlug, approveSubmission
park_type: 'theme_park', } = await import('../helpers/approvalTestHelpers');
status: 'operating',
is_test_data: true const userId = await getCurrentUserId();
}) const authToken = await getAuthToken();
.select('id') const parkData = generateUniqueParkData('perf-002');
const { submissionId, itemId } = await createTestParkSubmission(parkData, userId, tracker);
const approval = await approveSubmission(submissionId, [itemId], authToken);
if (!approval.success) {
throw new Error(`Park creation failed: ${approval.error || 'Unknown error'}`);
}
// Get park ID from submission item
const { data: parkItem } = await supabase
.from('submission_items')
.select('approved_entity_id')
.eq('id', itemId)
.single(); .single();
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`); parkId = parkItem?.approved_entity_id || null;
parkId = park.id; if (!parkId) throw new Error('No park ID after approval');
tracker.track('parks', parkId); tracker.track('parks', parkId);
// Create multiple versions (updates) // Create multiple versions (updates)
@@ -182,7 +197,7 @@ export const performanceTestSuite: TestSuite = {
suite: 'Performance & Scalability', suite: 'Performance & Scalability',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} finally { } finally {
@@ -265,7 +280,7 @@ export const performanceTestSuite: TestSuite = {
suite: 'Performance & Scalability', suite: 'Performance & Scalability',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }

View File

@@ -8,6 +8,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { TestDataTracker } from '../TestDataTracker'; import { TestDataTracker } from '../TestDataTracker';
import { formatTestError } from '../formatTestError';
import { import {
generateUniqueParkData, generateUniqueParkData,
generateUniqueRideData, generateUniqueRideData,
@@ -115,7 +116,7 @@ export const submissionTestSuite: TestSuite = {
suite: 'Entity Submission & Validation', suite: 'Entity Submission & Validation',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} finally { } finally {
@@ -208,7 +209,7 @@ export const submissionTestSuite: TestSuite = {
suite: 'Entity Submission & Validation', suite: 'Entity Submission & Validation',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} finally { } finally {
@@ -295,7 +296,7 @@ export const submissionTestSuite: TestSuite = {
suite: 'Entity Submission & Validation', suite: 'Entity Submission & Validation',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} finally { } finally {
@@ -404,7 +405,7 @@ export const submissionTestSuite: TestSuite = {
suite: 'Entity Submission & Validation', suite: 'Entity Submission & Validation',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} finally { } finally {

View File

@@ -7,6 +7,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { TestDataTracker } from '../TestDataTracker'; import { TestDataTracker } from '../TestDataTracker';
import { formatTestError } from '../formatTestError';
export const unitConversionTestSuite: TestSuite = { export const unitConversionTestSuite: TestSuite = {
id: 'unit-conversion', id: 'unit-conversion',
@@ -24,65 +25,93 @@ export const unitConversionTestSuite: TestSuite = {
let rideId: string | null = null; let rideId: string | null = null;
try { try {
// Create test park // Import helpers and create via pipeline
const parkSlug = `test-park-units-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const {
const { data: park, error: parkError } = await supabase getCurrentUserId,
.from('parks') getAuthToken,
.insert({ generateUniqueParkData,
name: 'Test Park Units', generateUniqueRideData,
slug: parkSlug, createTestParkSubmission,
park_type: 'theme_park', createTestRideSubmission,
status: 'operating', approveSubmission
is_test_data: true } = await import('../helpers/approvalTestHelpers');
})
.select('id') const userId = await getCurrentUserId();
const authToken = await getAuthToken();
// Create and approve park
const parkData = generateUniqueParkData('unit-001-park');
const { submissionId: parkSubId, itemId: parkItemId } = await createTestParkSubmission(parkData, userId, tracker);
const parkApproval = await approveSubmission(parkSubId, [parkItemId], authToken);
if (!parkApproval.success) {
throw new Error(`Park creation failed: ${parkApproval.error || 'Unknown error'}`);
}
// Get park ID from submission item
const { data: parkItem } = await supabase
.from('submission_items')
.select('approved_entity_id')
.eq('id', parkItemId)
.single(); .single();
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`); parkId = parkItem?.approved_entity_id || null;
parkId = park.id; if (!parkId) throw new Error('No park ID after approval');
tracker.track('parks', parkId); tracker.track('parks', parkId);
// Create ride with metric values // Create and approve ride with metric values
const rideSlug = `test-ride-units-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const rideData = {
const testData = { ...generateUniqueRideData(parkId, 'unit-001-ride'),
name: 'Test Ride Metric', max_speed_kmh: 100.0,
slug: rideSlug, max_height_meters: 50.0,
park_id: parkId, length_meters: 1000.0,
category: 'roller_coaster', drop_height_meters: 45.0,
status: 'operating', height_requirement: 120
max_speed_kmh: 100.0, // km/h (metric)
max_height_meters: 50.0, // meters (metric)
length_meters: 1000.0, // meters (metric)
drop_height_meters: 45.0, // meters (metric)
height_requirement: 120 // cm (metric)
}; };
const { data: ride, error: rideError } = await supabase const { submissionId: rideSubId, itemId: rideItemId } = await createTestRideSubmission(rideData, userId, tracker);
.from('rides') const rideApproval = await approveSubmission(rideSubId, [rideItemId], authToken);
.insert({ ...testData, is_test_data: true })
.select('id, max_speed_kmh, max_height_meters, length_meters, drop_height_meters, height_requirement') if (!rideApproval.success) {
throw new Error(`Ride creation failed: ${rideApproval.error || 'Unknown error'}`);
}
// Get ride ID from submission item
const { data: rideItem } = await supabase
.from('submission_items')
.select('approved_entity_id')
.eq('id', rideItemId)
.single(); .single();
if (rideError) throw new Error(`Ride creation failed: ${rideError.message}`); rideId = rideItem?.approved_entity_id || null;
if (!ride) throw new Error('Ride not returned'); if (!rideId) throw new Error('No ride ID after approval');
rideId = ride.id;
tracker.track('rides', rideId); tracker.track('rides', rideId);
// Validate values are stored in metric // Fetch ride data for validation
const tolerance = 0.01; // Allow small floating point differences const { data: ride, error: rideError } = await supabase
.from('rides')
.select('id, max_speed_kmh, max_height_meters, length_meters, drop_height_meters, height_requirement')
.eq('id', rideId)
.single();
if (Math.abs((ride.max_speed_kmh ?? 0) - testData.max_speed_kmh) > tolerance) { if (rideError || !ride) throw new Error('Ride not found after creation');
throw new Error(`max_speed_kmh mismatch: expected ${testData.max_speed_kmh}, got ${ride.max_speed_kmh}`);
// Validate values are stored in metric
const tolerance = 0.01;
if (Math.abs((ride.max_speed_kmh ?? 0) - 100.0) > tolerance) {
throw new Error(`max_speed_kmh mismatch: expected 100.0, got ${ride.max_speed_kmh}`);
} }
if (Math.abs((ride.max_height_meters ?? 0) - testData.max_height_meters) > tolerance) { if (Math.abs((ride.max_height_meters ?? 0) - 50.0) > tolerance) {
throw new Error(`max_height_meters mismatch: expected ${testData.max_height_meters}, got ${ride.max_height_meters}`); throw new Error(`max_height_meters mismatch: expected 50.0, got ${ride.max_height_meters}`);
} }
if (Math.abs((ride.length_meters ?? 0) - testData.length_meters) > tolerance) { if (Math.abs((ride.length_meters ?? 0) - 1000.0) > tolerance) {
throw new Error(`length_meters mismatch: expected ${testData.length_meters}, got ${ride.length_meters}`); throw new Error(`length_meters mismatch: expected 1000.0, got ${ride.length_meters}`);
} }
if (Math.abs((ride.height_requirement ?? 0) - testData.height_requirement) > tolerance) { if (Math.abs((ride.height_requirement ?? 0) - 120) > tolerance) {
throw new Error(`height_requirement mismatch: expected ${testData.height_requirement} cm, got ${ride.height_requirement}`); throw new Error(`height_requirement mismatch: expected 120 cm, got ${ride.height_requirement}`);
} }
const duration = Date.now() - startTime; const duration = Date.now() - startTime;
@@ -108,7 +137,7 @@ export const unitConversionTestSuite: TestSuite = {
suite: 'Unit Conversion Tests', suite: 'Unit Conversion Tests',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} finally { } finally {
@@ -131,44 +160,66 @@ export const unitConversionTestSuite: TestSuite = {
let rideId: string | null = null; let rideId: string | null = null;
try { try {
// Create test park // Import helpers and create via pipeline
const parkSlug = `test-park-ver-units-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const {
const { data: park, error: parkError } = await supabase getCurrentUserId,
.from('parks') getAuthToken,
.insert({ generateUniqueParkData,
name: 'Test Park Version Units', generateUniqueRideData,
slug: parkSlug, createTestParkSubmission,
park_type: 'theme_park', createTestRideSubmission,
status: 'operating', approveSubmission
is_test_data: true } = await import('../helpers/approvalTestHelpers');
})
.select('id') const userId = await getCurrentUserId();
const authToken = await getAuthToken();
// Create and approve park
const parkData = generateUniqueParkData('unit-002-park');
const { submissionId: parkSubId, itemId: parkItemId } = await createTestParkSubmission(parkData, userId, tracker);
const parkApproval = await approveSubmission(parkSubId, [parkItemId], authToken);
if (!parkApproval.success) {
throw new Error(`Park creation failed: ${parkApproval.error || 'Unknown error'}`);
}
// Get park ID from submission item
const { data: parkItem } = await supabase
.from('submission_items')
.select('approved_entity_id')
.eq('id', parkItemId)
.single(); .single();
if (parkError) throw new Error(`Park creation failed: ${parkError.message}`); parkId = parkItem?.approved_entity_id || null;
parkId = park.id; if (!parkId) throw new Error('No park ID after approval');
tracker.track('parks', parkId); tracker.track('parks', parkId);
// Create ride with metric values // Create and approve ride with metric values
const rideSlug = `test-ride-ver-units-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const rideData = {
const { data: ride, error: rideError } = await supabase ...generateUniqueRideData(parkId, 'unit-002-ride'),
.from('rides')
.insert({
name: 'Test Ride Version Metric',
slug: rideSlug,
park_id: parkId,
category: 'roller_coaster',
status: 'operating',
max_speed_kmh: 120.0, max_speed_kmh: 120.0,
max_height_meters: 60.0, max_height_meters: 60.0,
height_requirement: 140, height_requirement: 140
is_test_data: true };
})
.select('id') const { submissionId: rideSubId, itemId: rideItemId } = await createTestRideSubmission(rideData, userId, tracker);
const rideApproval = await approveSubmission(rideSubId, [rideItemId], authToken);
if (!rideApproval.success) {
throw new Error(`Ride creation failed: ${rideApproval.error || 'Unknown error'}`);
}
// Get ride ID from submission item
const { data: rideItem } = await supabase
.from('submission_items')
.select('approved_entity_id')
.eq('id', rideItemId)
.single(); .single();
if (rideError) throw new Error(`Ride creation failed: ${rideError.message}`); rideId = rideItem?.approved_entity_id || null;
rideId = ride.id; if (!rideId) throw new Error('No ride ID after approval');
tracker.track('rides', rideId); tracker.track('rides', rideId);
// Poll for version creation // Poll for version creation
@@ -226,7 +277,7 @@ export const unitConversionTestSuite: TestSuite = {
suite: 'Unit Conversion Tests', suite: 'Unit Conversion Tests',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} finally { } finally {
@@ -307,7 +358,7 @@ export const unitConversionTestSuite: TestSuite = {
suite: 'Unit Conversion Tests', suite: 'Unit Conversion Tests',
status: 'fail', status: 'fail',
duration: Date.now() - startTime, duration: Date.now() - startTime,
error: error instanceof Error ? error.message : String(error), error: formatTestError(error),
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
}; };
} }

View File

@@ -10,6 +10,7 @@
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import type { TestSuite, TestResult } from '../testRunner'; import type { TestSuite, TestResult } from '../testRunner';
import { TestDataTracker } from '../TestDataTracker'; import { TestDataTracker } from '../TestDataTracker';
import { formatTestError } from '../formatTestError';
import { import {
generateUniqueParkData, generateUniqueParkData,
createTestParkSubmission, createTestParkSubmission,
@@ -106,7 +107,7 @@ export const versioningTestSuite: TestSuite = {
suite: 'Versioning & Rollback', suite: 'Versioning & Rollback',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -211,7 +212,7 @@ export const versioningTestSuite: TestSuite = {
suite: 'Versioning & Rollback', suite: 'Versioning & Rollback',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -304,7 +305,7 @@ export const versioningTestSuite: TestSuite = {
suite: 'Versioning & Rollback', suite: 'Versioning & Rollback',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };
@@ -441,7 +442,7 @@ export const versioningTestSuite: TestSuite = {
suite: 'Versioning & Rollback', suite: 'Versioning & Rollback',
status: 'fail', status: 'fail',
duration, duration,
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()
}; };

View File

@@ -53,9 +53,9 @@ export class IntegrationTestRunner {
private onProgress?: (result: TestResult) => void; private onProgress?: (result: TestResult) => void;
private delayBetweenTests: number; private delayBetweenTests: number;
constructor(onProgress?: (result: TestResult) => void, delayBetweenTests: number = 2500) { constructor(onProgress?: (result: TestResult) => void, delayBetweenTests: number = 5000) {
this.onProgress = onProgress; this.onProgress = onProgress;
this.delayBetweenTests = delayBetweenTests; // Default 2.5 seconds to prevent rate limiting this.delayBetweenTests = delayBetweenTests; // Default 5 seconds to prevent rate limiting
} }
/** /**
@@ -189,12 +189,41 @@ export class IntegrationTestRunner {
this.isRunning = true; this.isRunning = true;
this.shouldStop = false; this.shouldStop = false;
for (const suite of suites) { for (let i = 0; i < suites.length; i++) {
await this.runSuite(suite); await this.runSuite(suites[i]);
if (this.shouldStop) { if (this.shouldStop) {
break; break;
} }
// Add delay between suites to prevent rate limiting
if (i < suites.length - 1 && this.delayBetweenTests > 0) {
const delaySeconds = this.delayBetweenTests / 1000;
const delayResult: TestResult = {
id: `suite-delay-${Date.now()}`,
name: `⏳ Suite completion delay: ${delaySeconds}s`,
suite: 'System',
status: 'running',
duration: 0,
timestamp: new Date().toISOString(),
details: { reason: 'Pausing between suites to prevent rate limiting' }
};
if (this.onProgress) {
this.onProgress(delayResult);
}
await this.delay(this.delayBetweenTests);
if (this.onProgress) {
this.onProgress({
...delayResult,
status: 'skip',
duration: this.delayBetweenTests,
details: { reason: 'Suite delay completed' }
});
}
}
} }
this.isRunning = false; this.isRunning = false;

View File

@@ -259,6 +259,7 @@ const handler = async (req: Request) => {
idempotency_key: idempotencyKey, idempotency_key: idempotencyKey,
submission_id: submissionId, submission_id: submissionId,
moderator_id: user.id, moderator_id: user.id,
item_ids: itemIds,
status: 'processing' status: 'processing'
}) })
.select() .select()

View File

@@ -262,6 +262,7 @@ const handler = async (req: Request) => {
idempotency_key: idempotencyKey, idempotency_key: idempotencyKey,
submission_id: submissionId, submission_id: submissionId,
moderator_id: user.id, moderator_id: user.id,
item_ids: itemIds,
status: 'processing' status: 'processing'
}) })
.select() .select()