"""Tests for cli module.""" from argparse import ArgumentParser from unittest.mock import call from unittest.mock import Mock from unittest.mock import patch from flows import cli def test_init_flow_sub_commands(): """Are sub command hooks properly run.""" flows = { 'test-digital': Mock(), 'test-theater': Mock()} sub_commands = [ { 'command': 'test_execute', 'help': 'test execute help', 'subparser': Mock()}, { 'command': 'test_worker', 'help': 'test worker help', 'subparser': Mock()}] subparser = Mock() subparser.add_parser.side_effect = [ cmd['subparser'] for cmd in sub_commands] cli.init_flow_sub_commands(subparser, flows, sub_commands) for cmd in sub_commands: # sub command is added subparser.add_parser.assert_any_call(cmd['command'], help=cmd['help']) # all flows initialize for the sub-command for flow_name, flow_mock in flows.items(): cmd['subparser'].add_subparsers().add_parser.assert_any_call( flow_name) method_name = 'init_{cmd}_parser'.format(cmd=cmd['command']) assert getattr(flow_mock, method_name).called @patch('flows.cli.flows') @patch('flows.cli.importlib') def test_get_flows_cli(importlib, flows): """Check to make sure it gets flow modules properly.""" # no flows flows.__all__ = {} modules = cli.get_flows_cli() assert modules == flows.__all__ # some flows module = Mock() modules = {'flows.foo.cli': module} expected = {'foo': module} flows.__all__ = ['foo'] importlib.import_module = lambda x: modules[x] modules = cli.get_flows_cli() assert modules == expected @patch('flows.cli.argparse') @patch('flows.cli.get_flows_cli') @patch('flows.cli.inspect') def test_main(inspect, get_flows_cli, parselib): """Test main function.""" flows = {'test_flow': Mock()} flows['test_flow'].__name__ = 'foo' get_flows_cli.return_value = flows args = Mock() args.log_level = 'CRITICAL' parser = Mock(spec=ArgumentParser()) parser.parse_args.return_value = args parselib.ArgumentParser.return_value = parser # what if no sub-command was given? expected_calls = [call(), call(['--help'])] args.sub_command = None args.sub_command_flow = None cli.main() assert parser.parse_args.call_args_list == expected_calls # what if no sub-command flow was given? expected_calls = [call(), call(['execute', '--help'])] args.sub_command = 'execute' parser.parse_args.return_value = args parser.reset_mock() cli.main() assert parser.parse_args.call_args_list == expected_calls # what if a full complete command was given? expected_calls = [call()] args.sub_command_flow = 'test_flow' args.run_param = 'some_value' args.other_param = 'other thing' parser.parse_args.return_value = args parser.reset_mock() cli.main() assert parser.parse_args.call_args_list == expected_calls # asserting this way because Mock has too much noise, can't use == call_args = flows['test_flow'].run_execute.call_args[1] for param_name in 'run_param', 'other_param': assert call_args[param_name] == getattr(args, param_name) @patch('flows.cli.argparse') @patch('flows.cli.get_flows_cli') @patch('flows.cli.inspect') def test_main_correlation_id(inspect, get_flows_cli, parselib): """Check if it sends the correlation ID when needed.""" flows = {'test_flow': Mock()} flows['test_flow'].__name__ = 'foo' get_flows_cli.return_value = flows args = Mock() args.log_level = 'CRITICAL' args.sub_command = 'execute' args.sub_command_flow = 'test_flow' parser = Mock(spec=ArgumentParser()) parser.parse_args.return_value = args parselib.ArgumentParser.return_value = parser inspect.signature.return_value = Mock(parameters={'correlation_id'}) cli.main() call_args = flows['test_flow'].run_execute.call_args[1] assert 'correlation_id' in call_args # looks like main() has a lot of state, or something :( inspect.signature.return_value = Mock(parameters={}) args = Mock() args.log_level = 'CRITICAL' args.sub_command = 'execute' args.sub_command_flow = 'test_flow' parser = Mock(spec=ArgumentParser()) parser.parse_args.return_value = args parselib.ArgumentParser.return_value = parser cli.main() call_args = flows['test_flow'].run_execute.call_args[1] assert 'correlation_id' not in call_args