Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion commitizen/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ def main():
parser.print_help(sys.stderr)
raise SystemExit()

# This is for the command required constraint in 2.0
try:
args = parser.parse_args()
except TypeError:
Expand All @@ -195,7 +196,7 @@ def main():
"'cz --version' will be deprecated in next major version. "
"Please use 'cz version' command from your scripts"
)
logging.getLogger("commitizen").setLevel(logging.DEBUG)
args.func = commands.Version

if args.debug:
warnings.warn(
Expand All @@ -205,7 +206,9 @@ def main():
logging.getLogger("commitizen").setLevel(logging.DEBUG)

# TODO: This try block can be removed after command is required in 2.0
# Handle the case that argument is given, but no command is provided
try:
args.func(conf, vars(args))()
except AttributeError:
out.error("Command is required")
raise SystemExit()
11 changes: 6 additions & 5 deletions commitizen/commands/bump.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,11 @@ def __call__(self):
try:
current_version_instance: Version = Version(self.parameters["version"])
except TypeError:
out.error("[NO_VERSION_SPECIFIED]")
out.error("Check if current version is specified in config file, like:")
out.error("version = 0.4.3")
out.error(
"[NO_VERSION_SPECIFIED]\n"
"Check if current version is specified in config file, like:\n"
"version = 0.4.3\n"
)
raise SystemExit(NO_VERSION_SPECIFIED)

# Initialize values from sources (conf)
Expand All @@ -95,8 +97,7 @@ def __call__(self):
# No commits, there is no need to create an empty tag.
# Unless we previously had a prerelease.
if not commits and not current_version_instance.is_prerelease:
out.error("[NO_COMMITS_FOUND]")
out.error("No new commits found.")
out.error("[NO_COMMITS_FOUND]\n" "No new commits found.")
raise SystemExit(NO_COMMITS_FOUND)

if increment is None:
Expand Down
11 changes: 11 additions & 0 deletions tests/commands/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import pytest

from commitizen import defaults
from commitizen.config import BaseConfig


@pytest.fixture()
def config():
_config = BaseConfig()
_config.settings.update({"name": defaults.name})
return _config
130 changes: 130 additions & 0 deletions tests/commands/test_bump_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import sys
import uuid
from pathlib import Path
from typing import Optional

import pytest

from commitizen import cli, cmd, git


@pytest.fixture(scope="function")
def tmp_git_project(tmpdir):
with tmpdir.as_cwd():
with open("pyproject.toml", "w") as f:
f.write("[tool.commitizen]\n" 'version="0.1.0"')

cmd.run("git init")

yield


def create_file_and_commit(message: str, filename: Optional[str] = None):
if not filename:
filename = str(uuid.uuid4())

Path(f"./{filename}").touch()
cmd.run("git add .")
git.commit(message)


@pytest.mark.usefixtures("tmp_git_project")
def test_bump_command(mocker):
# MINOR
create_file_and_commit("feat: new file")

testargs = ["cz", "bump", "--yes"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

tag_exists = git.tag_exist("0.2.0")
assert tag_exists is True

# PATCH
create_file_and_commit("fix: username exception")

testargs = ["cz", "bump"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

tag_exists = git.tag_exist("0.2.1")
assert tag_exists is True

# PRERELEASE
create_file_and_commit("feat: location")

testargs = ["cz", "bump", "--prerelease", "alpha"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

tag_exists = git.tag_exist("0.3.0a0")
assert tag_exists is True

# PRERELEASE BUMP CREATES VERSION WITHOUT PRERELEASE
testargs = ["cz", "bump"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

tag_exists = git.tag_exist("0.3.0")
assert tag_exists is True

# MAJOR
create_file_and_commit(
"feat: new user interface\n\nBREAKING CHANGE: age is no longer supported"
)

testargs = ["cz", "bump"]
mocker.patch.object(sys, "argv", testargs)
cli.main()

tag_exists = git.tag_exist("1.0.0")
assert tag_exists is True


def test_bump_when_bumpping_is_not_support(mocker, capsys, tmpdir):
with tmpdir.as_cwd():
with open("./pyproject.toml", "w") as f:
f.write("[tool.commitizen]\n" 'version="0.1.0"')

cmd.run("git init")
create_file_and_commit(
"feat: new user interface\n\nBREAKING CHANGE: age is no longer supported"
)

testargs = ["cz", "-n", "cz_jira", "bump", "--yes"]
mocker.patch.object(sys, "argv", testargs)

with pytest.raises(SystemExit):
cli.main()

_, err = capsys.readouterr()
assert "'cz_jira' rule does not support bump" in err


def test_bump_is_not_specify(mocker, capsys, tmpdir):
mocker.patch.object(sys, "argv", ["cz", "bump"])

with pytest.raises(SystemExit):
with tmpdir.as_cwd():
cli.main()

expected_error_message = (
"[NO_VERSION_SPECIFIED]\n"
"Check if current version is specified in config file, like:\n"
"version = 0.4.3\n"
)

_, err = capsys.readouterr()
assert expected_error_message in err


def test_bump_when_not_new_commit(mocker, capsys, tmp_git_project):
testargs = ["cz", "bump", "--yes"]
mocker.patch.object(sys, "argv", testargs)

with pytest.raises(SystemExit):
cli.main()

expected_error_message = "[NO_COMMITS_FOUND]\n" "No new commits found."
_, err = capsys.readouterr()
assert expected_error_message in err
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest

from commitizen import cli
from commitizen import commands


def test_check_jira_fails(mocker, capsys):
Expand Down Expand Up @@ -76,3 +77,34 @@ def test_check_conventional_commit_succeeds(mocker, capsys):
cli.main()
out, _ = capsys.readouterr()
assert "Commit validation: successful!" in out


def test_check_no_conventional_commit(config, mocker, tmpdir):
with pytest.raises(SystemExit):
error_mock = mocker.patch("commitizen.out.error")

tempfile = tmpdir.join("temp_commit_file")
tempfile.write("no conventional commit")

check_cmd = commands.Check(
config=config, arguments={"commit_msg_file": tempfile}
)
check_cmd()
error_mock.assert_called_once()


def test_check_conventional_commit(config, mocker, tmpdir):
success_mock = mocker.patch("commitizen.out.success")

tempfile = tmpdir.join("temp_commit_file")
tempfile.write("feat(lang): added polish language")

check_cmd = commands.Check(config=config, arguments={"commit_msg_file": tempfile})

check_cmd()
success_mock.assert_called_once()


def test_check_command_when_commit_file_not_found(config):
with pytest.raises(FileNotFoundError):
commands.Check(config=config, arguments={"commit_msg_file": ""})()
125 changes: 125 additions & 0 deletions tests/commands/test_commit_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import os

import pytest

from commitizen import cmd, commands
from commitizen.cz.exceptions import CzException


@pytest.fixture
def staging_is_clean(mocker):
is_staging_clean_mock = mocker.patch("commitizen.git.is_staging_clean")
is_staging_clean_mock.return_value = False


@pytest.mark.usefixtures("staging_is_clean")
def test_commit(config, mocker):
prompt_mock = mocker.patch("questionary.prompt")
prompt_mock.return_value = {
"prefix": "feat",
"subject": "user created",
"scope": "",
"is_breaking_change": False,
"body": "",
"footer": "",
}

commit_mock = mocker.patch("commitizen.git.commit")
commit_mock.return_value = cmd.Command("success", "", "", "")
success_mock = mocker.patch("commitizen.out.success")

commands.Commit(config, {})()
success_mock.assert_called_once()


@pytest.mark.usefixtures("staging_is_clean")
def test_commit_retry_fails_no_backup(config, mocker):
commit_mock = mocker.patch("commitizen.git.commit")
commit_mock.return_value = cmd.Command("success", "", "", "")

with pytest.raises(SystemExit):
commands.Commit(config, {"retry": True})()


@pytest.mark.usefixtures("staging_is_clean")
def test_commit_retry_works(config, mocker):
prompt_mock = mocker.patch("questionary.prompt")
prompt_mock.return_value = {
"prefix": "feat",
"subject": "user created",
"scope": "",
"is_breaking_change": False,
"body": "closes #21",
"footer": "",
}

commit_mock = mocker.patch("commitizen.git.commit")
commit_mock.return_value = cmd.Command("", "error", "", "")
error_mock = mocker.patch("commitizen.out.error")

with pytest.raises(SystemExit):
commit_cmd = commands.Commit(config, {})
temp_file = commit_cmd.temp_file
commit_cmd()

prompt_mock.assert_called_once()
error_mock.assert_called_once()
assert os.path.isfile(temp_file)

# Previous commit failed, so retry should pick up the backup commit
# commit_mock = mocker.patch("commitizen.git.commit")
commit_mock.return_value = cmd.Command("success", "", "", "")
success_mock = mocker.patch("commitizen.out.success")

commands.Commit(config, {"retry": True})()

commit_mock.assert_called_with("feat: user created\n\ncloses #21")
prompt_mock.assert_called_once()
success_mock.assert_called_once()
assert not os.path.isfile(temp_file)


@pytest.mark.usefixtures("staging_is_clean")
def test_commit_command_with_dry_run_option(config, mocker):
prompt_mock = mocker = mocker.patch("questionary.prompt")
prompt_mock.return_value = {
"prefix": "feat",
"subject": "user created",
"scope": "",
"is_breaking_change": False,
"body": "closes #57",
"footer": "",
}

with pytest.raises(SystemExit):
commit_cmd = commands.Commit(config, {"dry_run": True})
commit_cmd()


def test_commit_when_nothing_to_commit(config, mocker):
is_staging_clean_mock = mocker.patch("commitizen.git.is_staging_clean")
is_staging_clean_mock.return_value = True

with pytest.raises(SystemExit) as err:
commit_cmd = commands.Commit(config, {})
commit_cmd()

assert err.value.code == commands.commit.NOTHING_TO_COMMIT


@pytest.mark.usefixtures("staging_is_clean")
def test_commit_when_customized_expected_raised(config, mocker, capsys):
_err = ValueError()
_err.__context__ = CzException("This is the root custom err")
prompt_mock = mocker.patch("questionary.prompt")
prompt_mock.side_effect = _err

with pytest.raises(SystemExit) as err:
commit_cmd = commands.Commit(config, {})
commit_cmd()

assert err.value.code == commands.commit.CUSTOM_ERROR

# Assert only the content in the formatted text
captured = capsys.readouterr()
assert "This is the root custom err" in captured.err
Loading