From f66afbca55affba7a03bc9934ebad75dba2144ea Mon Sep 17 00:00:00 2001
From: Benedikt Ziegler <benediktziegler@gmail.com>
Date: Fri, 13 Sep 2024 13:21:03 +0200
Subject: [PATCH 1/6] feat: add custom validation

---
 commitizen/commands/check.py         | 41 ++++++---------
 commitizen/cz/base.py                | 41 +++++++++++++++
 docs/customization.md                | 68 ++++++++++++++++++++++++-
 tests/commands/test_check_command.py | 41 +++++++++++++++
 tests/conftest.py                    | 74 +++++++++++++++++++++++++++-
 5 files changed, 236 insertions(+), 29 deletions(-)

diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py
index 13b8555b6d..49bd451b98 100644
--- a/commitizen/commands/check.py
+++ b/commitizen/commands/check.py
@@ -1,7 +1,6 @@
 from __future__ import annotations
 
 import os
-import re
 import sys
 from typing import Any
 
@@ -65,7 +64,7 @@ def __call__(self):
         """Validate if commit messages follows the conventional pattern.
 
         Raises:
-            InvalidCommitMessageError: if the commit provided not follows the conventional pattern
+            InvalidCommitMessageError: if the commit provided does not follow the conventional pattern
         """
         commits = self._get_commits()
         if not commits:
@@ -73,22 +72,22 @@ def __call__(self):
 
         pattern = self.cz.schema_pattern()
         ill_formated_commits = [
-            commit
+            (commit, check[1])
             for commit in commits
-            if not self.validate_commit_message(commit.message, pattern)
+            if not (
+                check := self.cz.validate_commit_message(
+                    commit.message,
+                    pattern,
+                    allow_abort=self.allow_abort,
+                    allowed_prefixes=self.allowed_prefixes,
+                    max_msg_length=self.max_msg_length,
+                )
+            )[0]
         ]
-        displayed_msgs_content = "\n".join(
-            [
-                f'commit "{commit.rev}": "{commit.message}"'
-                for commit in ill_formated_commits
-            ]
-        )
-        if displayed_msgs_content:
+
+        if ill_formated_commits:
             raise InvalidCommitMessageError(
-                "commit validation: failed!\n"
-                "please enter a commit message in the commitizen format.\n"
-                f"{displayed_msgs_content}\n"
-                f"pattern: {pattern}"
+                self.cz.format_exception_message(ill_formated_commits)
             )
         out.success("Commit validation: successful!")
 
@@ -139,15 +138,3 @@ def _filter_comments(msg: str) -> str:
             if not line.startswith("#"):
                 lines.append(line)
         return "\n".join(lines)
-
-    def validate_commit_message(self, commit_msg: str, pattern: str) -> bool:
-        if not commit_msg:
-            return self.allow_abort
-
-        if any(map(commit_msg.startswith, self.allowed_prefixes)):
-            return True
-        if self.max_msg_length:
-            msg_len = len(commit_msg.partition("\n")[0].strip())
-            if msg_len > self.max_msg_length:
-                return False
-        return bool(re.match(pattern, commit_msg))
diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py
index bd116ceb02..07c479ad2c 100644
--- a/commitizen/cz/base.py
+++ b/commitizen/cz/base.py
@@ -1,5 +1,6 @@
 from __future__ import annotations
 
+import re
 from abc import ABCMeta, abstractmethod
 from typing import Any, Callable, Iterable, Protocol
 
@@ -95,6 +96,46 @@ def schema_pattern(self) -> str | None:
         """Regex matching the schema used for message validation."""
         raise NotImplementedError("Not Implemented yet")
 
