import pathlib import shutil import pytest from solo_tool.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 checkLimit(uut, mockPlayer, 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 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_abLimitEnabledGetter(uut): assert not uut.isAbLimitEnabled() uut.setAbLimitEnable(True) assert uut.isAbLimitEnabled() uut.setAbLimitEnable(False) assert not uut.isAbLimitEnabled() 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] ] uut.addSong(song) uut.setSong(0) uut.setAbLimitEnable(True) for ab in abLimits: uut.storeAbLimits(ab[0], ab[1]) checkLimit(uut, mockPlayer, 0.0, 0.0) # default limits uut.nextStoredAbLimits() checkLimit(uut, mockPlayer, abLimits[0][0], abLimits[0][1]) uut.nextStoredAbLimits() checkLimit(uut, mockPlayer, abLimits[1][0], abLimits[1][1]) uut.nextStoredAbLimits() checkLimit(uut, mockPlayer, abLimits[1][0], abLimits[1][1]) uut.previousStoredAbLimits() checkLimit(uut, mockPlayer, abLimits[0][0], abLimits[0][1]) uut.previousStoredAbLimits() checkLimit(uut, mockPlayer, abLimits[0][0], abLimits[0][1]) def test_abLimitsWhenChangingSongs(uut, mockPlayer): songs = [ "test.flac", "test.mp3" ] abLimits = [ [0.2, 0.4], [0.1, 0.3], [0.7, 0.8] ] uut.setAbLimitEnable(True) for s in songs: uut.addSong(s) uut.setSong(0) for ab in abLimits: uut.storeAbLimits(ab[0], ab[1]) uut.setSong(1) uut.storeAbLimits(abLimits[0][0], abLimits[0][1]) uut.setSong(0) uut.loadAbLimits(len(abLimits) - 1) checkLimit(uut, mockPlayer, abLimits[-1][0], abLimits[-1][1]) uut.setSong(1) checkLimit(uut, mockPlayer, abLimits[-1][0], abLimits[-1][1]) uut.previousStoredAbLimits() checkLimit(uut, mockPlayer, 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 receivedValue = None def callback(value): nonlocal called, receivedValue called = True receivedValue = value uut.registerPlayingStateCallback(callback) assert mockPlayer.state == MockPlayer.STOPPED assert not called uut.play() assert called assert receivedValue == True called = False uut.play() assert not called uut.pause() assert called assert receivedValue == False called = False uut.pause() assert not called uut.play() assert called assert receivedValue == True called = False uut.stop() assert called assert receivedValue == False called = False uut.stop() assert not called def test_playbackVolumeNotification(uut, mockPlayer): song = "test.flac" uut.addSong(song) uut.setSong(0) called = False receivedValue = None def callback(value): nonlocal called, receivedValue called = True receivedValue = value uut.registerPlaybackVolumeCallback(callback) assert not called uut.setPlaybackVolume(0.3) assert called assert receivedValue == 0.3 called = False uut.setPlaybackVolume(0.3) assert not called def test_playbackRateNotification(uut, mockPlayer): song = "test.flac" uut.addSong(song) uut.setSong(0) called = False receivedValue = None def callback(value): nonlocal called, receivedValue called = True receivedValue = value uut.registerPlaybackRateCallback(callback) assert not called uut.setPlaybackRate(0.5) assert called assert receivedValue == 0.5 called = False uut.setPlaybackRate(0.5) assert not called def test_currentSongNotification(uut): called = False receivedValue = None def callback(value): nonlocal called, receivedValue called = True receivedValue = value uut.registerCurrentSongCallback(callback) assert not called songs = [ "test.flac", "test.mp3" ] uut.addSong(songs[0]) assert not called uut.setSong(0) assert called assert receivedValue == 0 called = False uut.addSong(songs[1]) assert not called uut.setSong(0) assert not called uut.setSong(1) assert called assert receivedValue == 1 called = False uut.previousSong() assert called assert receivedValue == 0 called = False uut.previousSong() assert not called uut.nextSong() assert called assert receivedValue == 1 called = False uut.nextSong() assert not called def test_currentAbNotification(uut): called = False receivedValue = None def callback(value): nonlocal called, receivedValue called = True receivedValue = value 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 assert receivedValue == 0 called = False uut.loadAbLimits(0) assert not called uut.loadAbLimits(1) assert called assert receivedValue == 1 called = False uut.previousStoredAbLimits() assert called assert receivedValue == 0 called = False uut.previousStoredAbLimits() assert not called uut.nextStoredAbLimits() assert called assert receivedValue == 1 called = False uut.nextStoredAbLimits() assert not called def test_abLimitEnabledNotification(uut): called = False receivedValue = None def callback(value): nonlocal called, receivedValue called = True receivedValue = value uut.registerAbLimitEnabledCallback(callback) assert not called uut.setAbLimitEnable(False) assert not called assert receivedValue is None uut.setAbLimitEnable(True) assert called assert receivedValue == True called = False receivedValue = None uut.setAbLimitEnable(True) assert not called assert receivedValue is None uut.setAbLimitEnable(False) assert called assert receivedValue == False