import pathlib import shutil import pytest from solo_tool import SoloTool from player_mock import Player as MockPlayer @pytest.fixture def mockPlayer(): return MockPlayer() @pytest.fixture def uut(mockPlayer): return SoloTool(mockPlayer) @pytest.fixture def prepared_tmp_path(tmp_path): testFiles = [ "test.flac", "test.mp3", "test_session.json" ] for f in testFiles: shutil.copy(pathlib.Path(f), tmp_path) return tmp_path def test_playerControls(uut, mockPlayer): assert mockPlayer.state == MockPlayer.STOPPED assert uut.isPlaying() == False uut.play() assert mockPlayer.state == MockPlayer.PLAYING assert uut.isPlaying() == True uut.pause() assert mockPlayer.state == MockPlayer.PAUSED assert uut.isPlaying() == False uut.stop() assert mockPlayer.state == MockPlayer.STOPPED assert uut.isPlaying() == False assert mockPlayer.rate == 1.0 uut.setPlaybackRate(0.5) assert mockPlayer.rate == 0.5 assert mockPlayer.position == 0.0 uut.setPlaybackPosition(0.5) assert mockPlayer.position == 0.5 assert mockPlayer.volume == 1.0 uut.setPlaybackVolume(0.5) assert mockPlayer.volume == 0.5 def test_addAndSetSongs(uut, mockPlayer): songs = [ "test.flac", "test.mp3" ] for s in songs: uut.addSong(s) assert mockPlayer.currentSong == None for i, s in enumerate(songs): uut.setSong(i) assert mockPlayer.currentSong == songs[i] def test_nextAndPreviousSong(uut, mockPlayer): songs = [ "test.flac", "test.mp3" ] for s in songs: uut.addSong(s) assert mockPlayer.currentSong == None uut.nextSong() assert mockPlayer.currentSong == songs[0] uut.previousSong() assert mockPlayer.currentSong == songs[0] uut.nextSong() assert mockPlayer.currentSong == songs[1] uut.nextSong() assert mockPlayer.currentSong == songs[1] def test_addAndSetAbLimits(uut, mockPlayer): song = "test.flac" abLimits = [ [0.2, 0.4], [0.1, 0.3] ] uut.addSong(song) uut.setSong(0) for ab in abLimits: uut.storeAbLimits(ab[0], ab[1]) mockPlayer.position = 0.0 uut.tick() assert mockPlayer.position == 0.0 mockPlayer.position = 0.5 uut.tick() assert mockPlayer.position == 0.5 uut.loadAbLimits(0) uut.tick() assert mockPlayer.position == 0.5 uut.setAbLimitEnable(True) uut.tick() assert mockPlayer.position == 0.2 uut.tick() assert mockPlayer.position == 0.2 uut.loadAbLimits(1) uut.tick() assert mockPlayer.position == 0.2 mockPlayer.position = 0.8 uut.tick() assert mockPlayer.position == 0.1 def test_multipleSongsAndAbLimits(uut, mockPlayer): songs = [ "test.flac", "test.mp3" ] abLimits = [ [0.2, 0.4], [0.5, 0.7] ] for s in songs: uut.addSong(s) for i, l in enumerate(abLimits): uut.setSong(i) uut.storeAbLimits(l[0], l[1]) uut.setAbLimitEnable(True) for i, l in enumerate(abLimits): uut.setSong(i) uut.loadAbLimits(0) mockPlayer.position = l[0] uut.tick() assert mockPlayer.position == l[0] mockPlayer.position = l[1] + 0.1 uut.tick() assert mockPlayer.position == l[0] def test_storeAbLimitsWithoutSong(uut, mockPlayer): song = "test.flac" abLimit = [0.2, 0.4] overflow = abLimit[1] + 0.1 default = 0.0 mockPlayer.position = overflow uut.setAbLimitEnable(True) uut.storeAbLimits(abLimit[0], abLimit[1]) uut.tick() assert mockPlayer.position == default mockPlayer.position = overflow uut.loadAbLimits(0) uut.tick() assert mockPlayer.position == default mockPlayer.position = overflow uut.addSong(song) uut.tick() assert mockPlayer.position == default mockPlayer.position = overflow uut.loadAbLimits(0) uut.tick() assert mockPlayer.position == default mockPlayer.position = overflow uut.setSong(0) uut.tick() assert mockPlayer.position == default mockPlayer.position = overflow uut.loadAbLimits(0) uut.tick() assert mockPlayer.position == default mockPlayer.position = overflow uut.storeAbLimits(abLimit[0], abLimit[1]) uut.tick() assert mockPlayer.position == default mockPlayer.position = overflow uut.loadAbLimits(0) uut.tick() assert mockPlayer.position == abLimit[0] def test_nextAndPreviousAbLimit(uut, mockPlayer): song = "test.flac" abLimits = [ [0.2, 0.4], [0.1, 0.3] ] def checkLimit(aLimit, bLimit): mockPlayer.position = bLimit - 0.1 uut.tick() assert mockPlayer.position == bLimit - 0.1 mockPlayer.position = bLimit + 0.1 uut.tick() assert mockPlayer.position == aLimit uut.addSong(song) uut.setSong(0) uut.setAbLimitEnable(True) for ab in abLimits: uut.storeAbLimits(ab[0], ab[1]) checkLimit(0.0, 0.0) # default limits uut.nextStoredAbLimits() checkLimit(abLimits[0][0], abLimits[0][1]) uut.nextStoredAbLimits() checkLimit(abLimits[1][0], abLimits[1][1]) uut.nextStoredAbLimits() checkLimit(abLimits[1][0], abLimits[1][1]) uut.previousStoredAbLimits() checkLimit(abLimits[0][0], abLimits[0][1]) uut.previousStoredAbLimits() checkLimit(abLimits[0][0], abLimits[0][1]) def test_loadAndSaveSession(prepared_tmp_path): mockPlayer = MockPlayer() uut = SoloTool(mockPlayer) loadedSessionFile = prepared_tmp_path / "test_session.json" savedSessionFile = prepared_tmp_path / "test_session_save.json" uut.loadSession(loadedSessionFile) uut.saveSession(savedSessionFile) import json with open(loadedSessionFile, "r") as f: loadedSession = json.loads(f.read()) with open(savedSessionFile, "r") as f: savedSession = json.loads(f.read()) assert loadedSession == savedSession def test_addInexistentFile(uut, mockPlayer): song = "not/a/real/file" uut.addSong(song) uut.setSong(0) assert mockPlayer.currentSong == None def test_getters(uut, mockPlayer): song = "test.flac" abLimit = [0.2, 0.4] uut.addSong(song) uut.setSong(0) uut.storeAbLimits(abLimit[0], abLimit[1]) assert uut.getSongs() == [song] limits = uut.getStoredAbLimits() assert len(limits) == 1 assert limits[0][0] == abLimit[0] assert limits[0][1] == abLimit[1] mockPlayer.position = 0.8 assert uut.getPlaybackPosition() == 0.8 mockPlayer.volume = 0.8 assert uut.getPlaybackVolume() == 0.8 mockPlayer.rate = 0.5 assert uut.getPlaybackRate() == 0.5 def test_setTemporaryLimits(uut, mockPlayer): song = "test.flac" abLimits = [ [0.2, 0.4], [0.1, 0.4] ] overflow = 0.5 uut.setAbLimitEnable(True) mockPlayer.position = overflow uut.addSong(song) uut.setSong(0) uut.storeAbLimits(abLimits[0][0], abLimits[0][1]) uut.loadAbLimits(0) uut.setAbLimits(abLimits[1][0], abLimits[1][1]) uut.tick() assert mockPlayer.position == abLimits[1][0] def test_jumpToA(uut, mockPlayer): abLimits = (0.2, 0.4) initialPosition = 0.8 mockPlayer.position = initialPosition uut.jumpToA() assert mockPlayer.position == 0.0 # default AB controller A limit uut.setAbLimits(abLimits[0], abLimits[1]) uut.jumpToA() assert mockPlayer.position == abLimits[0] def test_playingStateNotification(uut, mockPlayer): song = "test.flac" uut.addSong(song) uut.setSong(0) called = False def callback(): nonlocal called called = True uut.registerPlayingStateCallback(callback) assert mockPlayer.state == MockPlayer.STOPPED assert not called uut.play() assert called called = False uut.play() assert not called uut.pause() assert called called = False uut.pause() assert not called uut.play() assert called called = False uut.stop() assert called called = False uut.stop() assert not called def test_playbackVolumeNotification(uut, mockPlayer): song = "test.flac" uut.addSong(song) uut.setSong(0) called = False def callback(): nonlocal called called = True uut.registerPlaybackVolumeCallback(callback) assert not called uut.setPlaybackVolume(0.0) assert called called = False uut.setPlaybackVolume(0.0) assert not called def test_playbackRateNotification(uut, mockPlayer): song = "test.flac" uut.addSong(song) uut.setSong(0) called = False def callback(): nonlocal called called = True uut.registerPlaybackRateCallback(callback) assert not called uut.setPlaybackRate(0.5) assert called called = False uut.setPlaybackRate(0.5) assert not called def test_currentSongNotification(uut): called = False def callback(): nonlocal called called = True uut.registerCurrentSongCallback(callback) assert not called songs = [ "test.flac", "test.mp3" ] uut.addSong(songs[0]) assert not called uut.setSong(0) assert called called = False uut.addSong(songs[1]) assert not called uut.setSong(0) assert not called uut.setSong(1) assert called called = False uut.previousSong() assert called called = False uut.previousSong() assert not called uut.nextSong() assert called called = False uut.nextSong() assert not called def test_currentAbNotification(uut): called = False def callback(): nonlocal called called = True uut.registerCurrentAbLimitsCallback(callback) assert not called song = "test.flac" uut.addSong(song) uut.setSong(0) abLimits = [ (0.2, 0.3), (0.4, 0.5) ] uut.storeAbLimits(abLimits[0][0], abLimits[0][1]) assert not called uut.storeAbLimits(abLimits[1][0], abLimits[1][1]) assert not called uut.loadAbLimits(0) assert called called = False uut.loadAbLimits(0) assert not called uut.loadAbLimits(1) assert called called = False uut.previousStoredAbLimits() assert called called = False uut.previousStoredAbLimits() assert not called uut.nextStoredAbLimits() assert called called = False uut.nextStoredAbLimits() assert not called