luminate/Tests/LuminateUITests/ClientEnvironmentKeyTests.swift

104 lines
4.6 KiB
Swift

//
// ClientEnvironmentKeyTests.swift
//
// Copyright 2026 Brendan Szymanski <hello@bscubed.dev>
//
// 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 <https://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
import Foundation
import LuminateCore
@_spi(Portico) import Portico
import Testing
@testable import LuminateUI
/// A ``JellyfinService`` that exists only to be told apart from the default.
private final class StubJellyfinService: JellyfinService {
var isAuthenticated: Bool { true }
func publicServerInfo() async throws -> JellyfinServerInfo { JellyfinServerInfo() }
func serverInfo() async throws -> JellyfinServerInfo { JellyfinServerInfo() }
func publicUsers() async throws -> [JellyfinUser] { [] }
func currentUser() async throws -> JellyfinUser { JellyfinUser() }
func authenticate(username: String, password: String) async throws -> JellyfinAuthentication {
JellyfinAuthentication(accessToken: "stub")
}
func quickConnectEnabled() async throws -> Bool { false }
func initiateQuickConnect() async throws -> JellyfinQuickConnectState { JellyfinQuickConnectState() }
func quickConnectState(secret: String) async throws -> JellyfinQuickConnectState { JellyfinQuickConnectState() }
func authenticateWithQuickConnect(secret: String) async throws -> JellyfinAuthentication {
JellyfinAuthentication(accessToken: "stub")
}
func updateUserPassword(
userID: String?,
currentPassword: String?,
currentPIN: String?,
newPassword: String?,
resetPassword: Bool?
) async throws {}
func libraries(_ options: JellyfinListOptions) async throws -> [JellyfinLibrary] { [] }
func items(_ query: JellyfinMediaQuery) async throws -> JellyfinMediaPage { JellyfinMediaPage() }
func item(id: String, userID: String?) async throws -> JellyfinMediaItem { JellyfinMediaItem() }
func resumeItems(_ options: JellyfinListOptions) async throws -> JellyfinMediaPage { JellyfinMediaPage() }
func nextUp(seriesID: String?, options: JellyfinListOptions) async throws -> JellyfinMediaPage {
JellyfinMediaPage()
}
func latestMedia(_ options: JellyfinListOptions) async throws -> [JellyfinMediaItem] { [] }
func seasons(seriesID: String, options: JellyfinListOptions) async throws -> JellyfinMediaPage {
JellyfinMediaPage()
}
func episodes(seriesID: String, options: JellyfinListOptions) async throws -> JellyfinMediaPage {
JellyfinMediaPage()
}
func searchHints(term: String, options: JellyfinListOptions) async throws -> [JellyfinSearchHint] { [] }
func image(
itemID: String,
type: JellyfinImageType,
index: Int32?,
request: JellyfinImageRequest
) async throws -> Data {
Data()
}
func markPlayed(itemID: String, userID: String?, datePlayed: Date?) async throws -> JellyfinUserData {
JellyfinUserData()
}
func markUnplayed(itemID: String, userID: String?) async throws -> JellyfinUserData { JellyfinUserData() }
func markFavorite(itemID: String, userID: String?) async throws -> JellyfinUserData { JellyfinUserData() }
func unmarkFavorite(itemID: String, userID: String?) async throws -> JellyfinUserData { JellyfinUserData() }
}
/// Guards the `\\.client` environment slot itself.
///
/// No widgets are constructed, so these run on a headless machine without `Gtk.initCheck()`.
@MainActor @Suite struct ClientEnvironmentKeyTests {
@Test("An unresolved slot falls back to the unconfigured service")
func defaultIsUnconfigured() {
#expect(EnvironmentValues().client is UnconfiguredJellyfinService)
}
@Test("The key path routes through the environment subscript")
func keyPathResolvesToABox() {
#expect(EnvironmentValues()._box(for: \.client) != nil)
}
@Test("An injected service replaces the default")
func injectionOverridesDefault() {
var values = EnvironmentValues()
values.client = StubJellyfinService()
#expect(values.client is StubJellyfinService)
}
}