308 lines
11 KiB
Python
308 lines
11 KiB
Python
"""
|
|
End-to-end tests for CodiMD CLI.
|
|
|
|
Tests use real files and simulate full CLI workflows.
|
|
"""
|
|
|
|
import pytest
|
|
import json
|
|
import subprocess
|
|
import tempfile
|
|
from pathlib import Path
|
|
from unittest.mock import Mock, patch
|
|
import sys
|
|
|
|
# Add parent directory to path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
|
|
|
from cli_anything.codimd.core import Config, Session, CodiMDClient
|
|
from cli_anything.codimd.codimd_cli import cli
|
|
from click.testing import CliRunner
|
|
|
|
|
|
class TestCLISubprocess:
|
|
"""Tests for installed CLI via subprocess."""
|
|
|
|
@staticmethod
|
|
def _resolve_cli(cli_name: str) -> str:
|
|
"""Resolve CLI command path.
|
|
|
|
If CLI_ANYTHING_FORCE_INSTALLED is set, use the command name directly.
|
|
Otherwise, use the Python module path.
|
|
"""
|
|
if "CLI_ANYTHING_FORCE_INSTALLED" in str(__import__("os").environ):
|
|
return cli_name
|
|
# For testing, use python -m to run the module
|
|
return f"python -m cli_anything.codimd.codimd_cli"
|
|
|
|
def test_cli_help(self):
|
|
"""Test CLI help command."""
|
|
result = subprocess.run(
|
|
["python", "-m", "cli_anything.codimd.codimd_cli", "--help"],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
assert result.returncode == 0
|
|
assert "CodiMD CLI" in result.stdout
|
|
|
|
def test_cli_version(self):
|
|
"""Test CLI version command."""
|
|
result = subprocess.run(
|
|
["python", "-m", "cli_anything.codimd.codimd_cli", "--version"],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
assert result.returncode == 0
|
|
assert "0.1.0" in result.stdout
|
|
|
|
|
|
class TestE2EClickRunner:
|
|
"""End-to-end tests using Click CliRunner."""
|
|
|
|
def setup_method(self):
|
|
"""Set up test environment."""
|
|
self.runner = CliRunner()
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
|
|
def teardown_method(self):
|
|
"""Clean up test environment."""
|
|
import shutil
|
|
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
|
|
@patch("cli_anything.codimd.codimd_cli.Config")
|
|
def test_config_get_command(self, mock_config_class):
|
|
"""Test config get command."""
|
|
mock_config = Mock()
|
|
mock_config.server = "http://localhost:3000"
|
|
mock_config.timeout = 30
|
|
mock_config.verify_ssl = True
|
|
mock_config_class.return_value = mock_config
|
|
|
|
result = self.runner.invoke(cli, ["config", "get"])
|
|
assert result.exit_code == 0
|
|
assert "Server:" in result.output or "localhost:3000" in result.output
|
|
|
|
@patch("cli_anything.codimd.codimd_cli.Config")
|
|
def test_config_set_command(self, mock_config_class):
|
|
"""Test config set command."""
|
|
mock_config = Mock()
|
|
mock_config.server = "http://localhost:3000"
|
|
mock_config_class.return_value = mock_config
|
|
|
|
result = self.runner.invoke(cli, ["config", "set", "timeout", "60"])
|
|
assert result.exit_code == 0
|
|
|
|
def test_help_command(self):
|
|
"""Test help command."""
|
|
result = self.runner.invoke(cli, ["--help"])
|
|
assert result.exit_code == 0
|
|
assert "CodiMD CLI" in result.output
|
|
assert "note" in result.output
|
|
assert "user" in result.output
|
|
assert "export" in result.output
|
|
|
|
def test_version_command(self):
|
|
"""Test version command."""
|
|
result = self.runner.invoke(cli, ["--version"])
|
|
assert result.exit_code == 0
|
|
assert "0.1.0" in result.output
|
|
|
|
def test_note_help(self):
|
|
"""Test note group help."""
|
|
result = self.runner.invoke(cli, ["note", "--help"])
|
|
assert result.exit_code == 0
|
|
assert "list" in result.output
|
|
assert "get" in result.output
|
|
assert "create" in result.output
|
|
|
|
def test_user_help(self):
|
|
"""Test user group help."""
|
|
result = self.runner.invoke(cli, ["user", "--help"])
|
|
assert result.exit_code == 0
|
|
assert "me" in result.output
|
|
assert "login" in result.output
|
|
assert "logout" in result.output
|
|
|
|
def test_export_help(self):
|
|
"""Test export group help."""
|
|
result = self.runner.invoke(cli, ["export", "--help"])
|
|
assert result.exit_code == 0
|
|
assert "markdown" in result.output
|
|
assert "pdf" in result.output
|
|
assert "html" in result.output
|
|
|
|
@patch("cli_anything.codimd.codimd_cli.Config")
|
|
@patch("cli_anything.codimd.codimd_cli.Session")
|
|
def test_json_output_mode(self, mock_session_class, mock_config_class):
|
|
"""Test JSON output mode."""
|
|
mock_config = Mock()
|
|
mock_config.config_dir = Path(self.temp_dir)
|
|
mock_config_class.return_value = mock_config
|
|
|
|
mock_session = Mock()
|
|
mock_session.is_authenticated.return_value = False
|
|
mock_session_class.return_value = mock_session
|
|
|
|
result = self.runner.invoke(cli, ["--json", "config", "get"])
|
|
# Should output JSON
|
|
assert '"status"' in result.output or '{"server"' in result.output or '"timeout"' in result.output
|
|
|
|
|
|
class TestE2ENoteCommands:
|
|
"""End-to-end tests for note commands."""
|
|
|
|
def setup_method(self):
|
|
"""Set up test environment."""
|
|
self.runner = CliRunner()
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
|
|
def teardown_method(self):
|
|
"""Clean up test environment."""
|
|
import shutil
|
|
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
|
|
@patch("cli_anything.codimd.codimd_cli.get_client")
|
|
@patch("cli_anything.codimd.codimd_cli.Config")
|
|
@patch("cli_anything.codimd.codimd_cli.Session")
|
|
def test_note_list_authenticated(self, mock_session_class, mock_config_class, mock_get_client):
|
|
"""Test listing notes when authenticated."""
|
|
mock_config = Mock()
|
|
mock_config.config_dir = Path(self.temp_dir)
|
|
mock_config_class.return_value = mock_config
|
|
|
|
mock_session = Mock()
|
|
mock_session.is_authenticated.return_value = True
|
|
mock_session_class.return_value = mock_session
|
|
|
|
mock_client = Mock()
|
|
mock_note_manager = Mock()
|
|
mock_note_manager.list_my_notes.return_value = [
|
|
{"id": "abc123", "text": "Test Note"}
|
|
]
|
|
mock_get_client.return_value = (mock_client, mock_session)
|
|
|
|
with patch("cli_anything.codimd.codimd_cli.NoteManager", return_value=mock_note_manager):
|
|
result = self.runner.invoke(cli, ["note", "list"])
|
|
assert result.exit_code == 0
|
|
|
|
@patch("cli_anything.codimd.codimd_cli.get_client")
|
|
@patch("cli_anything.codimd.codimd_cli.Config")
|
|
@patch("cli_anything.codimd.codimd_cli.Session")
|
|
def test_note_create(self, mock_session_class, mock_config_class, mock_get_client):
|
|
"""Test creating a note."""
|
|
mock_config = Mock()
|
|
mock_config.config_dir = Path(self.temp_dir)
|
|
mock_config_class.return_value = mock_config
|
|
|
|
mock_session = Mock()
|
|
mock_session_class.return_value = mock_session
|
|
|
|
mock_client = Mock()
|
|
mock_note_manager = Mock()
|
|
mock_note_manager.create_note.return_value = {
|
|
"id": "new-id",
|
|
"url": "http://example.com/new-id",
|
|
"status": "created"
|
|
}
|
|
mock_get_client.return_value = (mock_client, mock_session)
|
|
|
|
with patch("cli_anything.codimd.codimd_cli.NoteManager", return_value=mock_note_manager):
|
|
result = self.runner.invoke(cli, ["note", "create", "--content", "Test content"])
|
|
assert result.exit_code == 0
|
|
assert "created" in result.output
|
|
|
|
|
|
class TestE2EExportCommands:
|
|
"""End-to-end tests for export commands."""
|
|
|
|
def setup_method(self):
|
|
"""Set up test environment."""
|
|
self.runner = CliRunner()
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
|
|
def teardown_method(self):
|
|
"""Clean up test environment."""
|
|
import shutil
|
|
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
|
|
@patch("cli_anything.codimd.codimd_cli.get_client")
|
|
@patch("cli_anything.codimd.codimd_cli.Config")
|
|
@patch("cli_anything.codimd.codimd_cli.Session")
|
|
def test_export_markdown_to_file(self, mock_session_class, mock_config_class, mock_get_client):
|
|
"""Test exporting markdown to file."""
|
|
mock_config = Mock()
|
|
mock_config.config_dir = Path(self.temp_dir)
|
|
mock_config_class.return_value = mock_config
|
|
|
|
mock_session = Mock()
|
|
mock_session_class.return_value = mock_session
|
|
|
|
mock_client = Mock()
|
|
mock_export_manager = Mock()
|
|
mock_export_manager.export_markdown.return_value = "# Test Note"
|
|
mock_get_client.return_value = (mock_client, mock_session)
|
|
|
|
output_file = Path(self.temp_dir) / "output.md"
|
|
|
|
with patch("cli_anything.codimd.codimd_cli.ExportManager", return_value=mock_export_manager):
|
|
result = self.runner.invoke(
|
|
cli,
|
|
["export", "markdown", "test-id", "--output", str(output_file)]
|
|
)
|
|
assert result.exit_code == 0
|
|
|
|
|
|
class TestE2EUserCommands:
|
|
"""End-to-end tests for user commands."""
|
|
|
|
def setup_method(self):
|
|
"""Set up test environment."""
|
|
self.runner = CliRunner()
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
|
|
def teardown_method(self):
|
|
"""Clean up test environment."""
|
|
import shutil
|
|
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
|
|
@patch("cli_anything.codimd.codimd_cli.get_client")
|
|
@patch("cli_anything.codimd.codimd_cli.Config")
|
|
@patch("cli_anything.codimd.codimd_cli.Session")
|
|
def test_user_logout(self, mock_session_class, mock_config_class, mock_get_client):
|
|
"""Test user logout."""
|
|
mock_config = Mock()
|
|
mock_config.config_dir = Path(self.temp_dir)
|
|
mock_config_class.return_value = mock_config
|
|
|
|
mock_session = Mock()
|
|
mock_session_class.return_value = mock_session
|
|
|
|
mock_get_client.return_value = (Mock(), mock_session)
|
|
|
|
result = self.runner.invoke(cli, ["user", "logout"])
|
|
assert result.exit_code == 0
|
|
assert "logged out" in result.output.lower()
|
|
|
|
@patch("cli_anything.codimd.codimd_cli.get_client")
|
|
@patch("cli_anything.codimd.codimd_cli.Config")
|
|
@patch("cli_anything.codimd.codimd_cli.Session")
|
|
def test_user_me_unauthenticated(self, mock_session_class, mock_config_class, mock_get_client):
|
|
"""Test getting user info when not authenticated."""
|
|
mock_config = Mock()
|
|
mock_config.config_dir = Path(self.temp_dir)
|
|
mock_config_class.return_value = mock_config
|
|
|
|
mock_session = Mock()
|
|
mock_session.is_authenticated.return_value = False
|
|
mock_session_class.return_value = mock_session
|
|
|
|
mock_get_client.return_value = (Mock(), mock_session)
|
|
|
|
result = self.runner.invoke(cli, ["user", "me"])
|
|
assert result.exit_code == 1
|
|
assert "authenticated" in result.output.lower()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|