def test_record_edit(self): """ Test edited record returns the same record ID with different data """ # GIVEN: Record entries in database add_records(self.projector, [Projector(**TEST1_DATA), Projector(**TEST2_DATA)]) # WHEN: We retrieve a specific record record = self.projector.get_projector_by_ip(TEST1_DATA['ip']) record_id = record.id # WHEN: Data is changed record.ip = TEST3_DATA['ip'] record.port = TEST3_DATA['port'] record.pin = TEST3_DATA['pin'] record.name = TEST3_DATA['name'] record.location = TEST3_DATA['location'] record.notes = TEST3_DATA['notes'] record.sw_version = TEST3_DATA['sw_version'] record.serial_no = TEST3_DATA['serial_no'] record.model_filter = TEST3_DATA['model_filter'] record.model_lamp = TEST3_DATA['model_lamp'] updated = self.projector.update_projector(record) assert updated is True, 'Save updated record should have returned True' record = self.projector.get_projector_by_ip(TEST3_DATA['ip']) # THEN: Record ID should remain the same, but data should be changed assert record_id == record.id, 'Edited record should have the same ID' assert compare_data( Projector(**TEST3_DATA), record) is True, 'Edited record should have new data'
def test_add_projector_fail(self): """ Test add_projector() fail """ # GIVEN: Test entry in the database self.projector.add_projector(Projector(**TEST1_DATA)) # WHEN: Attempt to add same projector entry results = self.projector.add_projector(Projector(**TEST1_DATA)) # THEN: We should have failed to add new entry assert results is False, 'add_projector() should have failed'
def test_delete_projector_fail(self): """ Test delete_projector(projector) fails to delete record """ # GIVEN: Test entry in db self.projector.add_projector(Projector(**TEST1_DATA)) # wHEN: Attempting to delete an entry not in the databae results = self.projector.delete_projector(Projector(**TEST2_DATA)) # THEN: Results should be False assert results is False, 'delete_projector() should have returned False'
def test_update_projector_not_in_db_fail(self): """ Test update_projector() when entry not in database """ # GIVEN: Projector entry in database self.projector.add_projector(Projector(**TEST1_DATA)) projector = Projector(**TEST2_DATA) # WHEN: Attempt to update data with a different ID results = self.projector.update_projector(projector) # THEN: Results should be False assert results is False, 'update_projector(projector=projector) should have returned False'
def test_process_command_future(self): """ Test command valid but no method to process yet """ # GIVEN: Test object with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.pjlink_functions = MagicMock() log_warning_text = [ call( '({ip}) Unable to process command="CLSS" (Future option?)'. format(ip=pjlink.name)) ] log_debug_text = [ call( '({ip}) Processing command "CLSS" with data "Huh?"'.format( ip=pjlink.name)) ] # WHEN: Processing a possible future command pjlink.process_command(cmd='CLSS', data="Huh?") # THEN: Appropriate log entries should have been made and methods called/not called mock_log.debug.assert_has_calls(log_debug_text) mock_log.warning.assert_has_calls(log_warning_text) assert pjlink.pjlink_functions.called is False, 'Should not have accessed pjlink_functions' assert mock_process_clss.called is False, 'Should not have called process_clss'
def test_projector_change_status_connection_status_connecting(self): """ Test change_status with connecting status """ # GIVEN: Test object and mocks with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.projector_status = 0 pjlink.status_connect = 0 log_debug_calls = [ call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, status=STATUS_CODE[S_CONNECTING], msg=STATUS_MSG[S_CONNECTING])), call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_CONNECTING], msg=STATUS_MSG[S_CONNECTING])), call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=STATUS_MSG[S_OK])), call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=STATUS_MSG[S_OK]))] # WHEN: change_status called with CONNECTING pjlink.change_status(status=S_CONNECTING) # THEN: Proper settings should change and signals sent mock_log.debug.assert_has_calls(log_debug_calls) mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, STATUS_MSG[S_CONNECTING]) assert pjlink.projector_status == S_OK, 'Projector status should not have changed' assert pjlink.status_connect == S_CONNECTING, 'Status connect should be CONNECTING' assert mock_UpdateIcons.emit.called is True, 'Should have called UpdateIcons'
def test_process_command_erra(self): """ Test ERRA - Authentication Error """ # GIVEN: Test object with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_pjlink') as mock_process_pjlink, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host') as mock_disconnect, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorAuthentication') as mock_authentication: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) log_error_calls = [ call('({ip}) PJLINK: {msg}'.format( ip=pjlink.name, msg=STATUS_MSG[E_AUTHENTICATION])) ] log_debug_calls = [ call('({ip}) Processing command "PJLINK" with data "ERRA"'. format(ip=pjlink.name)) ] # WHEN: process_command called with ERRA pjlink.process_command(cmd='PJLINK', data=PJLINK_ERRORS[E_AUTHENTICATION]) # THEN: Appropriate log entries should have been made and methods called/not called assert mock_disconnect.called is True, 'disconnect_from_host should have been called' mock_log.error.assert_has_calls(log_error_calls) mock_log.debug.assert_has_calls(log_debug_calls) mock_change_status.assert_called_once_with(status=E_AUTHENTICATION) mock_authentication.emit.assert_called_once_with(pjlink.name) mock_process_pjlink.assert_not_called()
def test_projector_change_status_connection_status_with_message(self): """ Test change_status with connection status """ # GIVEN: Test object and mocks with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.projector_status = 0 pjlink.status_connect = 0 test_message = 'Different Status Message than default' log_debug_calls = [ call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, status=STATUS_CODE[S_ON], msg=test_message)), call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=test_message)), call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_ON], msg=test_message)), call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=test_message))] # WHEN: change_status called with projector ON status pjlink.change_status(status=S_ON, msg=test_message) # THEN: Proper settings should change and signals sent mock_log.debug.assert_has_calls(log_debug_calls) mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_ON, test_message) assert pjlink.projector_status == S_ON, 'Projector status should be ON' assert pjlink.status_connect == S_OK, 'Status connect should not have changed'
def test_find_record_by_name(self): """ Test find record by name """ # GIVEN: Record entries in database add_records(self.projector, [Projector(**TEST1_DATA), Projector(**TEST2_DATA)]) # WHEN: Search for record using name record = self.projector.get_projector_by_name(TEST2_DATA['name']) # THEN: Verify proper record returned assert compare_data( Projector(**TEST2_DATA), record) is True, 'Record found should have been test_2 data'
def test_process_command_err4(self): """ Test ERR3 - Unavailable error """ # GIVEN: Test object with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) log_error_text = [ call('({ip}) CLSS: {msg}'.format(ip=pjlink.name, msg=STATUS_MSG[E_PROJECTOR])) ] log_debug_text = [ call( '({ip}) Processing command "CLSS" with data "ERR4"'.format( ip=pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=pjlink.name)) ] # WHEN: process_command called with ERR4 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR]) # THEN: Appropriate log entries should have been made and methods called mock_log.error.assert_has_calls(log_error_text) mock_log.debug.assert_has_calls(log_debug_text) mock_process_clss.assert_called_once_with( data=PJLINK_ERRORS[E_PROJECTOR])
def test_get_projector_by_name_fail(self): """ Test get_projector_by_name() fail """ # GIVEN: Test entry in database self.projector.add_projector(Projector(**TEST1_DATA)) # WHEN: We attempt to get a projector that's not in database results = self.projector.get_projector_by_name(name=TEST2_DATA['name']) # THEN: We should have None assert results is None, 'projector.get_projector_by_name() should have returned None'
def test_projector_get_status_unknown(self): """ Test to check returned information for unknown code """ # GIVEN: Test object pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) # WHEN: get_status called code, message = pjlink._get_status(status=9999) # THEN: Proper strings should have been returned assert code is None, 'Code returned should have been the same code that was sent' assert message is None, 'Should have returned None as message'
def test_socket_abort(self): """ Test PJLink.socket_abort calls disconnect_from_host """ # GIVEN: Test object with patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host') as mock_disconnect: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) # WHEN: Calling socket_abort pjlink.socket_abort() # THEN: disconnect_from_host should be called assert mock_disconnect.called is True, 'Should have called disconnect_from_host'
def test_get_projector_all_many(self): """ Test get_projector_all() with multiple entries in db """ # GIVEN: multiple entries in database projector_list = [] projector_list.append(Projector(**TEST1_DATA)) projector_list.append(Projector(**TEST2_DATA)) projector_list.append(Projector(**TEST3_DATA)) for projector in projector_list: self.projector.add_projector(projector) # WHEN: We retrieve the database entries results = self.projector.get_projector_all() # THEN: We should have a list with three entries assert len(results) == len( projector_list ), 'Returned results should have returned a list with three entries' for projector in results: assert ( projector in projector_list ) is True, 'Projector DB entry should have been in expected list'
def test_projector_get_status_valid(self): """ Test to check returned information for status codes """ # GIVEN: Test object test_message = 'Not Connected' pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) # WHEN: get_status called code, message = pjlink._get_status(status=S_NOT_CONNECTED) # THEN: Proper strings should have been returned assert code == 'S_NOT_CONNECTED', 'Code returned should have been the same code that was sent' assert message == test_message, 'Description of code should have been returned'
def test_projector_get_status_invalid(self): """ Test to check returned information for error code """ # GIVEN: Test object pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) test_string = 'NaN test' # WHEN: get_status called code, message = pjlink._get_status(status=test_string) # THEN: Proper data should have been returned assert code == -1, 'Should have returned -1 as a bad status check' assert message is None, 'Invalid code type should have returned None for message'
def test_record_delete(self): """ Test record can be deleted """ # GIVEN: Record in database add_records(self.projector, [ Projector(**TEST3_DATA), ]) record = self.projector.get_projector_by_ip(TEST3_DATA['ip']) # WHEN: Record deleted self.projector.delete_projector(record) # THEN: Verify record not retrievable found = self.projector.get_projector_by_ip(TEST3_DATA['ip']) assert found is None, 'test_3 record should have been deleted'
def test_poll_loop_not_connected(self): """ Test PJLink.poll_loop not connected return """ # GIVEN: Test object and mocks pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.state = MagicMock() pjlink.timer = MagicMock() pjlink.state.return_value = False pjlink.ConnectedState = True # WHEN: PJLink.poll_loop called pjlink.poll_loop() # THEN: poll_loop should exit without calling any other method assert pjlink.timer.called is False, 'Should have returned without calling any other method'
def exec(self, projector=None): if projector is None: self.projector = Projector() self.new_projector = True self.ip_text_edit.setVisible(True) self.ip_text_edit.setFocus() self.ip_text_label.setVisible(False) else: self.projector = projector self.new_projector = False self.ip_text_edit.setVisible(False) self.ip_text_label.setVisible(True) # Since it's already defined, IP address is unchangeable, so focus on port number self.port_text.setFocus() self.retranslate_ui(self) reply = QtWidgets.QDialog.exec(self) return reply
def test_get_data_unknown_command(self, mock_log): """ Test not a valid command """ # GIVEN: Test object pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.pjlink_functions = MagicMock() log_warning_text = [ call('({ip}) get_data(): Invalid packet - ' 'unknown command "UNKN"'.format(ip=pjlink.name)) ] log_debug_text = [ call( 'PJlink(projector="< Projector(id="None", ip="111.111.111.111", port="1111", ' 'mac_adx="11:11:11:11:11:11", pin="1111", name="___TEST_ONE___", ' 'location="location one", notes="notes one", pjlink_name="None", ' 'pjlink_class="None", manufacturer="None", model="None", serial_no="Serial Number 1", ' 'other="None", sources="None", source_list="[]", model_filter="Filter type 1", ' 'model_lamp="Lamp type 1", sw_version="Version 1") >", ' 'args="()" kwargs="{\'no_poll\': True}")'), call('PJlinkCommands(args=() kwargs={})'), call( '(___TEST_ONE___) reset_information() connect status is S_NOT_CONNECTED' ), call('(___TEST_ONE___) get_data(buffer="%1UNKN=Huh?"'), call('(___TEST_ONE___) get_data(): Checking new data "%1UNKN=Huh?"' ), call('(___TEST_ONE___) get_data() header="%1UNKN" data="Huh?"'), call('(___TEST_ONE___) get_data() version="1" cmd="UNKN"'), call( '(___TEST_ONE___) Cleaning buffer - msg = "get_data(): Invalid packet - ' 'unknown command "UNKN""'), call( '(___TEST_ONE___) Finished cleaning buffer - 0 bytes dropped'), call( '(___TEST_ONE___) _send_command(): Nothing to send - returning' ) ] # WHEN: get_data called with an unknown command pjlink.get_data(buff='{prefix}1UNKN=Huh?'.format(prefix=PJLINK_PREFIX)) # THEN: Appropriate log entries should have been made and methods called/not called mock_log.warning.assert_has_calls(log_warning_text) mock_log.debug.assert_has_calls(log_debug_text) assert pjlink.pjlink_functions.called is False, 'Should not have accessed pjlink_functions'
def test_status_change(self): """ Test process_command call with ERR2 (Parameter) status """ # GIVEN: Test object with patch('openlp.core.projectors.pjlink.PJLink.changeStatus') as mock_changeStatus: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) # WHEN: process_command is called with "ERR2" status from projector pjlink.process_command('POWR', 'ERR2') # THEN: change_status should have called change_status with E_UNDEFINED # as first parameter mock_changeStatus.called_with(E_PARAMETER, 'change_status should have been called with "{}"'.format( STATUS_CODE[E_PARAMETER]))
def test_get_projector_all_one(self): """ Test get_projector_all() with one entry in db """ # GIVEN: One entry in database projector = Projector(**TEST1_DATA) self.projector.add_projector(projector) # WHEN: We retrieve the database entries results = self.projector.get_projector_all() # THEN: We should have a list with one entry assert 1 == len( results ), 'Returned results should have returned a list with one entry' assert (projector in results ) is True, 'Result should have been equal to TEST1_DATA'
def test_projector_reset_information(self): """ Test reset_information() resets all information and stops timers """ # GIVEN: Test object with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) log_debug_calls = [call('({ip}): Calling poll_timer.stop()'.format(ip=pjlink.name)), call('({ip}): Calling socket_timer.stop()'.format(ip=pjlink.name))] # timer and socket_timer not available until instantiation, so mock here with patch.object(pjlink, 'socket_timer') as mock_socket_timer, \ patch.object(pjlink, 'poll_timer') as mock_timer: pjlink.power = S_ON pjlink.pjlink_name = 'OPENLPTEST' pjlink.manufacturer = 'PJLINK' pjlink.model = '1' pjlink.shutter = True pjlink.mute = True pjlink.lamp = True pjlink.fan = True pjlink.source_available = True pjlink.other_info = 'ANOTHER TEST' pjlink.send_queue = True pjlink.send_busy = True # WHEN: reset_information() is called pjlink.reset_information() # THEN: All information should be reset and timers stopped assert pjlink.power == S_OFF, 'Projector power should be OFF' assert pjlink.pjlink_name is None, 'Projector pjlink_name should be None' assert pjlink.manufacturer is None, 'Projector manufacturer should be None' assert pjlink.model is None, 'Projector model should be None' assert pjlink.shutter is None, 'Projector shutter should be None' assert pjlink.mute is None, 'Projector shuttter should be None' assert pjlink.lamp is None, 'Projector lamp should be None' assert pjlink.fan is None, 'Projector fan should be None' assert pjlink.source_available is None, 'Projector source_available should be None' assert pjlink.source is None, 'Projector source should be None' assert pjlink.other_info is None, 'Projector other_info should be None' assert pjlink.send_queue == [], 'Projector send_queue should be an empty list' assert pjlink.send_busy is False, 'Projector send_busy should be False' assert mock_timer.stop.called is True, 'Projector timer.stop() should have been called' assert mock_socket_timer.stop.called is True, 'Projector socket_timer.stop() should have been called' mock_log.debug.assert_has_calls(log_debug_calls)
def test_edit_form_edit_projector(self, mocked_exec): """ Test projector edit form with existing projector entry :return: """ # GIVEN: Mocked setup # WHEN: Calling edit form with existing projector instance self.projector_form.exec(projector=Projector(**TEST1_DATA)) item = self.projector_form.projector # THEN: Should be editing an existing entry self.assertFalse( self.projector_form.new_projector, 'Projector edit form should be marked as existing entry') self.assertTrue( (item.ip is TEST1_DATA['ip'] and item.name is TEST1_DATA['name']), 'Projector edit form should have TEST1_DATA() instance to edit')
def setUp(self, mocked_init_url): """ Set up anything necessary for all tests """ mocked_init_url.return_value = 'sqlite:///{}'.format(TEST_DB) self.setup_application() self.build_settings() Registry.create() # Do not try to recreate if we've already been created from a previous test if not hasattr(self, 'projectordb'): self.projectordb = ProjectorDB() # Retrieve/create a database record self.projector = self.projectordb.get_projector_by_ip(TEST1_DATA['ip']) if not self.projector: self.projectordb.add_projector(projector=Projector(**TEST1_DATA)) self.projector = self.projectordb.get_projector_by_ip(TEST1_DATA['ip']) self.projector.dbid = self.projector.id self.projector.db_item = self.projector
def test_projector_get_power_status(self): """ Test sending command to retrieve current power state """ # GIVEN: Test object and mocks with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) test_data = 'POWR' log_debug_calls = [call('({ip}) reset_information() connect status is ' '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_input_source is called pjlink.get_power_status() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data, priority=False)
def test_process_pjlink_invalid_authentication_data_length_error(self): """ Test initial connection prompt with authentication no salt """ # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) log_check = [call('({ip}) Authenticated connection but not enough info - aborting'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with no salt pjlink.process_pjlink(data='1') # THEN: socket should be closed and invalid data logged mock_log.error.assert_has_calls(log_check) assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once' mock_send_command.assert_not_called()
def test_projectorsource_repr(self): """ Test ProjectorSource.__repr__() text """ # GIVEN: test setup projector1 = Projector(**TEST1_DATA) self.projector.add_projector(projector1) item = self.projector.get_projector_by_id(projector1.id) item_id = item.id # WHEN: A source entry is saved for item source = ProjectorSource(projector_id=item_id, code='11', text='First RGB source') self.projector.add_source(source) # THEN: __repr__ should return a proper string assert str(source) == '<ProjectorSource(id="1", code="11", text="First RGB source", projector_id="1")>', \ 'ProjectorSource.__repr__)_ should have returned a proper representation string'
def test_process_pjlink_normal_with_salt_error(self): """ Test process_pjlinnk called with no authentication but pin is set """ # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.pin = TEST_PIN log_check = [call('({ip}) Normal connection with extra information - aborting'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with invalid authentication scheme pjlink.process_pjlink(data='0 {salt}'.format(salt=TEST_SALT)) # THEN: Proper calls should be made mock_log.error.assert_has_calls(log_check) assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once' mock_send_command.assert_not_called()
def test_poll_loop_set_interval(self): """ Test PJLink.poll_loop makes correct calls """ # GIVEN: Mocks and test data with patch('openlp.core.projectors.pjlink.PJLink.send_command') as mock_send_command: pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.state = MagicMock() pjlink.state.return_value = QSOCKET_STATE[S_CONNECTED] pjlink.poll_timer = MagicMock() pjlink.poll_timer.interval.return_value = 10 pjlink.poll_time = 20 pjlink.power = S_ON pjlink.source_available = None pjlink.other_info = None pjlink.manufacturer = None pjlink.model = None pjlink.pjlink_name = None call_list = [ call('POWR'), call('ERST'), call('LAMP'), call('AVMT'), call('INPT'), call('INST'), call('INFO'), call('INF1'), call('INF2'), call('NAME'), ] # WHEN: PJLink.poll_loop is called pjlink.poll_loop() # THEN: proper calls were made to retrieve projector data # First, call to update the timer with the next interval assert pjlink.poll_timer.setInterval.called is True, 'Timer update interval should have been called' # Finally, should have called send_command with a list of projetctor status checks mock_send_command.assert_has_calls(call_list, 'Should have queued projector queries')