import MusicAssistantCore import XCTest final class SongProjectValidatorTests: XCTestCase { func testValidatorReportsInvalidProjectRelationshipsAndTiming() { let project = SongProject( title: "Invalid Project", idea: "Validate structure", duration: SongDuration(seconds: 0), bpm: ManualAutoValue(mode: .manual, value: 0), sections: [ SongSection(id: "verse", type: .verse, title: "Verse", startTime: 12, endTime: 8), SongSection(id: "verse", type: .chorus, title: "Chorus") ], instruments: [ InstrumentTrack( instrumentId: "piano", placements: [InstrumentPlacement(sectionId: "missing", startTime: -1, endTime: 4)] ) ], vocalists: [Vocalist(label: "Lead", assignedSections: ["missing"])] ) let issues = SongProjectValidator().validate(project) XCTAssertEqual( issues, [ .invalidDuration, .invalidBPM(0), .duplicateSectionID("verse"), .invalidSectionTiming("verse"), .invalidInstrumentTiming("piano"), .unknownSectionReference("missing") ] ) } func testValidatorAcceptsConsistentProject() { let project = SongProject( title: "Valid Project", idea: "Validate structure", duration: SongDuration(seconds: 180), bpm: ManualAutoValue(mode: .manual, value: 100), sections: [SongSection(id: "verse", type: .verse, title: "Verse", startTime: 0, endTime: 30)], instruments: [InstrumentTrack(instrumentId: "piano", placements: [InstrumentPlacement(sectionId: "verse", startTime: 0, endTime: 30)])], vocalists: [Vocalist(label: "Lead", assignedSections: ["verse"])] ) XCTAssertTrue(SongProjectValidator().validate(project).isEmpty) } }