Files
music-assistant/Tests/MusicAssistantCoreTests/StructuredAIResponseSchemaTests.swift
T
2026-09-13 20:21:10 +02:00

115 lines
4.5 KiB
Swift

import MusicAssistantCore
import XCTest
final class StructuredAIResponseSchemaTests: XCTestCase {
func testStructuredSongProjectUpdateResponseDecodesFromJSON() throws {
let json = """
{
"project": {
"title": "Updated Song",
"idea": "A brighter chorus",
"conversationMode": "auto",
"languages": [{"id": "english", "name": "English"}],
"dialects": [],
"arabicPronunciationSettings": {
"isEnabled": false,
"diacritizationPolicy": "unspecified",
"tanweenPolicy": "unspecified",
"preservedSpellings": []
},
"genres": [{"id": "pop", "name": "Pop", "aliases": []}],
"moods": [{"id": "hopeful", "name": "Hopeful"}],
"emotionalArc": [],
"sections": [
{
"id": "chorus",
"type": "chorus",
"title": "Chorus",
"order": 0,
"lyrics": "Lift the hook higher"
}
],
"instruments": [
{
"instrumentId": "piano",
"selected": true,
"autoArrangementEnabled": true,
"placements": []
}
],
"vocalists": [],
"lyrics": {
"text": "Lift the hook higher",
"sectionTexts": {"chorus": "Lift the hook higher"}
},
"productionDirections": [],
"sunoOutput": {
"lyricsText": "Lift the hook higher",
"stylePrompt": "Hopeful pop with piano",
"additionalFields": {},
"generatedAt": "2026-09-13T18:00:00Z"
}
},
"changedScopes": ["lyrics", "structure", "sunoOutput"],
"notes": ["Updated requested creative fields."],
"followUpQuestions": ["Should the final chorus repeat?"]
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let response = try decoder.decode(StructuredSongProjectUpdateResponse.self, from: json)
XCTAssertEqual(StructuredSongProjectUpdateResponse.schemaName, "song_project_update_response")
XCTAssertEqual(response.project.title, "Updated Song")
XCTAssertEqual(response.project.sections.first?.type, .chorus)
XCTAssertEqual(response.project.instruments.first?.instrumentId, "piano")
XCTAssertEqual(response.changedScopes, [.lyrics, .structure, .sunoOutput])
XCTAssertEqual(response.notes, ["Updated requested creative fields."])
XCTAssertEqual(response.followUpQuestions, ["Should the final chorus repeat?"])
}
func testStructuredSongProjectUpdateResponseCreatesUpdateResultWhilePreservingProjectIdentityAndVersions() {
let createdAt = Date(timeIntervalSince1970: 100)
let updatedAt = Date(timeIntervalSince1970: 200)
var existingProject = SongProject(
id: "project-id",
title: "Original",
idea: "Original idea",
createdAt: createdAt,
updatedAt: createdAt
)
let version = existingProject.createVersion(
id: "version-id",
label: "Before AI update",
createdAt: createdAt
)
let response = StructuredSongProjectUpdateResponse(
project: SongProjectSnapshot(
title: "Updated",
idea: "Updated idea",
genres: [GenreStyle(id: "cinematic", name: "Cinematic")],
lyrics: Lyrics(text: "Updated lyrics")
),
changedScopes: [.genres, .lyrics],
notes: ["Proposed focused update."],
followUpQuestions: ["Keep it minimal?"]
)
let result = response.makeUpdateResult(
updating: existingProject,
updatedAt: updatedAt
)
XCTAssertEqual(result.project.id, "project-id")
XCTAssertEqual(result.project.createdAt, createdAt)
XCTAssertEqual(result.project.updatedAt, updatedAt)
XCTAssertEqual(result.project.versions, [version])
XCTAssertEqual(result.project.title, "Updated")
XCTAssertEqual(result.project.lyrics.text, "Updated lyrics")
XCTAssertEqual(result.changedScopes, [.genres, .lyrics])
XCTAssertEqual(result.notes, ["Proposed focused update."])
XCTAssertEqual(result.followUpQuestions, ["Keep it minimal?"])
}
}