mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 11:31:12 -05:00
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
418 lines
14 KiB
TypeScript
418 lines
14 KiB
TypeScript
/**
|
|
* Submission Pipeline Validation Tests
|
|
*
|
|
* Tests submission creation, validation, and the full approval flow.
|
|
* All tests follow the sacred pipeline architecture.
|
|
*/
|
|
|
|
import { supabase } from '@/lib/supabaseClient';
|
|
import type { TestSuite, TestResult } from '../testRunner';
|
|
import { TestDataTracker } from '../TestDataTracker';
|
|
import { formatTestError } from '../formatTestError';
|
|
import {
|
|
generateUniqueParkData,
|
|
generateUniqueRideData,
|
|
generateUniqueCompanyData,
|
|
generateUniqueRideModelData,
|
|
createTestParkSubmission,
|
|
createTestRideSubmission,
|
|
createTestCompanySubmission,
|
|
createTestRideModelSubmission,
|
|
approveSubmission,
|
|
pollForEntity,
|
|
getAuthToken,
|
|
getCurrentUserId,
|
|
} from '../helpers/approvalTestHelpers';
|
|
|
|
export const submissionTestSuite: TestSuite = {
|
|
id: 'submission',
|
|
name: 'Entity Submission & Validation',
|
|
description: 'Tests submission creation, validation, and approval pipeline',
|
|
tests: [
|
|
{
|
|
id: 'submission-001',
|
|
name: 'Park Creation Validation',
|
|
description: 'Validates park submission and approval creates entity',
|
|
run: async (): Promise<TestResult> => {
|
|
const startTime = Date.now();
|
|
const tracker = new TestDataTracker();
|
|
|
|
try {
|
|
const userId = await getCurrentUserId();
|
|
const authToken = await getAuthToken();
|
|
const parkData = generateUniqueParkData('submission-001');
|
|
|
|
// Create submission
|
|
const { submissionId, itemId } = await createTestParkSubmission(parkData, userId, tracker);
|
|
|
|
// Verify submission was created
|
|
const { data: submission } = await supabase
|
|
.from('content_submissions')
|
|
.select('status, submission_type')
|
|
.eq('id', submissionId)
|
|
.single();
|
|
|
|
if (!submission) throw new Error('Submission not found');
|
|
if (submission.status !== 'pending') {
|
|
throw new Error(`Expected status "pending", got "${submission.status}"`);
|
|
}
|
|
if (submission.submission_type !== 'park') {
|
|
throw new Error(`Expected type "park", got "${submission.submission_type}"`);
|
|
}
|
|
|
|
// Approve submission
|
|
const approval = await approveSubmission(submissionId, [itemId], authToken);
|
|
if (!approval.success) {
|
|
throw new Error(`Approval failed: ${approval.error}`);
|
|
}
|
|
|
|
// Verify entity was created
|
|
const { data: item } = await supabase
|
|
.from('submission_items')
|
|
.select('approved_entity_id, status')
|
|
.eq('id', itemId)
|
|
.single();
|
|
|
|
if (!item?.approved_entity_id) {
|
|
throw new Error('No entity created after approval');
|
|
}
|
|
if (item.status !== 'approved') {
|
|
throw new Error(`Expected item status "approved", got "${item.status}"`);
|
|
}
|
|
|
|
tracker.track('parks', item.approved_entity_id);
|
|
|
|
// Verify park data
|
|
const park = await pollForEntity('parks', item.approved_entity_id);
|
|
if (!park) throw new Error('Park entity not found');
|
|
|
|
if (park.name !== parkData.name) {
|
|
throw new Error(`Expected name "${parkData.name}", got "${park.name}"`);
|
|
}
|
|
if (park.slug !== parkData.slug) {
|
|
throw new Error(`Expected slug "${parkData.slug}", got "${park.slug}"`);
|
|
}
|
|
|
|
const duration = Date.now() - startTime;
|
|
|
|
return {
|
|
id: 'submission-001',
|
|
name: 'Park Creation Validation',
|
|
suite: 'Entity Submission & Validation',
|
|
status: 'pass',
|
|
duration,
|
|
timestamp: new Date().toISOString(),
|
|
details: {
|
|
submissionId,
|
|
parkId: item.approved_entity_id,
|
|
validationsPassed: ['submission_created', 'approval_succeeded', 'entity_created']
|
|
}
|
|
};
|
|
|
|
} catch (error) {
|
|
return {
|
|
id: 'submission-001',
|
|
name: 'Park Creation Validation',
|
|
suite: 'Entity Submission & Validation',
|
|
status: 'fail',
|
|
duration: Date.now() - startTime,
|
|
error: formatTestError(error),
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
} finally {
|
|
await tracker.cleanup();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: 'submission-002',
|
|
name: 'Ride Creation with Dependencies',
|
|
description: 'Validates ride submission requires valid park and creates correctly',
|
|
run: async (): Promise<TestResult> => {
|
|
const startTime = Date.now();
|
|
const tracker = new TestDataTracker();
|
|
|
|
try {
|
|
const userId = await getCurrentUserId();
|
|
const authToken = await getAuthToken();
|
|
|
|
// First create and approve a park
|
|
const parkData = generateUniqueParkData('submission-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 approval failed: ${parkApproval.error}`);
|
|
}
|
|
|
|
const { data: parkItem } = await supabase
|
|
.from('submission_items')
|
|
.select('approved_entity_id')
|
|
.eq('id', parkItemId)
|
|
.single();
|
|
|
|
const parkId = parkItem?.approved_entity_id;
|
|
if (!parkId) throw new Error('Park not created');
|
|
|
|
tracker.track('parks', parkId);
|
|
|
|
// Now create ride submission
|
|
const rideData = generateUniqueRideData(parkId, 'submission-002');
|
|
const { submissionId: rideSubId, itemId: rideItemId } = await createTestRideSubmission(rideData, userId, tracker);
|
|
|
|
// Approve ride
|
|
const rideApproval = await approveSubmission(rideSubId, [rideItemId], authToken);
|
|
if (!rideApproval.success) {
|
|
throw new Error(`Ride approval failed: ${rideApproval.error}`);
|
|
}
|
|
|
|
// Verify ride created
|
|
const { data: rideItem } = await supabase
|
|
.from('submission_items')
|
|
.select('approved_entity_id')
|
|
.eq('id', rideItemId)
|
|
.single();
|
|
|
|
const rideId = rideItem?.approved_entity_id;
|
|
if (!rideId) throw new Error('Ride not created after approval');
|
|
|
|
tracker.track('rides', rideId);
|
|
|
|
// Verify ride data
|
|
const ride = await pollForEntity('rides', rideId);
|
|
if (!ride) throw new Error('Ride entity not found');
|
|
|
|
if (ride.park_id !== parkId) {
|
|
throw new Error(`Expected park_id "${parkId}", got "${ride.park_id}"`);
|
|
}
|
|
|
|
const duration = Date.now() - startTime;
|
|
|
|
return {
|
|
id: 'submission-002',
|
|
name: 'Ride Creation with Dependencies',
|
|
suite: 'Entity Submission & Validation',
|
|
status: 'pass',
|
|
duration,
|
|
timestamp: new Date().toISOString(),
|
|
details: {
|
|
parkId,
|
|
rideId,
|
|
validationsPassed: ['park_created', 'ride_created', 'dependency_valid']
|
|
}
|
|
};
|
|
|
|
} catch (error) {
|
|
return {
|
|
id: 'submission-002',
|
|
name: 'Ride Creation with Dependencies',
|
|
suite: 'Entity Submission & Validation',
|
|
status: 'fail',
|
|
duration: Date.now() - startTime,
|
|
error: formatTestError(error),
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
} finally {
|
|
await tracker.cleanup();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: 'submission-003',
|
|
name: 'Company Creation All Types',
|
|
description: 'Validates company submission for all company types',
|
|
run: async (): Promise<TestResult> => {
|
|
const startTime = Date.now();
|
|
const tracker = new TestDataTracker();
|
|
|
|
try {
|
|
const userId = await getCurrentUserId();
|
|
const authToken = await getAuthToken();
|
|
const companyTypes = ['manufacturer', 'operator', 'designer', 'property_owner'] as const;
|
|
const createdCompanies: Array<{ type: string; id: string }> = [];
|
|
|
|
for (const companyType of companyTypes) {
|
|
const companyData = generateUniqueCompanyData(companyType, `submission-003-${companyType}`);
|
|
|
|
// Create submission
|
|
const { submissionId, itemId } = await createTestCompanySubmission(
|
|
companyType,
|
|
companyData,
|
|
userId,
|
|
tracker
|
|
);
|
|
|
|
// Approve submission
|
|
const approval = await approveSubmission(submissionId, [itemId], authToken);
|
|
if (!approval.success) {
|
|
throw new Error(`${companyType} approval failed: ${approval.error}`);
|
|
}
|
|
|
|
// Verify entity created
|
|
const { data: item } = await supabase
|
|
.from('submission_items')
|
|
.select('approved_entity_id')
|
|
.eq('id', itemId)
|
|
.single();
|
|
|
|
const companyId = item?.approved_entity_id;
|
|
if (!companyId) {
|
|
throw new Error(`${companyType} not created after approval`);
|
|
}
|
|
|
|
tracker.track('companies', companyId);
|
|
|
|
// Verify company type
|
|
const company = await pollForEntity('companies', companyId);
|
|
if (!company) throw new Error(`${companyType} entity not found`);
|
|
|
|
if (company.company_type !== companyType) {
|
|
throw new Error(`Expected company_type "${companyType}", got "${company.company_type}"`);
|
|
}
|
|
|
|
createdCompanies.push({ type: companyType, id: companyId });
|
|
}
|
|
|
|
const duration = Date.now() - startTime;
|
|
|
|
return {
|
|
id: 'submission-003',
|
|
name: 'Company Creation All Types',
|
|
suite: 'Entity Submission & Validation',
|
|
status: 'pass',
|
|
duration,
|
|
timestamp: new Date().toISOString(),
|
|
details: {
|
|
companiesCreated: createdCompanies.length,
|
|
companyTypes: companyTypes,
|
|
companies: createdCompanies
|
|
}
|
|
};
|
|
|
|
} catch (error) {
|
|
return {
|
|
id: 'submission-003',
|
|
name: 'Company Creation All Types',
|
|
suite: 'Entity Submission & Validation',
|
|
status: 'fail',
|
|
duration: Date.now() - startTime,
|
|
error: formatTestError(error),
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
} finally {
|
|
await tracker.cleanup();
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: 'submission-004',
|
|
name: 'Ride Model with Images',
|
|
description: 'Validates ride model submission with image fields',
|
|
run: async (): Promise<TestResult> => {
|
|
const startTime = Date.now();
|
|
const tracker = new TestDataTracker();
|
|
|
|
try {
|
|
const userId = await getCurrentUserId();
|
|
const authToken = await getAuthToken();
|
|
|
|
// Create and approve manufacturer
|
|
const mfgData = generateUniqueCompanyData('manufacturer', 'submission-004-mfg');
|
|
const { submissionId: mfgSubId, itemId: mfgItemId } = await createTestCompanySubmission(
|
|
'manufacturer',
|
|
mfgData,
|
|
userId,
|
|
tracker
|
|
);
|
|
|
|
const mfgApproval = await approveSubmission(mfgSubId, [mfgItemId], authToken);
|
|
if (!mfgApproval.success) {
|
|
throw new Error(`Manufacturer approval failed: ${mfgApproval.error}`);
|
|
}
|
|
|
|
const { data: mfgItem } = await supabase
|
|
.from('submission_items')
|
|
.select('approved_entity_id')
|
|
.eq('id', mfgItemId)
|
|
.single();
|
|
|
|
const manufacturerId = mfgItem?.approved_entity_id;
|
|
if (!manufacturerId) throw new Error('Manufacturer not created');
|
|
|
|
tracker.track('companies', manufacturerId);
|
|
|
|
// Create ride model submission
|
|
const modelData = generateUniqueRideModelData(manufacturerId, 'submission-004');
|
|
const { submissionId, itemId } = await createTestRideModelSubmission(modelData, userId, tracker);
|
|
|
|
// Approve ride model
|
|
const approval = await approveSubmission(submissionId, [itemId], authToken);
|
|
if (!approval.success) {
|
|
throw new Error(`Ride model approval failed: ${approval.error}`);
|
|
}
|
|
|
|
// Verify entity created
|
|
const { data: item } = await supabase
|
|
.from('submission_items')
|
|
.select('approved_entity_id')
|
|
.eq('id', itemId)
|
|
.single();
|
|
|
|
const modelId = item?.approved_entity_id;
|
|
if (!modelId) throw new Error('Ride model not created after approval');
|
|
|
|
tracker.track('ride_models', modelId);
|
|
|
|
// Verify model data
|
|
const model = await pollForEntity('ride_models', modelId);
|
|
if (!model) throw new Error('Ride model entity not found');
|
|
|
|
if (model.manufacturer_id !== manufacturerId) {
|
|
throw new Error(`Expected manufacturer_id "${manufacturerId}", got "${model.manufacturer_id}"`);
|
|
}
|
|
|
|
// Verify version created
|
|
const { data: version } = await supabase
|
|
.from('ride_model_versions')
|
|
.select('version_number')
|
|
.eq('ride_model_id', modelId)
|
|
.eq('version_number', 1)
|
|
.single();
|
|
|
|
if (!version) throw new Error('Version not created for ride model');
|
|
|
|
const duration = Date.now() - startTime;
|
|
|
|
return {
|
|
id: 'submission-004',
|
|
name: 'Ride Model with Images',
|
|
suite: 'Entity Submission & Validation',
|
|
status: 'pass',
|
|
duration,
|
|
timestamp: new Date().toISOString(),
|
|
details: {
|
|
modelId,
|
|
manufacturerId,
|
|
versionCreated: true,
|
|
followedPipeline: true
|
|
}
|
|
};
|
|
|
|
} catch (error) {
|
|
return {
|
|
id: 'submission-004',
|
|
name: 'Ride Model with Images',
|
|
suite: 'Entity Submission & Validation',
|
|
status: 'fail',
|
|
duration: Date.now() - startTime,
|
|
error: formatTestError(error),
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
} finally {
|
|
await tracker.cleanup();
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|