11import pytest
2+ from pytest_mock import MockFixture
23
4+ from commitizen import cmd , commands
35from commitizen .config import BaseConfig , JsonConfig , TomlConfig , YAMLConfig
46from commitizen .cz .customize import CustomizeCommitsCz
5- from commitizen .exceptions import MissingCzCustomizeConfigError
7+ from commitizen .cz .utils import (
8+ multiple_line_breaker ,
9+ required_validator ,
10+ required_validator_scope ,
11+ required_validator_subject_strip ,
12+ required_validator_title_strip ,
13+ )
14+ from commitizen .exceptions import MissingCzCustomizeConfigError , NotAllowed
615
716TOML_STR = r"""
817 [tool.commitizen]
3645 ]
3746 message = "Select the type of change you are committing"
3847
48+ [[tool.commitizen.customize.questions]]
49+ type = "input"
50+ name = "subject"
51+ message = "Subject."
52+ filter = "required_validator_subject_strip"
53+
3954 [[tool.commitizen.customize.questions]]
4055 type = "input"
4156 name = "message"
4257 message = "Body."
58+ filter = "multiple_line_breaker"
4359
4460 [[tool.commitizen.customize.questions]]
4561 type = "confirm"
89105 ],
90106 "message": "Select the type of change you are committing"
91107 },
108+ {
109+ "type": "input",
110+ "name": "subject",
111+ "message": "Subject.",
112+ "filter": "required_validator_subject_strip"
113+ },
92114 {
93115 "type": "input",
94116 "name": "message",
95- "message": "Body."
117+ "message": "Body.",
118+ "filter": "multiple_line_breaker"
96119 },
97120 {
98121 "type": "confirm",
139162 - value: bug fix
140163 name: 'bug fix: A bug fix.'
141164 message: Select the type of change you are committing
165+ - type: input
166+ name: subject
167+ message: Subject.
168+ filter: required_validator_subject_strip
142169 - type: input
143170 name: message
144171 message: Body.
172+ filter: multiple_line_breaker
145173 - type: confirm
146174 name: show_message
147175 message: Do you want to add body message in commit?
330358"""
331359
332360
361+ @pytest .fixture
362+ def staging_is_clean (mocker : MockFixture , tmp_git_project ):
363+ is_staging_clean_mock = mocker .patch ("commitizen.git.is_staging_clean" )
364+ is_staging_clean_mock .return_value = False
365+ return tmp_git_project
366+
367+
333368@pytest .fixture (
334369 params = [
335370 TomlConfig (data = TOML_STR , path = "not_exist.toml" ),
@@ -346,6 +381,15 @@ def config(request):
346381 return request .param
347382
348383
384+ @pytest .fixture (
385+ params = [
386+ YAMLConfig (data = YAML_STR , path = "not_exist.yaml" ),
387+ ]
388+ )
389+ def config_filters (request ):
390+ return request .param
391+
392+
349393@pytest .fixture (
350394 params = [
351395 TomlConfig (data = TOML_STR_INFO_PATH , path = "not_exist.toml" ),
@@ -437,7 +481,7 @@ def test_change_type_order_unicode(config_with_unicode):
437481 ]
438482
439483
440- def test_questions (config ):
484+ def test_questions_default (config ):
441485 cz = CustomizeCommitsCz (config )
442486 questions = cz .questions ()
443487 expected_questions = [
@@ -450,7 +494,18 @@ def test_questions(config):
450494 ],
451495 "message" : "Select the type of change you are committing" ,
452496 },
453- {"type" : "input" , "name" : "message" , "message" : "Body." },
497+ {
498+ "type" : "input" ,
499+ "name" : "subject" ,
500+ "message" : "Subject." ,
501+ "filter" : "required_validator_subject_strip" ,
502+ },
503+ {
504+ "type" : "input" ,
505+ "name" : "message" ,
506+ "message" : "Body." ,
507+ "filter" : "multiple_line_breaker" ,
508+ },
454509 {
455510 "type" : "confirm" ,
456511 "name" : "show_message" ,
@@ -460,6 +515,81 @@ def test_questions(config):
460515 assert list (questions ) == expected_questions
461516
462517
518+ @pytest .mark .usefixtures ("staging_is_clean" )
519+ def test_questions_filter_default (config , mocker : MockFixture ):
520+ is_staging_clean_mock = mocker .patch ("commitizen.git.is_staging_clean" )
521+ is_staging_clean_mock .return_value = False
522+
523+ prompt_mock = mocker .patch ("questionary.prompt" )
524+ prompt_mock .return_value = {
525+ "change_type" : "feature" ,
526+ "subject" : "user created" ,
527+ "message" : "body of the commit" ,
528+ "show_message" : True ,
529+ }
530+
531+ commit_mock = mocker .patch ("commitizen.git.commit" )
532+ commit_mock .return_value = cmd .Command ("success" , "" , b"" , b"" , 0 )
533+
534+ commands .Commit (config , {})()
535+
536+ prompts_questions = prompt_mock .call_args [0 ][0 ]
537+ assert prompts_questions [0 ]["type" ] == "list"
538+ assert prompts_questions [0 ]["name" ] == "change_type"
539+ assert prompts_questions [0 ]["use_shortcuts" ] is False
540+ assert prompts_questions [1 ]["type" ] == "input"
541+ assert prompts_questions [1 ]["name" ] == "subject"
542+ assert prompts_questions [1 ]["filter" ] == required_validator_subject_strip
543+ assert prompts_questions [2 ]["type" ] == "input"
544+ assert prompts_questions [2 ]["name" ] == "message"
545+ assert prompts_questions [2 ]["filter" ] == multiple_line_breaker
546+ assert prompts_questions [3 ]["type" ] == "confirm"
547+ assert prompts_questions [3 ]["name" ] == "show_message"
548+
549+
550+ @pytest .mark .usefixtures ("staging_is_clean" )
551+ def test_questions_filter_values (config_filters , mocker : MockFixture ):
552+ is_staging_clean_mock = mocker .patch ("commitizen.git.is_staging_clean" )
553+ is_staging_clean_mock .return_value = False
554+
555+ prompt_mock = mocker .patch ("questionary.prompt" )
556+ prompt_mock .return_value = {
557+ "change_type" : "feature" ,
558+ "subject" : "user created" ,
559+ "message" : "body of the commit" ,
560+ "show_message" : True ,
561+ }
562+
563+ commit_mock = mocker .patch ("commitizen.git.commit" )
564+ commit_mock .return_value = cmd .Command ("success" , "" , b"" , b"" , 0 )
565+
566+ commit_cmd = commands .Commit (config_filters , {})
567+
568+ assert isinstance (commit_cmd .cz , CustomizeCommitsCz )
569+
570+ for filter_desc in [
571+ ("multiple_line_breaker" , multiple_line_breaker ),
572+ ("required_validator" , required_validator ),
573+ ("required_validator_scope" , required_validator_scope ),
574+ ("required_validator_subject_strip" , required_validator_subject_strip ),
575+ ("required_validator_title_strip" , required_validator_title_strip ),
576+ ]:
577+ commit_cmd .cz .custom_settings ["questions" ][1 ]["filter" ] = filter_desc [0 ] # type: ignore[index]
578+ commit_cmd ()
579+
580+ prompts_questions = prompt_mock .call_args [0 ][0 ]
581+ assert prompts_questions [1 ]["filter" ] == filter_desc [1 ]
582+
583+ for filter_name in [
584+ "" ,
585+ "faulty_value" ,
586+ ]:
587+ commit_cmd .cz .custom_settings ["questions" ][1 ]["filter" ] = filter_name # type: ignore[index]
588+
589+ with pytest .raises (NotAllowed ):
590+ commit_cmd ()
591+
592+
463593def test_questions_unicode (config_with_unicode ):
464594 cz = CustomizeCommitsCz (config_with_unicode )
465595 questions = cz .questions ()
0 commit comments