diff --git a/src/lib/testDataGenerator.ts b/src/lib/testDataGenerator.ts index bcd0d49f..41088a4c 100644 --- a/src/lib/testDataGenerator.ts +++ b/src/lib/testDataGenerator.ts @@ -1,6 +1,23 @@ import { supabase } from '@/lib/supabaseClient'; import type { ParkSubmissionData, RideSubmissionData, CompanySubmissionData, RideModelSubmissionData } from '@/types/submission-data'; import { logger } from './logger'; +import { + randomInt, + randomFloat, + randomItem, + randomDate, + randomDatePrecision, + shouldPopulateField, + generateWaterRideFields, + generateDarkRideFields, + generateFlatRideFields, + generateKiddieRideFields, + generateTransportationRideFields, + generateRideMaterials, + generateSourceUrl, + generateSubmissionNotes, + type FieldDensity +} from './testDataGeneratorHelpers'; // Preset configurations export const PRESETS = { @@ -21,26 +38,6 @@ const COMPANY_SUFFIXES = ['Industries', 'Manufacturing', 'Enterprises', 'Solutio const CITIES = ['New York', 'Los Angeles', 'Chicago', 'London', 'Paris', 'Tokyo', 'Sydney', 'Toronto', 'Berlin', 'Madrid']; const COUNTRIES = ['USA', 'UK', 'France', 'Japan', 'Australia', 'Canada', 'Germany', 'Spain', 'Italy', 'Netherlands']; -// Helper functions -function randomItem(array: T[]): T { - return array[Math.floor(Math.random() * array.length)]; -} - -function randomInt(min: number, max: number): number { - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -function randomFloat(min: number, max: number, decimals = 2): number { - return parseFloat((Math.random() * (max - min) + min).toFixed(decimals)); -} - -function randomDate(startYear: number, endYear: number): string { - const start = new Date(startYear, 0, 1); - const end = new Date(endYear, 11, 31); - const date = new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())); - return date.toISOString().split('T')[0]; -} - function generateSlug(name: string, counter?: number): string { let slug = name .toLowerCase() @@ -107,18 +104,20 @@ export class TestDataContext { } // Random data generators -export function generateRandomPark(counter: number): ParkSubmissionData { +export function generateRandomPark(counter: number, density: FieldDensity = 'mixed'): ParkSubmissionData { const name = `${randomItem(PARK_ADJECTIVES)} ${randomItem(PARK_NOUNS)}`; const slug = generateSlug(name, counter); + const openingDate = randomDate(1950, 2024); + const status = randomItem(['operating', 'operating', 'operating', 'seasonal']); // More likely to be operating - return { + const parkData: ParkSubmissionData = { name, slug, description: `A thrilling amusement park featuring world-class attractions and entertainment.`, park_type: randomItem(['theme_park', 'amusement_park', 'water_park', 'adventure_park']), - status: randomItem(['operating', 'operating', 'operating', 'seasonal']), // More likely to be operating - opening_date: randomDate(1950, 2024), - closing_date: Math.random() > 0.9 ? randomDate(2000, 2024) : null, + status, + opening_date: openingDate, + opening_date_precision: randomDatePrecision(), website_url: `https://${slug}.example.com`, phone: `+1-555-${randomInt(100, 999)}-${randomInt(1000, 9999)}`, email: `info@${slug}.example.com`, @@ -131,25 +130,48 @@ export function generateRandomPark(counter: number): ParkSubmissionData { card_image_id: null, is_test_data: true }; + + // Add closing date for closed/seasonal parks + if ((status === 'closed' || status === 'seasonal') && shouldPopulateField(density, counter, 'high')) { + const openYear = parseInt(openingDate.split('-')[0]); + parkData.closing_date = randomDate(openYear + 5, 2024); + parkData.closing_date_precision = randomDatePrecision(); + } + + // Add source URL + if (shouldPopulateField(density, counter, 'low')) { + parkData.source_url = generateSourceUrl('park', counter); + } + + // Add submission notes + const notes = generateSubmissionNotes(density, counter, 'park'); + if (notes) { + parkData.submission_notes = notes; + } + + return parkData; } -export function generateRandomRide(parkId: string, counter: number): RideSubmissionData { +export function generateRandomRide(parkId: string, counter: number, density: FieldDensity = 'mixed'): RideSubmissionData { const name = `${randomItem(RIDE_PREFIXES)} ${randomItem(RIDE_TYPES)}`; const slug = generateSlug(name, counter); - const category = randomItem(['roller_coaster', 'flat_ride', 'water_ride', 'dark_ride', 'family_ride']); + const category = randomItem(['roller_coaster', 'flat_ride', 'water_ride', 'dark_ride', 'family_ride', 'transport_ride', 'kiddie_ride']); + const openingDate = randomDate(1980, 2024); + const status = randomItem(['operating', 'operating', 'operating', 'seasonal']); - return { + const rideData: RideSubmissionData = { name, slug, description: `An exciting ${category.replace('_', ' ')} experience for all ages.`, category, ride_sub_type: null, - status: randomItem(['operating', 'operating', 'operating', 'seasonal']), + status, park_id: parkId, ride_model_id: null, manufacturer_id: null, designer_id: null, - opening_date: randomDate(1980, 2024), + opening_date: openingDate, + opening_date_precision: randomDatePrecision(), closing_date: Math.random() > 0.95 ? randomDate(2010, 2024) : null, height_requirement: randomInt(90, 140), age_requirement: null, @@ -171,19 +193,57 @@ export function generateRandomRide(parkId: string, counter: number): RideSubmiss image_url: null, is_test_data: true }; + + // Add closing date precision if closing date exists + if (rideData.closing_date && shouldPopulateField(density, counter, 'medium')) { + rideData.closing_date_precision = randomDatePrecision(); + } + + // Add material arrays for appropriate rides + if (category === 'roller_coaster' && shouldPopulateField(density, counter, 'medium')) { + const materials = generateRideMaterials(category); + Object.assign(rideData, materials); + } + + // Add category-specific fields + if (category === 'water_ride') { + Object.assign(rideData, generateWaterRideFields(density, counter)); + } else if (category === 'dark_ride') { + Object.assign(rideData, generateDarkRideFields(density, counter)); + } else if (category === 'flat_ride') { + Object.assign(rideData, generateFlatRideFields(density, counter)); + } else if (category === 'kiddie_ride') { + Object.assign(rideData, generateKiddieRideFields(density, counter)); + } else if (category === 'transport_ride') { + Object.assign(rideData, generateTransportationRideFields(density, counter)); + } + + // Add source URL + if (shouldPopulateField(density, counter, 'low')) { + rideData.source_url = generateSourceUrl('ride', counter); + } + + // Add submission notes + const notes = generateSubmissionNotes(density, counter, 'ride'); + if (notes) { + rideData.submission_notes = notes; + } + + return rideData; } -export function generateRandomCompany(type: 'manufacturer' | 'operator' | 'designer' | 'property_owner', counter: number): CompanySubmissionData { +export function generateRandomCompany(type: 'manufacturer' | 'operator' | 'designer' | 'property_owner', counter: number, density: FieldDensity = 'mixed'): CompanySubmissionData { const name = `${randomItem(COMPANY_PREFIXES)} ${randomItem(COMPANY_SUFFIXES)}`; const slug = generateSlug(name, counter); + const foundedYear = randomInt(1950, 2020); - return { + const companyData: CompanySubmissionData = { name, slug, company_type: type, description: `A leading ${type.replace('_', ' ')} in the amusement industry.`, person_type: Math.random() > 0.9 ? 'individual' : 'company', - founded_year: randomInt(1950, 2020), + founded_year: foundedYear, headquarters_location: `${randomItem(CITIES)}, ${randomItem(COUNTRIES)}`, website_url: `https://${slug}.example.com`, logo_url: null, @@ -193,14 +253,40 @@ export function generateRandomCompany(type: 'manufacturer' | 'operator' | 'desig card_image_id: null, is_test_data: true }; + + // Add full founded date with precision + if (shouldPopulateField(density, counter, 'medium')) { + companyData.founded_date = `${foundedYear}-01-01`; + companyData.founded_date_precision = randomItem(['year', 'month', 'day']); + } + + // Add defunct date for some companies + if (shouldPopulateField(density, counter, 'low') && Math.random() > 0.85) { + const defunctYear = randomInt(foundedYear + 10, 2024); + companyData.defunct_date = `${defunctYear}-12-31`; + companyData.defunct_date_precision = randomItem(['year', 'month', 'day']); + } + + // Add source URL + if (shouldPopulateField(density, counter, 'low')) { + companyData.source_url = generateSourceUrl('company', counter); + } + + // Add submission notes + const notes = generateSubmissionNotes(density, counter, 'company'); + if (notes) { + companyData.submission_notes = notes; + } + + return companyData; } -export function generateRandomRideModel(manufacturerId: string, counter: number): RideModelSubmissionData { +export function generateRandomRideModel(manufacturerId: string, counter: number, density: FieldDensity = 'mixed'): RideModelSubmissionData { const name = `${randomItem(RIDE_PREFIXES)} Model ${randomInt(100, 999)}`; const slug = generateSlug(name, counter); const category = randomItem(['roller_coaster', 'flat_ride', 'water_ride', 'dark_ride']); - return { + const modelData: RideModelSubmissionData = { name, slug, manufacturer_id: manufacturerId, @@ -213,6 +299,19 @@ export function generateRandomRideModel(manufacturerId: string, counter: number) card_image_id: null, is_test_data: true }; + + // Add source URL + if (shouldPopulateField(density, counter, 'low')) { + modelData.source_url = generateSourceUrl('ride-model', counter); + } + + // Add submission notes + const notes = generateSubmissionNotes(density, counter, 'ride model'); + if (notes) { + modelData.submission_notes = notes; + } + + return modelData; } // Cleanup utilities diff --git a/src/lib/testDataGeneratorHelpers.ts b/src/lib/testDataGeneratorHelpers.ts new file mode 100644 index 00000000..f1ce6e77 --- /dev/null +++ b/src/lib/testDataGeneratorHelpers.ts @@ -0,0 +1,191 @@ +/** + * Test Data Generator Helpers + * + * Reusable utilities for generating category-specific fields and managing field density. + */ + +// ============================================================================ +// Field Density Logic +// ============================================================================ + +export type FieldDensity = 'minimal' | 'standard' | 'maximum' | 'mixed'; +export type FieldImportance = 'low' | 'medium' | 'high'; + +/** + * Determine if a field should be populated based on density and importance + */ +export function shouldPopulateField( + density: FieldDensity, + index: number, + fieldImportance: FieldImportance +): boolean { + const rand = Math.random(); + + if (density === 'minimal') { + return fieldImportance === 'high' ? rand < 0.5 : rand < 0.1; + } else if (density === 'standard') { + return fieldImportance === 'high' ? rand < 0.8 : rand < 0.5; + } else if (density === 'maximum') { + return rand < 0.95; // Almost everything + } else if (density === 'mixed') { + // Vary by entity index + if (index % 3 === 0) return shouldPopulateField('minimal', index, fieldImportance); + if (index % 3 === 1) return shouldPopulateField('standard', index, fieldImportance); + return shouldPopulateField('maximum', index, fieldImportance); + } + + return false; +} + +// ============================================================================ +// Random Data Generators +// ============================================================================ + +export function randomInt(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +export function randomFloat(min: number, max: number, decimals = 2): number { + const value = Math.random() * (max - min) + min; + return parseFloat(value.toFixed(decimals)); +} + +export function randomItem(array: T[]): T { + return array[randomInt(0, array.length - 1)]; +} + +export function randomDate(startYear: number, endYear: number): string { + const year = randomInt(startYear, endYear); + const month = randomInt(1, 12); + const day = randomInt(1, 28); + return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; +} + +export function randomDatePrecision(): 'day' | 'month' | 'year' { + return randomItem(['day', 'month', 'year']); +} + +// ============================================================================ +// Category-Specific Field Generators +// ============================================================================ + +/** + * Generate water ride specific fields + */ +export function generateWaterRideFields(density: FieldDensity, index: number) { + if (!shouldPopulateField(density, index, 'medium')) return {}; + + return { + water_depth_cm: randomInt(30, 300), + splash_height_meters: randomFloat(1, 20, 1), + wetness_level: randomItem(['dry', 'light', 'moderate', 'soaked']), + flume_type: randomItem(['log', 'tube', 'raft', 'boat']), + boat_capacity: randomInt(2, 20) + }; +} + +/** + * Generate dark ride specific fields + */ +export function generateDarkRideFields(density: FieldDensity, index: number) { + if (!shouldPopulateField(density, index, 'medium')) return {}; + + return { + theme_name: randomItem(['Space Adventure', 'Haunted Mansion', 'Underwater Journey', 'Fantasy Quest']), + story_description: 'An immersive journey through a themed environment with exciting scenes.', + show_duration_seconds: randomInt(180, 600), + animatronics_count: randomInt(5, 50), + projection_type: randomItem(['2d', '3d', 'holographic', 'mixed']), + ride_system: randomItem(['omnimover', 'tracked', 'trackless', 'boat']), + scenes_count: randomInt(5, 20) + }; +} + +/** + * Generate flat ride specific fields + */ +export function generateFlatRideFields(density: FieldDensity, index: number) { + if (!shouldPopulateField(density, index, 'medium')) return {}; + + return { + rotation_type: randomItem(['horizontal', 'vertical', 'both', 'none']), + motion_pattern: randomItem(['circular', 'pendulum', 'spinning', 'wave', 'random']), + platform_count: randomInt(1, 8), + swing_angle_degrees: randomInt(45, 180), + rotation_speed_rpm: randomInt(5, 30), + arm_length_meters: randomFloat(5, 25, 1), + max_height_reached_meters: randomFloat(10, 80, 1) + }; +} + +/** + * Generate kiddie ride specific fields + */ +export function generateKiddieRideFields(density: FieldDensity, index: number) { + if (!shouldPopulateField(density, index, 'medium')) return {}; + + return { + min_age: randomInt(2, 5), + max_age: randomInt(8, 12), + educational_theme: randomItem(['counting', 'colors', 'animals', 'shapes', 'letters']), + character_theme: randomItem(['dinosaurs', 'princesses', 'superheroes', 'animals', 'vehicles']) + }; +} + +/** + * Generate transportation ride specific fields + */ +export function generateTransportationRideFields(density: FieldDensity, index: number) { + if (!shouldPopulateField(density, index, 'medium')) return {}; + + return { + transport_type: randomItem(['monorail', 'train', 'skyway', 'gondola', 'ferry']), + route_length_meters: randomInt(500, 5000), + stations_count: randomInt(2, 8), + vehicle_capacity: randomInt(20, 200), + vehicles_count: randomInt(2, 12), + round_trip_duration_seconds: randomInt(300, 1800) + }; +} + +/** + * Generate material arrays for rides + */ +export function generateRideMaterials(category: string) { + if (category === 'roller_coaster') { + return { + track_material: [randomItem(['steel', 'wood', 'hybrid'])], + support_material: [randomItem(['steel', 'wood', 'concrete'])], + propulsion_method: [randomItem(['chain_lift', 'cable_lift', 'launch', 'gravity', 'tire_drive'])] + }; + } + return {}; +} + +/** + * Generate source URL for testing + */ +export function generateSourceUrl(entityType: string, index: number): string { + return `https://example.com/source/${entityType}/${index + 1}`; +} + +/** + * Generate submission notes based on field density + */ +export function generateSubmissionNotes( + density: FieldDensity, + index: number, + entityType: string +): string | undefined { + if (!shouldPopulateField(density, index, 'low')) return undefined; + + const notes = [ + `Updated ${entityType} information from official source`, + `Added comprehensive data for testing purposes`, + `Verified information through multiple sources`, + `Historical data added for completeness`, + `Technical specifications verified with manufacturer` + ]; + + return randomItem(notes); +} diff --git a/src/types/submission-data.ts b/src/types/submission-data.ts index e1a0ebea..24dfa389 100644 --- a/src/types/submission-data.ts +++ b/src/types/submission-data.ts @@ -113,6 +113,8 @@ export interface CompanySubmissionData { founded_year?: number | null; // Legacy field founded_date?: string | null; founded_date_precision?: string | null; + defunct_date?: string | null; + defunct_date_precision?: string | null; headquarters_location?: string | null; website_url?: string | null; logo_url?: string | null; diff --git a/tests/fixtures/test-data.ts b/tests/fixtures/test-data.ts index fa724fd4..89d7fa8d 100644 --- a/tests/fixtures/test-data.ts +++ b/tests/fixtures/test-data.ts @@ -17,6 +17,11 @@ export interface ParkTestData { latitude: number; longitude: number; opened_date: string; + opening_date_precision?: string; + closing_date?: string; + closing_date_precision?: string; + source_url?: string; + submission_notes?: string; is_test_data: boolean; } @@ -28,7 +33,45 @@ export interface RideTestData { status: string; park_id: string; opened_date: string; + opening_date_precision?: string; + closing_date?: string; + closing_date_precision?: string; + track_material?: string[]; + support_material?: string[]; + propulsion_method?: string[]; + source_url?: string; + submission_notes?: string; is_test_data: boolean; + // Category-specific fields (optional) + water_depth_cm?: number; + splash_height_meters?: number; + wetness_level?: string; + flume_type?: string; + boat_capacity?: number; + theme_name?: string; + story_description?: string; + show_duration_seconds?: number; + animatronics_count?: number; + projection_type?: string; + ride_system?: string; + scenes_count?: number; + rotation_type?: string; + motion_pattern?: string; + platform_count?: number; + swing_angle_degrees?: number; + rotation_speed_rpm?: number; + arm_length_meters?: number; + max_height_reached_meters?: number; + min_age?: number; + max_age?: number; + educational_theme?: string; + character_theme?: string; + transport_type?: string; + route_length_meters?: number; + stations_count?: number; + vehicle_capacity?: number; + vehicles_count?: number; + round_trip_duration_seconds?: number; } export interface CompanyTestData { @@ -38,6 +81,11 @@ export interface CompanyTestData { company_type: string; person_type: string; founded_date: string; + founded_date_precision?: string; + defunct_date?: string; + defunct_date_precision?: string; + source_url?: string; + submission_notes?: string; is_test_data: boolean; } @@ -47,6 +95,8 @@ export interface RideModelTestData { description: string; category: string; manufacturer_id: string; + source_url?: string; + submission_notes?: string; is_test_data: boolean; } @@ -55,21 +105,40 @@ export interface RideModelTestData { */ export function generateParkData(overrides?: Partial): ParkTestData { const name = faker.company.name() + ' Park'; + const openedDate = faker.date.past({ years: 50 }).toISOString().split('T')[0]; + const status = faker.helpers.arrayElement(['operating', 'closed', 'under_construction']); - return { + const data: ParkTestData = { name, slug: faker.helpers.slugify(name).toLowerCase(), description: faker.lorem.paragraphs(2), park_type: faker.helpers.arrayElement(['theme_park', 'amusement_park', 'water_park']), - status: faker.helpers.arrayElement(['operating', 'closed', 'under_construction']), + status, location_country: faker.location.countryCode(), location_city: faker.location.city(), latitude: parseFloat(faker.location.latitude()), longitude: parseFloat(faker.location.longitude()), - opened_date: faker.date.past({ years: 50 }).toISOString().split('T')[0], + opened_date: openedDate, + opening_date_precision: faker.helpers.arrayElement(['day', 'month', 'year']), is_test_data: true, - ...overrides, }; + + // Add closing date for closed parks + if (status === 'closed') { + data.closing_date = faker.date.between({ from: openedDate, to: new Date() }).toISOString().split('T')[0]; + data.closing_date_precision = faker.helpers.arrayElement(['day', 'month', 'year']); + } + + // Add optional fields + if (faker.datatype.boolean()) { + data.source_url = faker.internet.url(); + } + + if (faker.datatype.boolean()) { + data.submission_notes = faker.lorem.sentence(); + } + + return { ...data, ...overrides }; } /** @@ -77,18 +146,74 @@ export function generateParkData(overrides?: Partial): ParkTestDat */ export function generateRideData(parkId: string, overrides?: Partial): RideTestData { const name = faker.word.adjective() + ' ' + faker.word.noun(); + const openedDate = faker.date.past({ years: 30 }).toISOString().split('T')[0]; + const status = faker.helpers.arrayElement(['operating', 'closed', 'sbno']); + const category = faker.helpers.arrayElement(['roller_coaster', 'flat_ride', 'water_ride', 'dark_ride']); - return { + const data: RideTestData = { name, slug: faker.helpers.slugify(name).toLowerCase(), description: faker.lorem.paragraphs(2), - category: faker.helpers.arrayElement(['roller_coaster', 'flat_ride', 'water_ride', 'dark_ride']), - status: faker.helpers.arrayElement(['operating', 'closed', 'sbno']), + category, + status, park_id: parkId, - opened_date: faker.date.past({ years: 30 }).toISOString().split('T')[0], + opened_date: openedDate, + opening_date_precision: faker.helpers.arrayElement(['day', 'month', 'year']), is_test_data: true, - ...overrides, }; + + // Add closing date for closed rides + if (status === 'closed') { + data.closing_date = faker.date.between({ from: openedDate, to: new Date() }).toISOString().split('T')[0]; + data.closing_date_precision = faker.helpers.arrayElement(['day', 'month', 'year']); + } + + // Add material arrays for roller coasters + if (category === 'roller_coaster' && faker.datatype.boolean()) { + data.track_material = [faker.helpers.arrayElement(['steel', 'wood', 'hybrid'])]; + data.support_material = [faker.helpers.arrayElement(['steel', 'wood', 'concrete'])]; + data.propulsion_method = [faker.helpers.arrayElement(['chain_lift', 'cable_lift', 'launch', 'gravity'])]; + } + + // Add category-specific fields + if (category === 'water_ride' && faker.datatype.boolean()) { + data.water_depth_cm = faker.number.int({ min: 30, max: 300 }); + data.splash_height_meters = faker.number.float({ min: 1, max: 20, fractionDigits: 1 }); + data.wetness_level = faker.helpers.arrayElement(['dry', 'light', 'moderate', 'soaked']); + data.flume_type = faker.helpers.arrayElement(['log', 'tube', 'raft', 'boat']); + data.boat_capacity = faker.number.int({ min: 2, max: 20 }); + } + + if (category === 'dark_ride' && faker.datatype.boolean()) { + data.theme_name = faker.lorem.words(2); + data.story_description = faker.lorem.sentence(); + data.show_duration_seconds = faker.number.int({ min: 180, max: 600 }); + data.animatronics_count = faker.number.int({ min: 5, max: 50 }); + data.projection_type = faker.helpers.arrayElement(['2d', '3d', 'holographic', 'mixed']); + data.ride_system = faker.helpers.arrayElement(['omnimover', 'tracked', 'trackless', 'boat']); + data.scenes_count = faker.number.int({ min: 5, max: 20 }); + } + + if (category === 'flat_ride' && faker.datatype.boolean()) { + data.rotation_type = faker.helpers.arrayElement(['horizontal', 'vertical', 'both', 'none']); + data.motion_pattern = faker.helpers.arrayElement(['circular', 'pendulum', 'spinning', 'wave']); + data.platform_count = faker.number.int({ min: 1, max: 8 }); + data.swing_angle_degrees = faker.number.int({ min: 45, max: 180 }); + data.rotation_speed_rpm = faker.number.int({ min: 5, max: 30 }); + data.arm_length_meters = faker.number.float({ min: 5, max: 25, fractionDigits: 1 }); + data.max_height_reached_meters = faker.number.float({ min: 10, max: 80, fractionDigits: 1 }); + } + + // Add optional fields + if (faker.datatype.boolean()) { + data.source_url = faker.internet.url(); + } + + if (faker.datatype.boolean()) { + data.submission_notes = faker.lorem.sentence(); + } + + return { ...data, ...overrides }; } /** @@ -99,17 +224,35 @@ export function generateCompanyData( overrides?: Partial ): CompanyTestData { const name = faker.company.name(); + const foundedDate = faker.date.past({ years: 100 }).toISOString().split('T')[0]; - return { + const data: CompanyTestData = { name, slug: faker.helpers.slugify(name).toLowerCase(), description: faker.lorem.paragraphs(2), company_type: companyType, person_type: faker.helpers.arrayElement(['individual', 'company']), - founded_date: faker.date.past({ years: 100 }).toISOString().split('T')[0], + founded_date: foundedDate, + founded_date_precision: faker.helpers.arrayElement(['day', 'month', 'year']), is_test_data: true, - ...overrides, }; + + // Add defunct date for some companies + if (faker.datatype.boolean(0.15)) { + data.defunct_date = faker.date.between({ from: foundedDate, to: new Date() }).toISOString().split('T')[0]; + data.defunct_date_precision = faker.helpers.arrayElement(['day', 'month', 'year']); + } + + // Add optional fields + if (faker.datatype.boolean()) { + data.source_url = faker.internet.url(); + } + + if (faker.datatype.boolean()) { + data.submission_notes = faker.lorem.sentence(); + } + + return { ...data, ...overrides }; } /** @@ -121,15 +264,25 @@ export function generateRideModelData( ): RideModelTestData { const name = faker.word.adjective() + ' Model'; - return { + const data: RideModelTestData = { name, slug: faker.helpers.slugify(name).toLowerCase(), description: faker.lorem.paragraphs(2), category: faker.helpers.arrayElement(['roller_coaster', 'flat_ride', 'water_ride']), manufacturer_id: manufacturerId, is_test_data: true, - ...overrides, }; + + // Add optional fields + if (faker.datatype.boolean()) { + data.source_url = faker.internet.url(); + } + + if (faker.datatype.boolean()) { + data.submission_notes = faker.lorem.sentence(); + } + + return { ...data, ...overrides }; } /**