diff options
| -rw-r--r-- | solo-tool-project/src/solo_tool/notifier.py | 5 | ||||
| -rw-r--r-- | solo-tool-project/src/solo_tool/solo_tool.py | 16 | ||||
| -rw-r--r-- | solo-tool-project/test/solo_tool_songs_integrationtest.py (renamed from solo-tool-project/src/solo_tool/solo_tool_songs_integrationtest.py) | 111 | 
3 files changed, 93 insertions, 39 deletions
| diff --git a/solo-tool-project/src/solo_tool/notifier.py b/solo-tool-project/src/solo_tool/notifier.py index dadf85c..ac1c736 100644 --- a/solo-tool-project/src/solo_tool/notifier.py +++ b/solo-tool-project/src/solo_tool/notifier.py @@ -3,8 +3,9 @@ class Notifier:      PLAYBACK_VOLUME_EVENT = 1      PLAYBACK_RATE_EVENT = 2      CURRENT_SONG_EVENT = 3 -    CURRENT_KEY_POINT_EVENT = 3 -    KEY_POINTS_EVENT = 4 +    SONG_LIST_EVENT = 4 +    CURRENT_KEY_POINT_EVENT = 5 +    KEY_POINTS_EVENT = 6      def __init__(self, player):          self._callbacks = dict() diff --git a/solo-tool-project/src/solo_tool/solo_tool.py b/solo-tool-project/src/solo_tool/solo_tool.py index f5b05c0..bc20013 100644 --- a/solo-tool-project/src/solo_tool/solo_tool.py +++ b/solo-tool-project/src/solo_tool/solo_tool.py @@ -4,8 +4,8 @@ from .notifier import Notifier  from .player_vlc import Player  class SoloTool: -    def __init__(self, playerOverride=None): -        self._player = Player() if playerOverride is None else playerOverride +    def __init__(self, player=None): +        self._player = Player() if player is None else player          self._notifier = Notifier(self._player)          self._songs = []          self._song = None @@ -31,8 +31,11 @@ class SoloTool:      def addSong(self, path: str) -> None:          if not os.path.isfile(path):              raise FileNotFoundError(path) +        if path in self._songs: +            return          self._songs.append(path)          self._keyPoints.append([]) +        self._notifier.notify(Notifier.SONG_LIST_EVENT, self.songs)          if self.song is None:              self.song = 0 @@ -116,6 +119,12 @@ class SoloTool:          if new is not None and new != self._player.getPlaybackPosition():              self._player.setPlaybackPosition(min(max(0.0, new), 1.0)) +    def registerSongSelectionCallback(self, callback): +        self._notifier.registerCallback(Notifier.CURRENT_SONG_EVENT, callback) + +    def registerSongListCallback(self, callback): +        self._notifier.registerCallback(Notifier.SONG_LIST_EVENT, callback) +      def registerPlayingStateCallback(self, callback):          self._notifier.registerCallback(Notifier.PLAYING_STATE_EVENT, callback) @@ -125,9 +134,6 @@ class SoloTool:      def registerRateCallback(self, callback):          self._notifier.registerCallback(Notifier.PLAYBACK_RATE_EVENT, callback) -    def registerCurrentSongCallback(self, callback): -        self._notifier.registerCallback(Notifier.CURRENT_SONG_EVENT, callback) -      def registerCurrentKeyPointCallback(self, callback):          self._notifier.registerCallback(Notifier.CURRENT_KEY_POINT_EVENT, callback) diff --git a/solo-tool-project/src/solo_tool/solo_tool_songs_integrationtest.py b/solo-tool-project/test/solo_tool_songs_integrationtest.py index 0023d81..3d9368b 100644 --- a/solo-tool-project/src/solo_tool/solo_tool_songs_integrationtest.py +++ b/solo-tool-project/test/solo_tool_songs_integrationtest.py @@ -46,15 +46,15 @@ def test_songSelectionFlow(uut, mockPlayer, testSongs):          assert uut.song == i          assert mockPlayer.currentSong == uut.songs[i] -def test_songSelectionSanitization(uut, mockPlayer, testSongs): +def test_songSelectionEdgeCases(uut, mockPlayer, testSongs): +    # When no songs are available, selecting has no effect +    uut.song = 0 +    assert uut.song == None +    assert mockPlayer.currentSong == None +      for song in testSongs:          uut.addSong(song) -    # Modifying the song list directly has no effect -    uut.songs.append("something") -    assert uut.songs == testSongs -    assert mockPlayer.currentSong == testSongs[0] -      # The current song cannot be de-selected      uut.song = None      assert uut.song == 0 @@ -69,44 +69,91 @@ def test_songSelectionSanitization(uut, mockPlayer, testSongs):      assert uut.song == 0      assert mockPlayer.currentSong == testSongs[0] -def test_addInexistentSong(uut, mockPlayer): -    # Songs must exist in the filesystem -    song = "not/a/real/file" - -    with pytest.raises(FileNotFoundError): +def test_songAdditionEdgeCases(uut, mockPlayer, testSongs): +    for song in testSongs:          uut.addSong(song) -    assert uut.songs == [] -    assert uut.song is None +    # Modifying the song list directly has no effect +    uut.songs.append("something") +    assert uut.songs == testSongs +    assert mockPlayer.currentSong == testSongs[0] + +    # Same song cannot be added twice +    uut.addSong(testSongs[0]) +    assert uut.song == 0 +    assert mockPlayer.currentSong == testSongs[0] +    assert uut.songs == testSongs + +    # Songs must exist in the filesystem +    with pytest.raises(FileNotFoundError): +        uut.addSong("/not/a/real/file") +    assert uut.song == 0 +    assert mockPlayer.currentSong == testSongs[0] +    assert uut.songs == testSongs  def test_songSelectionNotification(uut, testSongs): -    called = False -    receivedValue = None -    def callback(value): -        nonlocal called, receivedValue -        called = True -        receivedValue = value +    selectionCalled = False +    selectionValue = None +    def selectionCallback(value): +        nonlocal selectionCalled, selectionValue +        selectionCalled = True +        selectionValue = value -    uut.registerSongSelectionCallback(callback) -    assert not called +    uut.registerSongSelectionCallback(selectionCallback) +    assert not selectionCalled      # Adding the first song triggers because the song is automatically selected -    uut.addSong(songs[0]) -    assert called -    assert receivedValue == 0 -    called = False +    uut.addSong(testSongs[0]) -    # Adding more songs does not trigger since the selection doesn't change -    for song in testSongs: +    assert selectionCalled +    assert selectionValue == 0 +    selectionCalled = False + +    # Adding more songs does not trigger +    for i, song in enumerate(testSongs[1:]):          uut.addSong(song) -        assert not called +        assert not selectionCalled      # Selecting another song triggers      uut.song = 1 -    assert called -    assert receivedValue == 1 -    called = False +    assert selectionCalled +    assert selectionValue == 1 +    selectionCalled = False      # Selecting the currently selected song does not trigger      uut.song = 1 -    assert not called +    assert not selectionCalled + +def test_songListNotification(uut, testSongs): +    listCalled = False +    listValue = None +    def listCallback(value): +        nonlocal listCalled, listValue +        listCalled = True +        listValue = value + +    uut.registerSongListCallback(listCallback) +    assert not listCalled + +    # Adding the first song triggers +    uut.addSong(testSongs[0]) + +    assert listCalled +    assert listValue == testSongs[0:1] +    listCalled = False + +    # Adding more songs triggers +    for i, song in enumerate(testSongs[1:]): +        uut.addSong(song) + +        assert listCalled +        assert listValue == testSongs[0:i + 2] +        listCalled = False + +    # Modifying the list in place does not trigger +    uut.songs.append("something") +    assert not listCalled + +    # Adding an existing song does not trigger +    uut.addSong(testSongs[0]) +    assert not listCalled | 
