import pytest from midi_controller_launchpad_mini import MidiController from solo_tool import SoloTool from player_mock import Player as PlayerMock class MidiWrapperMock: def __init__(self): self.callback = None self.connectedDevice = None self.lastMessageSent = None def setCallback(self, callback): self.callback = callback def connect(self, deviceName): self.connectedDevice = deviceName def sendMessage(self, note, velocity=127, channel=0): pass def simulateInput(self, note, velocity=127, channel=0): if self.callback is not None: from mido import Message msg = Message("note_on", note=note, velocity=velocity, channel=channel) self.callback(msg) @pytest.fixture def playerMock(): return PlayerMock() @pytest.fixture def soloTool(playerMock): return SoloTool(playerMock) @pytest.fixture def midiWrapperMock(): return MidiWrapperMock() @pytest.fixture def uut(soloTool, midiWrapperMock): return MidiController(soloTool, midiWrapperMock) def test_connect(uut, midiWrapperMock): expectedDevice = "Launchpad Mini MIDI 1" uut.connect() assert midiWrapperMock.connectedDevice == expectedDevice def test_startStopAndPauseButtons(uut, midiWrapperMock, playerMock): playPauseButton = 112 stopButton = 96 uut.connect() assert playerMock.state == PlayerMock.STOPPED midiWrapperMock.simulateInput(playPauseButton) assert playerMock.state == PlayerMock.PLAYING midiWrapperMock.simulateInput(stopButton) assert playerMock.state == PlayerMock.STOPPED midiWrapperMock.simulateInput(playPauseButton) midiWrapperMock.simulateInput(playPauseButton) assert playerMock.state == PlayerMock.PAUSED midiWrapperMock.simulateInput(playPauseButton) assert playerMock.state == PlayerMock.PLAYING midiWrapperMock.simulateInput(playPauseButton) midiWrapperMock.simulateInput(stopButton) assert playerMock.state == PlayerMock.STOPPED def test_jumpToAButton(uut, midiWrapperMock, soloTool, playerMock): ab = (0.5, 0.6) uut.connect() soloTool.setAbLimits(ab[0], ab[1]) assert playerMock.position == 0.0 midiWrapperMock.simulateInput(101) assert playerMock.position == ab[0] def test_previousAndNextSongButtons(uut, midiWrapperMock, soloTool, playerMock): nextSongButton = 119 previousSongButton = 118 songs = [ "test.flac", "test.mp3" ] for s in songs: soloTool.addSong(s) uut.connect() assert playerMock.currentSong == None midiWrapperMock.simulateInput(nextSongButton) assert playerMock.currentSong == songs[0] midiWrapperMock.simulateInput(nextSongButton) assert playerMock.currentSong == songs[1] midiWrapperMock.simulateInput(previousSongButton) assert playerMock.currentSong == songs[0] midiWrapperMock.simulateInput(previousSongButton) assert playerMock.currentSong == songs[0] def test_previousAndNextAbButtons(uut, midiWrapperMock, soloTool, playerMock): nextLimitButton = 103 previousLimitButton = 102 song = "test.flac" abLimits = [ [0.2, 0.4], [0.1, 0.3] ] soloTool.addSong(song) soloTool.setSong(0) soloTool.setAbLimitEnable(True) for ab in abLimits: soloTool.storeAbLimits(ab[0], ab[1]) uut.connect() def checkLimit(aLimit, bLimit): playerMock.position = bLimit - 0.1 soloTool.tick() assert playerMock.position == bLimit - 0.1 playerMock.position = bLimit + 0.1 soloTool.tick() assert playerMock.position == aLimit checkLimit(0.0, 0.0) midiWrapperMock.simulateInput(nextLimitButton) checkLimit(abLimits[0][0], abLimits[0][1]) midiWrapperMock.simulateInput(nextLimitButton) checkLimit(abLimits[1][0], abLimits[1][1]) midiWrapperMock.simulateInput(nextLimitButton) checkLimit(abLimits[1][0], abLimits[1][1]) midiWrapperMock.simulateInput(previousLimitButton) checkLimit(abLimits[0][0], abLimits[0][1]) midiWrapperMock.simulateInput(previousLimitButton) checkLimit(abLimits[0][0], abLimits[0][1]) def test_unassignedButton(uut, midiWrapperMock): unassignedButton = 48 uut.connect() # expect no crash midiWrapperMock.simulateInput(unassignedButton) # XXX would be better to assert that nothing changed in the solo tool