+    def validate_commit_message(
+        self,
+        commit_msg: str,
+        pattern: str | None,
+        allow_abort: bool,
+        allowed_prefixes: list[str],
+        max_msg_length: int,
+    ) -> tuple[bool, list]:
+        """Validate commit message against the pattern."""
+        if not commit_msg:
+            return allow_abort, []
+
+        if pattern is None:
+            return True, []
+
+        if any(map(commit_msg.startswith, allowed_prefixes)):
+            return True, []
+        if max_msg_length:
+            msg_len = len(commit_msg.partition("\n")[0].strip())
+            if msg_len > max_msg_length:
+                return False, []
+        return bool(re.match(pattern, commit_msg)), []
+
+    def format_exception_message(
+        self, ill_formated_commits: list[tuple[git.GitCommit, list]]
+    ) -> str:
+        """Format commit errors."""
+        displayed_msgs_content = "\n".join(
+            [
+                f'commit "{commit.rev}": "{commit.message}"'
+                for commit, _ in ill_formated_commits
+            ]
+        )
+        return (
+            "commit validation: failed!\n"
+            "please enter a commit message in the commitizen format.\n"
+            f"{displayed_msgs_content}\n"
+            f"pattern: {self.schema_pattern}"
+        )
+
     def info(self) -> str | None:
         """Information about the standardized commit message."""
         raise NotImplementedError("Not Implemented yet")
diff --git a/docs/customization.md b/docs/customization.md
index e8f233fce1..ac88906adf 100644
--- a/docs/customization.md
+++ b/docs/customization.md
@@ -1,4 +1,4 @@
-Customizing commitizen is not hard at all.
+from commitizen import BaseCommitizenCustomizing commitizen is not hard at all.
 We have two different ways to do so.
 
 ## 1. Customize in configuration file
@@ -308,6 +308,72 @@ cz -n cz_strange bump
 
 [convcomms]: https://github.com/commitizen-tools/commitizen/blob/master/commitizen/cz/conventional_commits/conventional_commits.py
 
+### Custom commit validation and error message
+
+The commit message validation can be customized by overriding the `validate_commit_message` and `format_error_message`
+methods from `BaseCommitizen`. This allows for a more detailed feedback to the user where the error originates from.
+
+```python
+import re
+
+from commitizen.cz.base import BaseCommitizen
+from commitizen import git
+
+
+class CustomValidationCz(BaseCommitizen):
+    def validate_commit_message(
+        self,
+        commit_msg: str,
+        pattern: str | None,
+        allow_abort: bool,
+        allowed_prefixes: list[str],
+        max_msg_length: int,
+    ) -> tuple[bool, list]:
+        """Validate commit message against the pattern."""
+        if not commit_msg:
+            return allow_abort, [] if allow_abort else [f"commit message is empty"]
+
+        if pattern is None:
+            return True, []
+
+        if any(map(commit_msg.startswith, allowed_prefixes)):
+            return True, []
+        if max_msg_length:
+            msg_len = len(commit_msg.partition("\n")[0].strip())
+            if msg_len > max_msg_length:
+                return False, [
+                    f"commit message is too long. Max length is {max_msg_length}"
+                ]
+        pattern_match = re.match(pattern, commit_msg)
+        if pattern_match:
+            return True, []
+        else:
+            # Perform additional validation of the commit message format
+            # and add custom error messages as needed
+            return False, ["commit message does not match the pattern"]
+
+    def format_exception_message(
+        self, ill_formated_commits: list[tuple[git.GitCommit, list]]
+    ) -> str:
+        """Format commit errors."""
+        displayed_msgs_content = "\n".join(
+            [
+                (
+                    f'commit "{commit.rev}": "{commit.message}"'
+                    f"errors:\n"
+                    "\n".join((f"- {error}" for error in errors))
+                )
+                for commit, errors in ill_formated_commits
+            ]
+        )
+        return (
+            "commit validation: failed!\n"
+            "please enter a commit message in the commitizen format.\n"
+            f"{displayed_msgs_content}\n"
+            f"pattern: {self.schema_pattern}"
+        )
+```
+
 ### Custom changelog generator
 
 The changelog generator should just work in a very basic manner without touching anything.
