mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-04 00:12:29 +00:00
[Release] openbb-v5.0.0 (#7741)
* merge branch develop with main * bump desktop version * fix the merge * sync Cargo.lock to desktop 2.0.0 * fix cli conftest.py --------- Co-authored-by: deeleeramone <>
This commit is contained in:
264
cli/tests/test_controllers_user_controller.py
Normal file
264
cli/tests/test_controllers_user_controller.py
Normal file
@@ -0,0 +1,264 @@
|
||||
"""Test the UserController class."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
MODULE = "openbb_cli.controllers.user_controller"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_user_session():
|
||||
"""Create a mock session for UserController."""
|
||||
with patch(f"{MODULE}.session") as sess:
|
||||
sess.console = MagicMock()
|
||||
yield sess
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_user_obb():
|
||||
"""Mock obb.user.preferences with sample fields."""
|
||||
with patch(f"{MODULE}.obb") as obb_mock:
|
||||
obb_mock.user.preferences = MagicMock()
|
||||
obb_mock.user.preferences.__class__.model_fields = {}
|
||||
obb_mock.user.preferences.model_fields = {}
|
||||
yield obb_mock
|
||||
|
||||
|
||||
class TestUserController:
|
||||
def test_generate_toggle_command(self, mock_user_session, mock_user_obb):
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
|
||||
field = {
|
||||
"command": "enable_feature",
|
||||
"field_name": "enable_feature",
|
||||
"description": "Enable a feature",
|
||||
"annotation": bool,
|
||||
"action": "toggle",
|
||||
}
|
||||
|
||||
ns = MagicMock()
|
||||
ctrl.parse_simple_args = MagicMock(return_value=(ns, []))
|
||||
mock_user_obb.user.preferences.enable_feature = True
|
||||
|
||||
ctrl._generate_command("enable_feature", field, "toggle")
|
||||
assert hasattr(ctrl, "call_enable_feature")
|
||||
|
||||
ctrl.call_enable_feature([])
|
||||
assert True
|
||||
mock_user_session.console.print.assert_called()
|
||||
|
||||
def test_generate_set_command_with_value(self, mock_user_session, mock_user_obb):
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
|
||||
field = {
|
||||
"command": "timezone",
|
||||
"field_name": "timezone",
|
||||
"description": "Set the timezone",
|
||||
"annotation": str,
|
||||
"action": "set",
|
||||
}
|
||||
|
||||
ns = MagicMock()
|
||||
ns.value = "US/Eastern"
|
||||
ctrl.parse_simple_args = MagicMock(return_value=(ns, []))
|
||||
|
||||
ctrl._generate_command("timezone", field, "set")
|
||||
assert hasattr(ctrl, "call_timezone")
|
||||
|
||||
ctrl.call_timezone(["-v", "US/Eastern"])
|
||||
mock_user_session.console.print.assert_called()
|
||||
|
||||
def test_generate_set_command_no_value_shows_current(
|
||||
self, mock_user_session, mock_user_obb
|
||||
):
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
|
||||
field = {
|
||||
"command": "timezone",
|
||||
"field_name": "timezone",
|
||||
"description": "Set the timezone",
|
||||
"annotation": str,
|
||||
"action": "set",
|
||||
}
|
||||
|
||||
ns = MagicMock()
|
||||
ns.value = None
|
||||
ctrl.parse_simple_args = MagicMock(return_value=(ns, []))
|
||||
mock_user_obb.user.preferences.timezone = "UTC"
|
||||
|
||||
ctrl._generate_command("timezone", field, "set")
|
||||
ctrl.call_timezone([])
|
||||
mock_user_session.console.print.assert_called()
|
||||
args = mock_user_session.console.print.call_args[0][0]
|
||||
assert "timezone" in args
|
||||
|
||||
def test_invalid_action_type(self, mock_user_session, mock_user_obb):
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
|
||||
field = {
|
||||
"command": "x",
|
||||
"field_name": "x",
|
||||
"description": "x",
|
||||
"annotation": str,
|
||||
"action": "bad",
|
||||
}
|
||||
|
||||
with pytest.raises(ValueError, match="not allowed"):
|
||||
ctrl._generate_command("x", field, "bad")
|
||||
|
||||
def test_call_credentials_loads_controller(self, mock_user_session, mock_user_obb):
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
ctrl.load_class = MagicMock(return_value=[])
|
||||
|
||||
ctrl.call_credentials(None)
|
||||
ctrl.load_class.assert_called_once()
|
||||
|
||||
def test_init_runs_super_and_generates_commands(
|
||||
self, mock_user_session, mock_user_obb
|
||||
):
|
||||
"""Real ``__init__`` calls super, runs ``_generate_command`` per pref, updates completer."""
|
||||
from unittest.mock import PropertyMock
|
||||
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
with (
|
||||
patch(
|
||||
"openbb_cli.controllers.base_controller.BaseController.__init__",
|
||||
return_value=None,
|
||||
) as super_init,
|
||||
patch.object(
|
||||
UserController,
|
||||
"choices_default",
|
||||
new_callable=PropertyMock,
|
||||
return_value={},
|
||||
),
|
||||
patch.object(UserController, "_generate_command") as gen,
|
||||
patch.object(UserController, "update_completer") as update_completer,
|
||||
):
|
||||
UserController(queue=["q"])
|
||||
super_init.assert_called_once_with(["q"])
|
||||
assert gen.call_count == len(UserController._PREF_COMMANDS)
|
||||
update_completer.assert_called_once()
|
||||
|
||||
def test_set_command_literal_annotation_uses_choices(
|
||||
self, mock_user_session, mock_user_obb
|
||||
):
|
||||
"""``Literal[...]`` annotation populates argparse choices and keeps type as str."""
|
||||
from typing import Literal
|
||||
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
field = {
|
||||
"command": "theme",
|
||||
"field_name": "theme",
|
||||
"description": "Theme",
|
||||
"annotation": Literal["dark", "light"],
|
||||
"action": "set",
|
||||
}
|
||||
ns = MagicMock()
|
||||
ns.value = "dark"
|
||||
ctrl.parse_simple_args = MagicMock(return_value=(ns, []))
|
||||
|
||||
ctrl._generate_command("theme", field, "set")
|
||||
ctrl.call_theme(["-v", "dark"])
|
||||
mock_user_session.console.print.assert_called()
|
||||
|
||||
def test_set_command_int_annotation_uses_int_type(
|
||||
self, mock_user_session, mock_user_obb
|
||||
):
|
||||
"""``int`` annotation makes argparse coerce the value to int."""
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
field = {
|
||||
"command": "limit",
|
||||
"field_name": "limit",
|
||||
"description": "Row limit",
|
||||
"annotation": int,
|
||||
"action": "set",
|
||||
}
|
||||
ns = MagicMock()
|
||||
ns.value = 10
|
||||
ctrl.parse_simple_args = MagicMock(return_value=(ns, []))
|
||||
|
||||
ctrl._generate_command("limit", field, "set")
|
||||
ctrl.call_limit(["-v", "10"])
|
||||
mock_user_session.console.print.assert_called()
|
||||
|
||||
def test_set_command_other_annotation_falls_back_to_str(
|
||||
self, mock_user_session, mock_user_obb
|
||||
):
|
||||
"""Unknown annotation (e.g. float) falls back to ``type_ = str`` branch."""
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
field = {
|
||||
"command": "ratio",
|
||||
"field_name": "ratio",
|
||||
"description": "A ratio",
|
||||
"annotation": float,
|
||||
"action": "set",
|
||||
}
|
||||
ns = MagicMock()
|
||||
ns.value = "0.5"
|
||||
ctrl.parse_simple_args = MagicMock(return_value=(ns, []))
|
||||
|
||||
ctrl._generate_command("ratio", field, "set")
|
||||
ctrl.call_ratio(["-v", "0.5"])
|
||||
mock_user_session.console.print.assert_called()
|
||||
|
||||
def test_print_help(self, mock_user_session, mock_user_obb):
|
||||
from openbb_cli.controllers.user_controller import UserController
|
||||
|
||||
ctrl = UserController.__new__(UserController)
|
||||
ctrl.queue = []
|
||||
ctrl.update_completer = MagicMock()
|
||||
ctrl._PREF_COMMANDS = {
|
||||
"enable_feature": {
|
||||
"command": "enable_feature",
|
||||
"field_name": "enable_feature",
|
||||
"description": "Enable a feature",
|
||||
"annotation": bool,
|
||||
"action": "toggle",
|
||||
},
|
||||
"timezone": {
|
||||
"command": "timezone",
|
||||
"field_name": "timezone",
|
||||
"description": "Set the timezone",
|
||||
"annotation": str,
|
||||
"action": "set",
|
||||
},
|
||||
}
|
||||
mock_user_obb.user.preferences.enable_feature = True
|
||||
mock_user_obb.user.preferences.timezone = "UTC"
|
||||
|
||||
ctrl.print_help()
|
||||
mock_user_session.console.print.assert_called_once()
|
||||
Reference in New Issue
Block a user