def test_action_failed(capsys, printer): failed_message = 'unable to find a package matching the name provided' printer.action(EliteState.RUNNING, 'brew', args={ 'name': 'htop', 'state': 'latest' }) printer.action(EliteState.FAILED, 'brew', args={ 'name': 'htop', 'state': 'latest' }, response=EliteResponse(changed=False, ok=False, failed_message=failed_message)) out, _err = capsys.readouterr() assert out == (ansi.WHITE + ' running ' + ansi.ENDC + ansi.BLUE + 'brew: ' + ansi.ENDC + ansi.YELLOW + "name='htop' state='latest'" + ansi.ENDC + '\r' + ansi.RED + ' failed ' + ansi.ENDC + ansi.BLUE + 'brew: ' + ansi.ENDC + ansi.YELLOW + "name='htop' state='latest'" + ansi.ENDC + '\n' + ' ' + ansi.BLUE + 'message: ' + ansi.ENDC + ansi.YELLOW + failed_message + ansi.ENDC + '\n')
def test_summary_no_ok(capsys, printer): actions = { EliteState.OK: [], EliteState.CHANGED: [('cask', { 'name': 'slack', 'state': 'latest' }, EliteResponse(changed=True, ok=True))], EliteState.FAILED: [('brew', { 'name': 'sheepsay', 'state': 'present' }, EliteResponse(changed=False, ok=False, failed_message= 'unable to find a package matching the name provided')) ] } printer.summary(actions) out, _err = capsys.readouterr() assert out == ( # Changed actions '\n' + ansi.BOLD + 'Changed Actions' + ansi.ENDC + '\n' + '\n' + # cask: slack ansi.YELLOW + ' changed ' + ansi.ENDC + ansi.BLUE + 'cask: ' + ansi.ENDC + ansi.YELLOW + f"name='slack' state='latest'" + ansi.ENDC + '\n' + # Failed actions '\n' + ansi.BOLD + 'Failed Actions' + ansi.ENDC + '\n' + '\n' + # brew: sheepsay ansi.RED + ' failed ' + ansi.ENDC + ansi.BLUE + 'brew: ' + ansi.ENDC + ansi.YELLOW + f"name='sheepsay' state='present'" + ansi.ENDC + '\n' + ' ' + ansi.BLUE + 'message: ' + ansi.ENDC + ansi.YELLOW + 'unable to find a package matching the name provided' + ansi.ENDC + '\n' # Totals '\n' + ansi.BOLD + 'Totals' + ansi.ENDC + '\n' + '\n' + ansi.GREEN + ' ok ' + ansi.ENDC + ' 0' + '\n' + ansi.YELLOW + ' changed ' + ansi.ENDC + ' 1' + '\n' + ansi.RED + ' failed ' + ansi.ENDC + ' 1' + '\n' + ' total ' + ' 2' + '\n')
def test_elite_run_action_changed(monkeypatch, printer): helpers.patch_root_runtime(monkeypatch) class MyAction(Action): def process(self): return self.changed() elite = Elite(printer) elite.register_action('my_action', MyAction) assert elite.my_action() == EliteResponse(changed=True, ok=True)
def test_elite_options_ignore_failed(monkeypatch, printer): helpers.patch_root_runtime(monkeypatch) class MyAction(Action): def process(self): raise ActionError('oh no') elite = Elite(printer) elite.register_action('my_action', MyAction) with elite.options(ignore_failed=True): assert elite.my_action() == EliteResponse(changed=False, ok=False, failed_message='oh no')
def test_summary_no_changed(capsys, printer): actions = { EliteState.OK: [('brew', { 'name': 'htop', 'state': 'latest' }, EliteResponse(changed=False, ok=True)), ('cask', { 'name': 'skype', 'state': 'present' }, EliteResponse(changed=False, ok=True))], EliteState.CHANGED: [], EliteState.FAILED: [] } printer.summary(actions) out, _err = capsys.readouterr() assert out == ( # Totals '\n' + ansi.BOLD + 'Totals' + ansi.ENDC + '\n' + '\n' + ansi.GREEN + ' ok ' + ansi.ENDC + ' 2' + '\n' + ansi.YELLOW + ' changed ' + ansi.ENDC + ' 0' + '\n' + ansi.RED + ' failed ' + ansi.ENDC + ' 0' + '\n' + ' total ' + ' 2' + '\n')
def test_elite_options_env(monkeypatch, printer): helpers.patch_root_runtime(monkeypatch) class MyAction(Action): def process(self): return self.ok(favourite_animal=os.environ['FAVOURITE_ANIMAL'], enjoy_mooing=bool(os.environ['ENJOY_MOOING'])) elite = Elite(printer) elite.register_action('my_action', MyAction) with elite.options(env={'FAVOURITE_ANIMAL': 'cows', 'ENJOY_MOOING': '1'}): assert elite.my_action() == EliteResponse(changed=False, ok=True, data={ 'favourite_animal': 'cows', 'enjoy_mooing': True })
def test_action_changed(capsys, printer): printer.action(EliteState.RUNNING, 'brew', args={ 'name': 'htop', 'state': 'latest' }) printer.action(EliteState.CHANGED, 'brew', args={ 'name': 'htop', 'state': 'latest' }, response=EliteResponse(changed=True, ok=True)) out, _err = capsys.readouterr() assert out == (ansi.WHITE + ' running ' + ansi.ENDC + ansi.BLUE + 'brew: ' + ansi.ENDC + ansi.YELLOW + "name='htop' state='latest'" + ansi.ENDC + '\r' + ansi.YELLOW + ' changed ' + ansi.ENDC + ansi.BLUE + 'brew: ' + ansi.ENDC + ansi.YELLOW + "name='htop' state='latest'" + ansi.ENDC + '\n')
def test_elite_options_sudo(seteuid_mock, setegid_mock, demote_mock, monkeypatch, printer): helpers.patch_root_runtime(monkeypatch) class MyAction(Action): def process(self): return self.ok() elite = Elite(printer) elite.register_action('my_action', MyAction) with elite.options(sudo=True): assert elite.my_action() == EliteResponse(changed=False, ok=True) assert seteuid_mock.call_args_list == [ mock.call(501), mock.call(0), mock.call(501) ] assert setegid_mock.call_args_list == [ mock.call(20), mock.call(0), mock.call(20) ] assert demote_mock.call_args == mock.call(0, 0)
def test_action_output_larger_than_terminal(capsys, printer): # Ensure that the message is larger than 80 x 24 message = 'o' * (80 * 25) printer.action(EliteState.RUNNING, 'info', args={'message': message}) printer.action(EliteState.OK, 'info', args={'message': message}, response=EliteResponse(changed=True, ok=True)) out, _err = capsys.readouterr() # The first line of output also contains the status and action name, so we subtract those # from the width of the first line of the message: # (terminal char width) 80 - (status) 10 - (action name) 6 - (args with quote) 9 = 55 # # The last line of output will lose the last 3 characters in place of ... cropped_message = 'o' * (55 + 80 * 22 + 77) + '...' assert out == (ansi.WHITE + ' running ' + ansi.ENDC + ansi.BLUE + 'info: ' + ansi.ENDC + ansi.YELLOW + f"message='{cropped_message}" + ansi.ENDC + '\r' + ansi.move_up(23) + ansi.GREEN + ' ok ' + ansi.ENDC + ansi.BLUE + 'info: ' + ansi.ENDC + ansi.YELLOW + f"message='{message}'" + ansi.ENDC + '\n')
def test_action_overlap(capsys, printer): message = ( 'this is truly a very very long message that will exceed the 80 characters that we have ' 'in our terminal and spill over into the next line which should cause the cursor to ' 'to move up to the starting line when printing the ok message') printer.action(EliteState.RUNNING, 'info', args={'message': message}) printer.action(EliteState.OK, 'info', args={'message': message}, response=EliteResponse(changed=True, ok=True)) out, _err = capsys.readouterr() # The final length of the line is as follows: # (status) 10 + (action name) 6 + (message) 230 = 246 => 4 lines (for an 80 x 24 terminal) # # As such, the cursor will be on line 4, so we move it to the left using a \r and up 3 lines # to reach the first line of output. assert out == (ansi.WHITE + ' running ' + ansi.ENDC + ansi.BLUE + 'info: ' + ansi.ENDC + ansi.YELLOW + f"message='{message}'" + ansi.ENDC + '\r' + ansi.move_up(3) + ansi.GREEN + ' ok ' + ansi.ENDC + ansi.BLUE + 'info: ' + ansi.ENDC + ansi.YELLOW + f"message='{message}'" + ansi.ENDC + '\n')