diff --git a/littlepay/commands/groups.py b/littlepay/commands/groups.py index 37a3dcd..1a7817c 100644 --- a/littlepay/commands/groups.py +++ b/littlepay/commands/groups.py @@ -7,12 +7,12 @@ from littlepay.commands import RESULT_FAILURE, RESULT_SUCCESS, print_active_message from littlepay.config import Config -config = Config() - def groups(args: Namespace = None) -> int: return_code = RESULT_SUCCESS + config = Config() client = Client.from_active_config(config) + client.oauth.ensure_active_token(client.token) config.active_token = client.token @@ -72,6 +72,7 @@ def groups(args: Namespace = None) -> int: def create_group(client: Client, group_label: str) -> int: + config = Config() print_active_message(config, "Creating group", f"[{group_label}]") return_code = RESULT_SUCCESS @@ -86,6 +87,7 @@ def create_group(client: Client, group_label: str) -> int: def remove_group(client: Client, group_id: str, force: bool = False) -> int: + config = Config() print_active_message(config, "Removing group", f"[{group_id}]") return_code = RESULT_SUCCESS @@ -112,6 +114,7 @@ def remove_group(client: Client, group_id: str, force: bool = False) -> int: def link_product(client: Client, group_id: str, product_id: str) -> int: + config = Config() print_active_message(config, "Linking group <-> product", f"[{group_id}] <-> [{product_id}]") return_code = RESULT_SUCCESS @@ -126,6 +129,7 @@ def link_product(client: Client, group_id: str, product_id: str) -> int: def unlink_product(client: Client, group_id: str, product_id: str) -> int: + config = Config() print_active_message(config, "Unlinking group <-> product", f"[{group_id}] <-> [{product_id}]") return_code = RESULT_SUCCESS diff --git a/littlepay/commands/products.py b/littlepay/commands/products.py index c9818f9..0c16f5b 100644 --- a/littlepay/commands/products.py +++ b/littlepay/commands/products.py @@ -6,12 +6,12 @@ from littlepay.commands.groups import link_product, unlink_product from littlepay.config import Config -config = Config() - def products(args: Namespace = None) -> int: return_code = RESULT_SUCCESS + config = Config() client = Client.from_active_config(config) + client.oauth.ensure_active_token(client.token) config.active_token = client.token diff --git a/littlepay/main.py b/littlepay/main.py index 47a4831..81e8e34 100644 --- a/littlepay/main.py +++ b/littlepay/main.py @@ -2,6 +2,7 @@ from argparse import ArgumentParser, _SubParsersAction from littlepay import __version__ as version +from littlepay.commands import RESULT_FAILURE from littlepay.commands.configure import configure from littlepay.commands.groups import groups from littlepay.commands.products import products @@ -44,7 +45,7 @@ def _maincmd(name, help): # littlepay config [CONFIG_PATH] config_parser = _maincmd("config", help="Get or set configuration") - config_parser.add_argument("config_path", nargs="?", default=Config.current_path()) + config_parser.add_argument("config_path", nargs="?") # littlepay groups [-f GROUP] [{create,link,products,remove,unlink}] [...] groups_parser = _maincmd("groups", help="Interact with groups in the active environment") @@ -108,19 +109,19 @@ def _maincmd(name, help): switch_parser.add_argument("switch_type", choices=CONFIG_TYPES, help="The type of object to switch", metavar="TYPE") switch_parser.add_argument("switch_arg", help="The new object value", metavar="VALUE") - if len(argv) == 0: - argv = ["config"] - args = main_parser.parse_args(argv) if args.command == "config" or args.config_path: - return configure(args.config_path) + return configure(args.config_path or Config().current_path()) elif args.command == "groups": return groups(args) elif args.command == "products": return products(args) elif args.command == "switch": return switch(args.switch_type, args.switch_arg) + else: + main_parser.print_help() + return RESULT_FAILURE if __name__ == "__main__": diff --git a/tests/commands/test_groups.py b/tests/commands/test_groups.py index 633e4ea..3f04894 100644 --- a/tests/commands/test_groups.py +++ b/tests/commands/test_groups.py @@ -18,7 +18,7 @@ @pytest.fixture(autouse=True) def mock_config(mocker): - mocker.patch("littlepay.commands.groups.config") + mocker.patch("littlepay.commands.groups.Config") @pytest.fixture diff --git a/tests/commands/test_products.py b/tests/commands/test_products.py index 7e75643..b81219d 100644 --- a/tests/commands/test_products.py +++ b/tests/commands/test_products.py @@ -16,7 +16,7 @@ @pytest.fixture(autouse=True) def mock_config(mocker): - mocker.patch("littlepay.commands.products.config") + mocker.patch("littlepay.commands.products.Config") @pytest.fixture diff --git a/tests/test_littlepay.py b/tests/test_littlepay.py index 8bb6635..39f43ee 100644 --- a/tests/test_littlepay.py +++ b/tests/test_littlepay.py @@ -1,9 +1,10 @@ from pathlib import Path +import re import subprocess import pytest -from littlepay.commands import RESULT_SUCCESS +from littlepay.commands import RESULT_FAILURE, RESULT_SUCCESS from littlepay.config import _get_current_path, _update_current_path from tests.conftest import CUSTOM_CONFIG_FILE @@ -33,11 +34,12 @@ def test_littlepay(capfd): res = subprocess.call(["littlepay"]) capture = capfd.readouterr() - assert "Config:" in capture.out - assert "Envs:" in capture.out - assert "Participants:" in capture.out - assert "Active:" in capture.out - assert res == RESULT_SUCCESS + assert "Config:" not in capture.out + assert "Envs:" not in capture.out + assert "Participants:" not in capture.out + assert "Active:" not in capture.out + assert "usage: littlepay" in capture.out + assert res == RESULT_FAILURE def test_config(capfd): @@ -49,3 +51,14 @@ def test_config(capfd): assert "Participants:" in capture.out assert "Active:" in capture.out assert res == RESULT_SUCCESS + + +@pytest.mark.parametrize("version_flag", ["-v", "--version"]) +def test_version(capfd, version_flag): + res = subprocess.call(["littlepay", version_flag]) + capture = capfd.readouterr() + + assert "Creating config file:" not in capture.out + assert "Config:" not in capture.out + assert re.match(r"littlepay \d+\.\d+\.", capture.out) + assert res == RESULT_SUCCESS diff --git a/tests/test_main.py b/tests/test_main.py index 5cabb9a..7a3851d 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,9 +1,12 @@ from argparse import Namespace from pathlib import Path +import re + import pytest -from littlepay.commands import RESULT_SUCCESS +from littlepay.commands import RESULT_FAILURE, RESULT_SUCCESS from littlepay.config import CONFIG_TYPES, Config +import littlepay.main from littlepay.main import main, __name__ as MODULE @@ -27,11 +30,13 @@ def mock_commands_switch(mock_commands_switch): return mock_commands_switch(MODULE) -def test_main_default(mock_commands_config): +def test_main_default(capfd, mock_commands_config): result = main(argv=[]) + capture = capfd.readouterr() - assert result == RESULT_SUCCESS - mock_commands_config.assert_called_once_with(Config().current_path()) + assert result == RESULT_FAILURE + assert "usage: littlepay" in capture.out + mock_commands_config.assert_not_called() @pytest.mark.parametrize("config_flag", ["-c", "--config"]) @@ -266,3 +271,21 @@ def test_main_unrecognized(capfd): capture = capfd.readouterr() assert err.value.code != RESULT_SUCCESS assert "usage: littlepay" in capture.err + + +@pytest.mark.parametrize("version_flag", ["-v", "--version"]) +def test_main_version_flag(version_flag, mocker, capfd, mock_commands_config): + # littlepay.main.Config (the class) + config_cls = mocker.patch.object(littlepay.main, "Config") + # littlepay.main.Config() (an instance) + config = config_cls.return_value + + with pytest.raises(SystemExit) as err: + main(argv=[version_flag]) + capture = capfd.readouterr() + + assert err.value.code == RESULT_SUCCESS + assert re.match(r"littlepay \d+\.\d+\.", capture.out) + mock_commands_config.assert_not_called() + # there should have been no calls to any method on littlepay.main.Config() + assert len(config.mock_calls) == 0