Implement artwork download and cache
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user