114 lines
4.3 KiB
Swift
114 lines
4.3 KiB
Swift
import Foundation
|
|
import XCTest
|
|
@testable import VelodyPersistence
|
|
|
|
final class FavoriteTrackStoreTests: XCTestCase {
|
|
func testFavoriteTrackStoreUpsertsAndRemovesByRemoteTrackID() async throws {
|
|
let store = InMemoryFavoriteTrackStore()
|
|
let originalFavorite = FavoriteTrackRecord(
|
|
remoteTrackId: "track-123",
|
|
favoritedAt: Date(timeIntervalSince1970: 1_000)
|
|
)
|
|
let updatedFavorite = FavoriteTrackRecord(
|
|
remoteTrackId: "track-123",
|
|
favoritedAt: Date(timeIntervalSince1970: 2_000)
|
|
)
|
|
let secondFavorite = FavoriteTrackRecord(
|
|
remoteTrackId: "track-456",
|
|
favoritedAt: Date(timeIntervalSince1970: 3_000)
|
|
)
|
|
|
|
try await store.saveFavoriteTrack(originalFavorite)
|
|
try await store.saveFavoriteTrack(updatedFavorite)
|
|
try await store.saveFavoriteTrack(secondFavorite)
|
|
|
|
let savedFavorites = try await store.loadFavoriteTracks()
|
|
|
|
XCTAssertEqual(savedFavorites.count, 2)
|
|
XCTAssertTrue(savedFavorites.contains(updatedFavorite))
|
|
XCTAssertTrue(savedFavorites.contains(secondFavorite))
|
|
|
|
try await store.removeFavoriteTrack(remoteTrackId: "track-123")
|
|
let remainingFavorites = try await store.loadFavoriteTracks()
|
|
|
|
XCTAssertEqual(remainingFavorites, [secondFavorite])
|
|
}
|
|
|
|
func testFileFavoriteTrackStorePersistsAcrossInstances() async throws {
|
|
let fileManager = FileManager.default
|
|
let tempDirectory = fileManager.temporaryDirectory.appendingPathComponent(
|
|
UUID().uuidString,
|
|
isDirectory: true
|
|
)
|
|
let fileURL = tempDirectory.appendingPathComponent("favorite-tracks.json")
|
|
let favorites = [
|
|
FavoriteTrackRecord(
|
|
remoteTrackId: "track-123",
|
|
favoritedAt: Date(timeIntervalSince1970: 1_000)
|
|
),
|
|
FavoriteTrackRecord(
|
|
remoteTrackId: "track-456",
|
|
favoritedAt: Date(timeIntervalSince1970: 2_000)
|
|
),
|
|
]
|
|
|
|
defer {
|
|
try? fileManager.removeItem(at: tempDirectory)
|
|
}
|
|
|
|
let firstStore = try FileFavoriteTrackStore(fileURL: fileURL)
|
|
try await firstStore.saveFavoriteTracks(favorites)
|
|
|
|
let secondStore = try FileFavoriteTrackStore(fileURL: fileURL)
|
|
let restoredFavorites = try await secondStore.loadFavoriteTracks()
|
|
|
|
XCTAssertEqual(restoredFavorites, favorites)
|
|
}
|
|
|
|
func testFileFavoriteTrackStoreWritesAtomicallyAndOverwritesOldContents() async throws {
|
|
let fileManager = FileManager.default
|
|
let tempDirectory = fileManager.temporaryDirectory.appendingPathComponent(
|
|
UUID().uuidString,
|
|
isDirectory: true
|
|
)
|
|
let fileURL = tempDirectory.appendingPathComponent("favorite-tracks.json")
|
|
let firstFavorites = [
|
|
FavoriteTrackRecord(
|
|
remoteTrackId: "track-b",
|
|
favoritedAt: Date(timeIntervalSince1970: 2_000)
|
|
),
|
|
FavoriteTrackRecord(
|
|
remoteTrackId: "track-a",
|
|
favoritedAt: Date(timeIntervalSince1970: 1_000)
|
|
),
|
|
]
|
|
let secondFavorites = [
|
|
FavoriteTrackRecord(
|
|
remoteTrackId: "track-c",
|
|
favoritedAt: Date(timeIntervalSince1970: 3_000)
|
|
),
|
|
]
|
|
let decoder = JSONDecoder()
|
|
decoder.dateDecodingStrategy = .iso8601
|
|
|
|
defer {
|
|
try? fileManager.removeItem(at: tempDirectory)
|
|
}
|
|
|
|
let store = try FileFavoriteTrackStore(fileURL: fileURL)
|
|
try await store.saveFavoriteTracks(firstFavorites)
|
|
try await store.saveFavoriteTracks(secondFavorites)
|
|
|
|
let rawData = try Data(contentsOf: fileURL)
|
|
let restoredFavorites = try decoder.decode([FavoriteTrackRecord].self, from: rawData)
|
|
let directoryContents = try fileManager.contentsOfDirectory(atPath: tempDirectory.path)
|
|
let json = try XCTUnwrap(
|
|
JSONSerialization.jsonObject(with: rawData) as? [[String: Any]]
|
|
)
|
|
|
|
XCTAssertEqual(restoredFavorites, secondFavorites)
|
|
XCTAssertEqual(directoryContents.sorted(), ["favorite-tracks.json"])
|
|
XCTAssertEqual(Set(json[0].keys), ["favoritedAt", "remoteTrackId"])
|
|
}
|
|
}
|