Adding upstream version 4.6.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f3ad83a1a5
commit
a7fbe822ec
278 changed files with 30423 additions and 0 deletions
53
tests/commands/conftest.py
Normal file
53
tests/commands/conftest.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from commitizen import defaults
|
||||
from commitizen.config import BaseConfig, JsonConfig
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config():
|
||||
_config = BaseConfig()
|
||||
_config.settings.update({"name": defaults.DEFAULT_SETTINGS["name"]})
|
||||
return _config
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config_customize():
|
||||
json_string = r"""{
|
||||
"commitizen": {
|
||||
"name": "cz_customize",
|
||||
"version": "3.0.0",
|
||||
"changelog_incremental": "true",
|
||||
"customize": {
|
||||
"message_template": "{{prefix}}({{scope}}): {{subject}}\n\n{{body}}{% if is_breaking_change %}\nBREAKING CHANGE: {{footer}}{% endif %}",
|
||||
"schema": "<type>(<scope>): <subject>\n<BLANK LINE>\n<body>\n<BLANK LINE>\n(BREAKING CHANGE: <footer>)",
|
||||
"schema_pattern": "(build|ci|docs|feat|fix|perf|refactor|style|test|chore|revert|bump)(\\(\\S+\\))?!?:(\\s.*)",
|
||||
"change_type_map": {
|
||||
"feat": "Feat",
|
||||
"fix": "Fix",
|
||||
"refactor": "Refactor",
|
||||
"perf": "Perf"
|
||||
},
|
||||
"change_type_order": ["Refactor", "Feat"],
|
||||
"commit_parser": "^(?P<change_type>feat|fix|refactor|perf|BREAKING CHANGE)(?:\\((?P<scope>[^()\\r\\n]*)\\)|\\()?(?P<breaking>!)?:\\s(?P<message>.*)?",
|
||||
"changelog_pattern": "^(BREAKING[\\-\\ ]CHANGE|feat|fix|refactor|perf)(\\(.+\\))?(!)?",
|
||||
"questions": [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
}"""
|
||||
_config = JsonConfig(data=json_string, path="not_exist.json")
|
||||
return _config
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def changelog_path() -> str:
|
||||
return os.path.join(os.getcwd(), "CHANGELOG.md")
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config_path() -> str:
|
||||
return os.path.join(os.getcwd(), "pyproject.toml")
|
1658
tests/commands/test_bump_command.py
Normal file
1658
tests/commands/test_bump_command.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,81 @@
|
|||
usage: cz bump [-h] [--dry-run] [--files-only] [--local-version] [--changelog]
|
||||
[--no-verify] [--yes] [--tag-format TAG_FORMAT]
|
||||
[--bump-message BUMP_MESSAGE] [--prerelease {alpha,beta,rc}]
|
||||
[--devrelease DEVRELEASE] [--increment {MAJOR,MINOR,PATCH}]
|
||||
[--increment-mode {linear,exact}] [--check-consistency]
|
||||
[--annotated-tag]
|
||||
[--annotated-tag-message ANNOTATED_TAG_MESSAGE] [--gpg-sign]
|
||||
[--changelog-to-stdout] [--git-output-to-stderr] [--retry]
|
||||
[--major-version-zero] [--template TEMPLATE] [--extra EXTRA]
|
||||
[--file-name FILE_NAME] [--prerelease-offset PRERELEASE_OFFSET]
|
||||
[--version-scheme {pep440,semver,semver2}]
|
||||
[--version-type {pep440,semver,semver2}]
|
||||
[--build-metadata BUILD_METADATA] [--get-next]
|
||||
[--allow-no-commit]
|
||||
[MANUAL_VERSION]
|
||||
|
||||
bump semantic version based on the git log
|
||||
|
||||
positional arguments:
|
||||
MANUAL_VERSION bump to the given version (e.g: 1.5.3)
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--dry-run show output to stdout, no commit, no modified files
|
||||
--files-only bump version in the files from the config
|
||||
--local-version bump only the local version portion
|
||||
--changelog, -ch generate the changelog for the newest version
|
||||
--no-verify this option bypasses the pre-commit and commit-msg
|
||||
hooks
|
||||
--yes accept automatically questions done
|
||||
--tag-format TAG_FORMAT
|
||||
the format used to tag the commit and read it, use it
|
||||
in existing projects, wrap around simple quotes
|
||||
--bump-message BUMP_MESSAGE
|
||||
template used to create the release commit, useful
|
||||
when working with CI
|
||||
--prerelease, -pr {alpha,beta,rc}
|
||||
choose type of prerelease
|
||||
--devrelease, -d DEVRELEASE
|
||||
specify non-negative integer for dev. release
|
||||
--increment {MAJOR,MINOR,PATCH}
|
||||
manually specify the desired increment
|
||||
--increment-mode {linear,exact}
|
||||
set the method by which the new version is chosen.
|
||||
'linear' (default) guesses the next version based on
|
||||
typical linear version progression, such that bumping
|
||||
of a pre-release with lower precedence than the
|
||||
current pre-release phase maintains the current phase
|
||||
of higher precedence. 'exact' applies the changes that
|
||||
have been specified (or determined from the commit
|
||||
log) without interpretation, such that the increment
|
||||
and pre-release are always honored
|
||||
--check-consistency, -cc
|
||||
check consistency among versions defined in commitizen
|
||||
configuration and version_files
|
||||
--annotated-tag, -at create annotated tag instead of lightweight one
|
||||
--annotated-tag-message, -atm ANNOTATED_TAG_MESSAGE
|
||||
create annotated tag message
|
||||
--gpg-sign, -s sign tag instead of lightweight one
|
||||
--changelog-to-stdout
|
||||
Output changelog to the stdout
|
||||
--git-output-to-stderr
|
||||
Redirect git output to stderr
|
||||
--retry retry commit if it fails the 1st time
|
||||
--major-version-zero keep major version at zero, even for breaking changes
|
||||
--template, -t TEMPLATE
|
||||
changelog template file name (relative to the current
|
||||
working directory)
|
||||
--extra, -e EXTRA a changelog extra variable (in the form 'key=value')
|
||||
--file-name FILE_NAME
|
||||
file name of changelog (default: 'CHANGELOG.md')
|
||||
--prerelease-offset PRERELEASE_OFFSET
|
||||
start pre-releases with this offset
|
||||
--version-scheme {pep440,semver,semver2}
|
||||
choose version scheme
|
||||
--version-type {pep440,semver,semver2}
|
||||
Deprecated, use --version-scheme
|
||||
--build-metadata BUILD_METADATA
|
||||
Add additional build-metadata to the version-number
|
||||
--get-next Determine the next version and write to stdout
|
||||
--allow-no-commit bump version without eligible commits
|
1927
tests/commands/test_changelog_command.py
Normal file
1927
tests/commands/test_changelog_command.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,10 @@
|
|||
## Unreleased
|
||||
|
||||
### BREAKING CHANGE
|
||||
|
||||
- migrate by renaming user to users
|
||||
|
||||
### Feat
|
||||
|
||||
- **users**: email pattern corrected
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
## Unreleased
|
||||
|
||||
### BREAKING CHANGE
|
||||
|
||||
- migrate by renaming user to users
|
||||
|
||||
### Feat
|
||||
|
||||
- **users**: email pattern corrected
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
## Unreleased
|
||||
|
||||
### BREAKING CHANGE
|
||||
|
||||
- migrate by renaming user to users.
|
||||
and then connect the thingy with the other thingy
|
||||
|
||||
### Feat
|
||||
|
||||
- **users**: email pattern corrected
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
## Unreleased
|
||||
|
||||
|
||||
- drop support for py36
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- **pipeline**: some text with breaking change
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
usage: cz changelog [-h] [--dry-run] [--file-name FILE_NAME]
|
||||
[--unreleased-version UNRELEASED_VERSION] [--incremental]
|
||||
[--start-rev START_REV] [--merge-prerelease]
|
||||
[--version-scheme {pep440,semver,semver2}]
|
||||
[--export-template EXPORT_TEMPLATE] [--template TEMPLATE]
|
||||
[--extra EXTRA]
|
||||
[rev_range]
|
||||
|
||||
generate changelog (note that it will overwrite existing file)
|
||||
|
||||
positional arguments:
|
||||
rev_range generates changelog for the given version (e.g: 1.5.3)
|
||||
or version range (e.g: 1.5.3..1.7.9)
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--dry-run show changelog to stdout
|
||||
--file-name FILE_NAME
|
||||
file name of changelog (default: 'CHANGELOG.md')
|
||||
--unreleased-version UNRELEASED_VERSION
|
||||
set the value for the new version (use the tag value),
|
||||
instead of using unreleased
|
||||
--incremental generates changelog from last created version, useful
|
||||
if the changelog has been manually modified
|
||||
--start-rev START_REV
|
||||
start rev of the changelog. If not set, it will
|
||||
generate changelog from the start
|
||||
--merge-prerelease collect all changes from prereleases into next non-
|
||||
prerelease. If not set, it will include prereleases in
|
||||
the changelog
|
||||
--version-scheme {pep440,semver,semver2}
|
||||
choose version scheme
|
||||
--export-template EXPORT_TEMPLATE
|
||||
Export the changelog template into this file instead
|
||||
of rendering it
|
||||
--template, -t TEMPLATE
|
||||
changelog template file name (relative to the current
|
||||
working directory)
|
||||
--extra, -e EXTRA a changelog extra variable (in the form 'key=value')
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
note: this should be persisted using increment
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
|
@ -0,0 +1,13 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 1.0.0 (1970-01-01)
|
|
@ -0,0 +1,13 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 1.0.0 (1970-01-01)
|
|
@ -0,0 +1,13 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 1.0.0 (1970-01-01)
|
|
@ -0,0 +1,7 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- after 0.2
|
||||
- after 0.2.0
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
## 0.2.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- new file
|
|
@ -0,0 +1,7 @@
|
|||
## 0.3.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- another feature
|
||||
- after 0.2.0
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
## 0.3.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- another feature
|
||||
- after 0.2.0
|
|
@ -0,0 +1,12 @@
|
|||
## 0.4.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- getting ready for this
|
||||
|
||||
## 0.3.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- another feature
|
||||
- after 0.2.0
|
|
@ -0,0 +1,12 @@
|
|||
## 0.3.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- another feature
|
||||
- after 0.2.0
|
||||
|
||||
## 0.2.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- new file
|
|
@ -0,0 +1,17 @@
|
|||
## legacy-0.4.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- new file
|
||||
|
||||
## legacy-0.3.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- new file
|
||||
|
||||
## old-0.2.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- new file
|
|
@ -0,0 +1,24 @@
|
|||
## 0.5.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- new shinny feature
|
||||
|
||||
## 0.4.1 (2022-02-13)
|
||||
|
||||
### Fix
|
||||
|
||||
- small error
|
||||
|
||||
## 0.4.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- getting ready for this
|
||||
|
||||
## 0.3.0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- another feature
|
||||
- after 0.2.0
|
|
@ -0,0 +1,9 @@
|
|||
== Unreleased
|
||||
|
||||
=== Feat
|
||||
|
||||
* new file
|
||||
|
||||
=== Refactor
|
||||
|
||||
* is in changelog
|
|
@ -0,0 +1,9 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- new file
|
||||
|
||||
### Refactor
|
||||
|
||||
- is in changelog
|
|
@ -0,0 +1,12 @@
|
|||
Unreleased
|
||||
==========
|
||||
|
||||
Feat
|
||||
----
|
||||
|
||||
- new file
|
||||
|
||||
Refactor
|
||||
--------
|
||||
|
||||
- is in changelog
|
|
@ -0,0 +1,9 @@
|
|||
h2. Unreleased
|
||||
|
||||
h3. Feat
|
||||
|
||||
- new file
|
||||
|
||||
h3. Refactor
|
||||
|
||||
- is in changelog
|
|
@ -0,0 +1,7 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- after 0.2
|
||||
- after 0.2.0
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
# [10.0.0-rc.3](https://github.com/angular/angular/compare/10.0.0-rc.2...10.0.0-rc.3) (2020-04-22)
|
||||
|
||||
### Bug Fixes
|
||||
* **common:** format day-periods that cross midnight ([#36611](https://github.com/angular/angular/issues/36611)) ([c6e5fc4](https://github.com/angular/angular/commit/c6e5fc4)), closes [#36566](https://github.com/angular/angular/issues/36566)
|
|
@ -0,0 +1,17 @@
|
|||
## v0.3.0 (2024-11-18)
|
||||
|
||||
### Feat
|
||||
|
||||
- another new file
|
||||
|
||||
## older-0.2.0 (2024-11-18)
|
||||
|
||||
### Feat
|
||||
|
||||
- new file
|
||||
|
||||
## older-0.1.0 (2024-11-18)
|
||||
|
||||
### Feat
|
||||
|
||||
- new file
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,37 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 0.2.0a0 (2023-04-16)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,37 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 0.2.0b0 (2023-04-16)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,37 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 0.2.0rc0 (2023-04-16)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0a1 (2021-06-11)
|
||||
|
||||
## 0.2.0a0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0b0 (2021-06-11)
|
||||
|
||||
## 0.2.0a0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0rc0 (2021-06-11)
|
||||
|
||||
## 0.2.0a0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0b1 (2021-06-11)
|
||||
|
||||
## 0.2.0b0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0b1 (2021-06-11)
|
||||
|
||||
## 0.2.0b0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0rc0 (2021-06-11)
|
||||
|
||||
## 0.2.0b0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0rc1 (2021-06-11)
|
||||
|
||||
## 0.2.0rc0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0rc1 (2021-06-11)
|
||||
|
||||
## 0.2.0rc0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,32 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.2.0rc1 (2021-06-11)
|
||||
|
||||
## 0.2.0rc0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,40 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
|
||||
## 0.2.0a0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,40 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
|
||||
## 0.2.0b0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,40 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
|
||||
## 0.2.0rc0 (2021-06-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
## [1.0.0] - 2017-06-20
|
||||
### Added
|
||||
- New visual identity by [@tylerfortune8](https://github.com/tylerfortune8).
|
||||
- Version navigation.
|
||||
|
||||
### Changed
|
||||
- Start using "changelog" over "change log" since it's the common usage.
|
||||
|
||||
### Removed
|
||||
- Section about "changelog" vs "CHANGELOG".
|
||||
|
||||
## [0.3.0] - 2015-12-03
|
||||
### Added
|
||||
- RU translation from [@aishek](https://github.com/aishek).
|
|
@ -0,0 +1,21 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
|
||||
## 0.2.0 (2022-08-14)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
||||
|
||||
note: this should be persisted using increment
|
|
@ -0,0 +1,11 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- no more explosions
|
||||
- output glitch
|
|
@ -0,0 +1,7 @@
|
|||
## 0.3.0-a0 (2022-02-13)
|
||||
|
||||
### Feat
|
||||
|
||||
- another feature
|
||||
- after 0.2.0
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
## 0.3.0-a1 (2022-02-13)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 1.0.0 (1970-01-01)
|
|
@ -0,0 +1,13 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 1.0.0 (1970-01-01)
|
|
@ -0,0 +1,13 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
- output glitch
|
||||
|
||||
## 1.0.0 (1970-01-01)
|
|
@ -0,0 +1,19 @@
|
|||
== Unreleased
|
||||
|
||||
=== Feat
|
||||
|
||||
* add more stuff
|
||||
|
||||
=== Fix
|
||||
|
||||
* mama gotta work
|
||||
|
||||
== 0.2.0 (2022-08-14)
|
||||
|
||||
=== Feat
|
||||
|
||||
* add new output
|
||||
|
||||
=== Fix
|
||||
|
||||
* output glitch
|
|
@ -0,0 +1,19 @@
|
|||
## Unreleased
|
||||
|
||||
### Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
### Fix
|
||||
|
||||
- mama gotta work
|
||||
|
||||
## 0.2.0 (2022-08-14)
|
||||
|
||||
### Feat
|
||||
|
||||
- add new output
|
||||
|
||||
### Fix
|
||||
|
||||
- output glitch
|
|
@ -0,0 +1,25 @@
|
|||
Unreleased
|
||||
==========
|
||||
|
||||
Feat
|
||||
----
|
||||
|
||||
- add more stuff
|
||||
|
||||
Fix
|
||||
---
|
||||
|
||||
- mama gotta work
|
||||
|
||||
0.2.0 (2022-08-14)
|
||||
==================
|
||||
|
||||
Feat
|
||||
----
|
||||
|
||||
- add new output
|
||||
|
||||
Fix
|
||||
---
|
||||
|
||||
- output glitch
|
|
@ -0,0 +1,19 @@
|
|||
h2. Unreleased
|
||||
|
||||
h3. Feat
|
||||
|
||||
- add more stuff
|
||||
|
||||
h3. Fix
|
||||
|
||||
- mama gotta work
|
||||
|
||||
h2. 0.2.0 (2022-08-14)
|
||||
|
||||
h3. Feat
|
||||
|
||||
- add new output
|
||||
|
||||
h3. Fix
|
||||
|
||||
- output glitch
|
|
@ -0,0 +1,20 @@
|
|||
## 0.4.0 (2022-02-13)
|
||||
|
||||
### Perf
|
||||
|
||||
- perf improvement
|
||||
|
||||
### Feat
|
||||
|
||||
- getting ready for this
|
||||
|
||||
## 0.3.0 (2022-02-13)
|
||||
|
||||
### Fix
|
||||
|
||||
- fix bug
|
||||
|
||||
### Feat
|
||||
|
||||
- another feature
|
||||
- after 0.2.0
|
|
@ -0,0 +1,6 @@
|
|||
## Unreleased
|
||||
|
||||
|
||||
- JRA-35 #time 1w 2d 4h 30m Total work logged
|
||||
- JRA-34 #comment corrected indent issue
|
||||
|
454
tests/commands/test_check_command.py
Normal file
454
tests/commands/test_check_command.py
Normal file
|
@ -0,0 +1,454 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from io import StringIO
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockFixture
|
||||
|
||||
from commitizen import cli, commands, git
|
||||
from commitizen.exceptions import (
|
||||
InvalidCommandArgumentError,
|
||||
InvalidCommitMessageError,
|
||||
NoCommitsFoundError,
|
||||
)
|
||||
from tests.utils import create_file_and_commit, skip_below_py_3_13
|
||||
|
||||
COMMIT_LOG = [
|
||||
"refactor: A code change that neither fixes a bug nor adds a feature",
|
||||
r"refactor(cz/connventional_commit): use \S to check scope",
|
||||
"refactor(git): remove unnecessary dot between git range",
|
||||
"bump: version 1.16.3 → 1.16.4",
|
||||
(
|
||||
"Merge pull request #139 from Lee-W/fix-init-clean-config-file\n\n"
|
||||
"Fix init clean config file"
|
||||
),
|
||||
"ci(pyproject.toml): add configuration for coverage",
|
||||
"fix(commands/init): fix clean up file when initialize commitizen config\n\n#138",
|
||||
"refactor(defaults): split config files into long term support and deprecated ones",
|
||||
"bump: version 1.16.2 → 1.16.3",
|
||||
(
|
||||
"Merge pull request #136 from Lee-W/remove-redundant-readme\n\n"
|
||||
"Remove redundant readme"
|
||||
),
|
||||
"fix: replace README.rst with docs/README.md in config files",
|
||||
(
|
||||
"refactor(docs): remove README.rst and use docs/README.md\n\n"
|
||||
"By removing README.rst, we no longer need to maintain "
|
||||
"two document with almost the same content\n"
|
||||
"Github can read docs/README.md as README for the project."
|
||||
),
|
||||
"docs(check): pin pre-commit to v1.16.2",
|
||||
"docs(check): fix pre-commit setup",
|
||||
"bump: version 1.16.1 → 1.16.2",
|
||||
"Merge pull request #135 from Lee-W/fix-pre-commit-hook\n\nFix pre commit hook",
|
||||
"docs(check): enforce cz check only when committing",
|
||||
(
|
||||
'Revert "fix(pre-commit): set pre-commit check stage to commit-msg"\n\n'
|
||||
"This reverts commit afc70133e4a81344928561fbf3bb20738dfc8a0b."
|
||||
),
|
||||
"feat!: add user stuff",
|
||||
"fixup! test(commands): ignore fixup! prefix",
|
||||
"fixup! test(commands): ignore squash! prefix",
|
||||
]
|
||||
|
||||
|
||||
def _build_fake_git_commits(commit_msgs: list[str]) -> list[git.GitCommit]:
|
||||
return [git.GitCommit("test_rev", commit_msg) for commit_msg in commit_msgs]
|
||||
|
||||
|
||||
def test_check_jira_fails(mocker: MockFixture):
|
||||
testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch(
|
||||
"commitizen.commands.check.open",
|
||||
mocker.mock_open(read_data="random message for J-2 #fake_command blah"),
|
||||
)
|
||||
with pytest.raises(InvalidCommitMessageError) as excinfo:
|
||||
cli.main()
|
||||
assert "commit validation: failed!" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_check_jira_command_after_issue_one_space(mocker: MockFixture, capsys):
|
||||
testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch(
|
||||
"commitizen.commands.check.open",
|
||||
mocker.mock_open(read_data="JR-23 #command some arguments etc"),
|
||||
)
|
||||
cli.main()
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Commit validation: successful!" in out
|
||||
|
||||
|
||||
def test_check_jira_command_after_issue_two_spaces(mocker: MockFixture, capsys):
|
||||
testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch(
|
||||
"commitizen.commands.check.open",
|
||||
mocker.mock_open(read_data="JR-2 #command some arguments etc"),
|
||||
)
|
||||
cli.main()
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Commit validation: successful!" in out
|
||||
|
||||
|
||||
def test_check_jira_text_between_issue_and_command(mocker: MockFixture, capsys):
|
||||
testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch(
|
||||
"commitizen.commands.check.open",
|
||||
mocker.mock_open(read_data="JR-234 some text #command some arguments etc"),
|
||||
)
|
||||
cli.main()
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Commit validation: successful!" in out
|
||||
|
||||
|
||||
def test_check_jira_multiple_commands(mocker: MockFixture, capsys):
|
||||
testargs = ["cz", "-n", "cz_jira", "check", "--commit-msg-file", "some_file"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch(
|
||||
"commitizen.commands.check.open",
|
||||
mocker.mock_open(read_data="JRA-23 some text #command1 args #command2 args"),
|
||||
)
|
||||
cli.main()
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Commit validation: successful!" in out
|
||||
|
||||
|
||||
def test_check_conventional_commit_succeeds(mocker: MockFixture, capsys):
|
||||
testargs = ["cz", "check", "--commit-msg-file", "some_file"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch(
|
||||
"commitizen.commands.check.open",
|
||||
mocker.mock_open(read_data="fix(scope): some commit message"),
|
||||
)
|
||||
cli.main()
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Commit validation: successful!" in out
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"commit_msg",
|
||||
(
|
||||
"feat!(lang): removed polish language",
|
||||
"no conventional commit",
|
||||
(
|
||||
"ci: check commit message on merge\n"
|
||||
"testing with more complex commit mes\n\n"
|
||||
"age with error"
|
||||
),
|
||||
),
|
||||
)
|
||||
def test_check_no_conventional_commit(commit_msg, config, mocker: MockFixture, tmpdir):
|
||||
with pytest.raises(InvalidCommitMessageError):
|
||||
error_mock = mocker.patch("commitizen.out.error")
|
||||
|
||||
tempfile = tmpdir.join("temp_commit_file")
|
||||
tempfile.write(commit_msg)
|
||||
|
||||
check_cmd = commands.Check(
|
||||
config=config, arguments={"commit_msg_file": tempfile}
|
||||
)
|
||||
check_cmd()
|
||||
error_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"commit_msg",
|
||||
(
|
||||
"feat(lang)!: removed polish language",
|
||||
"feat(lang): added polish language",
|
||||
"feat: add polish language",
|
||||
"bump: 0.0.1 -> 1.0.0",
|
||||
),
|
||||
)
|
||||
def test_check_conventional_commit(commit_msg, config, mocker: MockFixture, tmpdir):
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
tempfile = tmpdir.join("temp_commit_file")
|
||||
tempfile.write(commit_msg)
|
||||
|
||||
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": "no_such_file"})()
|
||||
|
||||
|
||||
def test_check_a_range_of_git_commits(config, mocker: MockFixture):
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
mocker.patch(
|
||||
"commitizen.git.get_commits", return_value=_build_fake_git_commits(COMMIT_LOG)
|
||||
)
|
||||
|
||||
check_cmd = commands.Check(
|
||||
config=config, arguments={"rev_range": "HEAD~10..master"}
|
||||
)
|
||||
|
||||
check_cmd()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_a_range_of_git_commits_and_failed(config, mocker: MockFixture):
|
||||
error_mock = mocker.patch("commitizen.out.error")
|
||||
mocker.patch(
|
||||
"commitizen.git.get_commits",
|
||||
return_value=_build_fake_git_commits(["This commit does not follow rule"]),
|
||||
)
|
||||
check_cmd = commands.Check(
|
||||
config=config, arguments={"rev_range": "HEAD~10..master"}
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidCommitMessageError):
|
||||
check_cmd()
|
||||
error_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_invalid_argument(config):
|
||||
with pytest.raises(InvalidCommandArgumentError) as excinfo:
|
||||
commands.Check(
|
||||
config=config,
|
||||
arguments={"commit_msg_file": "some_file", "rev_range": "HEAD~10..master"},
|
||||
)
|
||||
assert (
|
||||
"Only one of --rev-range, --message, and --commit-msg-file is permitted by check command!"
|
||||
in str(excinfo.value)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("tmp_commitizen_project")
|
||||
def test_check_command_with_empty_range(config, mocker: MockFixture):
|
||||
# must initialize git with a commit
|
||||
create_file_and_commit("feat: initial")
|
||||
|
||||
check_cmd = commands.Check(config=config, arguments={"rev_range": "master..master"})
|
||||
with pytest.raises(NoCommitsFoundError) as excinfo:
|
||||
check_cmd()
|
||||
|
||||
assert "No commit found with range: 'master..master'" in str(excinfo)
|
||||
|
||||
|
||||
def test_check_a_range_of_failed_git_commits(config, mocker: MockFixture):
|
||||
ill_formated_commits_msgs = [
|
||||
"First commit does not follow rule",
|
||||
"Second commit does not follow rule",
|
||||
("Third commit does not follow rule\nIll-formatted commit with body"),
|
||||
]
|
||||
mocker.patch(
|
||||
"commitizen.git.get_commits",
|
||||
return_value=_build_fake_git_commits(ill_formated_commits_msgs),
|
||||
)
|
||||
check_cmd = commands.Check(
|
||||
config=config, arguments={"rev_range": "HEAD~10..master"}
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidCommitMessageError) as excinfo:
|
||||
check_cmd()
|
||||
assert all([msg in str(excinfo.value) for msg in ill_formated_commits_msgs])
|
||||
|
||||
|
||||
def test_check_command_with_valid_message(config, mocker: MockFixture):
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
check_cmd = commands.Check(
|
||||
config=config, arguments={"message": "fix(scope): some commit message"}
|
||||
)
|
||||
|
||||
check_cmd()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_invalid_message(config, mocker: MockFixture):
|
||||
error_mock = mocker.patch("commitizen.out.error")
|
||||
check_cmd = commands.Check(config=config, arguments={"message": "bad commit"})
|
||||
|
||||
with pytest.raises(InvalidCommitMessageError):
|
||||
check_cmd()
|
||||
error_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_empty_message(config, mocker: MockFixture):
|
||||
error_mock = mocker.patch("commitizen.out.error")
|
||||
check_cmd = commands.Check(config=config, arguments={"message": ""})
|
||||
|
||||
with pytest.raises(InvalidCommitMessageError):
|
||||
check_cmd()
|
||||
error_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_allow_abort_arg(config, mocker: MockFixture):
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
check_cmd = commands.Check(
|
||||
config=config, arguments={"message": "", "allow_abort": True}
|
||||
)
|
||||
|
||||
check_cmd()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_allow_abort_config(config, mocker: MockFixture):
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
config.settings["allow_abort"] = True
|
||||
check_cmd = commands.Check(config=config, arguments={"message": ""})
|
||||
|
||||
check_cmd()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_override_allow_abort_config(config, mocker: MockFixture):
|
||||
error_mock = mocker.patch("commitizen.out.error")
|
||||
config.settings["allow_abort"] = True
|
||||
check_cmd = commands.Check(
|
||||
config=config, arguments={"message": "", "allow_abort": False}
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidCommitMessageError):
|
||||
check_cmd()
|
||||
error_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_allowed_prefixes_arg(config, mocker: MockFixture):
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
check_cmd = commands.Check(
|
||||
config=config,
|
||||
arguments={"message": "custom! test", "allowed_prefixes": ["custom!"]},
|
||||
)
|
||||
|
||||
check_cmd()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_allowed_prefixes_config(config, mocker: MockFixture):
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
config.settings["allowed_prefixes"] = ["custom!"]
|
||||
check_cmd = commands.Check(config=config, arguments={"message": "custom! test"})
|
||||
|
||||
check_cmd()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_override_allowed_prefixes_config(config, mocker: MockFixture):
|
||||
error_mock = mocker.patch("commitizen.out.error")
|
||||
config.settings["allow_abort"] = ["fixup!"]
|
||||
check_cmd = commands.Check(
|
||||
config=config,
|
||||
arguments={"message": "fixup! test", "allowed_prefixes": ["custom!"]},
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidCommitMessageError):
|
||||
check_cmd()
|
||||
error_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_pipe_message(mocker: MockFixture, capsys):
|
||||
testargs = ["cz", "check"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch("sys.stdin", StringIO("fix(scope): some commit message"))
|
||||
|
||||
cli.main()
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Commit validation: successful!" in out
|
||||
|
||||
|
||||
def test_check_command_with_pipe_message_and_failed(mocker: MockFixture):
|
||||
testargs = ["cz", "check"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch("sys.stdin", StringIO("bad commit message"))
|
||||
|
||||
with pytest.raises(InvalidCommitMessageError) as excinfo:
|
||||
cli.main()
|
||||
assert "commit validation: failed!" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_check_command_with_comment_in_messege_file(mocker: MockFixture, capsys):
|
||||
testargs = ["cz", "check", "--commit-msg-file", "some_file"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch(
|
||||
"commitizen.commands.check.open",
|
||||
mocker.mock_open(
|
||||
read_data="# <type>: (If applied, this commit will...) <subject>\n"
|
||||
"# |<---- Try to Limit to a Max of 50 char ---->|\n"
|
||||
"ci: add commitizen pre-commit hook\n"
|
||||
"\n"
|
||||
"# Explain why this change is being made\n"
|
||||
"# |<---- Try To Limit Each Line to a Max Of 72 Char ---->|\n"
|
||||
"This pre-commit hook will check our commits automatically."
|
||||
),
|
||||
)
|
||||
cli.main()
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Commit validation: successful!" in out
|
||||
|
||||
|
||||
def test_check_conventional_commit_succeed_with_git_diff(mocker, capsys):
|
||||
commit_msg = (
|
||||
"feat: This is a test commit\n"
|
||||
"# Please enter the commit message for your changes. Lines starting\n"
|
||||
"# with '#' will be ignored, and an empty message aborts the commit.\n"
|
||||
"#\n"
|
||||
"# On branch ...\n"
|
||||
"# Changes to be committed:\n"
|
||||
"# modified: ...\n"
|
||||
"#\n"
|
||||
"# ------------------------ >8 ------------------------\n"
|
||||
"# Do not modify or remove the line above.\n"
|
||||
"# Everything below it will be ignored.\n"
|
||||
"diff --git a/... b/...\n"
|
||||
"index f1234c..1c5678 1234\n"
|
||||
"--- a/...\n"
|
||||
"+++ b/...\n"
|
||||
"@@ -92,3 +92,4 @@ class Command(BaseCommand):\n"
|
||||
'+ "this is a test"\n'
|
||||
)
|
||||
testargs = ["cz", "check", "--commit-msg-file", "some_file"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
mocker.patch(
|
||||
"commitizen.commands.check.open",
|
||||
mocker.mock_open(read_data=commit_msg),
|
||||
)
|
||||
cli.main()
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Commit validation: successful!" in out
|
||||
|
||||
|
||||
@skip_below_py_3_13
|
||||
def test_check_command_shows_description_when_use_help_option(
|
||||
mocker: MockFixture, capsys, file_regression
|
||||
):
|
||||
testargs = ["cz", "check", "--help"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
out, _ = capsys.readouterr()
|
||||
file_regression.check(out, extension=".txt")
|
||||
|
||||
|
||||
def test_check_command_with_message_length_limit(config, mocker: MockFixture):
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
message = "fix(scope): some commit message"
|
||||
check_cmd = commands.Check(
|
||||
config=config,
|
||||
arguments={"message": message, "message_length_limit": len(message) + 1},
|
||||
)
|
||||
|
||||
check_cmd()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_check_command_with_message_length_limit_exceeded(config, mocker: MockFixture):
|
||||
error_mock = mocker.patch("commitizen.out.error")
|
||||
message = "fix(scope): some commit message"
|
||||
check_cmd = commands.Check(
|
||||
config=config,
|
||||
arguments={"message": message, "message_length_limit": len(message) - 1},
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidCommitMessageError):
|
||||
check_cmd()
|
||||
error_mock.assert_called_once()
|
|
@ -0,0 +1,25 @@
|
|||
usage: cz check [-h] [--commit-msg-file COMMIT_MSG_FILE |
|
||||
--rev-range REV_RANGE | -m MESSAGE] [--allow-abort]
|
||||
[--allowed-prefixes [ALLOWED_PREFIXES ...]]
|
||||
[-l MESSAGE_LENGTH_LIMIT]
|
||||
|
||||
validates that a commit message matches the commitizen schema
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--commit-msg-file COMMIT_MSG_FILE
|
||||
ask for the name of the temporal file that contains
|
||||
the commit message. Using it in a git hook script:
|
||||
MSG_FILE=$1
|
||||
--rev-range REV_RANGE
|
||||
a range of git rev to check. e.g, master..HEAD
|
||||
-m, --message MESSAGE
|
||||
commit message that needs to be checked
|
||||
--allow-abort allow empty commit messages, which typically abort a
|
||||
commit
|
||||
--allowed-prefixes [ALLOWED_PREFIXES ...]
|
||||
allowed commit message prefixes. If the message starts
|
||||
by one of these prefixes, the message won't be checked
|
||||
against the regex
|
||||
-l, --message-length-limit MESSAGE_LENGTH_LIMIT
|
||||
length limit of the commit message; 0 for no limit
|
527
tests/commands/test_commit_command.py
Normal file
527
tests/commands/test_commit_command.py
Normal file
|
@ -0,0 +1,527 @@
|
|||
import os
|
||||
import sys
|
||||
from unittest.mock import ANY
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockFixture
|
||||
|
||||
from commitizen import cli, cmd, commands
|
||||
from commitizen.cz.exceptions import CzException
|
||||
from commitizen.cz.utils import get_backup_file_path
|
||||
from commitizen.exceptions import (
|
||||
CommitError,
|
||||
CommitMessageLengthExceededError,
|
||||
CustomError,
|
||||
DryRunExit,
|
||||
NoAnswersError,
|
||||
NoCommitBackupError,
|
||||
NotAGitProjectError,
|
||||
NotAllowed,
|
||||
NothingToCommitError,
|
||||
)
|
||||
from tests.utils import skip_below_py_3_13
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def staging_is_clean(mocker: MockFixture, tmp_git_project):
|
||||
is_staging_clean_mock = mocker.patch("commitizen.git.is_staging_clean")
|
||||
is_staging_clean_mock.return_value = False
|
||||
return tmp_git_project
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def backup_file(tmp_git_project):
|
||||
with open(get_backup_file_path(), "w") as backup_file:
|
||||
backup_file.write("backup commit")
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit(config, mocker: MockFixture):
|
||||
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", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
commands.Commit(config, {})()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_backup_on_failure(config, mocker: MockFixture):
|
||||
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", b"", b"", 9)
|
||||
error_mock = mocker.patch("commitizen.out.error")
|
||||
|
||||
with pytest.raises(CommitError):
|
||||
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)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_retry_fails_no_backup(config, mocker: MockFixture):
|
||||
commit_mock = mocker.patch("commitizen.git.commit")
|
||||
commit_mock.return_value = cmd.Command("success", "", b"", b"", 0)
|
||||
|
||||
with pytest.raises(NoCommitBackupError) as excinfo:
|
||||
commands.Commit(config, {"retry": True})()
|
||||
|
||||
assert NoCommitBackupError.message in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean", "backup_file")
|
||||
def test_commit_retry_works(config, mocker: MockFixture):
|
||||
prompt_mock = mocker.patch("questionary.prompt")
|
||||
|
||||
commit_mock = mocker.patch("commitizen.git.commit")
|
||||
commit_mock.return_value = cmd.Command("success", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
commit_cmd = commands.Commit(config, {"retry": True})
|
||||
temp_file = commit_cmd.temp_file
|
||||
commit_cmd()
|
||||
|
||||
commit_mock.assert_called_with("backup commit", args="")
|
||||
prompt_mock.assert_not_called()
|
||||
success_mock.assert_called_once()
|
||||
assert not os.path.isfile(temp_file)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_retry_after_failure_no_backup(config, mocker: MockFixture):
|
||||
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("success", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
config.settings["retry_after_failure"] = True
|
||||
commands.Commit(config, {})()
|
||||
|
||||
commit_mock.assert_called_with("feat: user created\n\ncloses #21", args="")
|
||||
prompt_mock.assert_called_once()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean", "backup_file")
|
||||
def test_commit_retry_after_failure_works(config, mocker: MockFixture):
|
||||
prompt_mock = mocker.patch("questionary.prompt")
|
||||
|
||||
commit_mock = mocker.patch("commitizen.git.commit")
|
||||
commit_mock.return_value = cmd.Command("success", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
config.settings["retry_after_failure"] = True
|
||||
commit_cmd = commands.Commit(config, {})
|
||||
temp_file = commit_cmd.temp_file
|
||||
commit_cmd()
|
||||
|
||||
commit_mock.assert_called_with("backup commit", args="")
|
||||
prompt_mock.assert_not_called()
|
||||
success_mock.assert_called_once()
|
||||
assert not os.path.isfile(temp_file)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean", "backup_file")
|
||||
def test_commit_retry_after_failure_with_no_retry_works(config, mocker: MockFixture):
|
||||
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("success", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
config.settings["retry_after_failure"] = True
|
||||
commit_cmd = commands.Commit(config, {"no_retry": True})
|
||||
temp_file = commit_cmd.temp_file
|
||||
commit_cmd()
|
||||
|
||||
commit_mock.assert_called_with("feat: user created\n\ncloses #21", args="")
|
||||
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: MockFixture):
|
||||
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(DryRunExit):
|
||||
commit_cmd = commands.Commit(config, {"dry_run": True})
|
||||
commit_cmd()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_command_with_write_message_to_file_option(
|
||||
config, tmp_path, mocker: MockFixture
|
||||
):
|
||||
tmp_file = tmp_path / "message"
|
||||
|
||||
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", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
commands.Commit(config, {"write_message_to_file": tmp_file})()
|
||||
success_mock.assert_called_once()
|
||||
assert tmp_file.exists()
|
||||
assert tmp_file.read_text() == "feat: user created"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_command_with_invalid_write_message_to_file_option(
|
||||
config, tmp_path, mocker: MockFixture
|
||||
):
|
||||
prompt_mock = mocker.patch("questionary.prompt")
|
||||
prompt_mock.return_value = {
|
||||
"prefix": "feat",
|
||||
"subject": "user created",
|
||||
"scope": "",
|
||||
"is_breaking_change": False,
|
||||
"body": "",
|
||||
"footer": "",
|
||||
}
|
||||
|
||||
with pytest.raises(NotAllowed):
|
||||
commit_cmd = commands.Commit(config, {"write_message_to_file": tmp_path})
|
||||
commit_cmd()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_command_with_signoff_option(config, mocker: MockFixture):
|
||||
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", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
commands.Commit(config, {"signoff": True})()
|
||||
|
||||
commit_mock.assert_called_once_with(ANY, args="-s")
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_command_with_always_signoff_enabled(config, mocker: MockFixture):
|
||||
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", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
config.settings["always_signoff"] = True
|
||||
commands.Commit(config, {})()
|
||||
|
||||
commit_mock.assert_called_once_with(ANY, args="-s")
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_command_with_gpgsign_and_always_signoff_enabled(
|
||||
config, mocker: MockFixture
|
||||
):
|
||||
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", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
config.settings["always_signoff"] = True
|
||||
commands.Commit(config, {"extra_cli_args": "-S"})()
|
||||
|
||||
commit_mock.assert_called_once_with(ANY, args="-S -s")
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("tmp_git_project")
|
||||
def test_commit_when_nothing_to_commit(config, mocker: MockFixture):
|
||||
is_staging_clean_mock = mocker.patch("commitizen.git.is_staging_clean")
|
||||
is_staging_clean_mock.return_value = True
|
||||
|
||||
with pytest.raises(NothingToCommitError) as excinfo:
|
||||
commit_cmd = commands.Commit(config, {})
|
||||
commit_cmd()
|
||||
|
||||
assert "No files added to staging!" in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_with_allow_empty(config, mocker: MockFixture):
|
||||
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("success", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
commands.Commit(config, {"extra_cli_args": "--allow-empty"})()
|
||||
|
||||
commit_mock.assert_called_with(
|
||||
"feat: user created\n\ncloses #21", args="--allow-empty"
|
||||
)
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_with_signoff_and_allow_empty(config, mocker: MockFixture):
|
||||
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("success", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
config.settings["always_signoff"] = True
|
||||
commands.Commit(config, {"extra_cli_args": "--allow-empty"})()
|
||||
|
||||
commit_mock.assert_called_with(
|
||||
"feat: user created\n\ncloses #21", args="--allow-empty -s"
|
||||
)
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_when_customized_expected_raised(config, mocker: MockFixture, 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(CustomError) as excinfo:
|
||||
commit_cmd = commands.Commit(config, {})
|
||||
commit_cmd()
|
||||
|
||||
# Assert only the content in the formatted text
|
||||
assert "This is the root custom err" in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_when_non_customized_expected_raised(
|
||||
config, mocker: MockFixture, capsys
|
||||
):
|
||||
_err = ValueError()
|
||||
prompt_mock = mocker.patch("questionary.prompt")
|
||||
prompt_mock.side_effect = _err
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
commit_cmd = commands.Commit(config, {})
|
||||
commit_cmd()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_when_no_user_answer(config, mocker: MockFixture, capsys):
|
||||
prompt_mock = mocker.patch("questionary.prompt")
|
||||
prompt_mock.return_value = None
|
||||
|
||||
with pytest.raises(NoAnswersError):
|
||||
commit_cmd = commands.Commit(config, {})
|
||||
commit_cmd()
|
||||
|
||||
|
||||
def test_commit_in_non_git_project(tmpdir, config):
|
||||
with tmpdir.as_cwd():
|
||||
with pytest.raises(NotAGitProjectError):
|
||||
commands.Commit(config, {})
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_command_with_all_option(config, mocker: MockFixture):
|
||||
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", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
add_mock = mocker.patch("commitizen.git.add")
|
||||
commands.Commit(config, {"all": True})()
|
||||
add_mock.assert_called()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_command_with_extra_args(config, mocker: MockFixture):
|
||||
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", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
commands.Commit(config, {"extra_cli_args": "-- -extra-args1 -extra-arg2"})()
|
||||
commit_mock.assert_called_once_with(ANY, args="-- -extra-args1 -extra-arg2")
|
||||
success_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
def test_commit_command_with_message_length_limit(config, mocker: MockFixture):
|
||||
prompt_mock = mocker.patch("questionary.prompt")
|
||||
prefix = "feat"
|
||||
subject = "random subject"
|
||||
message_length = len(prefix) + len(": ") + len(subject)
|
||||
prompt_mock.return_value = {
|
||||
"prefix": prefix,
|
||||
"subject": subject,
|
||||
"scope": "",
|
||||
"is_breaking_change": False,
|
||||
"body": "random body",
|
||||
"footer": "random footer",
|
||||
}
|
||||
|
||||
commit_mock = mocker.patch("commitizen.git.commit")
|
||||
commit_mock.return_value = cmd.Command("success", "", b"", b"", 0)
|
||||
success_mock = mocker.patch("commitizen.out.success")
|
||||
|
||||
commands.Commit(config, {"message_length_limit": message_length})()
|
||||
success_mock.assert_called_once()
|
||||
|
||||
with pytest.raises(CommitMessageLengthExceededError):
|
||||
commands.Commit(config, {"message_length_limit": message_length - 1})()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("staging_is_clean")
|
||||
@pytest.mark.parametrize("editor", ["vim", None])
|
||||
def test_manual_edit(editor, config, mocker: MockFixture, tmp_path):
|
||||
mocker.patch("commitizen.git.get_core_editor", return_value=editor)
|
||||
subprocess_mock = mocker.patch("subprocess.call")
|
||||
|
||||
mocker.patch("shutil.which", return_value=editor)
|
||||
|
||||
test_message = "Initial commit message"
|
||||
temp_file = tmp_path / "temp_commit_message"
|
||||
temp_file.write_text(test_message)
|
||||
|
||||
mock_temp_file = mocker.patch("tempfile.NamedTemporaryFile")
|
||||
mock_temp_file.return_value.__enter__.return_value.name = str(temp_file)
|
||||
|
||||
commit_cmd = commands.Commit(config, {"edit": True})
|
||||
|
||||
if editor is None:
|
||||
with pytest.raises(RuntimeError):
|
||||
commit_cmd.manual_edit(test_message)
|
||||
else:
|
||||
edited_message = commit_cmd.manual_edit(test_message)
|
||||
|
||||
subprocess_mock.assert_called_once_with(["vim", str(temp_file)])
|
||||
|
||||
assert edited_message == test_message.strip()
|
||||
|
||||
temp_file.unlink()
|
||||
|
||||
|
||||
@skip_below_py_3_13
|
||||
def test_commit_command_shows_description_when_use_help_option(
|
||||
mocker: MockFixture, capsys, file_regression
|
||||
):
|
||||
testargs = ["cz", "commit", "--help"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
out, _ = capsys.readouterr()
|
||||
file_regression.check(out, extension=".txt")
|
|
@ -0,0 +1,22 @@
|
|||
usage: cz commit [-h] [--retry] [--no-retry] [--dry-run]
|
||||
[--write-message-to-file FILE_PATH] [-s] [-a] [-e]
|
||||
[-l MESSAGE_LENGTH_LIMIT] [--]
|
||||
|
||||
create new commit
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--retry retry last commit
|
||||
--no-retry skip retry if retry_after_failure is set to true
|
||||
--dry-run show output to stdout, no commit, no modified files
|
||||
--write-message-to-file FILE_PATH
|
||||
write message to file before committing (can be
|
||||
combined with --dry-run)
|
||||
-s, --signoff sign off the commit
|
||||
-a, --all Tell the command to automatically stage files that
|
||||
have been modified and deleted, but new files you have
|
||||
not told Git about are not affected.
|
||||
-e, --edit edit the commit message before committing
|
||||
-l, --message-length-limit MESSAGE_LENGTH_LIMIT
|
||||
length limit of the commit message; 0 for no limit
|
||||
-- Positional arguments separator (recommended)
|
26
tests/commands/test_example_command.py
Normal file
26
tests/commands/test_example_command.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import sys
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from commitizen import cli, commands
|
||||
from tests.utils import skip_below_py_3_10
|
||||
|
||||
|
||||
def test_example(config, mocker: MockerFixture):
|
||||
write_mock = mocker.patch("commitizen.out.write")
|
||||
commands.Example(config)()
|
||||
write_mock.assert_called_once()
|
||||
|
||||
|
||||
@skip_below_py_3_10
|
||||
def test_example_command_shows_description_when_use_help_option(
|
||||
mocker: MockerFixture, capsys, file_regression
|
||||
):
|
||||
testargs = ["cz", "example", "--help"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
out, _ = capsys.readouterr()
|
||||
file_regression.check(out, extension=".txt")
|
|
@ -0,0 +1,6 @@
|
|||
usage: cz example [-h]
|
||||
|
||||
show commit example
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
26
tests/commands/test_info_command.py
Normal file
26
tests/commands/test_info_command.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import sys
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from commitizen import cli, commands
|
||||
from tests.utils import skip_below_py_3_10
|
||||
|
||||
|
||||
def test_info(config, mocker: MockerFixture):
|
||||
write_mock = mocker.patch("commitizen.out.write")
|
||||
commands.Info(config)()
|
||||
write_mock.assert_called_once()
|
||||
|
||||
|
||||
@skip_below_py_3_10
|
||||
def test_info_command_shows_description_when_use_help_option(
|
||||
mocker: MockerFixture, capsys, file_regression
|
||||
):
|
||||
testargs = ["cz", "info", "--help"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
out, _ = capsys.readouterr()
|
||||
file_regression.check(out, extension=".txt")
|
|
@ -0,0 +1,6 @@
|
|||
usage: cz info [-h]
|
||||
|
||||
show information about the cz
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
268
tests/commands/test_init_command.py
Normal file
268
tests/commands/test_init_command.py
Normal file
|
@ -0,0 +1,268 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from pytest_mock import MockFixture
|
||||
|
||||
from commitizen import cli, commands
|
||||
from commitizen.__version__ import __version__
|
||||
from commitizen.exceptions import InitFailedError, NoAnswersError
|
||||
from tests.utils import skip_below_py_3_10
|
||||
|
||||
|
||||
class FakeQuestion:
|
||||
def __init__(self, expected_return):
|
||||
self.expected_return = expected_return
|
||||
|
||||
def ask(self):
|
||||
return self.expected_return
|
||||
|
||||
def unsafe_ask(self):
|
||||
return self.expected_return
|
||||
|
||||
|
||||
pre_commit_config_filename = ".pre-commit-config.yaml"
|
||||
cz_hook_config = {
|
||||
"repo": "https://github.com/commitizen-tools/commitizen",
|
||||
"rev": f"v{__version__}",
|
||||
"hooks": [
|
||||
{"id": "commitizen"},
|
||||
{"id": "commitizen-branch", "stages": ["push"]},
|
||||
],
|
||||
}
|
||||
|
||||
expected_config = (
|
||||
"[tool.commitizen]\n"
|
||||
'name = "cz_conventional_commits"\n'
|
||||
'tag_format = "$version"\n'
|
||||
'version_scheme = "semver"\n'
|
||||
'version = "0.0.1"\n'
|
||||
"update_changelog_on_bump = true\n"
|
||||
"major_version_zero = true\n"
|
||||
)
|
||||
|
||||
EXPECTED_DICT_CONFIG = {
|
||||
"commitizen": {
|
||||
"name": "cz_conventional_commits",
|
||||
"tag_format": "$version",
|
||||
"version_scheme": "semver",
|
||||
"version": "0.0.1",
|
||||
"update_changelog_on_bump": True,
|
||||
"major_version_zero": True,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def test_init_without_setup_pre_commit_hook(tmpdir, mocker: MockFixture, config):
|
||||
mocker.patch(
|
||||
"questionary.select",
|
||||
side_effect=[
|
||||
FakeQuestion("pyproject.toml"),
|
||||
FakeQuestion("cz_conventional_commits"),
|
||||
FakeQuestion("commitizen"),
|
||||
FakeQuestion("semver"),
|
||||
],
|
||||
)
|
||||
mocker.patch("questionary.confirm", return_value=FakeQuestion(True))
|
||||
mocker.patch("questionary.text", return_value=FakeQuestion("$version"))
|
||||
# Return None to skip hook installation
|
||||
mocker.patch("questionary.checkbox", return_value=FakeQuestion(None))
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
commands.Init(config)()
|
||||
|
||||
with open("pyproject.toml", encoding="utf-8") as toml_file:
|
||||
config_data = toml_file.read()
|
||||
assert config_data == expected_config
|
||||
|
||||
assert not os.path.isfile(pre_commit_config_filename)
|
||||
|
||||
|
||||
def test_init_when_config_already_exists(config, capsys):
|
||||
# Set config path
|
||||
path = os.sep.join(["tests", "pyproject.toml"])
|
||||
config.add_path(path)
|
||||
|
||||
commands.Init(config)()
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == f"Config file {path} already exists\n"
|
||||
|
||||
|
||||
def test_init_without_choosing_tag(config, mocker: MockFixture, tmpdir):
|
||||
mocker.patch(
|
||||
"commitizen.commands.init.get_tag_names", return_value=["0.0.2", "0.0.1"]
|
||||
)
|
||||
mocker.patch("commitizen.commands.init.get_latest_tag_name", return_value="0.0.2")
|
||||
mocker.patch(
|
||||
"questionary.select",
|
||||
side_effect=[
|
||||
FakeQuestion("pyproject.toml"),
|
||||
FakeQuestion("cz_conventional_commits"),
|
||||
FakeQuestion("commitizen"),
|
||||
FakeQuestion(""),
|
||||
],
|
||||
)
|
||||
mocker.patch("questionary.confirm", return_value=FakeQuestion(False))
|
||||
mocker.patch("questionary.text", return_value=FakeQuestion("y"))
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
with pytest.raises(NoAnswersError):
|
||||
commands.Init(config)()
|
||||
|
||||
|
||||
def test_executed_pre_commit_command(config):
|
||||
init = commands.Init(config)
|
||||
expected_cmd = "pre-commit install --hook-type commit-msg --hook-type pre-push"
|
||||
assert init._gen_pre_commit_cmd(["commit-msg", "pre-push"]) == expected_cmd
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def pre_commit_installed(mocker: MockFixture):
|
||||
# Assume the `pre-commit` is installed
|
||||
mocker.patch(
|
||||
"commitizen.commands.init.ProjectInfo.is_pre_commit_installed",
|
||||
return_value=True,
|
||||
)
|
||||
# And installation success (i.e. no exception raised)
|
||||
mocker.patch(
|
||||
"commitizen.commands.init.Init._exec_install_pre_commit_hook",
|
||||
return_value=None,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function", params=["pyproject.toml", ".cz.json", ".cz.yaml"])
|
||||
def default_choice(request, mocker: MockFixture):
|
||||
mocker.patch(
|
||||
"questionary.select",
|
||||
side_effect=[
|
||||
FakeQuestion(request.param),
|
||||
FakeQuestion("cz_conventional_commits"),
|
||||
FakeQuestion("commitizen"),
|
||||
FakeQuestion("semver"),
|
||||
],
|
||||
)
|
||||
mocker.patch("questionary.confirm", return_value=FakeQuestion(True))
|
||||
mocker.patch("questionary.text", return_value=FakeQuestion("$version"))
|
||||
mocker.patch(
|
||||
"questionary.checkbox",
|
||||
return_value=FakeQuestion(["commit-msg", "pre-push"]),
|
||||
)
|
||||
yield request.param
|
||||
|
||||
|
||||
def check_cz_config(config: str):
|
||||
"""
|
||||
Check the content of commitizen config is as expected
|
||||
|
||||
Args:
|
||||
config: The config path
|
||||
"""
|
||||
with open(config) as file:
|
||||
if "json" in config:
|
||||
assert json.load(file) == EXPECTED_DICT_CONFIG
|
||||
elif "yaml" in config:
|
||||
assert yaml.load(file, Loader=yaml.FullLoader) == EXPECTED_DICT_CONFIG
|
||||
else:
|
||||
config_data = file.read()
|
||||
assert config_data == expected_config
|
||||
|
||||
|
||||
def check_pre_commit_config(expected: list[dict[str, Any]]):
|
||||
"""
|
||||
Check the content of pre-commit config is as expected
|
||||
"""
|
||||
with open(pre_commit_config_filename) as pre_commit_file:
|
||||
pre_commit_config_data = yaml.safe_load(pre_commit_file.read())
|
||||
assert pre_commit_config_data == {"repos": expected}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("pre_commit_installed")
|
||||
class TestPreCommitCases:
|
||||
def test_no_existing_pre_commit_conifg(_, default_choice, tmpdir, config):
|
||||
with tmpdir.as_cwd():
|
||||
commands.Init(config)()
|
||||
check_cz_config(default_choice)
|
||||
check_pre_commit_config([cz_hook_config])
|
||||
|
||||
def test_empty_pre_commit_config(_, default_choice, tmpdir, config):
|
||||
with tmpdir.as_cwd():
|
||||
p = tmpdir.join(pre_commit_config_filename)
|
||||
p.write("")
|
||||
|
||||
commands.Init(config)()
|
||||
check_cz_config(default_choice)
|
||||
check_pre_commit_config([cz_hook_config])
|
||||
|
||||
def test_pre_commit_config_without_cz_hook(_, default_choice, tmpdir, config):
|
||||
existing_hook_config = {
|
||||
"repo": "https://github.com/pre-commit/pre-commit-hooks",
|
||||
"rev": "v1.2.3",
|
||||
"hooks": [{"id", "trailing-whitespace"}],
|
||||
}
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
p = tmpdir.join(pre_commit_config_filename)
|
||||
p.write(yaml.safe_dump({"repos": [existing_hook_config]}))
|
||||
|
||||
commands.Init(config)()
|
||||
check_cz_config(default_choice)
|
||||
check_pre_commit_config([existing_hook_config, cz_hook_config])
|
||||
|
||||
def test_cz_hook_exists_in_pre_commit_config(_, default_choice, tmpdir, config):
|
||||
with tmpdir.as_cwd():
|
||||
p = tmpdir.join(pre_commit_config_filename)
|
||||
p.write(yaml.safe_dump({"repos": [cz_hook_config]}))
|
||||
|
||||
commands.Init(config)()
|
||||
check_cz_config(default_choice)
|
||||
# check that config is not duplicated
|
||||
check_pre_commit_config([cz_hook_config])
|
||||
|
||||
|
||||
class TestNoPreCommitInstalled:
|
||||
def test_pre_commit_not_installed(
|
||||
_, mocker: MockFixture, config, default_choice, tmpdir
|
||||
):
|
||||
# Assume `pre-commit` is not installed
|
||||
mocker.patch(
|
||||
"commitizen.commands.init.ProjectInfo.is_pre_commit_installed",
|
||||
return_value=False,
|
||||
)
|
||||
with tmpdir.as_cwd():
|
||||
with pytest.raises(InitFailedError):
|
||||
commands.Init(config)()
|
||||
|
||||
def test_pre_commit_exec_failed(
|
||||
_, mocker: MockFixture, config, default_choice, tmpdir
|
||||
):
|
||||
# Assume `pre-commit` is installed
|
||||
mocker.patch(
|
||||
"commitizen.commands.init.ProjectInfo.is_pre_commit_installed",
|
||||
return_value=True,
|
||||
)
|
||||
# But pre-commit installation will fail
|
||||
mocker.patch(
|
||||
"commitizen.commands.init.Init._exec_install_pre_commit_hook",
|
||||
side_effect=InitFailedError("Mock init failed error."),
|
||||
)
|
||||
with tmpdir.as_cwd():
|
||||
with pytest.raises(InitFailedError):
|
||||
commands.Init(config)()
|
||||
|
||||
|
||||
@skip_below_py_3_10
|
||||
def test_init_command_shows_description_when_use_help_option(
|
||||
mocker: MockFixture, capsys, file_regression
|
||||
):
|
||||
testargs = ["cz", "init", "--help"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
out, _ = capsys.readouterr()
|
||||
file_regression.check(out, extension=".txt")
|
|
@ -0,0 +1,6 @@
|
|||
usage: cz init [-h]
|
||||
|
||||
init commitizen configuration
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
26
tests/commands/test_ls_command.py
Normal file
26
tests/commands/test_ls_command.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import sys
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from commitizen import cli, commands
|
||||
from tests.utils import skip_below_py_3_10
|
||||
|
||||
|
||||
def test_list_cz(config, mocker: MockerFixture):
|
||||
write_mock = mocker.patch("commitizen.out.write")
|
||||
commands.ListCz(config)()
|
||||
write_mock.assert_called_once()
|
||||
|
||||
|
||||
@skip_below_py_3_10
|
||||
def test_ls_command_shows_description_when_use_help_option(
|
||||
mocker: MockerFixture, capsys, file_regression
|
||||
):
|
||||
testargs = ["cz", "ls", "--help"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
out, _ = capsys.readouterr()
|
||||
file_regression.check(out, extension=".txt")
|
|
@ -0,0 +1,6 @@
|
|||
usage: cz ls [-h]
|
||||
|
||||
show available commitizens
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
26
tests/commands/test_schema_command.py
Normal file
26
tests/commands/test_schema_command.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import sys
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from commitizen import cli, commands
|
||||
from tests.utils import skip_below_py_3_10
|
||||
|
||||
|
||||
def test_schema(config, mocker: MockerFixture):
|
||||
write_mock = mocker.patch("commitizen.out.write")
|
||||
commands.Schema(config)()
|
||||
write_mock.assert_called_once()
|
||||
|
||||
|
||||
@skip_below_py_3_10
|
||||
def test_schema_command_shows_description_when_use_help_option(
|
||||
mocker: MockerFixture, capsys, file_regression
|
||||
):
|
||||
testargs = ["cz", "schema", "--help"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
out, _ = capsys.readouterr()
|
||||
file_regression.check(out, extension=".txt")
|
|
@ -0,0 +1,6 @@
|
|||
usage: cz schema [-h]
|
||||
|
||||
show commit schema
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
122
tests/commands/test_version_command.py
Normal file
122
tests/commands/test_version_command.py
Normal file
|
@ -0,0 +1,122 @@
|
|||
import platform
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from commitizen import cli, commands
|
||||
from commitizen.__version__ import __version__
|
||||
from commitizen.config.base_config import BaseConfig
|
||||
from tests.utils import skip_below_py_3_10
|
||||
|
||||
|
||||
def test_version_for_showing_project_version(config, capsys):
|
||||
# No version exist
|
||||
commands.Version(
|
||||
config,
|
||||
{"report": False, "project": True, "commitizen": False, "verbose": False},
|
||||
)()
|
||||
captured = capsys.readouterr()
|
||||
assert "No project information in this project." in captured.err
|
||||
|
||||
config.settings["version"] = "v0.0.1"
|
||||
commands.Version(
|
||||
config,
|
||||
{"report": False, "project": True, "commitizen": False, "verbose": False},
|
||||
)()
|
||||
captured = capsys.readouterr()
|
||||
assert "v0.0.1" in captured.out
|
||||
|
||||
|
||||
def test_version_for_showing_commitizen_version(config, capsys):
|
||||
commands.Version(
|
||||
config,
|
||||
{"report": False, "project": False, "commitizen": True, "verbose": False},
|
||||
)()
|
||||
captured = capsys.readouterr()
|
||||
assert f"{__version__}" in captured.out
|
||||
|
||||
# default showing commitizen version
|
||||
commands.Version(
|
||||
config,
|
||||
{"report": False, "project": False, "commitizen": False, "verbose": False},
|
||||
)()
|
||||
captured = capsys.readouterr()
|
||||
assert f"{__version__}" in captured.out
|
||||
|
||||
|
||||
def test_version_for_showing_both_versions(config, capsys):
|
||||
commands.Version(
|
||||
config,
|
||||
{"report": False, "project": False, "commitizen": False, "verbose": True},
|
||||
)()
|
||||
captured = capsys.readouterr()
|
||||
assert f"Installed Commitizen Version: {__version__}" in captured.out
|
||||
assert "No project information in this project." in captured.err
|
||||
|
||||
config.settings["version"] = "v0.0.1"
|
||||
commands.Version(
|
||||
config,
|
||||
{"report": False, "project": False, "commitizen": False, "verbose": True},
|
||||
)()
|
||||
captured = capsys.readouterr()
|
||||
expected_out = (
|
||||
f"Installed Commitizen Version: {__version__}\nProject Version: v0.0.1"
|
||||
)
|
||||
assert expected_out in captured.out
|
||||
|
||||
|
||||
def test_version_for_showing_commitizen_system_info(config, capsys):
|
||||
commands.Version(
|
||||
config,
|
||||
{"report": True, "project": False, "commitizen": False, "verbose": False},
|
||||
)()
|
||||
captured = capsys.readouterr()
|
||||
assert f"Commitizen Version: {__version__}" in captured.out
|
||||
assert f"Python Version: {sys.version}" in captured.out
|
||||
assert f"Operating System: {platform.system()}" in captured.out
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", (True, False))
|
||||
@pytest.mark.usefixtures("tmp_git_project")
|
||||
def test_version_use_version_provider(
|
||||
mocker: MockerFixture,
|
||||
config: BaseConfig,
|
||||
capsys: pytest.CaptureFixture,
|
||||
project: bool,
|
||||
):
|
||||
version = "0.0.0"
|
||||
mock = mocker.MagicMock(name="provider")
|
||||
mock.get_version.return_value = version
|
||||
get_provider = mocker.patch(
|
||||
"commitizen.commands.version.get_provider", return_value=mock
|
||||
)
|
||||
|
||||
commands.Version(
|
||||
config,
|
||||
{
|
||||
"report": False,
|
||||
"project": project,
|
||||
"commitizen": False,
|
||||
"verbose": not project,
|
||||
},
|
||||
)()
|
||||
captured = capsys.readouterr()
|
||||
|
||||
assert version in captured.out
|
||||
get_provider.assert_called_once()
|
||||
mock.get_version.assert_called_once()
|
||||
mock.set_version.assert_not_called()
|
||||
|
||||
|
||||
@skip_below_py_3_10
|
||||
def test_version_command_shows_description_when_use_help_option(
|
||||
mocker: MockerFixture, capsys, file_regression
|
||||
):
|
||||
testargs = ["cz", "version", "--help"]
|
||||
mocker.patch.object(sys, "argv", testargs)
|
||||
with pytest.raises(SystemExit):
|
||||
cli.main()
|
||||
|
||||
out, _ = capsys.readouterr()
|
||||
file_regression.check(out, extension=".txt")
|
|
@ -0,0 +1,12 @@
|
|||
usage: cz version [-h] [-r | -p | -c | -v]
|
||||
|
||||
get the version of the installed commitizen or the current project (default:
|
||||
installed commitizen)
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-r, --report get system information for reporting bugs
|
||||
-p, --project get the version of the current project
|
||||
-c, --commitizen get the version of the installed commitizen
|
||||
-v, --verbose get the version of both the installed commitizen and the
|
||||
current project
|
Loading…
Add table
Add a link
Reference in a new issue