diff --git a/pyproject.toml b/pyproject.toml index d61ab97..68d12e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ dependencies = [ "Babel", "click", "click-default-group", - "pymonzo>=2.0.0", + "pymonzo>=2.1.0", "rich", "rich-click", ] diff --git a/src/monz/command_line.py b/src/monz/command_line.py index 9063dc4..cc115df 100644 --- a/src/monz/command_line.py +++ b/src/monz/command_line.py @@ -19,6 +19,14 @@ rich_console = Console() +# Options used in multiple places +option_account_id = click.option( + "--account_id", + "-a", + type=str, + help="Monzo account ID. Can be omitted if user has only one (active) account.", +) + @click.group(cls=DefaultRichGroup, default="info", default_if_no_args=True) @rich_click.rich_config(help_config=help_config) @@ -143,12 +151,7 @@ def accounts(monzo_api: MonzoAPI) -> None: @cli.command() -@click.option( - "--account_id", - "-a", - type=str, - help="Monzo account ID. Can be omitted if user has only one (active) account.", -) +@option_account_id @click.pass_obj def balance(monzo_api: MonzoAPI, account_id: Optional[str]) -> None: """Show Monzo account balance. @@ -164,12 +167,33 @@ def balance(monzo_api: MonzoAPI, account_id: Optional[str]) -> None: @cli.command() +@option_account_id @click.option( - "--account_id", - "-a", - type=str, - help="Monzo account ID. Can be omitted if user has only one (active) account.", + "--show_deleted/--hide_deleted", + default=False, + help="Whether to show deleted pots.", ) +@click.pass_obj +def pots(monzo_api: MonzoAPI, account_id: Optional[str], show_deleted: bool) -> None: + """Show Monzo pots.""" + try: + monzo_pots = monzo_api.pots.list(account_id=account_id) + except PyMonzoError as e: + raise click.UsageError(str(e)) from e + + if not show_deleted: + monzo_pots = [pot for pot in monzo_pots if not pot.deleted] + + for n, pot in enumerate(monzo_pots, start=1): + rich_console.print(pot) + + # Print a new line between accounts + if n != len(monzo_pots): + rich_console.print() + + +@cli.command() +@option_account_id @click.option( "--num", "-n", @@ -208,5 +232,6 @@ def transactions(monzo_api: MonzoAPI, account_id: Optional[str], num: int) -> No for n, transaction in enumerate(list(reversed(monzo_transactions))[:num], start=1): rich_console.print(transaction) + # Print a new line between transactions if n != len(monzo_transactions): - click.echo() # Print a new line between transactions + rich_console.print() diff --git a/tests/monz/conftest.py b/tests/monz/conftest.py index 11f5fc2..0b5a52d 100644 --- a/tests/monz/conftest.py +++ b/tests/monz/conftest.py @@ -9,6 +9,7 @@ from .factories import ( MonzoAccountFactory, MonzoBalanceFactory, + MonzoPotFactory, MonzoTransactionFactory, MonzoWhoAmIFactory, ) @@ -27,6 +28,8 @@ def mocked_monzo_api(mocker: MockerFixture) -> MagicMock: account1 = MonzoAccountFactory.build() account2 = MonzoAccountFactory.build() balance = MonzoBalanceFactory.build() + pot1 = MonzoPotFactory.build(deleted=False) + pot2 = MonzoPotFactory.build(deleted=False) transaction1 = MonzoTransactionFactory.build() transaction2 = MonzoTransactionFactory.build() transaction3 = MonzoTransactionFactory.build() @@ -36,6 +39,7 @@ def mocked_monzo_api(mocker: MockerFixture) -> MagicMock: monzo_api = mocker.MagicMock() monzo_api.accounts.list.return_value = [account1, account2] monzo_api.balance.get.return_value = balance + monzo_api.pots.list.return_value = [pot1, pot2] monzo_api.transactions.list.return_value = [ transaction1, transaction2, diff --git a/tests/monz/factories.py b/tests/monz/factories.py index eb3dc3e..d35227e 100644 --- a/tests/monz/factories.py +++ b/tests/monz/factories.py @@ -3,6 +3,7 @@ from polyfactory.factories.pydantic_factory import ModelFactory from pymonzo.accounts import MonzoAccount from pymonzo.balance import MonzoBalance +from pymonzo.pots import MonzoPot from pymonzo.transactions import MonzoTransaction from pymonzo.whoami import MonzoWhoAmI @@ -15,6 +16,10 @@ class MonzoBalanceFactory(ModelFactory[MonzoBalance]): """Factory for `MonzoBalance` schema.""" +class MonzoPotFactory(ModelFactory[MonzoPot]): + """Factory for `MonzoPot` schema.""" + + class MonzoTransactionFactory(ModelFactory[MonzoTransaction]): """Factory for `MonzoTransaction` schema.""" diff --git a/tests/monz/test_command_line.py b/tests/monz/test_command_line.py index b1895ee..4e8bb91 100644 --- a/tests/monz/test_command_line.py +++ b/tests/monz/test_command_line.py @@ -130,6 +130,34 @@ def test_balance( # TODO: Test `--account_id` option +def test_pots( + mocker: MockerFixture, + cli_runner: CliRunner, + mocked_monzo_api: MagicMock, +) -> None: + """Outputs user accounts.""" + mocked_MonzoAPI = mocker.patch( # noqa + "monz.command_line.MonzoAPI", + autospec=True, + return_value=mocked_monzo_api, + ) + + result = cli_runner.invoke(cli, args=["pots"]) + + mocked_MonzoAPI.assert_called_once_with(access_token=None) + mocked_monzo_api.pots.list.assert_called_once_with(account_id=None) + + assert result.exit_code == 0 + assert result.output + + pots = mocked_monzo_api.pots.list() + for pot in pots: + assert renderable_to_str(pot) in result.output + + # TODO: Test `--account_id` option + # TODO: Test `--show_deleted` option + + def test_transactions( mocker: MockerFixture, time_machine: TimeMachineFixture,