Skip to content

Commit 5f6482b

Browse files
test: move fixture and dummy class
docs: fix type annotation
1 parent 75e8833 commit 5f6482b

File tree

3 files changed

+100
-92
lines changed

3 files changed

+100
-92
lines changed

docs/customization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ methods from `BaseCommitizen`. This allows for a more detailed feedback to the u
320320
```python
321321
import re
322322
323-
from commitizen.cz.base import BaseCommitizen
323+
from commitizen.cz.base import BaseCommitizen, ValidationResult
324324
from commitizen import git
325325
326326
@@ -333,7 +333,7 @@ class CustomValidationCz(BaseCommitizen):
333333
allow_abort: bool,
334334
allowed_prefixes: list[str],
335335
max_msg_length: int,
336-
) -> tuple[bool, list]:
336+
) -> ValidationResult:
337337
"""Validate commit message against the pattern."""
338338
if not commit_msg:
339339
return allow_abort, [] if allow_abort else [f"commit message is empty"]

tests/commands/test_check_command.py

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
from __future__ import annotations
22

3+
import re
34
import sys
5+
from collections.abc import Mapping
46
from io import StringIO
7+
from typing import Any
58

69
import pytest
710
from pytest_mock import MockFixture
811

912
from commitizen import cli, commands, git
13+
from commitizen.cz import registry
14+
from commitizen.cz.base import BaseCommitizen, ValidationResult
1015
from commitizen.exceptions import (
1116
CommitMessageLengthExceededError,
1217
InvalidCommandArgumentError,
1318
InvalidCommitMessageError,
1419
NoCommitsFoundError,
1520
)
21+
from commitizen.question import CzQuestion
1622
from tests.utils import create_file_and_commit, skip_below_py_3_13
1723

1824
COMMIT_LOG = [
@@ -519,6 +525,89 @@ def test_check_command_cli_overrides_config_message_length_limit(
519525
)
520526

521527

528+
class ValidationCz(BaseCommitizen):
529+
def questions(self) -> list[CzQuestion]:
530+
return [
531+
{"type": "input", "name": "commit", "message": "Initial commit:\n"},
532+
{"type": "input", "name": "issue_nb", "message": "ABC-123"},
533+
]
534+
535+
def message(self, answers: Mapping[str, Any]) -> str:
536+
return f"{answers['issue_nb']}: {answers['commit']}"
537+
538+
def schema(self) -> str:
539+
return "<issue_nb>: <commit>"
540+
541+
def schema_pattern(self) -> str:
542+
return r"^(?P<issue_nb>[A-Z]{3}-\d+): (?P<commit>.*)$"
543+
544+
def example(self) -> str:
545+
return "ABC-123: fixed a bug"
546+
547+
def info(self) -> str:
548+
return "Commit message must start with an issue number like ABC-123"
549+
550+
def validate_commit_message(
551+
self,
552+
*,
553+
commit_msg: str,
554+
pattern: re.Pattern[str],
555+
allow_abort: bool,
556+
allowed_prefixes: list[str],
557+
max_msg_length: int | None,
558+
commit_hash: str,
559+
) -> ValidationResult:
560+
"""Validate commit message against the pattern."""
561+
if not commit_msg:
562+
return ValidationResult(
563+
allow_abort, [] if allow_abort else ["commit message is empty"]
564+
)
565+
566+
if any(map(commit_msg.startswith, allowed_prefixes)):
567+
return ValidationResult(True, [])
568+
569+
if max_msg_length:
570+
msg_len = len(commit_msg.partition("\n")[0].strip())
571+
if msg_len > max_msg_length:
572+
# TODO: capitalize the first letter of the error message for consistency in v5
573+
raise CommitMessageLengthExceededError(
574+
f"commit validation: failed!\n"
575+
f"commit message length exceeds the limit.\n"
576+
f'commit "{commit_hash}": "{commit_msg}"\n'
577+
f"message length limit: {max_msg_length} (actual: {msg_len})"
578+
)
579+
580+
return ValidationResult(
581+
bool(pattern.match(commit_msg)), [f"pattern: {pattern.pattern}"]
582+
)
583+
584+
def format_exception_message(
585+
self, invalid_commits: list[tuple[git.GitCommit, list]]
586+
) -> str:
587+
"""Format commit errors."""
588+
displayed_msgs_content = "\n".join(
589+
[
590+
(
591+
f'commit "{commit.rev}": "{commit.message}"\nerrors:\n\n'.join(
592+
f"- {error}" for error in errors
593+
)
594+
)
595+
for (commit, errors) in invalid_commits
596+
]
597+
)
598+
return (
599+
"commit validation: failed!\n"
600+
"please enter a commit message in the commitizen format.\n"
601+
f"{displayed_msgs_content}"
602+
)
603+
604+
605+
@pytest.fixture
606+
def use_cz_custom_validator(mocker):
607+
new_cz = {**registry, "cz_custom_validator": ValidationCz}
608+
mocker.patch.dict("commitizen.cz.registry", new_cz)
609+
610+
522611
@pytest.mark.usefixtures("use_cz_custom_validator")
523612
def test_check_command_with_custom_validator_succeed(mocker: MockFixture, capsys):
524613
testargs = [
@@ -552,9 +641,13 @@ def test_check_command_with_custom_validator_failed(mocker: MockFixture):
552641
mocker.patch.object(sys, "argv", testargs)
553642
mocker.patch(
554643
"commitizen.commands.check.open",
555-
mocker.mock_open(read_data="ABC-123 add commitizen pre-commit hook"),
644+
mocker.mock_open(
645+
read_data="123-ABC issue id has wrong format and misses colon"
646+
),
556647
)
557648
with pytest.raises(InvalidCommitMessageError) as excinfo:
558649
cli.main()
559-
assert "commit validation: failed!" in str(excinfo.value)
560-
assert "pattern: " in str(excinfo.value)
650+
assert "commit validation: failed!" in str(excinfo.value), (
651+
"Pattern validation unexpectedly passed"
652+
)
653+
assert "pattern: " in str(excinfo.value), "Pattern not found in error message"

tests/conftest.py

Lines changed: 2 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,18 @@
55
import tempfile
66
from collections.abc import Iterator, Mapping
77
from pathlib import Path
8-
from typing import Any
98

109
import pytest
1110
from pytest_mock import MockerFixture
1211

13-
from commitizen import cmd, defaults, git
12+
from commitizen import cmd, defaults
1413
from commitizen.changelog_formats import (
1514
ChangelogFormat,
1615
get_changelog_format,
1716
)
1817
from commitizen.config import BaseConfig
1918
from commitizen.cz import registry
20-
from commitizen.cz.base import BaseCommitizen, ValidationResult
21-
from commitizen.exceptions import CommitMessageLengthExceededError
19+
from commitizen.cz.base import BaseCommitizen
2220
from commitizen.question import CzQuestion
2321
from tests.utils import create_file_and_commit
2422

@@ -263,89 +261,6 @@ def mock_plugin(mocker: MockerFixture, config: BaseConfig) -> BaseCommitizen:
263261
return mock
264262

265263

266-
class ValidationCz(BaseCommitizen):
267-
def questions(self) -> list[CzQuestion]:
268-
return [
269-
{"type": "input", "name": "commit", "message": "Initial commit:\n"},
270-
{"type": "input", "name": "issue_nb", "message": "ABC-123"},
271-
]
272-
273-
def message(self, answers: Mapping[str, Any]) -> str:
274-
return f"{answers['issue_nb']}: {answers['commit']}"
275-
276-
def schema(self) -> str:
277-
return "<issue_nb>: <commit>"
278-
279-
def schema_pattern(self) -> str:
280-
return r"^(?P<issue_nb>[A-Z]{3}-\d+): (?P<commit>.*)$"
281-
282-
def example(self) -> str:
283-
return "ABC-123: fixed a bug"
284-
285-
def info(self) -> str:
286-
return "Commit message must start with an issue number like ABC-123"
287-
288-
def validate_commit_message(
289-
self,
290-
*,
291-
commit_msg: str,
292-
pattern: re.Pattern[str],
293-
allow_abort: bool,
294-
allowed_prefixes: list[str],
295-
max_msg_length: int | None,
296-
commit_hash: str,
297-
) -> ValidationResult:
298-
"""Validate commit message against the pattern."""
299-
if not commit_msg:
300-
return ValidationResult(
301-
allow_abort, [] if allow_abort else ["commit message is empty"]
302-
)
303-
304-
if any(map(commit_msg.startswith, allowed_prefixes)):
305-
return ValidationResult(True, [])
306-
307-
if max_msg_length:
308-
msg_len = len(commit_msg.partition("\n")[0].strip())
309-
if msg_len > max_msg_length:
310-
# TODO: capitalize the first letter of the error message for consistency in v5
311-
raise CommitMessageLengthExceededError(
312-
f"commit validation: failed!\n"
313-
f"commit message length exceeds the limit.\n"
314-
f'commit "{commit_hash}": "{commit_msg}"\n'
315-
f"message length limit: {max_msg_length} (actual: {msg_len})"
316-
)
317-
318-
return ValidationResult(
319-
bool(pattern.match(commit_msg)), [f"pattern: {pattern.pattern}"]
320-
)
321-
322-
def format_exception_message(
323-
self, invalid_commits: list[tuple[git.GitCommit, list]]
324-
) -> str:
325-
"""Format commit errors."""
326-
displayed_msgs_content = "\n".join(
327-
[
328-
(
329-
f'commit "{commit.rev}": "{commit.message}"\nerrors:\n\n'.join(
330-
f"- {error}" for error in errors
331-
)
332-
)
333-
for (commit, errors) in invalid_commits
334-
]
335-
)
336-
return (
337-
"commit validation: failed!\n"
338-
"please enter a commit message in the commitizen format.\n"
339-
f"{displayed_msgs_content}"
340-
)
341-
342-
343-
@pytest.fixture
344-
def use_cz_custom_validator(mocker):
345-
new_cz = {**registry, "cz_custom_validator": ValidationCz}
346-
mocker.patch.dict("commitizen.cz.registry", new_cz)
347-
348-
349264
SUPPORTED_FORMATS = ("markdown", "textile", "asciidoc", "restructuredtext")
350265

351266

0 commit comments

Comments
 (0)