import pytest from midi_controller_launchpad_mini import MidiController 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) class SoloToolMock: STOPPED = 0 PLAYING = 1 PAUSED = 2 def __init__(self): self.state = SoloToolMock.STOPPED self.position = 0.0 self.currentAbLimit = (0.0, 0.0) self.currentLoadedAbLimitIndex = None self.currentSong = None def play(self): self.state = SoloToolMock.PLAYING def pause(self): self.state = SoloToolMock.PAUSED def stop(self): self.state = SoloToolMock.STOPPED def isPlaying(self): return self.state == SoloToolMock.PLAYING def jumpToA(self): self.position = self.currentAbLimit[0] def loadAbLimits(self, index): self.currentLoadedAbLimitIndex = index def setSong(self, index): self.currentSong = index def nextSong(self): if self.currentSong is None: self.currentSong = 0 else: self.currentSong += 1 def previousSong(self): if self.currentSong is None: self.currentSong = 0 else: self.currentSong = max(self.currentSong - 1, 0) @pytest.fixture def soloToolMock(): return SoloToolMock() @pytest.fixture def midiWrapperMock(): return MidiWrapperMock() @pytest.fixture def uut(soloToolMock, midiWrapperMock): return MidiController(soloToolMock, midiWrapperMock) def test_connect(uut, midiWrapperMock): expectedDevice = "Launchpad Mini MIDI 1" uut.connect() assert midiWrapperMock.connectedDevice == expectedDevice def test_startStopAndPauseButtons(uut, midiWrapperMock, soloToolMock): playPauseButton = 112 stopButton = 96 uut.connect() assert soloToolMock.state == SoloToolMock.STOPPED midiWrapperMock.simulateInput(playPauseButton) assert soloToolMock.state == SoloToolMock.PLAYING midiWrapperMock.simulateInput(stopButton) assert soloToolMock.state == SoloToolMock.STOPPED midiWrapperMock.simulateInput(playPauseButton) midiWrapperMock.simulateInput(playPauseButton) assert soloToolMock.state == SoloToolMock.PAUSED midiWrapperMock.simulateInput(playPauseButton) assert soloToolMock.state == SoloToolMock.PLAYING midiWrapperMock.simulateInput(playPauseButton) midiWrapperMock.simulateInput(stopButton) assert soloToolMock.state == SoloToolMock.STOPPED def test_jumpToAButton(uut, midiWrapperMock, soloToolMock): ab = (0.5, 0.6) uut.connect() soloToolMock.currentAbLimit = (ab[0], ab[1]) assert soloToolMock.position == 0.0 midiWrapperMock.simulateInput(101) assert soloToolMock.position == ab[0] def test_previousAndNextSongButtons(uut, midiWrapperMock, soloToolMock): uut.connect() assert soloToolMock.currentSong == None midiWrapperMock.simulateInput(119) assert soloToolMock.currentSong == 0 midiWrapperMock.simulateInput(119) assert soloToolMock.currentSong == 1 midiWrapperMock.simulateInput(118) assert soloToolMock.currentSong == 0 midiWrapperMock.simulateInput(118) assert soloToolMock.currentSong == 0 def test_unprogrammedButton(uut, midiWrapperMock, soloToolMock): unusedButton = 48 uut.connect() # expect no crash midiWrapperMock.simulateInput(48)