Surface the existing pin (keep-from-cull) and per-file delete actions as visible inline buttons on each offline cache row instead of context-menu-only: a star toggles protection from auto-cull (and restore-if-missing), a trash culls that file early. Aligns wording/icons to the star metaphor. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
72 lines
3.3 KiB
Swift
72 lines
3.3 KiB
Swift
import XCTest
|
|
@testable import TVAnarchyCore
|
|
|
|
@MainActor
|
|
final class NowPlayingTests: XCTestCase {
|
|
// MARK: pure decisions
|
|
|
|
func testIsActivelyPlaying() {
|
|
XCTAssertTrue(NowPlayingController.isActivelyPlaying(
|
|
PlaybackStatus(playing: true, paused: false)))
|
|
XCTAssertFalse(NowPlayingController.isActivelyPlaying(
|
|
PlaybackStatus(playing: true, paused: true))) // paused → not active
|
|
XCTAssertFalse(NowPlayingController.isActivelyPlaying(
|
|
PlaybackStatus(playing: false)))
|
|
// hosts that don't report `paused` (nil) count as playing when playing.
|
|
XCTAssertTrue(NowPlayingController.isActivelyPlaying(
|
|
PlaybackStatus(playing: true, paused: nil)))
|
|
}
|
|
|
|
func testCanStep() {
|
|
XCTAssertTrue(NowPlayingController.canStep(playlistCount: 5, isEnqueueable: false))
|
|
XCTAssertTrue(NowPlayingController.canStep(playlistCount: 1, isEnqueueable: true))
|
|
XCTAssertFalse(NowPlayingController.canStep(playlistCount: 1, isEnqueueable: false))
|
|
XCTAssertFalse(NowPlayingController.canStep(playlistCount: nil, isEnqueueable: false))
|
|
}
|
|
|
|
func testVolumeStepAndAdjust() {
|
|
XCTAssertEqual(NowPlayingController.volumeStep(scale: 125), 5)
|
|
XCTAssertEqual(NowPlayingController.adjustedVolume(current: 50, delta: 5, scale: 125), 55)
|
|
XCTAssertEqual(NowPlayingController.adjustedVolume(current: 2, delta: -5, scale: 125), 0)
|
|
XCTAssertEqual(NowPlayingController.adjustedVolume(current: 122, delta: 5, scale: 125), 125)
|
|
XCTAssertEqual(NowPlayingController.adjustedVolume(current: nil, delta: -5, scale: 125), 95)
|
|
}
|
|
|
|
// MARK: registration is idempotent + safe
|
|
|
|
func testEnableDisableIdempotent() {
|
|
let np = NowPlayingController()
|
|
XCTAssertFalse(np.isEnabled)
|
|
XCTAssertFalse(np.volumeKeysEnabled)
|
|
let h = NowPlayingController.Handlers(toggle: {}, play: {}, pause: {},
|
|
next: {}, previous: {}, seek: { _ in },
|
|
volumeUp: { false }, volumeDown: { false })
|
|
np.enable(h)
|
|
XCTAssertTrue(np.isEnabled)
|
|
XCTAssertTrue(np.volumeKeysEnabled)
|
|
np.enable(h) // second enable is a no-op
|
|
np.update(title: "Ep 1", posterPath: nil, position: 10, duration: 100,
|
|
playing: true, canStep: true) // must not crash
|
|
np.disable()
|
|
XCTAssertFalse(np.isEnabled)
|
|
XCTAssertFalse(np.volumeKeysEnabled)
|
|
np.disable() // second disable is a no-op
|
|
}
|
|
|
|
func testTransportAndVolumeIndependent() {
|
|
let np = NowPlayingController()
|
|
let h = NowPlayingController.Handlers(toggle: {}, play: {}, pause: {},
|
|
next: {}, previous: {}, seek: { _ in },
|
|
volumeUp: { false }, volumeDown: { false })
|
|
np.enableTransport(h)
|
|
XCTAssertTrue(np.isEnabled)
|
|
XCTAssertFalse(np.volumeKeysEnabled)
|
|
np.enableVolumeKeys(h)
|
|
XCTAssertTrue(np.volumeKeysEnabled)
|
|
np.disableVolumeKeys()
|
|
XCTAssertTrue(np.isEnabled)
|
|
XCTAssertFalse(np.volumeKeysEnabled)
|
|
np.disableTransport()
|
|
XCTAssertFalse(np.isEnabled)
|
|
}
|
|
}
|