summaryrefslogtreecommitdiffstats
path: root/qa/test_hooks.py
blob: 96a09dd200de4160b8d2b0c5fd551b36c8bb41d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from sh import git, gitlint  # pylint: disable=no-name-in-module
from qa.base import BaseTestCase


class HookTests(BaseTestCase):
    VIOLATIONS = ['gitlint: checking commit message...\n',
                  '1: T3 Title has trailing punctuation (.): "WIP: This is a title."\n',
                  '1: T5 Title contains the word \'WIP\' (case-insensitive): "WIP: This is a title."\n',
                  '2: B4 Second line is not empty: "Content on the second line"\n',
                  '3: B6 Body message is missing\n',
                  '-----------------------------------------------\n',
                  'gitlint: \x1b[31mYour commit message contains the above violations.\x1b[0m\n']

    def setUp(self):
        self.responses = []
        self.response_index = 0
        self.githook_output = []

        # install git commit-msg hook and assert output
        output_installed = gitlint("install-hook", _cwd=self.tmp_git_repo)
        expected_installed = "Successfully installed gitlint commit-msg hook in %s/.git/hooks/commit-msg\n" % \
                             self.tmp_git_repo
        self.assertEqual(output_installed, expected_installed)

    def tearDown(self):
        # uninstall git commit-msg hook and assert output
        output_uninstalled = gitlint("uninstall-hook", _cwd=self.tmp_git_repo)
        expected_uninstalled = "Successfully uninstalled gitlint commit-msg hook from %s/.git/hooks/commit-msg\n" % \
                               self.tmp_git_repo
        self.assertEqual(output_uninstalled, expected_uninstalled)

    def _violations(self):
        # Make a copy of the violations array so that we don't inadvertently edit it in the test (like I did :D)
        return list(self.VIOLATIONS)

        # callback function that captures git commit-msg hook output

    def _interact(self, line, stdin):
        self.githook_output.append(line)
        # Answer 'yes' to question to keep violating commit-msg
        if "Your commit message contains the above violations" in line:
            response = self.responses[self.response_index]
            stdin.put("{0}\n".format(response))
            self.response_index = (self.response_index + 1) % len(self.responses)

    def test_commit_hook_continue(self):
        self.responses = ["y"]
        test_filename = self._create_simple_commit("WIP: This is a title.\nContent on the second line",
                                                   out=self._interact)

        # Determine short commit-msg hash, needed to determine expected output
        short_hash = git("rev-parse", "--short", "HEAD", _cwd=self.tmp_git_repo, _tty_in=True).replace("\n", "")

        expected_output = self._violations()
        expected_output += ['Continue with commit anyways (this keeps the current commit message)? ' +
                            '[y(es)/n(no)/e(dit)] ' +
                            '[master (root-commit) %s] WIP: This is a title. Content on the second line\n' % short_hash,
                            ' 1 file changed, 0 insertions(+), 0 deletions(-)\n',
                            ' create mode 100644 %s\n' % test_filename]

        self.assertListEqual(expected_output, self.githook_output)

    def test_commit_hook_abort(self):
        self.responses = ["n"]
        test_filename = self._create_simple_commit("WIP: This is a title.\nContent on the second line",
                                                   out=self._interact, ok_code=1)
        git("rm", "-f", test_filename, _cwd=self.tmp_git_repo)

        # Determine short commit-msg hash, needed to determine expected output

        expected_output = self._violations()
        expected_output += ['Continue with commit anyways (this keeps the current commit message)? ' +
                            '[y(es)/n(no)/e(dit)] ' +
                            'Commit aborted.\n',
                            'Your commit message: \n',
                            '-----------------------------------------------\n',
                            'WIP: This is a title.\n',
                            'Content on the second line\n',
                            '-----------------------------------------------\n']

        self.assertListEqual(expected_output, self.githook_output)

    def test_commit_hook_edit(self):
        self.responses = ["e", "y"]
        env = {"EDITOR": ":"}
        test_filename = self._create_simple_commit("WIP: This is a title.\nContent on the second line",
                                                   out=self._interact, env=env, ok_code=1)
        git("rm", "-f", test_filename, _cwd=self.tmp_git_repo)

        short_hash = git("rev-parse", "--short", "HEAD", _cwd=self.tmp_git_repo, _tty_in=True).replace("\n", "")

        # Determine short commit-msg hash, needed to determine expected output

        expected_output = self._violations()
        expected_output += ['Continue with commit anyways (this keeps the current commit message)? ' +
                            '[y(es)/n(no)/e(dit)] ' + self._violations()[0]]
        expected_output += self._violations()[1:]
        expected_output += ['Continue with commit anyways (this keeps the current commit message)? ' +
                            '[y(es)/n(no)/e(dit)] ' +
                            '[master %s] WIP: This is a title. Content on the second line\n' % short_hash,
                            ' 1 file changed, 0 insertions(+), 0 deletions(-)\n',
                            ' create mode 100644 %s\n' % test_filename]

        self.assertListEqual(expected_output, self.githook_output)