def test_raw_help_group( file_regression: FileRegressionFixture, cli_runner: CliRunner, ): @click_group(cls=consolekit.commands.RawHelpGroup) def demo(): """ This is the summary line. This **program** does *the* ``following``: * This * That * ~~The other~~ (deprecated) """ @demo.command(cls=consolekit.commands.RawHelpCommand) def foo(): """ This is the summary line. This **program** does *the* ``following``: * This * That * ~~The other~~ (deprecated) """ result = cli_runner.invoke(demo, args=["--help"]) result.check_stdout(file_regression, extension="_group.md") result = cli_runner.invoke(foo, args=["--help"]) result.check_stdout(file_regression, extension="_command.md")
def test_cli( example_file, tmp_pathplus, file_regression: FileRegressionFixture, cli_runner: CliRunner, ): st = (example_file).stat() assert st == st time.sleep( 0.1 ) # the whole thing happens so quickly the mtime was ending up the same result: Result = cli_runner.invoke(main, catch_exceptions=False, args=[str(example_file)]) check_file_output(example_file, file_regression) assert result.exit_code == 1 # mtime should have changed new_st = (example_file).stat() assert new_st.st_mtime != st.st_mtime assert new_st != st # Calling a second time shouldn't change anything result = cli_runner.invoke(main, catch_exceptions=False, args=[str(example_file)]) check_file_output(example_file, file_regression) assert result.exit_code == 0 # mtime should be the same assert (example_file).stat().st_mtime == new_st.st_mtime assert (example_file).stat() == new_st
def test_release_unclean( temp_repo, advanced_file_regression: AdvancedFileRegressionFixture): (temp_repo.path / "file.txt").write_clean("Hello World") temp_repo.stage("file.txt") result: Result for command in (major, minor, patch): with in_directory(temp_repo.path): runner = CliRunner(mix_stderr=False) result = runner.invoke(command, catch_exceptions=False) assert result.exit_code == 1 assert result.stderr.splitlines() == [ "Git working directory is not clean:", " A file.txt", "Aborted!", ] assert not result.stdout with in_directory(temp_repo.path): runner = CliRunner(mix_stderr=False) result = runner.invoke(release, catch_exceptions=False, args=["1.2.3"]) assert result.exit_code == 1 assert result.stderr.splitlines() == [ "Git working directory is not clean:", " A file.txt", "Aborted!", ] assert not result.stdout
def test_suggestion_group( file_regression: FileRegressionFixture, cli_runner: CliRunner, ): @click_group(context_settings={ **CONTEXT_SETTINGS, "token_normalize_func": lambda x: x.lower() }) def demo(): """ A program. """ @demo.command() def search(): """ Conduct a search. """ result = cli_runner.invoke(demo, args=["searh"]) result.check_stdout(file_regression, extension="_success.md") assert result.exit_code == 2 result = cli_runner.invoke(demo, args=["list"]) result.check_stdout(file_regression, extension="_failure.md") assert result.exit_code == 2 result = cli_runner.invoke(demo, args=["SEARCH"]) assert not result.stdout.rstrip() assert result.exit_code == 0
def test_add_requirement( tmp_pathplus: PathPlus, requirement: str, cassette, advanced_file_regression: AdvancedFileRegressionFixture): (tmp_pathplus / "repo_helper.yml").touch() (tmp_pathplus / "requirements.txt").touch() (tmp_pathplus / "tests").mkdir() (tmp_pathplus / "tests" / "requirements.txt").touch() result: Result with in_directory(tmp_pathplus): runner = CliRunner() result = runner.invoke(add.requirement, args=requirement) assert result.exit_code == 0 advanced_file_regression.check_file(tmp_pathplus / "requirements.txt") with in_directory(tmp_pathplus): runner = CliRunner() result = runner.invoke( add.requirement, args=[requirement, "--file", "tests/requirements.txt"]) assert result.exit_code == 0 advanced_file_regression.check_file(tmp_pathplus / "tests" / "requirements.txt")
def test_reformat( tmp_pathplus: PathPlus, toml_string: str, cli_runner: CliRunner, advanced_file_regression: AdvancedFileRegressionFixture, show_diff: bool, ): (tmp_pathplus / "pyproject.toml").write_clean(toml_string) (tmp_pathplus / "README.rst").write_clean("This is the README") (tmp_pathplus / "LICENSE").write_clean("This is the LICENSE") if show_diff: args = ["--no-colour", "--show-diff"] else: args = [] with in_directory(tmp_pathplus): result: Result = cli_runner.invoke(reformat, args=args, catch_exceptions=False) assert result.exit_code == 1 advanced_file_regression.check_file(tmp_pathplus / "pyproject.toml") result.check_stdout(advanced_file_regression, extension=".diff") # Should be no changes with in_directory(tmp_pathplus): result = cli_runner.invoke(reformat, args=args, catch_exceptions=False) assert result.exit_code == 0 advanced_file_regression.check_file(tmp_pathplus / "pyproject.toml") assert result.stdout == "Reformatting 'pyproject.toml'\n"
def test_requirements_concise( self, tmp_repo, advanced_file_regression: AdvancedFileRegressionFixture, py_version, fixed_version_number, ): for directory in show_directories: with in_directory(directory): runner = CliRunner() result: Result = runner.invoke(show.requirements, catch_exceptions=False, args=["--concise", "--no-venv"]) assert result.exit_code == 0 result.check_stdout(advanced_file_regression, extension=".tree") with in_directory(directory): runner = CliRunner() result = runner.invoke(show.requirements, catch_exceptions=False, args=["-c", "--no-venv"]) assert result.exit_code == 0 result.check_stdout(advanced_file_regression, extension=".tree")
def test_auto_default_option( file_regression: FileRegressionFixture, cli_runner: CliRunner, ): @auto_default_option( "--width", type=click.INT, help="The max width to display.", show_default=True, ) @click_command() def main(width: int = 80): print(width) argument = main.params[0] assert argument.default == 80 assert not argument.required assert argument.show_default # type: ignore result = cli_runner.invoke(main, args="--help") result.check_stdout(file_regression, extension=".md") assert result.exit_code == 0 result = cli_runner.invoke(main, catch_exceptions=False) assert result.stdout.rstrip() == "80" assert result.exit_code == 0 for width in [0, 8, 36, 48, 130]: result = cli_runner.invoke(main, args=["--width", str(width)]) assert result.stdout.rstrip() == str(width) assert result.exit_code == 0
def test_multi_value_option(cli_runner: CliRunner): @click.option( "--select", type=click.STRING, help="The checks to enable", cls=MultiValueOption, ) @colour_option() @click_command() def main(select: Iterable[str], colour: bool): select = list(select) print(*select) print(", ".join(select)) result: Result = cli_runner.invoke(main, catch_exceptions=False) assert result.stdout.rstrip() == '' assert result.exit_code == 0 result = cli_runner.invoke(main, args=["--select", "E102", "F223"]) assert result.stdout.rstrip() == "E102 F223\nE102, F223" assert result.exit_code == 0 result = cli_runner.invoke(main, args=["--select", "E102", "F223", "--colour"]) assert result.stdout.rstrip() == "E102 F223\nE102, F223" assert result.exit_code == 0 result = cli_runner.invoke(main, args=["--select", "E102"]) assert result.stdout.rstrip() == "E102\nE102" assert result.exit_code == 0
def test_version_option(file_regression: FileRegressionFixture, cli_runner: CliRunner): def version_callback(ctx: click.Context, param: click.Option, value: int): if not value or ctx.resilient_parsing: return if value > 1: click.echo("consolekit version 1.2.3, Python 3.8.5") else: click.echo("consolekit version 1.2.3") ctx.exit() @version_option(version_callback) @click_command() def main(): sys.exit(1) result = cli_runner.invoke(main, args="--version") assert result.stdout.rstrip() == "consolekit version 1.2.3" assert result.exit_code == 0 result = cli_runner.invoke(main, args=["--version", "--version"]) assert result.stdout.rstrip() == "consolekit version 1.2.3, Python 3.8.5" assert result.exit_code == 0
def test_described_argument( file_regression: FileRegressionFixture, cli_runner: CliRunner, ): @click.argument( "dest", cls=DescribedArgument, type=click.STRING, description="The destination directory.", ) @click_command() def main(dest: str): print(dest) result = cli_runner.invoke(main, args="--help") result.check_stdout(file_regression, extension=".md") assert result.exit_code == 0 result = cli_runner.invoke(main, catch_exceptions=False, args="./staging") assert result.stdout.rstrip() == "./staging" assert result.exit_code == 0 ctx = click.Context(main, info_name="main", parent=None) argument = ctx.command.params[0] assert isinstance(argument, DescribedArgument) assert argument.description == "The destination directory."
def test_toggle(temp_repo): toggler = Toggler(temp_repo) with in_directory(temp_repo): runner = CliRunner() result: Result = runner.invoke(main) assert result.exit_code == 0 assert toggler.get_current_remote( ) == "https://github.com/domdfcoding/git-toggle.git" assert toggler.get_current_remote( "upstream") == "[email protected]:repo-helper/git-toggler.git" result = runner.invoke(main, args="ssh") assert result.exit_code == 0 assert toggler.get_current_remote( ) == "[email protected]:domdfcoding/git-toggle.git" assert toggler.get_current_remote( "upstream") == "[email protected]:repo-helper/git-toggler.git" result = runner.invoke(main, args="http") assert result.exit_code == 0 assert toggler.get_current_remote( ) == "https://github.com/domdfcoding/git-toggle.git" assert toggler.get_current_remote( "upstream") == "[email protected]:repo-helper/git-toggler.git" result = runner.invoke(main, args=["https", "--name", "upstream"]) assert result.exit_code == 0 assert toggler.get_current_remote( ) == "https://github.com/domdfcoding/git-toggle.git" assert toggler.get_current_remote( "upstream") == "https://github.com/repo-helper/git-toggler.git"
def test_cli_verbose_verbose( tmp_pathplus: PathPlus, advanced_file_regression: AdvancedFileRegressionFixture, advanced_data_regression: AdvancedDataRegressionFixture, demo_environment, ): result: Result with in_directory(tmp_pathplus): runner = CliRunner(mix_stderr=False) result = runner.invoke( main, args=["code.py", "--no-colour", "--diff", "--verbose", "-v"], ) assert result.exit_code == 1 advanced_file_regression.check_file(tmp_pathplus / "code.py") # Calling a second time shouldn't change anything with in_directory(tmp_pathplus): runner = CliRunner(mix_stderr=False) result = runner.invoke( main, args=[ "code.py", "code.c", "--no-colour", "--diff", "--verbose", "-v" ], ) assert result.exit_code == 0 check_out(result, advanced_data_regression)
def test_traceback_handler_show_traceback(exception, cli_runner: CliRunner): @click.command() def demo(): with handle_tracebacks(True, CustomTracebackHandler): raise exception with pytest.raises(type(exception), match=re.escape(str(exception))): cli_runner.invoke(demo, catch_exceptions=False)
def test_bad_config_cli_traceback(tmp_pathplus: PathPlus, config: Dict, match: str): dom_toml.dump({"project": config}, tmp_pathplus / "pyproject.toml") with in_directory(tmp_pathplus): runner = CliRunner() with pytest.raises(BadConfigError, match=match): runner.invoke(main, args=["-T"])
def test_help(file_regression: FileRegressionFixture): runner = CliRunner() result: Result = runner.invoke(main, args="-h") assert result.exit_code == 0 result.check_stdout(file_regression) result = runner.invoke(main, args="--help") assert result.exit_code == 0 result.check_stdout(file_regression)
def test_check_error( toml_string: str, tmp_pathplus: PathPlus, match: str, cli_runner: CliRunner, ): (tmp_pathplus / "pyproject.toml").write_clean(toml_string) with pytest.raises(BadConfigError, match=match), in_directory(tmp_pathplus): cli_runner.invoke(check, catch_exceptions=False, args=["-T"])
def test_version(): runner = CliRunner() result: Result = runner.invoke(github, args=["--version"]) assert result.exit_code == 0 assert re.match(f"repo_helper_github version {__version__}", result.stdout.rstrip()) result = runner.invoke(github, args=["--version", "--version"]) assert result.exit_code == 0 assert re.match( f"repo_helper_github version {__version__}, repo_helper .*", result.stdout.rstrip())
def test_flag_option(cli_runner: CliRunner): @flag_option("--no-colour") @click_command() def main(no_colour: bool): print(no_colour) result = cli_runner.invoke(main, catch_exceptions=False) assert result.stdout.rstrip() == "False" assert result.exit_code == 0 result = cli_runner.invoke(main, args="--no-colour") assert result.stdout.rstrip() == "True" assert result.exit_code == 0
def test_handle_tracebacks_show_traceback( exception, file_regression, cli_runner: CliRunner, ): @click.command() def demo(): with handle_tracebacks(show_traceback=True): raise exception with pytest.raises(type(exception), match=re.escape(str(exception))): cli_runner.invoke(demo, catch_exceptions=False)
def test_markdown_help_group( file_regression: FileRegressionFixture, force_not_pycharm, markdown_demo_group, cli_runner: CliRunner, ): demo_group, demo_command = markdown_demo_group result = cli_runner.invoke(demo_group, args=["--help"], color=True) result.check_stdout(file_regression, extension="_group.md") result = cli_runner.invoke(demo_command, args=["--help"], color=True) result.check_stdout(file_regression, extension="_command.md")
def test_cli_syntax_error_py310( tmp_pathplus: PathPlus, advanced_file_regression: AdvancedFileRegressionFixture, advanced_data_regression: AdvancedDataRegressionFixture, demo_environment, ): code = [ "class F:", "\tfrom collections import (", "Iterable,", "\tCounter,", "\t\t)", '', "\tdef foo(self):", "\t\tpass", '', "print('hello world'", ] (tmp_pathplus / "code.py").write_lines(code, trailing_whitespace=True) with in_directory(tmp_pathplus): runner = CliRunner(mix_stderr=False) result: Result = runner.invoke( main, args=["code.py", "--no-colour", "--verbose"]) assert result.exit_code == 126 check_out(result, advanced_data_regression)
def test_suggest_classifiers_add_existing(tmp_pathplus, advanced_file_regression: AdvancedFileRegressionFixture): (tmp_pathplus / "repo_helper.yml").write_lines([ "modname: repo_helper", 'copyright_years: "2020"', 'author: "Dominic Davis-Foster"', 'email: "*****@*****.**"', 'version: "0.0.1"', 'username: "******"', "license: 'LGPLv3+'", "short_desc: 'Update multiple configuration files, build scripts etc. from a single location.'", '', "classifiers:", " - 'Framework :: Flake8'", " - 'Intended Audience :: Developers'", ]) (tmp_pathplus / "requirements.txt").touch() (tmp_pathplus / "repo_helper").mkdir() with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke( suggest.classifiers, catch_exceptions=False, args=["-s", '4', "-l", "--add"] ) assert result.exit_code == 0 advanced_file_regression.check_file(tmp_pathplus / "repo_helper.yml")
def test_mkrecipe_bad_type( tmp_pathplus, pyproject_file, advanced_file_regression: AdvancedFileRegressionFixture, click_ver, ): (tmp_pathplus / "pyproject.toml").write_text( (configs_dir / pyproject_file).read_text()) (tmp_pathplus / "requirements.txt").write_lines([ "click>=7.1.2", 'colorama>=0.4.3; python_version < "3.10"', "deprecation-alias>=0.1.1", "domdf-python-tools>=2.5.1", "mistletoe>=0.7.2", "typing-extensions>=3.7.4.3", ]) with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(main, args=["--type", "egg"], catch_exceptions=False) assert result.exit_code == 2 result.check_stdout(advanced_file_regression)
def test_conda_recipe_specifiers( tmp_pathplus, file_regression: FileRegressionFixture, example_config, ): config = example_config.replace("repo_helper_demo", "repo_helper").replace("0.0.1", "2021.3.8") (tmp_pathplus / "repo_helper.yml").write_text(config) (tmp_pathplus / "requirements.txt").write_lines([ 'apeye>=0.3.0; python_version < "3.10"', "attrs[extra]>=20.2.0", ]) with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(make_recipe, catch_exceptions=False) assert result.exit_code == 0 if os.sep == '/': assert re.match(r"Wrote recipe to .*/conda/meta\.yaml", result.stdout) elif os.sep == '\\': assert re.match(r"Wrote recipe to .*(\\)?conda\\meta\.yaml", result.stdout.splitlines()[0]) else: raise NotImplementedError(os.sep) check_file_output(tmp_pathplus / "conda/meta.yaml", file_regression)
def test_devenv_verbose(temp_repo: Repo, extra_args, tests): lib_requirements = [ "click", "flask", "werkzeug", "consolekit", "requests", "apeye", ] test_requirements = [ "pytest", "hypothesis", ] repo_path = PathPlus(temp_repo.path) (repo_path / "requirements.txt").write_lines(lib_requirements) if tests: (repo_path / "tests").mkdir() (repo_path / "tests/requirements.txt").write_lines(test_requirements) else: with (repo_path / "repo_helper.yml").open('a') as fp: fp.write("enable_tests: false") with in_directory(temp_repo.path): runner = CliRunner() result: Result = runner.invoke(devenv, args=extra_args) assert result.exit_code == 0 assert "Installing project requirements" in result.stdout assert "Successfully created development virtualenv." in result.stdout if tests: assert "Installing test requirements" in result.stdout
def check_file(self, filename: str, mode: black.Mode, kwargs: dict, *, data: bool = True) -> None: source, expected = read_data(filename, data=data) result: Result with TemporaryPathPlus() as tmp_pathplus: (tmp_pathplus / filename).write_text(source) toml_data = dom_toml.load( PathPlus(__file__).parent / "example_formate.toml") toml_data["hooks"]["black"]["kwargs"] = kwargs dom_toml.dump(toml_data, tmp_pathplus / "formate.toml") with in_directory(tmp_pathplus): runner = CliRunner(mix_stderr=False) result = runner.invoke( main, args=[ filename, "--no-colour", "--diff", "--verbose", "-v" ], ) # TODO: check stdout actual = (tmp_pathplus / filename).read_text() self.assertFormatEqual(expected, actual) if source != actual: black.assert_equivalent(source, actual) black.assert_stable(source, actual, mode)
def test_list_remotes(temp_repo, file_regression: FileRegressionFixture): with in_directory(temp_repo): runner = CliRunner() result: Result = runner.invoke(main, args="--list") assert result.exit_code == 0 check_file_regression(result.stdout, file_regression)
def test_devenv(temp_repo: Repo): lib_requirements = [ "click", "flask", "werkzeug", "consolekit", "requests", "apeye", ] test_requirements = [ "pytest", "hypothesis", ] repo_path = PathPlus(temp_repo.path) (repo_path / "requirements.txt").write_lines(lib_requirements) (repo_path / "tests").mkdir() (repo_path / "tests/requirements.txt").write_lines(test_requirements) with in_directory(temp_repo.path): runner = CliRunner() result: Result = runner.invoke(devenv) assert result.exit_code == 0 assert result.stdout == 'Successfully created development virtualenv.\n' # Check list of packages in virtualenv venv_dir = repo_path / "venv" if sys.platform == "win32": version_dirs = [(venv_dir / "Lib")] elif PYPY: version_dirs = [venv_dir] else: version_dirs = list((venv_dir / "lib").glob("py*")) for version_dir in version_dirs: for package in lib_requirements: assert (version_dir / "site-packages" / package).is_dir() for package in test_requirements: assert (version_dir / "site-packages" / package).is_dir() assert len(version_dirs) == 1 pyvenv_config: Dict[str, str] = read_pyvenv(venv_dir) assert "prompt" in pyvenv_config assert pyvenv_config["prompt"] == "(repo_helper_demo) " assert "repo_helper_devenv" in pyvenv_config assert pyvenv_config["repo_helper_devenv"] == __version__ assert "virtualenv" in pyvenv_config assert "include-system-site-packages" in pyvenv_config assert not strtobool(pyvenv_config["include-system-site-packages"])
def test_bad_config_cli(tmp_pathplus: PathPlus, config: Dict, match: str): dom_toml.dump({"project": config}, tmp_pathplus / "pyproject.toml") with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(main) assert result.exit_code == 1 assert match in result.stdout