-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
deae7f8
commit 3dcf7c8
Showing
6 changed files
with
466 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
"""Test the Config completer.""" | ||
|
||
import pytest | ||
from openbb_cli.config.completer import WordCompleter | ||
from prompt_toolkit.completion import CompleteEvent | ||
from prompt_toolkit.document import Document | ||
|
||
# pylint: disable=redefined-outer-name, import-outside-toplevel | ||
|
||
|
||
@pytest.fixture | ||
def word_completer(): | ||
"""Return a simple word completer.""" | ||
words = ["test", "example", "demo"] | ||
return WordCompleter(words, ignore_case=True) | ||
|
||
|
||
def test_word_completer_simple(word_completer): | ||
"""Test the word completer with a simple word list.""" | ||
doc = Document(text="ex", cursor_position=2) | ||
completions = list(word_completer.get_completions(doc, CompleteEvent())) | ||
assert len(completions) == 1 | ||
assert completions[0].text == "example" | ||
|
||
|
||
def test_word_completer_case_insensitive(word_completer): | ||
"""Test the word completer with case-insensitive matching.""" | ||
doc = Document(text="Ex", cursor_position=2) | ||
completions = list(word_completer.get_completions(doc, CompleteEvent())) | ||
assert len(completions) == 1 | ||
assert completions[0].text == "example" | ||
|
||
|
||
def test_word_completer_no_match(word_completer): | ||
"""Test the word completer with no matches.""" | ||
doc = Document(text="xyz", cursor_position=3) | ||
completions = list(word_completer.get_completions(doc, CompleteEvent())) | ||
assert len(completions) == 0 | ||
|
||
|
||
@pytest.fixture | ||
def nested_completer(): | ||
"""Return a nested completer.""" | ||
from openbb_cli.config.completer import NestedCompleter | ||
|
||
data = { | ||
"show": { | ||
"version": None, | ||
"interfaces": None, | ||
"clock": None, | ||
"ip": {"interface": {"brief": None}}, | ||
}, | ||
"exit": None, | ||
"enable": None, | ||
} | ||
return NestedCompleter.from_nested_dict(data) | ||
|
||
|
||
def test_nested_completer_root_command(nested_completer): | ||
"""Test the nested completer with a root command.""" | ||
doc = Document(text="sh", cursor_position=2) | ||
completions = list(nested_completer.get_completions(doc, CompleteEvent())) | ||
assert "show" in [c.text for c in completions] | ||
|
||
|
||
def test_nested_completer_sub_command(nested_completer): | ||
"""Test the nested completer with a sub-command.""" | ||
doc = Document(text="show ", cursor_position=5) | ||
completions = list(nested_completer.get_completions(doc, CompleteEvent())) | ||
assert "version" in [c.text for c in completions] | ||
assert "interfaces" in [c.text for c in completions] | ||
|
||
|
||
def test_nested_completer_no_match(nested_completer): | ||
"""Test the nested completer with no matches.""" | ||
doc = Document(text="random ", cursor_position=7) | ||
completions = list(nested_completer.get_completions(doc, CompleteEvent())) | ||
assert len(completions) == 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
"""Test Config Console.""" | ||
|
||
from unittest.mock import patch | ||
|
||
import pytest | ||
from openbb_cli.config.console import Console | ||
from rich.text import Text | ||
|
||
# pylint: disable=redefined-outer-name, unused-argument, unused-variable, protected-access | ||
|
||
|
||
@pytest.fixture | ||
def mock_settings(): | ||
"""Mock settings to inject into Console.""" | ||
|
||
class MockSettings: | ||
TEST_MODE = False | ||
ENABLE_RICH_PANEL = True | ||
SHOW_VERSION = True | ||
VERSION = "1.0" | ||
|
||
return MockSettings() | ||
|
||
|
||
@pytest.fixture | ||
def console(mock_settings): | ||
"""Create a Console instance with mocked settings.""" | ||
with patch("rich.console.Console") as MockRichConsole: # noqa: F841 | ||
return Console(settings=mock_settings) | ||
|
||
|
||
def test_print_without_panel(console, mock_settings): | ||
"""Test printing without a rich panel when disabled.""" | ||
mock_settings.ENABLE_RICH_PANEL = False | ||
with patch.object(console._console, "print") as mock_print: | ||
console.print(text="Hello, world!", menu="Home Menu") | ||
mock_print.assert_called_once_with("Hello, world!") | ||
|
||
|
||
def test_blend_text(): | ||
"""Test blending text colors.""" | ||
message = "Hello" | ||
color1 = (255, 0, 0) # Red | ||
color2 = (0, 0, 255) # Blue | ||
blended_text = Console._blend_text(message, color1, color2) | ||
assert isinstance(blended_text, Text) | ||
assert "Hello" in blended_text.plain |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
"""Test Config Menu Text.""" | ||
|
||
import pytest | ||
from openbb_cli.config.menu_text import MenuText | ||
|
||
# pylint: disable=redefined-outer-name, protected-access | ||
|
||
|
||
@pytest.fixture | ||
def menu_text(): | ||
"""Fixture to create a MenuText instance for testing.""" | ||
return MenuText(path="/test/path") | ||
|
||
|
||
def test_initialization(menu_text): | ||
"""Test initialization of the MenuText class.""" | ||
assert menu_text.menu_text == "" | ||
assert menu_text.menu_path == "/test/path" | ||
assert menu_text.warnings == [] | ||
|
||
|
||
def test_add_raw(menu_text): | ||
"""Test adding raw text.""" | ||
menu_text.add_raw("Example raw text") | ||
assert "Example raw text" in menu_text.menu_text | ||
|
||
|
||
def test_add_section(menu_text): | ||
"""Test adding a section with and without description.""" | ||
menu_text.add_section("Section Title", "Description here", leading_new_line=True) | ||
assert "\n Section Title" in menu_text.menu_text | ||
assert "Description here" in menu_text.menu_text | ||
|
||
|
||
def test_add_info(menu_text): | ||
"""Test adding informational text.""" | ||
menu_text.add_info("Info text") | ||
assert "[info]Info text:[/info]" in menu_text.menu_text | ||
|
||
|
||
def test_add_cmd(menu_text): | ||
"""Test adding a command.""" | ||
menu_text.add_cmd("command", "Performs an action") | ||
assert "command" in menu_text.menu_text | ||
assert "Performs an action" in menu_text.menu_text | ||
|
||
|
||
def test_format_cmd_name(menu_text): | ||
"""Test formatting of command names that are too long.""" | ||
long_name = "x" * 50 # Assuming CMD_NAME_LENGTH is 23 | ||
formatted_name = menu_text._format_cmd_name(long_name) | ||
assert len(formatted_name) <= menu_text.CMD_NAME_LENGTH | ||
assert menu_text.warnings # Check that a warning was added | ||
|
||
|
||
def test_format_cmd_description(menu_text): | ||
"""Test truncation of long descriptions.""" | ||
long_description = "y" * 100 # Assuming CMD_DESCRIPTION_LENGTH is 65 | ||
formatted_description = menu_text._format_cmd_description("cmd", long_description) | ||
assert len(formatted_description) <= menu_text.CMD_DESCRIPTION_LENGTH | ||
|
||
|
||
def test_add_menu(menu_text): | ||
"""Test adding a menu item.""" | ||
menu_text.add_menu("Settings", "Configure your settings") | ||
assert "Settings" in menu_text.menu_text | ||
assert "Configure your settings" in menu_text.menu_text | ||
|
||
|
||
def test_add_setting(menu_text): | ||
"""Test adding a setting.""" | ||
menu_text.add_setting("Enable Feature", True, "Feature description") | ||
assert "Enable Feature" in menu_text.menu_text | ||
assert "Feature description" in menu_text.menu_text | ||
assert "[green]" in menu_text.menu_text |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
"""Test the Config Setup.""" | ||
|
||
from unittest.mock import patch | ||
|
||
import pytest | ||
from openbb_cli.config.setup import bootstrap | ||
|
||
# pylint: disable=unused-variable | ||
|
||
|
||
def test_bootstrap_creates_directory_and_file(): | ||
"""Test that bootstrap creates the settings directory and environment file.""" | ||
with patch("pathlib.Path.mkdir") as mock_mkdir, patch( | ||
"pathlib.Path.touch" | ||
) as mock_touch: | ||
bootstrap() | ||
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True) | ||
mock_touch.assert_called_once_with(exist_ok=True) | ||
|
||
|
||
def test_bootstrap_directory_exists(): | ||
"""Test bootstrap when the directory already exists.""" | ||
with patch("pathlib.Path.mkdir") as mock_mkdir, patch( | ||
"pathlib.Path.touch" | ||
) as mock_touch: | ||
bootstrap() | ||
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True) | ||
mock_touch.assert_called_once_with(exist_ok=True) | ||
|
||
|
||
def test_bootstrap_file_exists(): | ||
"""Test bootstrap when the environment file already exists.""" | ||
with patch("pathlib.Path.mkdir") as mock_mkdir, patch( | ||
"pathlib.Path.touch" | ||
) as mock_touch: | ||
bootstrap() | ||
mock_mkdir.assert_called_once_with(parents=True, exist_ok=True) | ||
mock_touch.assert_called_once_with(exist_ok=True) | ||
|
||
|
||
def test_bootstrap_permission_error(): | ||
"""Test bootstrap handles permission errors gracefully.""" | ||
with patch("pathlib.Path.mkdir") as mock_mkdir, patch( | ||
"pathlib.Path.touch" | ||
) as mock_touch, pytest.raises( # noqa: F841 | ||
PermissionError | ||
): | ||
mock_mkdir.side_effect = PermissionError("No permission to create directory") | ||
bootstrap() # Expecting to raise a PermissionError and be caught by pytest.raises |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"""Test Config Style.""" | ||
|
||
from pathlib import Path | ||
from unittest.mock import MagicMock, patch | ||
|
||
import pytest | ||
from openbb_cli.config.style import Style | ||
|
||
# pylint: disable=redefined-outer-name, protected-access | ||
|
||
|
||
@pytest.fixture | ||
def mock_style_directory(tmp_path): | ||
"""Fixture to create a mock styles directory.""" | ||
(tmp_path / "styles" / "default").mkdir(parents=True, exist_ok=True) | ||
return tmp_path / "styles" | ||
|
||
|
||
@pytest.fixture | ||
def style(mock_style_directory): | ||
"""Fixture to create a Style instance for testing.""" | ||
return Style(directory=mock_style_directory) | ||
|
||
|
||
def test_initialization(style): | ||
"""Test that Style class initializes with default properties.""" | ||
assert style.line_width == 1.5 | ||
assert isinstance(style.console_style, dict) | ||
|
||
|
||
@patch("pathlib.Path.exists", MagicMock(return_value=True)) | ||
@patch("pathlib.Path.rglob") | ||
def test_load_styles(mock_rglob, style, mock_style_directory): | ||
"""Test loading styles from directories.""" | ||
mock_rglob.return_value = [mock_style_directory / "default" / "dark.richstyle.json"] | ||
style._load(mock_style_directory) | ||
assert "dark" in style.console_styles_available | ||
|
||
|
||
@patch("builtins.open", new_callable=MagicMock) | ||
@patch("json.load", MagicMock(return_value={"background": "black"})) | ||
def test_from_json(mock_open, style, mock_style_directory): | ||
"""Test loading style from a JSON file.""" | ||
json_file = mock_style_directory / "dark.richstyle.json" | ||
result = style._from_json(json_file) | ||
assert result == {"background": "black"} | ||
mock_open.assert_called_once_with(json_file) | ||
|
||
|
||
def test_apply_invalid_style(style, mock_style_directory, capsys): | ||
"""Test applying an invalid style and falling back to default.""" | ||
style.apply("nonexistent", mock_style_directory) | ||
captured = capsys.readouterr() | ||
assert "Invalid console style" in captured.out | ||
|
||
|
||
def test_available_styles(style): | ||
"""Test listing available styles.""" | ||
style.console_styles_available = {"dark": Path("/path/to/dark.richstyle.json")} | ||
assert "dark" in style.available_styles |
Oops, something went wrong.