import Foundation import XCTest import VelodyDomain @testable import VelodyPlayback @MainActor final class PlaybackControllerTests: XCTestCase { func testPlayPauseRestartsTrackAfterPlaybackFinishesAtQueueEnd() { let engine = FakePlaybackEngine() let sessionStore = InMemoryPlaybackSessionStore() let controller = PlaybackController( engine: engine, sessionStore: sessionStore ) let track = LibraryTrack( id: "track-1", title: "Finished Track", artist: "Tester", durationSeconds: 120, localFilePath: "/tmp/finished-track.mp3" ) controller.setCatalogTracks([track]) controller.play(trackID: track.id) XCTAssertEqual(engine.loadTrackCallCount, 1) XCTAssertEqual(engine.playCallCount, 1) XCTAssertTrue(controller.nowPlayingState.isPlaying) engine.simulatePlaybackFinished() XCTAssertFalse(controller.nowPlayingState.isPlaying) XCTAssertEqual(controller.nowPlayingState.currentTime, 120) controller.playPause() XCTAssertEqual(engine.loadTrackCallCount, 2) XCTAssertEqual(engine.playCallCount, 2) XCTAssertEqual(engine.lastLoadedStartTime, 0) XCTAssertTrue(controller.nowPlayingState.isPlaying) XCTAssertEqual(controller.nowPlayingState.currentTime, 0) } } @MainActor private final class FakePlaybackEngine: PlaybackEngine { var onEvent: (@MainActor @Sendable (PlaybackEngineEvent) -> Void)? var currentTime: Double = 0 var duration: Double = 120 var isPlaying = false private(set) var loadTrackCallCount = 0 private(set) var playCallCount = 0 private(set) var lastLoadedStartTime: Double? func loadTrack(at fileURL: URL, startTime: Double) throws { loadTrackCallCount += 1 lastLoadedStartTime = startTime currentTime = startTime isPlaying = false } func play() throws { playCallCount += 1 isPlaying = true } func pause() { isPlaying = false } func stop() { isPlaying = false currentTime = 0 } func seek(to time: Double) throws { currentTime = min(max(time, 0), duration) } func simulatePlaybackFinished() { isPlaying = false currentTime = duration onEvent?(.finishedPlaying) } }