# Tests for CLI help formatting # # SPDX-FileCopyrightText: 2025 Nguyễn Gia Phong # SPDX-License-Identifier: AGPL-3.0-or-later from contextlib import redirect_stdout, suppress from io import StringIO from hypothesis import example, given from pytest import fixture, mark, raises from scadere import EXAMPLE_PREFIX, EXAMPLE_DESCRIPTION_PREFIX, NetLoc from scadere.check import main as check from scadere.listen import main as listen @fixture(scope='session') def help_string(request): string = StringIO() with suppress(SystemExit), redirect_stdout(string): request.param(arguments=['--help']) return string.getvalue() @mark.parametrize('help_string', [check, listen], indirect=True) def test_usage_prefix(help_string): assert help_string.startswith('Usage: ') @mark.parametrize('help_string', [check, listen], indirect=True) def test_options_heading(help_string): assert '\n\nOptions:\n' in help_string @mark.parametrize('help_string', [check], indirect=True) def test_one_or_more(help_string): assert ' HOST[:PORT]...\n' in help_string @mark.parametrize('help_string', [check], indirect=True) @mark.parametrize('short,long,metavar', [('-d', '--days', 'DAYS'), ('-o', '--output', 'PATH')]) def test_long_option(help_string, short, long, metavar): assert f'{short} {metavar}, {long}={metavar}' in help_string @mark.parametrize('help_string', [check, listen], indirect=True) def test_examples(help_string): epilog_index = help_string.find('\n\nExamples:\n') assert epilog_index >= 0 epilog = help_string[epilog_index:].removeprefix('\n\n') examples = epilog[:epilog.find('\n\n')] lines = examples.removeprefix('Examples:\n').splitlines() assert EXAMPLE_DESCRIPTION_PREFIX.startswith(EXAMPLE_PREFIX) assert not lines[0].startswith(EXAMPLE_DESCRIPTION_PREFIX) assert lines[-1].startswith(EXAMPLE_DESCRIPTION_PREFIX) must_be_desc = False for line in lines: if must_be_desc: assert line.startswith(EXAMPLE_DESCRIPTION_PREFIX) must_be_desc = False else: assert line.startswith(EXAMPLE_PREFIX) must_be_desc = not line.startswith(EXAMPLE_DESCRIPTION_PREFIX) @example('a.example:b', None) # string is unlikely to match .*:\D+ @example('a.example:98', None) # string is unlikely to match .*:\d+ @given(...) def test_netloc(string: str, default_port: int | None): netloc = NetLoc(default_port) if ':' not in string: assert netloc(string) == (string, default_port) else: hostname, port = string.rsplit(':', 1) try: port_number = int(port) except ValueError: with raises(ValueError): netloc(string) else: assert netloc(string) == (hostname, port_number)