import Foundation import XCTest import VelodyDomain @testable import VelodyPersistence final class ArtworkStoreTests: XCTestCase { func testFileArtworkStoreWritesAndReadsArtworkData() async throws { let fileManager = FileManager.default let tempDirectory = fileManager.temporaryDirectory.appendingPathComponent( UUID().uuidString, isDirectory: true ) defer { try? fileManager.removeItem(at: tempDirectory) } let store = try FileArtworkStore(baseDirectoryURL: tempDirectory) let artwork = RemoteArtwork( artworkId: "artwork-123", sha256: String(repeating: "a", count: 64), mimeType: "image/png", width: 1, height: 1 ) let bytes = sampleArtworkData() let localFilePath = try await store.saveArtwork(bytes, artwork: artwork) let storedBytes = try await store.readArtwork(at: localFilePath) let fileExists = await store.fileExists(at: localFilePath) let cachedFilePath = await store.cachedFilePath(for: artwork) XCTAssertEqual(storedBytes, bytes) XCTAssertTrue(fileExists) XCTAssertEqual(cachedFilePath, localFilePath) } func testFileArtworkStoreRejectsEmptyArtworkData() async throws { let store = try FileArtworkStore( baseDirectoryURL: FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) ) await XCTAssertThrowsErrorAsync { _ = try await store.saveArtwork( Data(), artwork: RemoteArtwork( artworkId: "artwork-123", sha256: String(repeating: "a", count: 64), mimeType: "image/png" ) ) } assertion: { error in XCTAssertEqual(error as? ArtworkStoreError, .emptyArtworkData) } } func testFileArtworkStorePersistsArtworkAcrossInstances() async throws { let fileManager = FileManager.default let tempDirectory = fileManager.temporaryDirectory.appendingPathComponent( UUID().uuidString, isDirectory: true ) let artwork = RemoteArtwork( artworkId: "artwork-123", sha256: String(repeating: "a", count: 64), mimeType: "image/png", width: 1, height: 1 ) defer { try? fileManager.removeItem(at: tempDirectory) } let firstStore = try FileArtworkStore(baseDirectoryURL: tempDirectory) let firstLocalFilePath = try await firstStore.saveArtwork( sampleArtworkData(), artwork: artwork ) let secondStore = try FileArtworkStore(baseDirectoryURL: tempDirectory) let restoredLocalFilePath = await secondStore.cachedFilePath(for: artwork) XCTAssertEqual(restoredLocalFilePath, firstLocalFilePath) } } private func sampleArtworkData() -> Data { Data( base64Encoded: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P8z8DwHwAFgwJ/lBi4NwAAAABJRU5ErkJggg==" )! } private func XCTAssertThrowsErrorAsync( _ expression: @escaping () async throws -> Void, assertion: (Error) -> Void, file: StaticString = #filePath, line: UInt = #line ) async { do { try await expression() XCTFail("Expected expression to throw an error.", file: file, line: line) } catch { assertion(error) } }