Skip to content
Snippets Groups Projects
Commit 30ce4d13 authored by Marcin Sobczyk's avatar Marcin Sobczyk
Browse files

Tests for CLI commands: show pending withdraws

process deposit, process withdrawal, process cancel-withdrawal
parent 2d5cb961
No related branches found
No related tags found
2 merge requests!309V1.27.5.7 release,!280Tests for Impement CLI commands: show pending withdraws
Showing
with 642 additions and 2 deletions
......@@ -123,7 +123,10 @@ testing_clive:
extends: .testing
script:
- echo -e "${TXT_BLUE}Launching clive concurrent tests...${TXT_CLEAR}"
- python3 -m pytest --ignore "tests/functional/beekeeper" --ignore "tests/tui" -k "not test_autocompletion_time" -n auto --durations 0 --junitxml=report.xml tests/
- python3 -m pytest
--ignore "tests/functional/beekeeper" --ignore "tests/tui" --ignore "tests/functional/cli"
-k "not test_autocompletion_time"
-n auto --durations 0 --junitxml=report.xml tests/
testing_clive_import_times_during_autocompletion:
extends: .testing
......@@ -137,6 +140,12 @@ testing_tui:
- echo -e "${TXT_BLUE}Launching tui tests...${TXT_CLEAR}"
- python3 -m pytest -n auto --durations 0 --junitxml=report.xml tests/tui
testing_cli:
extends: .testing
script:
- echo -e "${TXT_BLUE}Launching cli commands tests...${TXT_CLEAR}"
- python3 -m pytest -n auto --durations 0 --junitxml=report.xml tests/functional/cli
testing_password_private_key_logging:
stage: tests
needs:
......
......@@ -17,6 +17,7 @@ from clive.__private.core.world import World
from clive.__private.storage.accounts import Account as WatchedAccount
from clive.__private.storage.accounts import WorkingAccount
from clive.main import _main as clive_main
from clive_local_tools.constants import TESTNET_CHAIN_ID
from clive_local_tools.testnet_block_log import (
get_alternate_chain_spec_path,
get_block_log,
......@@ -71,7 +72,7 @@ def prepare_node() -> tt.RawNode:
async def prepare_profile(node: tt.RawNode) -> None:
tt.logger.info("Configuring ProfileData for clive")
settings["secrets.node_address"] = node.http_endpoint.as_string()
settings["node.chain_id"] = "18dcf0a285365fc58b71f18b3d3fec954aa0c141c44e4e5cb4cf777b9eab274e"
settings["node.chain_id"] = TESTNET_CHAIN_ID
ProfileData(
WORKING_ACCOUNT.name,
......
from __future__ import annotations
from typing import TYPE_CHECKING
from .show import balances as show_balances
if TYPE_CHECKING:
from typing import Literal
import test_tools as tt
from click.testing import Result
from typer.testing import CliRunner
from clive.__private.cli.clive_typer import CliveTyper
def assert_no_exit_code_error(result: Result) -> None:
exit_code = 0
message = f"Exit code '{result.exit_code}' is different than expected '{exit_code}'. Output:\n{result.output}"
assert result.exit_code == exit_code, message
def assert_exit_code(result: Result, expected_code: int) -> None:
message = f"Exit code '{result.exit_code}' is different than expected '{expected_code}'. Output:\n{result.output}"
assert result.exit_code == expected_code, message
def assert_balances(
runner: CliRunner,
cli: CliveTyper,
account_name: str,
asset_amount: tt.Asset.AnyT,
balance: Literal["Liquid", "Savings", "Unclaimed"],
) -> None:
result = show_balances(runner, cli, account_name=account_name)
output = result.output
assert_no_exit_code_error(result)
assert account_name in output, f"no balances of {account_name} account in balances output: {output}"
assert any(
asset_amount.token() in line and asset_amount.pretty_amount() in line and balance in line
for line in output.split("\n")
), f"no {asset_amount.pretty_amount()} {asset_amount.token()} in balances output:\n{output}"
def assert_pending_withrawals(output: str, *, account_name: str, asset_amount: tt.Asset.AnyT) -> None:
assert any(
account_name in line and asset_amount.pretty_amount() in line and asset_amount.token() in line.upper()
for line in output.split("\n")
), f"no {asset_amount.pretty_amount()} {asset_amount.token()} in pending withdrawals output:\n{output}"
from __future__ import annotations
from typing import TYPE_CHECKING
import test_tools as tt
if TYPE_CHECKING:
from click.testing import Result
from typer.testing import CliRunner
from clive.__private.cli.clive_typer import CliveTyper
def balances(
runner: CliRunner, cli: CliveTyper, profile_name: str | None = None, account_name: str | None = None
) -> Result:
"""If profile_name or account_name is None then default value is used."""
command = ["show", "balances"]
if profile_name is not None:
command.append(f"--profile-name={profile_name}")
if account_name is not None:
command.append(f"--account-name={account_name}")
tt.logger.info(f"executing command {command}")
return runner.invoke(cli, command)
......@@ -2,4 +2,16 @@ from __future__ import annotations
from typing import Final
import test_tools as tt
TESTNET_CHAIN_ID: Final[str] = "18dcf0a285365fc58b71f18b3d3fec954aa0c141c44e4e5cb4cf777b9eab274e"
CREATOR_ACCOUNT: Final[tt.Account] = tt.Account("initminer")
WORKING_ACCOUNT: Final[tt.Account] = tt.Account("alice")
WATCHED_ACCOUNTS: Final[list[tt.Account]] = [tt.Account(name) for name in ("bob", "timmy", "john")]
WORKING_ACCOUNT_KEY_ALIAS: Final[str] = f"{WORKING_ACCOUNT.name}_key"
WORKING_ACCOUNT_HIVE_LIQUID_BALANCE: Final[tt.Asset.TestT] = tt.Asset.Test(1234)
WORKING_ACCOUNT_HBD_LIQUID_BALANCE: Final[tt.Asset.TbdT] = tt.Asset.Tbd(2345)
WORKING_ACCOUNT_VEST_BALANCE: Final[tt.Asset.TestT] = tt.Asset.Test(3456)
from __future__ import annotations
from typing import TYPE_CHECKING
import pytest
import test_tools as tt
from typer.testing import CliRunner
from clive.__private.core.commands.create_wallet import CreateWallet
from clive.__private.core.keys.keys import PrivateKeyAliased
from clive.__private.core.profile_data import ProfileData
from clive.__private.core.world import World
from clive.__private.storage.accounts import Account as WatchedAccount
from clive.__private.storage.accounts import WorkingAccount
from clive.core.url import Url
from clive_local_tools.constants import (
CREATOR_ACCOUNT,
WATCHED_ACCOUNTS,
WORKING_ACCOUNT,
WORKING_ACCOUNT_HBD_LIQUID_BALANCE,
WORKING_ACCOUNT_HIVE_LIQUID_BALANCE,
WORKING_ACCOUNT_KEY_ALIAS,
WORKING_ACCOUNT_VEST_BALANCE,
)
if TYPE_CHECKING:
from clive.__private.cli.clive_typer import CliveTyper
@pytest.fixture()
async def cli_with_runner() -> tuple[CliveTyper, CliRunner]:
"""Will run init node, configure profile and return CliRunner from typer.testing module."""
init_node = tt.InitNode()
init_node.config.plugin.append("transaction_status_api")
init_node.config.plugin.append("account_history_api")
init_node.config.plugin.append("account_history_rocksdb")
init_node.config.plugin.append("reputation_api")
init_node.run()
cli_wallet = tt.Wallet(attach_to=init_node, additional_arguments=["--transaction-serialization", "hf26"])
cli_wallet.api.import_key(init_node.config.private_key[0])
with cli_wallet.in_single_transaction():
creator_account_name = CREATOR_ACCOUNT.name
for account in [WORKING_ACCOUNT, *WATCHED_ACCOUNTS]:
key = tt.PublicKey(account.name)
cli_wallet.api.create_account_with_keys(
creator_account_name,
account.name,
"{}",
key,
key,
key,
key,
)
cli_wallet.api.transfer(
creator_account_name, account.name, WORKING_ACCOUNT_HIVE_LIQUID_BALANCE.as_nai(), "memo"
)
cli_wallet.api.transfer_to_vesting(
creator_account_name, account.name, WORKING_ACCOUNT_VEST_BALANCE.as_nai()
)
cli_wallet.api.transfer(
creator_account_name, account.name, WORKING_ACCOUNT_HBD_LIQUID_BALANCE.as_nai(), "memo"
)
ProfileData(
WORKING_ACCOUNT.name,
working_account=WorkingAccount(name=WORKING_ACCOUNT.name),
watched_accounts=[WatchedAccount(acc.name) for acc in WATCHED_ACCOUNTS],
).save()
async with World(WORKING_ACCOUNT.name) as world:
await CreateWallet(
app_state=world.app_state,
beekeeper=world.beekeeper,
wallet=WORKING_ACCOUNT.name,
password=WORKING_ACCOUNT.name,
).execute_with_result()
await world.node.set_address(Url.parse(init_node.http_endpoint.as_string()))
world.profile_data.working_account.keys.add_to_import(
PrivateKeyAliased(value=WORKING_ACCOUNT.private_key, alias=f"{WORKING_ACCOUNT_KEY_ALIAS}")
)
await world.commands.sync_data_with_beekeeper()
runner = CliRunner()
# import cli after default profile is set, default values for --profile-name option are set during loading
from clive.__private.cli.main import cli
return cli, runner
from __future__ import annotations
from typing import TYPE_CHECKING
import test_tools as tt
from clive_local_tools.cli import checkers
from clive_local_tools.constants import (
WATCHED_ACCOUNTS,
WORKING_ACCOUNT,
WORKING_ACCOUNT_HIVE_LIQUID_BALANCE,
WORKING_ACCOUNT_KEY_ALIAS,
)
if TYPE_CHECKING:
from typer.testing import CliRunner
from clive.__private.cli.clive_typer import CliveTyper
amount_to_deposit = tt.Asset.Test(0.235)
large_amount = tt.Asset.Test(234234.235)
async def test_deposit_valid(cli_with_runner: tuple[CliveTyper, CliRunner]) -> None:
# ARRANGE
cli, runner = cli_with_runner
# ACT
result = runner.invoke(
cli,
[
"process",
"savings",
"deposit",
f"--amount={amount_to_deposit.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
# ASSERT
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=amount_to_deposit,
balance="Savings",
)
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=WORKING_ACCOUNT_HIVE_LIQUID_BALANCE - amount_to_deposit.amount,
balance="Liquid",
)
async def test_deposit_to_other_account(cli_with_runner: tuple[CliveTyper, CliRunner]) -> None:
# ARRANGE
cli, runner = cli_with_runner
other_account = WATCHED_ACCOUNTS[0]
# ACT
result = runner.invoke(
cli,
[
"process",
"savings",
"deposit",
f"--amount={amount_to_deposit.as_legacy()}",
f"--from={WORKING_ACCOUNT.name}",
f"--to={other_account.name}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
# ASSERT
checkers.assert_balances(
runner,
cli,
account_name=f"{other_account.name}",
asset_amount=amount_to_deposit,
balance="Savings",
)
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=tt.Asset.Hive(0),
balance="Savings",
)
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=WORKING_ACCOUNT_HIVE_LIQUID_BALANCE - amount_to_deposit.amount,
balance="Liquid",
)
async def test_deposit_not_enough_hive(cli_with_runner: tuple[CliveTyper, CliRunner]) -> None:
# ARRANGE
cli, runner = cli_with_runner
# ACT
result = runner.invoke(
cli,
[
"process",
"savings",
"deposit",
f"--amount={large_amount.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_exit_code(result, expected_code=1)
# ASSERT
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=tt.Asset.Hive(0),
balance="Savings",
)
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=WORKING_ACCOUNT_HIVE_LIQUID_BALANCE,
balance="Liquid",
)
from __future__ import annotations
from typing import TYPE_CHECKING
import test_tools as tt
from clive_local_tools.cli import checkers
from clive_local_tools.constants import WORKING_ACCOUNT, WORKING_ACCOUNT_HIVE_LIQUID_BALANCE, WORKING_ACCOUNT_KEY_ALIAS
if TYPE_CHECKING:
from typer.testing import CliRunner
from clive.__private.cli.clive_typer import CliveTyper
amount_to_deposit = tt.Asset.Test(0.236)
large_amount = tt.Asset.Test(234234.236)
async def test_withdrawal_valid(cli_with_runner: tuple[CliveTyper, CliRunner]) -> None:
# ARRANGE
cli, runner = cli_with_runner
result = runner.invoke(
cli,
[
"process",
"savings",
"deposit",
f"--amount={amount_to_deposit.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
# ACT
result = runner.invoke(
cli,
[
"process",
"savings",
"withdrawal",
f"--amount={amount_to_deposit.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
# ASSERT
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=tt.Asset.Hive(0),
balance="Savings",
)
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=WORKING_ACCOUNT_HIVE_LIQUID_BALANCE - amount_to_deposit.amount,
balance="Liquid",
)
async def test_withdrawal_invalid(cli_with_runner: tuple[CliveTyper, CliRunner]) -> None:
# ARRANGE
cli, runner = cli_with_runner
# ACT
result = runner.invoke(
cli,
[
"process",
"savings",
"withdrawal",
f"--amount={large_amount.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
# ASSERT
checkers.assert_exit_code(result, expected_code=1)
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=tt.Asset.Hive(0),
balance="Savings",
)
checkers.assert_balances(
runner,
cli,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=WORKING_ACCOUNT_HIVE_LIQUID_BALANCE,
balance="Liquid",
)
from __future__ import annotations
from typing import TYPE_CHECKING
import test_tools as tt
from clive_local_tools.cli import checkers
from clive_local_tools.constants import WORKING_ACCOUNT, WORKING_ACCOUNT_KEY_ALIAS
if TYPE_CHECKING:
from typer.testing import CliRunner
from clive.__private.cli.clive_typer import CliveTyper
amount_to_deposit = tt.Asset.Test(0.234)
async def test_withdrawal_cancel_valid(cli_with_runner: tuple[CliveTyper, CliRunner]) -> None:
# ARRANGE
cli, runner = cli_with_runner
request_id = 13
result = runner.invoke(
cli,
[
"process",
"savings",
"deposit",
f"--amount={amount_to_deposit.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
result = runner.invoke(
cli,
[
"process",
"savings",
"withdrawal",
f"--request-id={request_id}",
f"--amount={amount_to_deposit.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
# ACT
result = runner.invoke(
cli,
[
"process",
"savings",
"withdrawal-cancel",
f"--request-id={request_id}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
# ASSERT
result = runner.invoke(cli, ["show", "pending", "withdrawals"])
checkers.assert_no_exit_code_error(result)
assert str(amount_to_deposit.amount) not in result.stdout
async def test_withdrawal_cancel_invalid(cli_with_runner: tuple[CliveTyper, CliRunner]) -> None:
# ARRANGE
cli, runner = cli_with_runner
actual_request_id = 23
invalid_request_id = 24
result = runner.invoke(
cli,
[
"process",
"savings",
"deposit",
f"--amount={amount_to_deposit.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
result = runner.invoke(
cli,
[
"process",
"savings",
"withdrawal",
f"--request-id={actual_request_id}",
f"--amount={amount_to_deposit.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
# ACT
result = runner.invoke(
cli,
[
"process",
"savings",
"withdrawal-cancel",
f"--request-id={invalid_request_id}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_exit_code(result, expected_code=1)
# ASSERT
result = runner.invoke(cli, ["show", "pending", "withdrawals"])
checkers.assert_no_exit_code_error(result)
checkers.assert_pending_withrawals(
result.stdout,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=amount_to_deposit,
)
from __future__ import annotations
from typing import TYPE_CHECKING
import test_tools as tt
from clive_local_tools.cli import checkers
from clive_local_tools.constants import WORKING_ACCOUNT, WORKING_ACCOUNT_KEY_ALIAS
if TYPE_CHECKING:
from typer.testing import CliRunner
from clive.__private.cli.clive_typer import CliveTyper
amount_to_withdraw = tt.Asset.Test(0.111)
amount_to_withdraw2 = tt.Asset.Test(0.112)
amount_to_deposit = tt.Asset.Test(0.345)
async def test_show_pending_withdrawals_none(
cli_with_runner: tuple[CliveTyper, CliRunner],
) -> None:
# ARRANGE
cli, runner = cli_with_runner
# ACT
result = runner.invoke(cli, ["show", "pending", "withdrawals"])
# ASSERT
checkers.assert_no_exit_code_error(result)
assert "no pending withdrawals" in result.stdout
async def test_show_pending_withdrawals_basic(
cli_with_runner: tuple[CliveTyper, CliRunner],
) -> None:
# ARRANGE
cli, runner = cli_with_runner
result = runner.invoke(
cli,
[
"process",
"savings",
"deposit",
f"--amount={amount_to_deposit.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
result = runner.invoke(
cli,
[
"process",
"savings",
"withdrawal",
f"--amount={amount_to_withdraw.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
result = runner.invoke(
cli,
[
"process",
"savings",
"withdrawal",
f"--amount={amount_to_withdraw2.as_legacy()}",
f"--password={WORKING_ACCOUNT.name}",
f"--sign={WORKING_ACCOUNT_KEY_ALIAS}",
],
)
checkers.assert_no_exit_code_error(result)
# ACT
result = runner.invoke(cli, ["show", "pending", "withdrawals"])
# ASSERT
checkers.assert_no_exit_code_error(result)
checkers.assert_pending_withrawals(
result.stdout,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=amount_to_withdraw,
)
checkers.assert_pending_withrawals(
result.stdout,
account_name=f"{WORKING_ACCOUNT.name}",
asset_amount=amount_to_withdraw2,
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment