From ff7500065b51a9dfaeac148e91c16c74c711d1df Mon Sep 17 00:00:00 2001 From: Andrew Barnes Date: Tue, 24 Mar 2026 12:47:01 -0400 Subject: [PATCH] test: add coverage for CLI utility functions (#7422) Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com> --- cli/tests/test_controllers_utils.py | 100 ++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/cli/tests/test_controllers_utils.py b/cli/tests/test_controllers_utils.py index 6cb87332251..1b7a662d73d 100644 --- a/cli/tests/test_controllers_utils.py +++ b/cli/tests/test_controllers_utils.py @@ -6,13 +6,16 @@ from unittest.mock import MagicMock, patch import pytest from openbb_cli.controllers.utils import ( + check_file_type_saved, check_non_negative, check_positive, get_flair_and_username, get_user_agent, parse_and_split_input, + parse_unknown_args_to_dict, print_goodbye, remove_file, + validate_register_key, welcome_message, ) @@ -138,3 +141,100 @@ def test_get_user_agent(): """Test getting the user agent.""" result = get_user_agent() assert result.startswith("Mozilla/5.0") + + +# --- Tests for parse_unknown_args_to_dict --- + + +@pytest.mark.parametrize( + "args, expected", + [ + (["--key", "value"], {"key": "value"}), + (["--a", "1", "--b", "hello"], {"a": 1, "b": "hello"}), + (["--flag"], {}), + (None, {}), + ([], {}), + ], +) +def test_parse_unknown_args_to_dict_basic(args, expected, mock_session): + """Test basic key-value parsing and edge cases.""" + result = parse_unknown_args_to_dict(args) + assert result == expected + + +@pytest.mark.parametrize( + "args, expected", + [ + (["--num", "42"], {"num": 42}), + (["--pi", "3.14"], {"pi": 3.14}), + (["--items", "[1, 2, 3]"], {"items": [1, 2, 3]}), + (["--mapping", "{'a': 1}"], {"mapping": {"a": 1}}), + (["--bool", "True"], {"bool": True}), + (["--plain", "not-a-literal"], {"plain": "not-a-literal"}), + ], +) +def test_parse_unknown_args_to_dict_literal_eval(args, expected, mock_session): + """Test that ast.literal_eval correctly parses typed values.""" + result = parse_unknown_args_to_dict(args) + assert result == expected + + +def test_parse_unknown_args_to_dict_missing_value(mock_session): + """Test that a trailing --flag with no value prints a warning.""" + result = parse_unknown_args_to_dict(["--orphan"]) + assert result == {} + mock_session.console.print.assert_called_once() + + +# --- Tests for validate_register_key --- + + +@pytest.mark.parametrize( + "key, should_raise", + [ + ("my_api_key", False), + ("secret_123", False), + ("OBB_KEY", True), + ("my_OBB_key", True), + ("OBB", True), + ], +) +def test_validate_register_key(key, should_raise): + """Test that keys containing 'OBB' are rejected.""" + if should_raise: + with pytest.raises(argparse.ArgumentTypeError, match="OBB"): + validate_register_key(key) + else: + assert validate_register_key(key) == key + + +# --- Tests for check_file_type_saved --- + + +def test_check_file_type_saved_valid(mock_session): + """Test valid filenames are accepted.""" + checker = check_file_type_saved(valid_types=[".csv", ".json"]) + assert checker("report.csv") == "report.csv" + assert checker("data.json") == "data.json" + assert checker("a.csv,b.json") == "a.csv,b.json" + + +def test_check_file_type_saved_invalid(mock_session): + """Test invalid filenames are rejected with a warning.""" + checker = check_file_type_saved(valid_types=[".csv"]) + result = checker("report.xlsx") + assert result == "" + mock_session.console.print.assert_called() + + +def test_check_file_type_saved_empty(mock_session): + """Test empty input returns empty string.""" + checker = check_file_type_saved(valid_types=[".csv"]) + assert checker("") == "" + assert checker() == "" + + +def test_check_file_type_saved_no_valid_types(mock_session): + """Test that None valid_types returns empty string.""" + checker = check_file_type_saved(valid_types=None) + assert checker("anything.csv") == ""