// // JellyfinModelTests.swift // // Copyright 2026 Brendan Szymanski // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // SPDX-License-Identifier: GPL-3.0-or-later // import Testing @testable import LuminateCore /// Guards the wire spellings Luminate's domain enums promise the service layer. /// /// These raw values are the entire contract between ``LuminateCore`` and the generated Jellyfin /// client: mapping is a `rawValue` round trip, so a typo here silently drops data at runtime rather /// than failing to compile. @Suite struct JellyfinModelTests { @Test("Media kind raw values match the server spellings") func mediaKindRawValues() { #expect(JellyfinMediaKind.movie.rawValue == "Movie") #expect(JellyfinMediaKind.boxSet.rawValue == "BoxSet") #expect(JellyfinMediaKind.collectionFolder.rawValue == "CollectionFolder") #expect(JellyfinMediaKind(rawValue: "Episode") == .episode) #expect(JellyfinMediaKind(rawValue: "MusicAlbum") == nil) } @Test("Collection type raw values are lowercase, as the server sends them") func collectionTypeRawValues() { #expect(JellyfinCollectionType(rawValue: "tvshows") == .tvShows) #expect(JellyfinCollectionType(rawValue: "movies") == .movies) #expect(JellyfinCollectionType(rawValue: "boxsets") == .boxSets) #expect(JellyfinCollectionType(rawValue: "TvShows") == nil) #expect(JellyfinCollectionType(rawValue: "music") == nil) } @Test("Sort field and item field keep their irregular server spellings") func irregularRawValues() { #expect(JellyfinSortField.defaultOrder.rawValue == "Default") #expect(JellyfinSortField.airedEpisodeOrder.rawValue == "AiredEpisodeOrder") #expect(JellyfinItemField.isHighDefinition.rawValue == "IsHD") #expect(JellyfinItemField.providerIDs.rawValue == "ProviderIds") #expect(JellyfinItemField.parentID.rawValue == "ParentId") } @Test("Image type and format raw values match the server spellings") func imageRawValues() { #expect(JellyfinImageType.primary.rawValue == "Primary") #expect(JellyfinImageType.boxRear.rawValue == "BoxRear") #expect(JellyfinImageFormat.jpg.rawValue == "Jpg") #expect(JellyfinSortOrder.descending.rawValue == "Descending") } @Test("An empty query sends nothing, so the server applies its own defaults") func emptyQueryIsFullyUnset() { let query = JellyfinMediaQuery() #expect(query.userID == nil) #expect(query.parentID == nil) #expect(query.includeItemKinds == nil) #expect(query.sortBy == nil) #expect(query.limit == nil) #expect(query.recursive == nil) #expect(query.enableImageTypes == nil) } @Test("Empty list options send nothing") func emptyListOptionsAreFullyUnset() { let options = JellyfinListOptions() #expect(options.userID == nil) #expect(options.parentID == nil) #expect(options.seasonID == nil) #expect(options.season == nil) #expect(options.limit == nil) #expect(options.fields == nil) #expect(options.includeItemKinds == nil) #expect(options.includeHidden == nil) #expect(options.groupItems == nil) } @Test("Collection defaults are empty rather than nil") func collectionDefaults() { #expect(JellyfinMediaPage().items.isEmpty) #expect(JellyfinMediaPage().totalRecordCount == nil) #expect(JellyfinMediaItem().imageTags.isEmpty) #expect(JellyfinMediaItem().backdropImageTags.isEmpty) #expect(JellyfinLibrary().backdropImageTags.isEmpty) } }