import Testing import Foundation @testable import Mobile_Music_Assistant // MARK: - Pagination Threshold @Suite("MALibraryManager – Pagination Threshold") struct PaginationThresholdTests { /// Replicates the "load more if needed" threshold logic. /// Returns true if a load should be triggered for the given currentIndex. private func shouldLoadMore(currentIndex: Int, totalLoaded: Int, threshold: Int = 10) -> Bool { guard totalLoaded > 0 else { return false } return currentIndex >= totalLoaded - threshold } @Test("Triggers load when item is within 10 of the end") func triggersNearEnd() { #expect(shouldLoadMore(currentIndex: 91, totalLoaded: 100)) #expect(shouldLoadMore(currentIndex: 95, totalLoaded: 100)) #expect(shouldLoadMore(currentIndex: 99, totalLoaded: 100)) } @Test("Does not trigger load when item is far from the end") func noTriggerFarFromEnd() { #expect(!shouldLoadMore(currentIndex: 50, totalLoaded: 100)) #expect(!shouldLoadMore(currentIndex: 0, totalLoaded: 100)) #expect(!shouldLoadMore(currentIndex: 89, totalLoaded: 100)) } @Test("Boundary: triggers exactly at threshold position") func triggersAtExactThreshold() { // With 100 items and threshold 10, position 90 is the boundary (100 - 10 = 90) #expect(shouldLoadMore(currentIndex: 90, totalLoaded: 100)) #expect(!shouldLoadMore(currentIndex: 89, totalLoaded: 100)) } @Test("Does not trigger with empty list") func noTriggerWithEmptyList() { #expect(!shouldLoadMore(currentIndex: 0, totalLoaded: 0)) } @Test("Always triggers with a single-item list") func alwaysTriggersForSingleItem() { #expect(shouldLoadMore(currentIndex: 0, totalLoaded: 1)) } } // MARK: - Page hasMore Detection @Suite("MALibraryManager – hasMore Detection") struct HasMoreDetectionTests { /// Returns false (no more pages) if returned count < pageSize. private func hasMorePages(returned: Int, pageSize: Int) -> Bool { returned >= pageSize } @Test("No more pages when returned count equals pageSize") func exactPageSizeHasMore() { #expect(hasMorePages(returned: 50, pageSize: 50)) } @Test("No more pages when returned count is less than pageSize") func partialPageMeansNoMore() { #expect(!hasMorePages(returned: 25, pageSize: 50)) #expect(!hasMorePages(returned: 0, pageSize: 50)) #expect(!hasMorePages(returned: 49, pageSize: 50)) } @Test("Has more pages when returned count is greater than pageSize (e.g. over-fetch)") func overFetchHasMore() { #expect(hasMorePages(returned: 51, pageSize: 50)) } } // MARK: - Favorite URI Collection @Suite("MALibraryManager – Favorite URI Collection") struct FavoriteURICollectionTests { @Test("Collects URIs of items marked as favorite") func collectsFavoriteURIs() throws { let items: [MAMediaItem] = try [ """{"uri":"spotify://1","name":"A","favorite":true}""", """{"uri":"spotify://2","name":"B","favorite":false}""", """{"uri":"spotify://3","name":"C","favorite":true}""", ].map { try JSONDecoder().decode(MAMediaItem.self, from: Data($0.utf8)) } let favorites = Set(items.filter(\.favorite).map(\.uri)) #expect(favorites == Set(["spotify://1", "spotify://3"])) } @Test("Returns empty set when no items are favorite") func emptyWhenNoFavorites() throws { let items: [MAMediaItem] = try [ """{"uri":"x://1","name":"A","favorite":false}""", """{"uri":"x://2","name":"B"}""", ].map { try JSONDecoder().decode(MAMediaItem.self, from: Data($0.utf8)) } let favorites = Set(items.filter(\.favorite).map(\.uri)) #expect(favorites.isEmpty) } @Test("isFavorite check on MALibraryManager respects favoriteURIs set") func isFavoriteCheck() { let manager = MALibraryManager() // Initially no favorites #expect(manager.isFavorite(uri: "spotify://track/1") == false) } } // MARK: - MALibraryManager Initial State @Suite("MALibraryManager – Initial State") struct LibraryManagerInitialStateTests { @Test("Artists collection starts empty") func artistsStartEmpty() { #expect(MALibraryManager().artists.isEmpty) } @Test("Albums collection starts empty") func albumsStartEmpty() { #expect(MALibraryManager().albums.isEmpty) } @Test("Playlists collection starts empty") func playlistsStartEmpty() { #expect(MALibraryManager().playlists.isEmpty) } @Test("Loading flags start as false") func loadingFlagsStartFalse() { let m = MALibraryManager() #expect(m.isLoadingArtists == false) #expect(m.isLoadingAlbums == false) #expect(m.isLoadingPlaylists == false) } @Test("favoriteURIs starts empty") func favoriteURIsStartEmpty() { #expect(MALibraryManager().favoriteURIs.isEmpty) } }