|
| 1 | +from __future__ import absolute_import |
| 2 | +from __future__ import unicode_literals |
| 3 | + |
| 4 | +import argparse |
| 5 | +import mock |
| 6 | +import pytest |
| 7 | +from plumbum import local |
| 8 | + |
| 9 | +from pre_commit import main |
| 10 | +from testing.auto_namedtuple import auto_namedtuple |
| 11 | + |
| 12 | + |
| 13 | +@pytest.yield_fixture |
| 14 | +def mock_commands(): |
| 15 | + with mock.patch.object(main, 'autoupdate') as autoupdate_mock: |
| 16 | + with mock.patch.object(main, 'clean') as clean_mock: |
| 17 | + with mock.patch.object(main, 'install') as install_mock: |
| 18 | + with mock.patch.object(main, 'uninstall') as uninstall_mock: |
| 19 | + with mock.patch.object(main, 'run') as run_mock: |
| 20 | + yield auto_namedtuple( |
| 21 | + autoupdate_mock=autoupdate_mock, |
| 22 | + clean_mock=clean_mock, |
| 23 | + install_mock=install_mock, |
| 24 | + uninstall_mock=uninstall_mock, |
| 25 | + run_mock=run_mock, |
| 26 | + ) |
| 27 | + |
| 28 | + |
| 29 | +class CalledExit(Exception): |
| 30 | + pass |
| 31 | + |
| 32 | + |
| 33 | +@pytest.yield_fixture |
| 34 | +def argparse_exit_mock(): |
| 35 | + with mock.patch.object( |
| 36 | + argparse.ArgumentParser, 'exit', side_effect=CalledExit, |
| 37 | + ) as exit_mock: |
| 38 | + yield exit_mock |
| 39 | + |
| 40 | + |
| 41 | +@pytest.yield_fixture |
| 42 | +def argparse_parse_args_spy(): |
| 43 | + parse_args_mock = mock.Mock() |
| 44 | + |
| 45 | + original_parse_args = argparse.ArgumentParser.parse_args |
| 46 | + |
| 47 | + def fake_parse_args(self, args): |
| 48 | + # call our spy object |
| 49 | + parse_args_mock(args) |
| 50 | + return original_parse_args(self, args) |
| 51 | + |
| 52 | + with mock.patch.object( |
| 53 | + argparse.ArgumentParser, 'parse_args', fake_parse_args, |
| 54 | + ): |
| 55 | + yield parse_args_mock |
| 56 | + |
| 57 | + |
| 58 | +def assert_only_one_mock_called(mock_objs): |
| 59 | + total_call_count = sum(mock_obj.call_count for mock_obj in mock_objs) |
| 60 | + assert total_call_count == 1 |
| 61 | + |
| 62 | + |
| 63 | +def test_overall_help(mock_commands, argparse_exit_mock): |
| 64 | + with pytest.raises(CalledExit): |
| 65 | + main.main(['--help']) |
| 66 | + |
| 67 | + |
| 68 | +def test_help_command( |
| 69 | + mock_commands, argparse_exit_mock, argparse_parse_args_spy, |
| 70 | +): |
| 71 | + with pytest.raises(CalledExit): |
| 72 | + main.main(['help']) |
| 73 | + |
| 74 | + argparse_parse_args_spy.assert_has_calls([ |
| 75 | + mock.call(['help']), |
| 76 | + mock.call(['--help']), |
| 77 | + ]) |
| 78 | + |
| 79 | + |
| 80 | +def test_help_other_command( |
| 81 | + mock_commands, argparse_exit_mock, argparse_parse_args_spy, |
| 82 | +): |
| 83 | + with pytest.raises(CalledExit): |
| 84 | + main.main(['help', 'run']) |
| 85 | + |
| 86 | + argparse_parse_args_spy.assert_has_calls([ |
| 87 | + mock.call(['help', 'run']), |
| 88 | + mock.call(['run', '--help']), |
| 89 | + ]) |
| 90 | + |
| 91 | + |
| 92 | +def test_install_command(mock_commands): |
| 93 | + main.main(['install']) |
| 94 | + assert mock_commands.install_mock.call_count == 1 |
| 95 | + assert_only_one_mock_called(mock_commands) |
| 96 | + |
| 97 | + |
| 98 | +def test_uninstall_command(mock_commands): |
| 99 | + main.main(['uninstall']) |
| 100 | + assert mock_commands.uninstall_mock.call_count == 1 |
| 101 | + assert_only_one_mock_called(mock_commands) |
| 102 | + |
| 103 | + |
| 104 | +def test_clean_command(mock_commands): |
| 105 | + main.main(['clean']) |
| 106 | + assert mock_commands.clean_mock.call_count == 1 |
| 107 | + assert_only_one_mock_called(mock_commands) |
| 108 | + |
| 109 | + |
| 110 | +def test_autoupdate_command(mock_commands): |
| 111 | + main.main(['autoupdate']) |
| 112 | + assert mock_commands.autoupdate_mock.call_count == 1 |
| 113 | + assert_only_one_mock_called(mock_commands) |
| 114 | + |
| 115 | + |
| 116 | +def test_run_command(mock_commands): |
| 117 | + main.main(['run']) |
| 118 | + assert mock_commands.run_mock.call_count == 1 |
| 119 | + assert_only_one_mock_called(mock_commands) |
| 120 | + |
| 121 | + |
| 122 | +def test_no_commands_run_command(mock_commands): |
| 123 | + main.main([]) |
| 124 | + assert mock_commands.run_mock.call_count == 1 |
| 125 | + assert_only_one_mock_called(mock_commands) |
| 126 | + |
| 127 | + |
| 128 | +def test_help_cmd_in_empty_directory( |
| 129 | + mock_commands, |
| 130 | + tmpdir_factory, |
| 131 | + argparse_exit_mock, |
| 132 | + argparse_parse_args_spy, |
| 133 | +): |
| 134 | + path = tmpdir_factory.get() |
| 135 | + |
| 136 | + with local.cwd(path): |
| 137 | + with pytest.raises(CalledExit): |
| 138 | + main.main(['help', 'run']) |
| 139 | + |
| 140 | + argparse_parse_args_spy.assert_has_calls([ |
| 141 | + mock.call(['help', 'run']), |
| 142 | + mock.call(['run', '--help']), |
| 143 | + ]) |
0 commit comments