diff --git a/tests/commands/test_check_command.py b/tests/commands/test_check_command.py
index 57bfe3f10a..5ebae9125a 100644
--- a/tests/commands/test_check_command.py
+++ b/tests/commands/test_check_command.py
@@ -452,3 +452,44 @@ def test_check_command_with_message_length_limit_exceeded(config, mocker: MockFi
     with pytest.raises(InvalidCommitMessageError):
         check_cmd()
         error_mock.assert_called_once()
+
+
+@pytest.mark.usefixtures("use_cz_custom_validator")
+def test_check_command_with_custom_validator_succeed(mocker: MockFixture, capsys):
+    testargs = [
+        "cz",
+        "--name",
+        "cz_custom_validator",
+        "check",
+        "--commit-msg-file",
+        "some_file",
+    ]
+    mocker.patch.object(sys, "argv", testargs)
+    mocker.patch(
+        "commitizen.commands.check.open",
+        mocker.mock_open(read_data="ABC-123: add commitizen pre-commit hook"),
+    )
+    cli.main()
+    out, _ = capsys.readouterr()
+    assert "Commit validation: successful!" in out
+
+
+@pytest.mark.usefixtures("use_cz_custom_validator")
+def test_check_command_with_custom_validator_failed(mocker: MockFixture):
+    testargs = [
+        "cz",
+        "--name",
+        "cz_custom_validator",
+        "check",
+        "--commit-msg-file",
+        "some_file",
+    ]
+    mocker.patch.object(sys, "argv", testargs)
+    mocker.patch(
+        "commitizen.commands.check.open",
+        mocker.mock_open(read_data="ABC-123 add commitizen pre-commit hook"),
+    )
+    with pytest.raises(InvalidCommitMessageError) as excinfo:
+        cli.main()
+    assert "commit validation: failed!" in str(excinfo.value)
+    assert "commit message does not match pattern" in str(excinfo.value)
diff --git a/tests/conftest.py b/tests/conftest.py
index cc306ac6d4..32089ca7bf 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -9,7 +9,7 @@
 import pytest
 from pytest_mock import MockerFixture
 
-from commitizen import cmd, defaults
+from commitizen import cmd, defaults, git
 from commitizen.changelog_formats import (
     ChangelogFormat,
     get_changelog_format,
@@ -231,6 +231,78 @@ def mock_plugin(mocker: MockerFixture, config: BaseConfig) -> BaseCommitizen:
     return mock
 
 
+class ValidationCz(BaseCommitizen):
+    def questions(self):
+        return [
+            {"type": "input", "name": "commit", "message": "Initial commit:\n"},
+            {"type": "input", "name": "issue_nb", "message": "ABC-123"},
+        ]
+
+    def message(self, answers: dict):
+        return f"{answers['issue_nb']}: {answers['commit']}"
+
+    def schema(self):
+        return "<issue_nb>: <commit>"
+
+    def schema_pattern(self):
+        return r"^(?P<issue_nb>[A-Z]{3}-\d+): (?P<commit>.*)$"
+
+    def validate_commit_message(
+        self,
+        commit_msg: str,
+        pattern: str | None,
+        allow_abort: bool,
+        allowed_prefixes: list[str],
+        max_msg_length: int,
+    ) -> tuple[bool, list]:
+        """Validate commit message against the pattern."""
+        if not commit_msg:
+            return allow_abort, [] if allow_abort else ["commit message is empty"]
+
+        if pattern is None:
+            return True, []
+
+        if any(map(commit_msg.startswith, allowed_prefixes)):
+            return True, []
+        if max_msg_length:
+            msg_len = len(commit_msg.partition("\n")[0].strip())
+            if msg_len > max_msg_length:
+                return False, [
+                    f"commit message is too long. Max length is {max_msg_length}"
+                ]
+        pattern_match = bool(re.match(pattern, commit_msg))
+        if not pattern_match:
+            return False, [f"commit message does not match pattern {pattern}"]
+        return True, []
+
+    def format_exception_message(
+        self, ill_formated_commits: list[tuple[git.GitCommit, list]]
+    ) -> str:
+        """Format commit errors."""
+        displayed_msgs_content = "\n".join(
+            [
+                (
+                    f'commit "{commit.rev}": "{commit.message}"\n'
+                    f"errors:\n"
+                    "\n".join(f"- {error}" for error in errors)
+                )
+                for (commit, errors) in ill_formated_commits
+            ]
+        )
+        return (
+            "commit validation: failed!\n"
+            "please enter a commit message in the commitizen format.\n"
+            f"{displayed_msgs_content}\n"
+            f"pattern: {self.schema_pattern}"
+        )
+
+
+@pytest.fixture
+def use_cz_custom_validator(mocker):
+    new_cz = {**registry, "cz_custom_validator": ValidationCz}
+    mocker.patch.dict("commitizen.cz.registry", new_cz)
+
+
 SUPPORTED_FORMATS = ("markdown", "textile", "asciidoc", "restructuredtext")
 
 

From 7bd16c3456216adecf2b317b97aab981cbf105bb Mon Sep 17 00:00:00 2001
From: Benedikt Ziegler <benediktziegler@gmail.com>
Date: Fri, 13 Sep 2024 15:08:35 +0200
Subject: [PATCH 2/6] test: add test to cover schema_pattern is None case

---
 tests/test_cz_base.py | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/tests/test_cz_base.py b/tests/test_cz_base.py
index 4ee1cc6eda..6553888c41 100644
--- a/tests/test_cz_base.py
+++ b/tests/test_cz_base.py
@@ -1,3 +1,5 @@
+from typing import Optional
+
 import pytest
 
 from commitizen.cz.base import BaseCommitizen
@@ -10,6 +12,9 @@ def questions(self):
     def message(self, answers: dict):
         return answers["commit"]
 
+    def schema_pattern(self) -> Optional[str]:
+        return None
+
 
 def test_base_raises_error(config):
     with pytest.raises(TypeError):
@@ -38,6 +43,11 @@ def test_schema(config):
         cz.schema()
 
 
+def test_validate_commit_message(config):
+    cz = DummyCz(config)
+    assert cz.validate_commit_message("test", None, False, [], 0) == (True, [])
+
+
 def test_info(config):
     cz = DummyCz(config)
     with pytest.raises(NotImplementedError):

From 8eaf37c980312c0fd10c36f10685b14f717cb7f4 Mon Sep 17 00:00:00 2001
From: Benedikt Ziegler <benediktziegler@gmail.com>
Date: Wed, 9 Oct 2024 13:34:29 +0200
Subject: [PATCH 3/6] fix: fix method call

---
 commitizen/cz/base.py | 2 +-
 docs/customization.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py
index 07c479ad2c..cf723f0be6 100644
--- a/commitizen/cz/base.py
+++ b/commitizen/cz/base.py
@@ -133,7 +133,7 @@ def format_exception_message(
             "commit validation: failed!\n"
             "please enter a commit message in the commitizen format.\n"
             f"{displayed_msgs_content}\n"
-            f"pattern: {self.schema_pattern}"
+            f"pattern: {self.schema_pattern()}"
         )
 
     def info(self) -> str | None:
diff --git a/docs/customization.md b/docs/customization.md
index ac88906adf..820a5b65c0 100644
--- a/docs/customization.md
+++ b/docs/customization.md
@@ -370,7 +370,7 @@ class CustomValidationCz(BaseCommitizen):
             "commit validation: failed!\n"
             "please enter a commit message in the commitizen format.\n"
             f"{displayed_msgs_content}\n"
-            f"pattern: {self.schema_pattern}"
+            f"pattern: {self.schema_pattern()}"
         )
 ```
 

From 784e3b4c67cbf7c45720923fb10e2d7a3da94ff7 Mon Sep 17 00:00:00 2001
From: Benedikt Ziegler <benediktziegler@gmail.com>
Date: Mon, 18 Nov 2024 14:32:43 +0100
Subject: [PATCH 4/6] refactor: make arguments keyword only

---
 commitizen/commands/check.py | 4 ++--
 commitizen/cz/base.py        | 1 +
 docs/customization.md        | 1 +
 tests/conftest.py            | 1 +
 tests/test_cz_base.py        | 8 +++++++-
 5 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py
index 49bd451b98..3d28273c0b 100644
--- a/commitizen/commands/check.py
+++ b/commitizen/commands/check.py
@@ -76,8 +76,8 @@ def __call__(self):
             for commit in commits
             if not (
                 check := self.cz.validate_commit_message(
-                    commit.message,
-                    pattern,
+                    commit_msg=commit.message,
+                    pattern=pattern,
                     allow_abort=self.allow_abort,
                     allowed_prefixes=self.allowed_prefixes,
                     max_msg_length=self.max_msg_length,
diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py
index cf723f0be6..5cf1136913 100644
--- a/commitizen/cz/base.py
+++ b/commitizen/cz/base.py
@@ -98,6 +98,7 @@ def schema_pattern(self) -> str | None:
 
     def validate_commit_message(
         self,
+        *,
         commit_msg: str,
         pattern: str | None,
         allow_abort: bool,
diff --git a/docs/customization.md b/docs/customization.md
index 820a5b65c0..754d5c90a3 100644
--- a/docs/customization.md
+++ b/docs/customization.md
@@ -323,6 +323,7 @@ from commitizen import git
 class CustomValidationCz(BaseCommitizen):
     def validate_commit_message(
         self,
+        *,
         commit_msg: str,
         pattern: str | None,
         allow_abort: bool,
diff --git a/tests/conftest.py b/tests/conftest.py
index 32089ca7bf..ce6e51956e 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -249,6 +249,7 @@ def schema_pattern(self):
 
     def validate_commit_message(
         self,
+        *,
         commit_msg: str,
         pattern: str | None,
         allow_abort: bool,
diff --git a/tests/test_cz_base.py b/tests/test_cz_base.py
index 6553888c41..ce1e4a09e7 100644
--- a/tests/test_cz_base.py
+++ b/tests/test_cz_base.py
@@ -45,7 +45,13 @@ def test_schema(config):
 
 def test_validate_commit_message(config):
     cz = DummyCz(config)
-    assert cz.validate_commit_message("test", None, False, [], 0) == (True, [])
+    assert cz.validate_commit_message(
+        commit_msg="test",
+        pattern=None,
+        allow_abort=False,
+        allowed_prefixes=[],
+        max_msg_length=0,
+    ) == (True, [])
 
 
 def test_info(config):

From 904f200ff74eb10272be9b4669297830efb40117 Mon Sep 17 00:00:00 2001
From: Benedikt Ziegler <benediktziegler@gmail.com>
Date: Mon, 18 Nov 2024 14:34:37 +0100
Subject: [PATCH 5/6] refactor: use namedtuple for return

---
 commitizen/commands/check.py |  4 ++--
 commitizen/cz/base.py        | 21 +++++++++++++--------
 tests/conftest.py            | 25 +++++++++++++++----------
 tests/test_cz_base.py        |  4 ++--
 4 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/commitizen/commands/check.py b/commitizen/commands/check.py
index 3d28273c0b..328b208971 100644
--- a/commitizen/commands/check.py
+++ b/commitizen/commands/check.py
@@ -72,7 +72,7 @@ def __call__(self):
 
         pattern = self.cz.schema_pattern()
         ill_formated_commits = [
-            (commit, check[1])
+            (commit, check.errors)
             for commit in commits
             if not (
                 check := self.cz.validate_commit_message(
@@ -82,7 +82,7 @@ def __call__(self):
                     allowed_prefixes=self.allowed_prefixes,
                     max_msg_length=self.max_msg_length,
                 )
-            )[0]
+            ).is_valid
         ]
 
         if ill_formated_commits:
diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py
index 5cf1136913..5854083b75 100644
--- a/commitizen/cz/base.py
+++ b/commitizen/cz/base.py
@@ -2,7 +2,7 @@
 
 import re
 from abc import ABCMeta, abstractmethod
-from typing import Any, Callable, Iterable, Protocol
+from typing import Any, Callable, Iterable, NamedTuple, Protocol
 
 from jinja2 import BaseLoader, PackageLoader
 from prompt_toolkit.styles import Style, merge_styles
@@ -24,6 +24,11 @@ def __call__(
     ) -> dict[str, Any]: ...
 
 
+class ValidationResult(NamedTuple):
+    is_valid: bool
+    errors: list
+
+
 class BaseCommitizen(metaclass=ABCMeta):
     bump_pattern: str | None = None
     bump_map: dict[str, str] | None = None
@@ -41,7 +46,7 @@ class BaseCommitizen(metaclass=ABCMeta):
         ("disabled", "fg:#858585 italic"),
     ]
 
-    # The whole subject will be parsed as message by default
+    # The whole subject will be parsed as a message by default
     # This allows supporting changelog for any rule system.
     # It can be modified per rule
     commit_parser: str | None = r"(?P<message>.*)"
@@ -104,21 +109,21 @@ def validate_commit_message(
         allow_abort: bool,
         allowed_prefixes: list[str],
         max_msg_length: int,
-    ) -> tuple[bool, list]:
+    ) -> ValidationResult:
         """Validate commit message against the pattern."""
         if not commit_msg:
-            return allow_abort, []
+            return ValidationResult(allow_abort, [])
 
         if pattern is None:
-            return True, []
+            return ValidationResult(True, [])
 
         if any(map(commit_msg.startswith, allowed_prefixes)):
-            return True, []
+            return ValidationResult(True, [])
         if max_msg_length:
             msg_len = len(commit_msg.partition("\n")[0].strip())
             if msg_len > max_msg_length:
-                return False, []
-        return bool(re.match(pattern, commit_msg)), []
+                return ValidationResult(False, [])
+        return ValidationResult(bool(re.match(pattern, commit_msg)), [])
 
     def format_exception_message(
         self, ill_formated_commits: list[tuple[git.GitCommit, list]]
diff --git a/tests/conftest.py b/tests/conftest.py
index ce6e51956e..d30c1f48b8 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -16,7 +16,7 @@
 )
 from commitizen.config import BaseConfig
 from commitizen.cz import registry
-from commitizen.cz.base import BaseCommitizen
+from commitizen.cz.base import BaseCommitizen, ValidationResult
 from tests.utils import create_file_and_commit
 
 SIGNER = "GitHub Action"
@@ -255,26 +255,31 @@ def validate_commit_message(
         allow_abort: bool,
         allowed_prefixes: list[str],
         max_msg_length: int,
-    ) -> tuple[bool, list]:
+    ) -> ValidationResult:
         """Validate commit message against the pattern."""
         if not commit_msg:
-            return allow_abort, [] if allow_abort else ["commit message is empty"]
+            return ValidationResult(
+                allow_abort, [] if allow_abort else ["commit message is empty"]
+            )
 
         if pattern is None:
-            return True, []
+            return ValidationResult(True, [])
 
         if any(map(commit_msg.startswith, allowed_prefixes)):
-            return True, []
+            return ValidationResult(True, [])
         if max_msg_length:
             msg_len = len(commit_msg.partition("\n")[0].strip())
             if msg_len > max_msg_length:
-                return False, [
-                    f"commit message is too long. Max length is {max_msg_length}"
-                ]
+                return ValidationResult(
+                    False,
+                    [f"commit message is too long. Max length is {max_msg_length}"],
+                )
         pattern_match = bool(re.match(pattern, commit_msg))
         if not pattern_match:
-            return False, [f"commit message does not match pattern {pattern}"]
-        return True, []
+            return ValidationResult(
+                False, [f"commit message does not match pattern {pattern}"]
+            )
+        return ValidationResult(True, [])
 
     def format_exception_message(
         self, ill_formated_commits: list[tuple[git.GitCommit, list]]
diff --git a/tests/test_cz_base.py b/tests/test_cz_base.py
index ce1e4a09e7..3f4029c5e3 100644
--- a/tests/test_cz_base.py
+++ b/tests/test_cz_base.py
@@ -2,7 +2,7 @@
 
 import pytest
 
-from commitizen.cz.base import BaseCommitizen
+from commitizen.cz.base import BaseCommitizen, ValidationResult
 
 
 class DummyCz(BaseCommitizen):
@@ -51,7 +51,7 @@ def test_validate_commit_message(config):
         allow_abort=False,
         allowed_prefixes=[],
         max_msg_length=0,
-    ) == (True, [])
+    ) == ValidationResult(True, [])
 
 
 def test_info(config):

From ff7eee588d5a9f744998a360e318a60796d4009e Mon Sep 17 00:00:00 2001
From: Benedikt Ziegler <benediktziegler@gmail.com>
Date: Mon, 18 Nov 2024 14:53:17 +0100
Subject: [PATCH 6/6] fix: fix type mismatch from merge

---
 tests/test_cz_base.py | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/tests/test_cz_base.py b/tests/test_cz_base.py
index 3f4029c5e3..76f82ac635 100644
--- a/tests/test_cz_base.py
+++ b/tests/test_cz_base.py
@@ -1,5 +1,3 @@
-from typing import Optional
-
 import pytest
 
 from commitizen.cz.base import BaseCommitizen, ValidationResult
@@ -12,8 +10,8 @@ def questions(self):
     def message(self, answers: dict):
         return answers["commit"]
 
-    def schema_pattern(self) -> Optional[str]:
-        return None
+    def schema_pattern(self) -> str:
+        return ".*"
 
 
 def test_base_raises_error(config):