Fix, remove, improve cli tests.
This commit is contained in:
parent
fe6c9000fa
commit
a805c640ec
4 changed files with 47 additions and 212 deletions
|
|
@ -2,7 +2,6 @@
|
||||||
Integration tests for CLI commands that test end-to-end functionality.
|
Integration tests for CLI commands that test end-to-end functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import pytest
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,7 @@ Tests for CLI edge cases and error scenarios with proper mocking.
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import argparse
|
import argparse
|
||||||
import tempfile
|
import types
|
||||||
import os
|
|
||||||
import asyncio
|
|
||||||
from unittest.mock import patch, MagicMock, AsyncMock
|
from unittest.mock import patch, MagicMock, AsyncMock
|
||||||
from cognee.cli.commands.add_command import AddCommand
|
from cognee.cli.commands.add_command import AddCommand
|
||||||
from cognee.cli.commands.search_command import SearchCommand
|
from cognee.cli.commands.search_command import SearchCommand
|
||||||
|
|
@ -35,21 +33,8 @@ class TestAddCommandEdgeCases:
|
||||||
command.execute(args)
|
command.execute(args)
|
||||||
mock_asyncio_run.assert_called_once()
|
mock_asyncio_run.assert_called_once()
|
||||||
|
|
||||||
@patch("builtins.__import__")
|
coro = mock_asyncio_run.call_args[0][0]
|
||||||
@patch("cognee.cli.commands.add_command.asyncio.run")
|
assert isinstance(coro, types.CoroutineType)
|
||||||
def test_add_very_long_dataset_name(self, mock_asyncio_run, mock_import):
|
|
||||||
"""Test add command with very long dataset name"""
|
|
||||||
# Mock the cognee module
|
|
||||||
mock_cognee = MagicMock()
|
|
||||||
mock_cognee.add = AsyncMock()
|
|
||||||
mock_import.return_value = mock_cognee
|
|
||||||
|
|
||||||
command = AddCommand()
|
|
||||||
long_name = "a" * 1000 # Very long dataset name
|
|
||||||
args = argparse.Namespace(data=["test.txt"], dataset_name=long_name)
|
|
||||||
|
|
||||||
command.execute(args)
|
|
||||||
mock_asyncio_run.assert_called_once()
|
|
||||||
|
|
||||||
@patch("cognee.cli.commands.add_command.asyncio.run")
|
@patch("cognee.cli.commands.add_command.asyncio.run")
|
||||||
def test_add_asyncio_run_exception(self, mock_asyncio_run):
|
def test_add_asyncio_run_exception(self, mock_asyncio_run):
|
||||||
|
|
@ -337,16 +322,37 @@ class TestCognifyCommandEdgeCases:
|
||||||
command.execute(args)
|
command.execute(args)
|
||||||
mock_asyncio_run.assert_called_once()
|
mock_asyncio_run.assert_called_once()
|
||||||
|
|
||||||
def test_cognify_empty_datasets_list(self):
|
@patch("builtins.__import__")
|
||||||
"""Test cognify command with empty datasets list"""
|
@patch("cognee.cli.commands.cognify_command.asyncio.run")
|
||||||
|
def test_cognify_empty_datasets_list(self, mock_asyncio_run, mock_import):
|
||||||
|
"""Test cognify command with nonexistent ontology file"""
|
||||||
|
# Mock the cognee module
|
||||||
|
mock_cognee = MagicMock()
|
||||||
|
mock_cognee.cognify = AsyncMock()
|
||||||
|
|
||||||
|
def mock_import_func(name, fromlist=None, *args, **kwargs):
|
||||||
|
if name == "cognee":
|
||||||
|
return mock_cognee
|
||||||
|
elif name == "cognee.modules.chunking":
|
||||||
|
module = MagicMock()
|
||||||
|
module.TextChunker = MagicMock()
|
||||||
|
return module
|
||||||
|
return MagicMock()
|
||||||
|
|
||||||
|
mock_import.side_effect = mock_import_func
|
||||||
|
|
||||||
command = CognifyCommand()
|
command = CognifyCommand()
|
||||||
parser = argparse.ArgumentParser()
|
args = argparse.Namespace(
|
||||||
command.configure_parser(parser)
|
datasets=[],
|
||||||
|
chunk_size=None,
|
||||||
# Empty datasets list should be handled
|
ontology_file=None,
|
||||||
args = parser.parse_args(["--datasets"])
|
chunker="TextChunker",
|
||||||
assert args.datasets == []
|
background=False,
|
||||||
|
verbose=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
command.execute(args)
|
||||||
|
mock_asyncio_run.assert_called_once()
|
||||||
|
|
||||||
class TestDeleteCommandEdgeCases:
|
class TestDeleteCommandEdgeCases:
|
||||||
"""Test edge cases for DeleteCommand"""
|
"""Test edge cases for DeleteCommand"""
|
||||||
|
|
@ -439,6 +445,7 @@ class TestConfigCommandEdgeCases:
|
||||||
|
|
||||||
# Should handle the exception gracefully
|
# Should handle the exception gracefully
|
||||||
command.execute(args)
|
command.execute(args)
|
||||||
|
mock_cognee.config.get.assert_called_once_with("nonexistent_key")
|
||||||
|
|
||||||
@patch("builtins.__import__")
|
@patch("builtins.__import__")
|
||||||
def test_config_set_complex_json_value(self, mock_import):
|
def test_config_set_complex_json_value(self, mock_import):
|
||||||
|
|
@ -450,9 +457,11 @@ class TestConfigCommandEdgeCases:
|
||||||
|
|
||||||
command = ConfigCommand()
|
command = ConfigCommand()
|
||||||
complex_json = '{"nested": {"key": "value"}, "array": [1, 2, 3]}'
|
complex_json = '{"nested": {"key": "value"}, "array": [1, 2, 3]}'
|
||||||
|
complex_json_expected_value = {"nested": {"key": "value"}, "array": [1, 2, 3]}
|
||||||
args = argparse.Namespace(config_action="set", key="complex_config", value=complex_json)
|
args = argparse.Namespace(config_action="set", key="complex_config", value=complex_json)
|
||||||
|
|
||||||
command.execute(args)
|
command.execute(args)
|
||||||
|
mock_cognee.config.set.assert_called_once_with("complex_config", complex_json_expected_value)
|
||||||
|
|
||||||
@patch("builtins.__import__")
|
@patch("builtins.__import__")
|
||||||
def test_config_set_invalid_json_value(self, mock_import):
|
def test_config_set_invalid_json_value(self, mock_import):
|
||||||
|
|
@ -467,6 +476,7 @@ class TestConfigCommandEdgeCases:
|
||||||
args = argparse.Namespace(config_action="set", key="test_key", value=invalid_json)
|
args = argparse.Namespace(config_action="set", key="test_key", value=invalid_json)
|
||||||
|
|
||||||
command.execute(args)
|
command.execute(args)
|
||||||
|
mock_cognee.config.set.assert_called_once_with("test_key", invalid_json)
|
||||||
|
|
||||||
@patch("cognee.cli.commands.config_command.fmt.confirm")
|
@patch("cognee.cli.commands.config_command.fmt.confirm")
|
||||||
@patch("builtins.__import__")
|
@patch("builtins.__import__")
|
||||||
|
|
@ -499,6 +509,7 @@ class TestConfigCommandEdgeCases:
|
||||||
|
|
||||||
# Should handle AttributeError gracefully
|
# Should handle AttributeError gracefully
|
||||||
command.execute(args)
|
command.execute(args)
|
||||||
|
mock_cognee.config.unset.assert_not_called()
|
||||||
|
|
||||||
def test_config_invalid_subcommand(self):
|
def test_config_invalid_subcommand(self):
|
||||||
"""Test config command with invalid subcommand"""
|
"""Test config command with invalid subcommand"""
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ Test runner and utilities for CLI tests.
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,6 @@
|
||||||
Tests for CLI utility functions and helper modules.
|
Tests for CLI utility functions and helper modules.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import pytest
|
|
||||||
from unittest.mock import patch, MagicMock
|
|
||||||
import click
|
|
||||||
from cognee.cli import echo as fmt
|
|
||||||
from cognee.cli.exceptions import CliCommandException, CliCommandInnerException
|
|
||||||
from cognee.cli import debug
|
from cognee.cli import debug
|
||||||
from cognee.cli.config import (
|
from cognee.cli.config import (
|
||||||
CLI_DESCRIPTION,
|
CLI_DESCRIPTION,
|
||||||
|
|
@ -16,155 +11,7 @@ from cognee.cli.config import (
|
||||||
CHUNKER_CHOICES,
|
CHUNKER_CHOICES,
|
||||||
OUTPUT_FORMAT_CHOICES,
|
OUTPUT_FORMAT_CHOICES,
|
||||||
)
|
)
|
||||||
|
from cognee.cli._cognee import _discover_commands
|
||||||
|
|
||||||
class TestEchoModule:
|
|
||||||
"""Test the CLI echo/formatting module"""
|
|
||||||
|
|
||||||
@patch("click.secho")
|
|
||||||
def test_echo_basic(self, mock_secho):
|
|
||||||
"""Test basic echo functionality"""
|
|
||||||
fmt.echo("test message")
|
|
||||||
mock_secho.assert_called_once_with("test message", fg=None, err=False)
|
|
||||||
|
|
||||||
@patch("click.secho")
|
|
||||||
def test_echo_with_color(self, mock_secho):
|
|
||||||
"""Test echo with color"""
|
|
||||||
fmt.echo("test message", color="red")
|
|
||||||
mock_secho.assert_called_once_with("test message", fg="red", err=False)
|
|
||||||
|
|
||||||
@patch("click.secho")
|
|
||||||
def test_echo_to_stderr(self, mock_secho):
|
|
||||||
"""Test echo to stderr"""
|
|
||||||
fmt.echo("test message", err=True)
|
|
||||||
mock_secho.assert_called_once_with("test message", fg=None, err=True)
|
|
||||||
|
|
||||||
@patch("cognee.cli.echo.echo")
|
|
||||||
def test_note(self, mock_echo):
|
|
||||||
"""Test note formatting"""
|
|
||||||
fmt.note("test note")
|
|
||||||
mock_echo.assert_called_once_with("Note: test note", color="blue")
|
|
||||||
|
|
||||||
@patch("cognee.cli.echo.echo")
|
|
||||||
def test_warning(self, mock_echo):
|
|
||||||
"""Test warning formatting"""
|
|
||||||
fmt.warning("test warning")
|
|
||||||
mock_echo.assert_called_once_with("Warning: test warning", color="yellow")
|
|
||||||
|
|
||||||
@patch("cognee.cli.echo.echo")
|
|
||||||
def test_error(self, mock_echo):
|
|
||||||
"""Test error formatting"""
|
|
||||||
fmt.error("test error")
|
|
||||||
mock_echo.assert_called_once_with("Error: test error", color="red", err=True)
|
|
||||||
|
|
||||||
@patch("cognee.cli.echo.echo")
|
|
||||||
def test_success(self, mock_echo):
|
|
||||||
"""Test success formatting"""
|
|
||||||
fmt.success("test success")
|
|
||||||
mock_echo.assert_called_once_with("Success: test success", color="green")
|
|
||||||
|
|
||||||
@patch("click.style")
|
|
||||||
def test_bold(self, mock_style):
|
|
||||||
"""Test bold text formatting"""
|
|
||||||
mock_style.return_value = "bold text"
|
|
||||||
result = fmt.bold("test text")
|
|
||||||
mock_style.assert_called_once_with("test text", bold=True)
|
|
||||||
assert result == "bold text"
|
|
||||||
|
|
||||||
@patch("click.confirm")
|
|
||||||
def test_confirm(self, mock_confirm):
|
|
||||||
"""Test confirmation prompt"""
|
|
||||||
mock_confirm.return_value = True
|
|
||||||
result = fmt.confirm("Are you sure?")
|
|
||||||
mock_confirm.assert_called_once_with("Are you sure?", default=False)
|
|
||||||
assert result is True
|
|
||||||
|
|
||||||
@patch("click.confirm")
|
|
||||||
def test_confirm_with_default(self, mock_confirm):
|
|
||||||
"""Test confirmation prompt with default"""
|
|
||||||
mock_confirm.return_value = False
|
|
||||||
result = fmt.confirm("Are you sure?", default=True)
|
|
||||||
mock_confirm.assert_called_once_with("Are you sure?", default=True)
|
|
||||||
assert result is False
|
|
||||||
|
|
||||||
@patch("click.prompt")
|
|
||||||
def test_prompt(self, mock_prompt):
|
|
||||||
"""Test user input prompt"""
|
|
||||||
mock_prompt.return_value = "user input"
|
|
||||||
result = fmt.prompt("Enter value:")
|
|
||||||
mock_prompt.assert_called_once_with("Enter value:", default=None)
|
|
||||||
assert result == "user input"
|
|
||||||
|
|
||||||
@patch("click.prompt")
|
|
||||||
def test_prompt_with_default(self, mock_prompt):
|
|
||||||
"""Test user input prompt with default"""
|
|
||||||
mock_prompt.return_value = "default value"
|
|
||||||
result = fmt.prompt("Enter value:", default="default value")
|
|
||||||
mock_prompt.assert_called_once_with("Enter value:", default="default value")
|
|
||||||
assert result == "default value"
|
|
||||||
|
|
||||||
|
|
||||||
class TestCliExceptions:
|
|
||||||
"""Test CLI exception classes"""
|
|
||||||
|
|
||||||
def test_cli_command_exception_basic(self):
|
|
||||||
"""Test basic CliCommandException"""
|
|
||||||
exc = CliCommandException("Test error")
|
|
||||||
assert str(exc) == "Test error"
|
|
||||||
assert exc.error_code == -1
|
|
||||||
assert exc.docs_url is None
|
|
||||||
assert exc.raiseable_exception is None
|
|
||||||
|
|
||||||
def test_cli_command_exception_full(self):
|
|
||||||
"""Test CliCommandException with all parameters"""
|
|
||||||
inner_exc = ValueError("Inner error")
|
|
||||||
exc = CliCommandException(
|
|
||||||
"Test error",
|
|
||||||
error_code=2,
|
|
||||||
docs_url="https://docs.test.com",
|
|
||||||
raiseable_exception=inner_exc,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert str(exc) == "Test error"
|
|
||||||
assert exc.error_code == 2
|
|
||||||
assert exc.docs_url == "https://docs.test.com"
|
|
||||||
assert exc.raiseable_exception is inner_exc
|
|
||||||
|
|
||||||
def test_cli_command_inner_exception(self):
|
|
||||||
"""Test CliCommandInnerException"""
|
|
||||||
exc = CliCommandInnerException("Inner error")
|
|
||||||
assert str(exc) == "Inner error"
|
|
||||||
assert isinstance(exc, Exception)
|
|
||||||
|
|
||||||
|
|
||||||
class TestDebugModule:
|
|
||||||
"""Test CLI debug functionality"""
|
|
||||||
|
|
||||||
def test_debug_initially_disabled(self):
|
|
||||||
"""Test that debug is initially disabled"""
|
|
||||||
# Reset debug state
|
|
||||||
debug._debug_enabled = False
|
|
||||||
assert not debug.is_debug_enabled()
|
|
||||||
|
|
||||||
def test_enable_debug(self):
|
|
||||||
"""Test enabling debug mode"""
|
|
||||||
debug.enable_debug()
|
|
||||||
assert debug.is_debug_enabled()
|
|
||||||
|
|
||||||
# Reset for other tests
|
|
||||||
debug._debug_enabled = False
|
|
||||||
|
|
||||||
def test_debug_state_persistence(self):
|
|
||||||
"""Test that debug state persists"""
|
|
||||||
debug.enable_debug()
|
|
||||||
assert debug.is_debug_enabled()
|
|
||||||
|
|
||||||
# Should still be enabled
|
|
||||||
assert debug.is_debug_enabled()
|
|
||||||
|
|
||||||
# Reset for other tests
|
|
||||||
debug._debug_enabled = False
|
|
||||||
|
|
||||||
|
|
||||||
class TestCliConfig:
|
class TestCliConfig:
|
||||||
"""Test CLI configuration constants"""
|
"""Test CLI configuration constants"""
|
||||||
|
|
@ -180,10 +27,17 @@ class TestCliConfig:
|
||||||
assert DEFAULT_DOCS_URL
|
assert DEFAULT_DOCS_URL
|
||||||
assert isinstance(DEFAULT_DOCS_URL, str)
|
assert isinstance(DEFAULT_DOCS_URL, str)
|
||||||
assert DEFAULT_DOCS_URL.startswith("https://")
|
assert DEFAULT_DOCS_URL.startswith("https://")
|
||||||
|
assert "cognee.ai" in DEFAULT_DOCS_URL
|
||||||
|
|
||||||
def test_command_descriptions_complete(self):
|
def test_command_descriptions_complete(self):
|
||||||
"""Test that all expected commands have descriptions"""
|
"""Test that all expected commands have descriptions"""
|
||||||
expected_commands = ["add", "search", "cognify", "delete", "config"]
|
commands = _discover_commands()
|
||||||
|
assert len(commands) > 0
|
||||||
|
|
||||||
|
expected_commands = []
|
||||||
|
for command_class in commands:
|
||||||
|
command = command_class()
|
||||||
|
expected_commands.append(command.command_string)
|
||||||
|
|
||||||
for command in expected_commands:
|
for command in expected_commands:
|
||||||
assert command in COMMAND_DESCRIPTIONS
|
assert command in COMMAND_DESCRIPTIONS
|
||||||
|
|
@ -224,7 +78,6 @@ class TestCliConfig:
|
||||||
for expected_format in expected_formats:
|
for expected_format in expected_formats:
|
||||||
assert expected_format in OUTPUT_FORMAT_CHOICES
|
assert expected_format in OUTPUT_FORMAT_CHOICES
|
||||||
|
|
||||||
|
|
||||||
class TestCliReference:
|
class TestCliReference:
|
||||||
"""Test CLI reference protocol"""
|
"""Test CLI reference protocol"""
|
||||||
|
|
||||||
|
|
@ -262,38 +115,11 @@ class TestCliReference:
|
||||||
class TestCliUtilityFunctions:
|
class TestCliUtilityFunctions:
|
||||||
"""Test utility functions and edge cases"""
|
"""Test utility functions and edge cases"""
|
||||||
|
|
||||||
def test_echo_empty_message(self):
|
|
||||||
"""Test echo with empty message"""
|
|
||||||
with patch("click.secho") as mock_secho:
|
|
||||||
fmt.echo()
|
|
||||||
mock_secho.assert_called_once_with("", fg=None, err=False)
|
|
||||||
|
|
||||||
def test_echo_none_message(self):
|
|
||||||
"""Test echo with None message (should not crash)"""
|
|
||||||
with patch("click.secho") as mock_secho:
|
|
||||||
# This might raise an exception, which is expected behavior
|
|
||||||
try:
|
|
||||||
fmt.echo(None)
|
|
||||||
except TypeError:
|
|
||||||
# Expected for None message
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_multiple_debug_enable_calls(self):
|
def test_multiple_debug_enable_calls(self):
|
||||||
"""Test multiple calls to enable_debug"""
|
"""Test multiple calls to enable_debug"""
|
||||||
debug.enable_debug()
|
debug.enable_debug()
|
||||||
debug.enable_debug() # Should not cause issues
|
debug.enable_debug() # Should not cause issues
|
||||||
assert debug.is_debug_enabled()
|
assert debug.is_debug_enabled() is True
|
||||||
|
|
||||||
# Reset for other tests
|
# Reset for other tests
|
||||||
debug._debug_enabled = False
|
debug._debug_enabled = False
|
||||||
|
|
||||||
def test_config_constants_immutability(self):
|
|
||||||
"""Test that config constants are not accidentally modified"""
|
|
||||||
original_description = CLI_DESCRIPTION
|
|
||||||
original_url = DEFAULT_DOCS_URL
|
|
||||||
original_commands = COMMAND_DESCRIPTIONS.copy()
|
|
||||||
|
|
||||||
# These should be the same after any test
|
|
||||||
assert CLI_DESCRIPTION == original_description
|
|
||||||
assert DEFAULT_DOCS_URL == original_url
|
|
||||||
assert COMMAND_DESCRIPTIONS == original_commands
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue