Merge branch 'develop' into feature_keyval_storage
This commit is contained in:
+277
-267
File diff suppressed because it is too large
Load Diff
+921
-247
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,456 @@
|
||||
"""
|
||||
Unit test file for rpc/external_message_consumer.py
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
import websockets
|
||||
|
||||
from freqtrade.data.dataprovider import DataProvider
|
||||
from freqtrade.rpc.external_message_consumer import ExternalMessageConsumer
|
||||
from tests.conftest import log_has, log_has_re, log_has_when
|
||||
|
||||
|
||||
_TEST_WS_TOKEN = "secret_Ws_t0ken"
|
||||
_TEST_WS_HOST = "127.0.0.1"
|
||||
_TEST_WS_PORT = 9989
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def patched_emc(default_conf, mocker):
|
||||
default_conf.update({
|
||||
"external_message_consumer": {
|
||||
"enabled": True,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": "null",
|
||||
"port": 9891,
|
||||
"ws_token": _TEST_WS_TOKEN
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
dataprovider = DataProvider(default_conf, None, None, None)
|
||||
emc = ExternalMessageConsumer(default_conf, dataprovider)
|
||||
|
||||
try:
|
||||
yield emc
|
||||
finally:
|
||||
emc.shutdown()
|
||||
|
||||
|
||||
def test_emc_start(patched_emc, caplog):
|
||||
# Test if the message was printed
|
||||
assert log_has_when("Starting ExternalMessageConsumer", caplog, "setup")
|
||||
# Test if the thread and loop objects were created
|
||||
assert patched_emc._thread and patched_emc._loop
|
||||
|
||||
# Test we call start again nothing happens
|
||||
prev_thread = patched_emc._thread
|
||||
patched_emc.start()
|
||||
assert prev_thread == patched_emc._thread
|
||||
|
||||
|
||||
def test_emc_shutdown(patched_emc, caplog):
|
||||
patched_emc.shutdown()
|
||||
|
||||
assert log_has("Stopping ExternalMessageConsumer", caplog)
|
||||
# Test the loop has stopped
|
||||
assert patched_emc._loop is None
|
||||
# Test if the thread has stopped
|
||||
assert patched_emc._thread is None
|
||||
|
||||
caplog.clear()
|
||||
patched_emc.shutdown()
|
||||
|
||||
# Test func didn't run again as it was called once already
|
||||
assert not log_has("Stopping ExternalMessageConsumer", caplog)
|
||||
|
||||
|
||||
def test_emc_init(patched_emc):
|
||||
# Test the settings were set correctly
|
||||
assert patched_emc.initial_candle_limit <= 1500
|
||||
assert patched_emc.wait_timeout > 0
|
||||
assert patched_emc.sleep_time > 0
|
||||
|
||||
|
||||
# Parametrize this?
|
||||
def test_emc_handle_producer_message(patched_emc, caplog, ohlcv_history):
|
||||
test_producer = {"name": "test", "url": "ws://test", "ws_token": "test"}
|
||||
producer_name = test_producer['name']
|
||||
invalid_msg = r"Invalid message .+"
|
||||
|
||||
caplog.set_level(logging.DEBUG)
|
||||
|
||||
# Test handle whitelist message
|
||||
whitelist_message = {"type": "whitelist", "data": ["BTC/USDT"]}
|
||||
patched_emc.handle_producer_message(test_producer, whitelist_message)
|
||||
|
||||
assert log_has(f"Received message of type `whitelist` from `{producer_name}`", caplog)
|
||||
assert log_has(
|
||||
f"Consumed message from `{producer_name}` of type `RPCMessageType.WHITELIST`", caplog)
|
||||
|
||||
# Test handle analyzed_df single candle message
|
||||
df_message = {
|
||||
"type": "analyzed_df",
|
||||
"data": {
|
||||
"key": ("BTC/USDT", "5m", "spot"),
|
||||
"df": ohlcv_history,
|
||||
"la": datetime.now(timezone.utc)
|
||||
}
|
||||
}
|
||||
patched_emc.handle_producer_message(test_producer, df_message)
|
||||
|
||||
assert log_has(f"Received message of type `analyzed_df` from `{producer_name}`", caplog)
|
||||
assert log_has_re(r"Holes in data or no existing df,.+", caplog)
|
||||
|
||||
# Test unhandled message
|
||||
unhandled_message = {"type": "status", "data": "RUNNING"}
|
||||
patched_emc.handle_producer_message(test_producer, unhandled_message)
|
||||
|
||||
assert log_has_re(r"Received unhandled message\: .*", caplog)
|
||||
|
||||
# Test malformed messages
|
||||
caplog.clear()
|
||||
malformed_message = {"type": "whitelist", "data": {"pair": "BTC/USDT"}}
|
||||
patched_emc.handle_producer_message(test_producer, malformed_message)
|
||||
|
||||
assert log_has_re(invalid_msg, caplog)
|
||||
caplog.clear()
|
||||
|
||||
malformed_message = {
|
||||
"type": "analyzed_df",
|
||||
"data": {
|
||||
"key": "BTC/USDT",
|
||||
"df": ohlcv_history,
|
||||
"la": datetime.now(timezone.utc)
|
||||
}
|
||||
}
|
||||
patched_emc.handle_producer_message(test_producer, malformed_message)
|
||||
|
||||
assert log_has(f"Received message of type `analyzed_df` from `{producer_name}`", caplog)
|
||||
assert log_has_re(invalid_msg, caplog)
|
||||
caplog.clear()
|
||||
|
||||
# Empty dataframe
|
||||
malformed_message = {
|
||||
"type": "analyzed_df",
|
||||
"data": {
|
||||
"key": ("BTC/USDT", "5m", "spot"),
|
||||
"df": ohlcv_history.loc[ohlcv_history['open'] < 0],
|
||||
"la": datetime.now(timezone.utc)
|
||||
}
|
||||
}
|
||||
patched_emc.handle_producer_message(test_producer, malformed_message)
|
||||
|
||||
assert log_has(f"Received message of type `analyzed_df` from `{producer_name}`", caplog)
|
||||
assert not log_has_re(invalid_msg, caplog)
|
||||
assert log_has_re(r"Received Empty Dataframe for.+", caplog)
|
||||
|
||||
caplog.clear()
|
||||
malformed_message = {"some": "stuff"}
|
||||
patched_emc.handle_producer_message(test_producer, malformed_message)
|
||||
|
||||
assert log_has_re(invalid_msg, caplog)
|
||||
caplog.clear()
|
||||
|
||||
caplog.clear()
|
||||
malformed_message = {"type": "whitelist", "data": None}
|
||||
patched_emc.handle_producer_message(test_producer, malformed_message)
|
||||
|
||||
assert log_has_re(r"Empty message .+", caplog)
|
||||
|
||||
|
||||
async def test_emc_create_connection_success(default_conf, caplog, mocker):
|
||||
default_conf.update({
|
||||
"external_message_consumer": {
|
||||
"enabled": True,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": _TEST_WS_HOST,
|
||||
"port": _TEST_WS_PORT,
|
||||
"ws_token": _TEST_WS_TOKEN
|
||||
}
|
||||
],
|
||||
"wait_timeout": 60,
|
||||
"ping_timeout": 60,
|
||||
"sleep_timeout": 60
|
||||
}
|
||||
})
|
||||
|
||||
mocker.patch('freqtrade.rpc.external_message_consumer.ExternalMessageConsumer.start',
|
||||
MagicMock())
|
||||
dp = DataProvider(default_conf, None, None, None)
|
||||
emc = ExternalMessageConsumer(default_conf, dp)
|
||||
|
||||
test_producer = default_conf['external_message_consumer']['producers'][0]
|
||||
lock = asyncio.Lock()
|
||||
|
||||
emc._running = True
|
||||
|
||||
async def eat(websocket):
|
||||
emc._running = False
|
||||
|
||||
try:
|
||||
async with websockets.serve(eat, _TEST_WS_HOST, _TEST_WS_PORT):
|
||||
await emc._create_connection(test_producer, lock)
|
||||
|
||||
assert log_has_re(r"Connected to channel.+", caplog)
|
||||
finally:
|
||||
emc.shutdown()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('host,port', [
|
||||
(_TEST_WS_HOST, -1),
|
||||
("10000.1241..2121/", _TEST_WS_PORT),
|
||||
])
|
||||
async def test_emc_create_connection_invalid_url(default_conf, caplog, mocker, host, port):
|
||||
default_conf.update({
|
||||
"external_message_consumer": {
|
||||
"enabled": True,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": host,
|
||||
"port": port,
|
||||
"ws_token": _TEST_WS_TOKEN
|
||||
}
|
||||
],
|
||||
"wait_timeout": 60,
|
||||
"ping_timeout": 60,
|
||||
"sleep_timeout": 60
|
||||
}
|
||||
})
|
||||
|
||||
dp = DataProvider(default_conf, None, None, None)
|
||||
# Handle start explicitly to avoid messing with threading in tests
|
||||
mocker.patch("freqtrade.rpc.external_message_consumer.ExternalMessageConsumer.start")
|
||||
mocker.patch("freqtrade.rpc.api_server.ws.channel.create_channel")
|
||||
emc = ExternalMessageConsumer(default_conf, dp)
|
||||
|
||||
try:
|
||||
emc._running = True
|
||||
await emc._create_connection(emc.producers[0], asyncio.Lock())
|
||||
assert log_has_re(r".+ is an invalid WebSocket URL .+", caplog)
|
||||
finally:
|
||||
emc.shutdown()
|
||||
|
||||
|
||||
async def test_emc_create_connection_error(default_conf, caplog, mocker):
|
||||
default_conf.update({
|
||||
"external_message_consumer": {
|
||||
"enabled": True,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": _TEST_WS_HOST,
|
||||
"port": _TEST_WS_PORT,
|
||||
"ws_token": _TEST_WS_TOKEN
|
||||
}
|
||||
],
|
||||
"wait_timeout": 60,
|
||||
"ping_timeout": 60,
|
||||
"sleep_timeout": 60
|
||||
}
|
||||
})
|
||||
|
||||
# Test unexpected error
|
||||
mocker.patch('websockets.connect', side_effect=RuntimeError)
|
||||
|
||||
dp = DataProvider(default_conf, None, None, None)
|
||||
emc = ExternalMessageConsumer(default_conf, dp)
|
||||
|
||||
try:
|
||||
await asyncio.sleep(0.05)
|
||||
assert log_has("Unexpected error has occurred:", caplog)
|
||||
finally:
|
||||
emc.shutdown()
|
||||
|
||||
|
||||
async def test_emc_receive_messages_valid(default_conf, caplog, mocker):
|
||||
caplog.set_level(logging.DEBUG)
|
||||
|
||||
default_conf.update({
|
||||
"external_message_consumer": {
|
||||
"enabled": True,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": _TEST_WS_HOST,
|
||||
"port": _TEST_WS_PORT,
|
||||
"ws_token": _TEST_WS_TOKEN
|
||||
}
|
||||
],
|
||||
"wait_timeout": 1,
|
||||
"ping_timeout": 60,
|
||||
"sleep_time": 60
|
||||
}
|
||||
})
|
||||
|
||||
mocker.patch('freqtrade.rpc.external_message_consumer.ExternalMessageConsumer.start',
|
||||
MagicMock())
|
||||
|
||||
lock = asyncio.Lock()
|
||||
test_producer = default_conf['external_message_consumer']['producers'][0]
|
||||
|
||||
dp = DataProvider(default_conf, None, None, None)
|
||||
emc = ExternalMessageConsumer(default_conf, dp)
|
||||
|
||||
class TestChannel:
|
||||
async def recv(self, *args, **kwargs):
|
||||
emc._running = False
|
||||
return {"type": "whitelist", "data": ["BTC/USDT"]}
|
||||
|
||||
async def ping(self, *args, **kwargs):
|
||||
return asyncio.Future()
|
||||
|
||||
try:
|
||||
emc._running = True
|
||||
await emc._receive_messages(TestChannel(), test_producer, lock)
|
||||
|
||||
assert log_has_re(r"Received message of type `whitelist`.+", caplog)
|
||||
finally:
|
||||
emc.shutdown()
|
||||
|
||||
|
||||
async def test_emc_receive_messages_invalid(default_conf, caplog, mocker):
|
||||
default_conf.update({
|
||||
"external_message_consumer": {
|
||||
"enabled": True,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": _TEST_WS_HOST,
|
||||
"port": _TEST_WS_PORT,
|
||||
"ws_token": _TEST_WS_TOKEN
|
||||
}
|
||||
],
|
||||
"wait_timeout": 1,
|
||||
"ping_timeout": 60,
|
||||
"sleep_time": 60
|
||||
}
|
||||
})
|
||||
|
||||
mocker.patch('freqtrade.rpc.external_message_consumer.ExternalMessageConsumer.start',
|
||||
MagicMock())
|
||||
|
||||
lock = asyncio.Lock()
|
||||
test_producer = default_conf['external_message_consumer']['producers'][0]
|
||||
|
||||
dp = DataProvider(default_conf, None, None, None)
|
||||
emc = ExternalMessageConsumer(default_conf, dp)
|
||||
|
||||
class TestChannel:
|
||||
async def recv(self, *args, **kwargs):
|
||||
emc._running = False
|
||||
return {"type": ["BTC/USDT"]}
|
||||
|
||||
async def ping(self, *args, **kwargs):
|
||||
return asyncio.Future()
|
||||
|
||||
try:
|
||||
emc._running = True
|
||||
await emc._receive_messages(TestChannel(), test_producer, lock)
|
||||
|
||||
assert log_has_re(r"Invalid message from.+", caplog)
|
||||
finally:
|
||||
emc.shutdown()
|
||||
|
||||
|
||||
async def test_emc_receive_messages_timeout(default_conf, caplog, mocker):
|
||||
default_conf.update({
|
||||
"external_message_consumer": {
|
||||
"enabled": True,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": _TEST_WS_HOST,
|
||||
"port": _TEST_WS_PORT,
|
||||
"ws_token": _TEST_WS_TOKEN
|
||||
}
|
||||
],
|
||||
"wait_timeout": 0.1,
|
||||
"ping_timeout": 1,
|
||||
"sleep_time": 1
|
||||
}
|
||||
})
|
||||
|
||||
mocker.patch('freqtrade.rpc.external_message_consumer.ExternalMessageConsumer.start',
|
||||
MagicMock())
|
||||
|
||||
lock = asyncio.Lock()
|
||||
test_producer = default_conf['external_message_consumer']['producers'][0]
|
||||
|
||||
dp = DataProvider(default_conf, None, None, None)
|
||||
emc = ExternalMessageConsumer(default_conf, dp)
|
||||
|
||||
def change_running():
|
||||
emc._running = not emc._running
|
||||
|
||||
class TestChannel:
|
||||
async def recv(self, *args, **kwargs):
|
||||
await asyncio.sleep(0.2)
|
||||
|
||||
async def ping(self, *args, **kwargs):
|
||||
return asyncio.Future()
|
||||
|
||||
try:
|
||||
change_running()
|
||||
|
||||
with pytest.raises(asyncio.TimeoutError):
|
||||
await emc._receive_messages(TestChannel(), test_producer, lock)
|
||||
|
||||
assert log_has_re(r"Ping error.+", caplog)
|
||||
finally:
|
||||
emc.shutdown()
|
||||
|
||||
|
||||
async def test_emc_receive_messages_handle_error(default_conf, caplog, mocker):
|
||||
default_conf.update({
|
||||
"external_message_consumer": {
|
||||
"enabled": True,
|
||||
"producers": [
|
||||
{
|
||||
"name": "default",
|
||||
"host": _TEST_WS_HOST,
|
||||
"port": _TEST_WS_PORT,
|
||||
"ws_token": _TEST_WS_TOKEN
|
||||
}
|
||||
],
|
||||
"wait_timeout": 1,
|
||||
"ping_timeout": 1,
|
||||
"sleep_time": 1
|
||||
}
|
||||
})
|
||||
|
||||
mocker.patch('freqtrade.rpc.external_message_consumer.ExternalMessageConsumer.start',
|
||||
MagicMock())
|
||||
|
||||
lock = asyncio.Lock()
|
||||
test_producer = default_conf['external_message_consumer']['producers'][0]
|
||||
|
||||
dp = DataProvider(default_conf, None, None, None)
|
||||
emc = ExternalMessageConsumer(default_conf, dp)
|
||||
|
||||
emc.handle_producer_message = MagicMock(side_effect=Exception)
|
||||
|
||||
class TestChannel:
|
||||
async def recv(self, *args, **kwargs):
|
||||
emc._running = False
|
||||
return {"type": "whitelist", "data": ["BTC/USDT"]}
|
||||
|
||||
async def ping(self, *args, **kwargs):
|
||||
return asyncio.Future()
|
||||
|
||||
try:
|
||||
emc._running = True
|
||||
await emc._receive_messages(TestChannel(), test_producer, lock)
|
||||
|
||||
assert log_has_re(r"Error handling producer message.+", caplog)
|
||||
finally:
|
||||
emc.shutdown()
|
||||
@@ -28,6 +28,7 @@ def test_init_telegram_disabled(mocker, default_conf, caplog) -> None:
|
||||
|
||||
def test_init_telegram_enabled(mocker, default_conf, caplog) -> None:
|
||||
caplog.set_level(logging.DEBUG)
|
||||
default_conf['telegram']['enabled'] = True
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
|
||||
|
||||
@@ -52,6 +53,7 @@ def test_cleanup_telegram_disabled(mocker, default_conf, caplog) -> None:
|
||||
|
||||
def test_cleanup_telegram_enabled(mocker, default_conf, caplog) -> None:
|
||||
caplog.set_level(logging.DEBUG)
|
||||
default_conf['telegram']['enabled'] = True
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.cleanup', MagicMock())
|
||||
|
||||
@@ -82,8 +84,25 @@ def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None:
|
||||
assert telegram_mock.call_count == 0
|
||||
|
||||
|
||||
def test_send_msg_telegram_error(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', side_effect=ValueError())
|
||||
default_conf['telegram']['enabled'] = True
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
rpc_manager = RPCManager(freqtradebot)
|
||||
rpc_manager.send_msg({
|
||||
'type': RPCMessageType.STATUS,
|
||||
'status': 'test'
|
||||
})
|
||||
|
||||
assert log_has("Sending rpc message: {'type': status, 'status': 'test'}", caplog)
|
||||
assert log_has("Exception occurred within RPC module telegram", caplog)
|
||||
|
||||
|
||||
def test_process_msg_queue(mocker, default_conf, caplog) -> None:
|
||||
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg')
|
||||
default_conf['telegram']['enabled'] = True
|
||||
default_conf['telegram']['allow_custom_messages'] = True
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init')
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
@@ -93,15 +112,15 @@ def test_process_msg_queue(mocker, default_conf, caplog) -> None:
|
||||
queue.append('Test message 2')
|
||||
rpc_manager.process_msg_queue(queue)
|
||||
|
||||
assert log_has("Sending rpc message: {'type': strategy_msg, 'msg': 'Test message'}", caplog)
|
||||
assert log_has("Sending rpc message: {'type': strategy_msg, 'msg': 'Test message 2'}", caplog)
|
||||
assert log_has("Sending rpc strategy_msg: Test message", caplog)
|
||||
assert log_has("Sending rpc strategy_msg: Test message 2", caplog)
|
||||
assert telegram_mock.call_count == 2
|
||||
|
||||
|
||||
def test_send_msg_telegram_enabled(mocker, default_conf, caplog) -> None:
|
||||
default_conf['telegram']['enabled'] = True
|
||||
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg')
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init')
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
rpc_manager = RPCManager(freqtradebot)
|
||||
rpc_manager.send_msg({
|
||||
@@ -150,7 +169,8 @@ def test_send_msg_webhook_CustomMessagetype(mocker, default_conf, caplog) -> Non
|
||||
caplog)
|
||||
|
||||
|
||||
def test_startupmessages_telegram_enabled(mocker, default_conf, caplog) -> None:
|
||||
def test_startupmessages_telegram_enabled(mocker, default_conf) -> None:
|
||||
default_conf['telegram']['enabled'] = True
|
||||
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
|
||||
|
||||
+843
-495
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
||||
# pragma pylint: disable=missing-docstring, C0103, protected-access
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from requests import RequestException
|
||||
|
||||
from freqtrade.enums import ExitType, RPCMessageType
|
||||
@@ -18,6 +18,10 @@ def get_webhook_dict() -> dict:
|
||||
"enabled": True,
|
||||
"url": "https://maker.ifttt.com/trigger/freqtrade_test/with/key/c764udvJ5jfSlswVRukZZ2/",
|
||||
"webhookentry": {
|
||||
# Intentionally broken, as "entry" should have priority.
|
||||
"value1": "Buying {pair55555}",
|
||||
},
|
||||
"entry": {
|
||||
"value1": "Buying {pair}",
|
||||
"value2": "limit {limit:8f}",
|
||||
"value3": "{stake_amount:8f} {stake_currency}",
|
||||
@@ -90,15 +94,15 @@ def test_send_msg_webhook(default_conf, mocker):
|
||||
webhook.send_msg(msg=msg)
|
||||
assert msg_mock.call_count == 1
|
||||
assert (msg_mock.call_args[0][0]["value1"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value1"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value1"].format(**msg))
|
||||
assert (msg_mock.call_args[0][0]["value2"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value2"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value2"].format(**msg))
|
||||
assert (msg_mock.call_args[0][0]["value3"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value3"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value3"].format(**msg))
|
||||
assert (msg_mock.call_args[0][0]["value4"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value4"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value4"].format(**msg))
|
||||
assert (msg_mock.call_args[0][0]["value5"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value5"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value5"].format(**msg))
|
||||
# Test short
|
||||
msg_mock.reset_mock()
|
||||
|
||||
@@ -117,15 +121,15 @@ def test_send_msg_webhook(default_conf, mocker):
|
||||
webhook.send_msg(msg=msg)
|
||||
assert msg_mock.call_count == 1
|
||||
assert (msg_mock.call_args[0][0]["value1"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value1"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value1"].format(**msg))
|
||||
assert (msg_mock.call_args[0][0]["value2"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value2"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value2"].format(**msg))
|
||||
assert (msg_mock.call_args[0][0]["value3"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value3"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value3"].format(**msg))
|
||||
assert (msg_mock.call_args[0][0]["value4"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value4"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value4"].format(**msg))
|
||||
assert (msg_mock.call_args[0][0]["value5"] ==
|
||||
default_conf["webhook"]["webhookentry"]["value5"].format(**msg))
|
||||
default_conf["webhook"]["entry"]["value5"].format(**msg))
|
||||
# Test buy cancel
|
||||
msg_mock.reset_mock()
|
||||
|
||||
@@ -328,7 +332,9 @@ def test_send_msg_webhook(default_conf, mocker):
|
||||
|
||||
|
||||
def test_exception_send_msg(default_conf, mocker, caplog):
|
||||
caplog.set_level(logging.DEBUG)
|
||||
default_conf["webhook"] = get_webhook_dict()
|
||||
del default_conf["webhook"]["entry"]
|
||||
del default_conf["webhook"]["webhookentry"]
|
||||
|
||||
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
||||
@@ -337,32 +343,32 @@ def test_exception_send_msg(default_conf, mocker, caplog):
|
||||
caplog)
|
||||
|
||||
default_conf["webhook"] = get_webhook_dict()
|
||||
default_conf["webhook"]["webhookentry"]["value1"] = "{DEADBEEF:8f}"
|
||||
default_conf["webhook"]["strategy_msg"] = {"value1": "{DEADBEEF:8f}"}
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
||||
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
||||
msg = {
|
||||
'type': RPCMessageType.ENTRY,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'ETH/BTC',
|
||||
'limit': 0.005,
|
||||
'order_type': 'limit',
|
||||
'stake_amount': 0.8,
|
||||
'stake_amount_fiat': 500,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'EUR'
|
||||
'type': RPCMessageType.STRATEGY_MSG,
|
||||
'msg': 'hello world',
|
||||
}
|
||||
webhook.send_msg(msg)
|
||||
assert log_has("Problem calling Webhook. Please check your webhook configuration. "
|
||||
"Exception: 'DEADBEEF'", caplog)
|
||||
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
||||
msg = {
|
||||
'type': 'DEADBEEF',
|
||||
'status': 'whatever'
|
||||
}
|
||||
with pytest.raises(NotImplementedError):
|
||||
# Test no failure for not implemented but known messagetypes
|
||||
for e in RPCMessageType:
|
||||
msg = {
|
||||
'type': e,
|
||||
'status': 'whatever'
|
||||
}
|
||||
webhook.send_msg(msg)
|
||||
|
||||
# Test no failure for not implemented but known messagetypes
|
||||
for e in RPCMessageType:
|
||||
msg = {
|
||||
'type': e,
|
||||
'status': 'whatever'
|
||||
}
|
||||
webhook.send_msg(msg)
|
||||
|
||||
|
||||
@@ -377,7 +383,7 @@ def test__send_msg(default_conf, mocker, caplog):
|
||||
webhook._send_msg(msg)
|
||||
|
||||
assert post.call_count == 1
|
||||
assert post.call_args[1] == {'data': msg}
|
||||
assert post.call_args[1] == {'data': msg, 'timeout': 10}
|
||||
assert post.call_args[0] == (default_conf['webhook']['url'], )
|
||||
|
||||
post = MagicMock(side_effect=RequestException)
|
||||
@@ -395,7 +401,7 @@ def test__send_msg_with_json_format(default_conf, mocker, caplog):
|
||||
mocker.patch("freqtrade.rpc.webhook.post", post)
|
||||
webhook._send_msg(msg)
|
||||
|
||||
assert post.call_args[1] == {'json': msg}
|
||||
assert post.call_args[1] == {'json': msg, 'timeout': 10}
|
||||
|
||||
|
||||
def test__send_msg_with_raw_format(default_conf, mocker, caplog):
|
||||
@@ -407,7 +413,11 @@ def test__send_msg_with_raw_format(default_conf, mocker, caplog):
|
||||
mocker.patch("freqtrade.rpc.webhook.post", post)
|
||||
webhook._send_msg(msg)
|
||||
|
||||
assert post.call_args[1] == {'data': msg['data'], 'headers': {'Content-Type': 'text/plain'}}
|
||||
assert post.call_args[1] == {
|
||||
'data': msg['data'],
|
||||
'headers': {'Content-Type': 'text/plain'},
|
||||
'timeout': 10
|
||||
}
|
||||
|
||||
|
||||
def test_send_msg_discord(default_conf, mocker):
|
||||
|
||||
Reference in New Issue
Block a user