import Foundation import MusicAssistantCore import XCTest final class LocalSongProjectStoreTests: XCTestCase { private var temporaryDirectoryURL: URL! override func setUpWithError() throws { temporaryDirectoryURL = FileManager.default.temporaryDirectory .appendingPathComponent("music-assistant-store-tests") .appendingPathComponent(UUID().uuidString) } override func tearDownWithError() throws { if let temporaryDirectoryURL { try? FileManager.default.removeItem(at: temporaryDirectoryURL) } temporaryDirectoryURL = nil } func testCreatesOpensSavesAndListsSongProjectsLocally() async throws { let store = LocalSongProjectStore(directoryURL: temporaryDirectoryURL) var project = SongProject( id: "local-project", title: "Local Project", idea: "Persist this song locally", genres: [GenreStyle(id: "pop", name: "Pop")] ) try await store.create(project) let createdProjectIDs = try await store.loadProjectIDs() let openedProject = try await store.open(id: project.id) XCTAssertEqual(createdProjectIDs, ["local-project"]) XCTAssertEqual(openedProject, project) project.title = "Updated Local Project" project.setBPMManually(100) try await store.save(project) let updatedProject = try await store.open(id: project.id) XCTAssertEqual(updatedProject, project) } func testCreateDoesNotOverwriteExistingProject() async throws { let store = LocalSongProjectStore(directoryURL: temporaryDirectoryURL) let project = SongProject( id: "duplicate-project", title: "Duplicate", idea: "Do not overwrite" ) try await store.create(project) do { try await store.create(project) XCTFail("Expected duplicate project creation to fail.") } catch let error as LocalSongProjectStoreError { XCTAssertEqual(error, .projectAlreadyExists(project.id)) } } func testOpenMissingProjectThrowsNotFound() async throws { let store = LocalSongProjectStore(directoryURL: temporaryDirectoryURL) do { _ = try await store.open(id: "missing") XCTFail("Expected missing project open to fail.") } catch let error as LocalSongProjectStoreError { XCTAssertEqual(error, .projectNotFound("missing")) } } }