from pathlib import Path from unittest.mock import MagicMock import pytest import rapidjson from freqtrade.commands.build_config_commands import ( ask_user_config, ask_user_overwrite, start_new_config, validate_is_float, validate_is_int, ) from freqtrade.exceptions import OperationalException from tests.conftest import get_args, log_has_re def test_validate_is_float(): assert validate_is_float("2.0") assert validate_is_float("2.1") assert validate_is_float("0.1") assert validate_is_float("-0.5") assert not validate_is_float("-0.5e") def test_validate_is_int(): assert validate_is_int("2") assert validate_is_int("6") assert validate_is_int("-1") assert validate_is_int("500") assert not validate_is_int("2.0") assert not validate_is_int("2.1") assert not validate_is_int("-2.1") assert not validate_is_int("-ee") @pytest.mark.parametrize("exchange", ["bybit", "binance", "kraken"]) def test_start_new_config(mocker, caplog, exchange): wt_mock = mocker.patch.object(Path, "write_text", MagicMock()) mocker.patch.object(Path, "exists", MagicMock(return_value=True)) unlink_mock = mocker.patch.object(Path, "unlink", MagicMock()) mocker.patch("freqtrade.commands.build_config_commands.ask_user_overwrite", return_value=True) sample_selections = { "max_open_trades": 3, "stake_currency": "USDT", "stake_amount": 100, "fiat_display_currency": "EUR", "timeframe": "15m", "dry_run": True, "trading_mode": "spot", "margin_mode": "", "exchange_name": exchange, "exchange_key": "sampleKey", "exchange_secret": "Samplesecret", "telegram": False, "telegram_token": "asdf1244", "telegram_chat_id": "1144444", "api_server": False, "api_server_listen_addr": "127.0.0.1", "api_server_username": "freqtrader", "api_server_password": "MoneyMachine", } mocker.patch( "freqtrade.commands.build_config_commands.ask_user_config", return_value=sample_selections ) args = ["new-config", "--config", "coolconfig.json"] start_new_config(get_args(args)) assert log_has_re("Writing config to .*", caplog) assert wt_mock.call_count == 1 assert unlink_mock.call_count == 1 result = rapidjson.loads( wt_mock.call_args_list[0][0][0], parse_mode=rapidjson.PM_COMMENTS | rapidjson.PM_TRAILING_COMMAS, ) assert result["exchange"]["name"] == exchange assert result["timeframe"] == "15m" def test_start_new_config_exists(mocker, caplog): mocker.patch.object(Path, "exists", MagicMock(return_value=True)) mocker.patch("freqtrade.commands.build_config_commands.ask_user_overwrite", return_value=False) args = ["new-config", "--config", "coolconfig.json"] with pytest.raises(OperationalException, match=r"Configuration .* already exists\."): start_new_config(get_args(args)) def test_ask_user_overwrite(mocker): """ Once https://github.com/tmbo/questionary/issues/35 is implemented, improve this test. """ prompt_mock = mocker.patch( "freqtrade.commands.build_config_commands.prompt", return_value={"overwrite": False} ) assert not ask_user_overwrite(Path("test.json")) assert prompt_mock.call_count == 1 prompt_mock.reset_mock() prompt_mock = mocker.patch( "freqtrade.commands.build_config_commands.prompt", return_value={"overwrite": True} ) assert ask_user_overwrite(Path("test.json")) assert prompt_mock.call_count == 1 def test_ask_user_config(mocker): """ Once https://github.com/tmbo/questionary/issues/35 is implemented, improve this test. """ prompt_mock = mocker.patch( "freqtrade.commands.build_config_commands.prompt", return_value={"overwrite": False} ) answers = ask_user_config() assert isinstance(answers, dict) assert prompt_mock.call_count == 1 prompt_mock = mocker.patch("freqtrade.commands.build_config_commands.prompt", return_value={}) with pytest.raises(OperationalException, match=r"User interrupted interactive questions\."): ask_user_config()