268 lines
9.3 KiB
Python
268 lines
9.3 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import pytest
|
|
from unittest.mock import Mock, patch, MagicMock
|
|
import argparse
|
|
from io import StringIO
|
|
import sys
|
|
|
|
from kumacli.cmd.monitor import setup_monitor_parser, handle_monitor_command
|
|
from kumacli.cmd.maintenance import setup_maintenance_parser, handle_maintenance_command
|
|
from kumacli.cmd.info import setup_info_parser, handle_info_command
|
|
|
|
|
|
class TestCLIIntegration:
|
|
def test_monitor_parser_setup(self):
|
|
"""Test monitor parser setup"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
|
|
monitor_parser = setup_monitor_parser(subparsers)
|
|
|
|
# Verify parser is created
|
|
assert monitor_parser is not None
|
|
assert monitor_parser.prog.endswith("monitor")
|
|
|
|
def test_maintenance_parser_setup(self):
|
|
"""Test maintenance parser setup"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
|
|
maintenance_parser = setup_maintenance_parser(subparsers)
|
|
|
|
# Verify parser is created
|
|
assert maintenance_parser is not None
|
|
assert maintenance_parser.prog.endswith("maintenance")
|
|
|
|
def test_info_parser_setup(self):
|
|
"""Test info parser setup"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
|
|
info_parser = setup_info_parser(subparsers)
|
|
|
|
# Verify parser is created
|
|
assert info_parser is not None
|
|
|
|
def test_monitor_help_message(self, mock_client, capsys):
|
|
"""Test monitor command shows help when no action specified"""
|
|
# Setup
|
|
mock_args = Mock()
|
|
mock_args.monitor_action = None
|
|
|
|
# Execute
|
|
result = handle_monitor_command(mock_args, mock_client)
|
|
|
|
# Verify
|
|
assert result is False
|
|
captured = capsys.readouterr()
|
|
assert "Error: No monitor action specified" in captured.out
|
|
|
|
def test_maintenance_help_message(self, mock_client, capsys):
|
|
"""Test maintenance command shows help when no action specified"""
|
|
# Setup
|
|
mock_args = Mock()
|
|
mock_args.maintenance_action = None
|
|
|
|
# Execute
|
|
result = handle_maintenance_command(mock_args, mock_client)
|
|
|
|
# Verify
|
|
assert result is False
|
|
captured = capsys.readouterr()
|
|
assert "Error: No maintenance action specified" in captured.out
|
|
|
|
def test_monitor_command_with_full_args(self, mock_client):
|
|
"""Test monitor command with complete argument structure"""
|
|
# Setup
|
|
mock_args = Mock()
|
|
mock_args.monitor_action = "pause"
|
|
mock_args.monitor = ["test*"]
|
|
mock_args.group = ["web-services"]
|
|
|
|
# Mock client methods
|
|
mock_client.find_and_get_monitors.return_value = [
|
|
{"id": 1, "name": "test-monitor"},
|
|
{"id": 2, "name": "web-service-monitor"},
|
|
]
|
|
mock_client.api.pause_monitor.return_value = {"msg": "Paused Successfully."}
|
|
|
|
# Execute
|
|
result = handle_monitor_command(mock_args, mock_client)
|
|
|
|
# Verify
|
|
assert result is True
|
|
mock_client.find_and_get_monitors.assert_called_once_with(
|
|
["test*"], ["web-services"]
|
|
)
|
|
# Should pause both monitors (deduplicated)
|
|
assert mock_client.api.pause_monitor.call_count == 2
|
|
|
|
def test_resume_all_monitors_integration(self, mock_client, mock_monitors):
|
|
"""Test resume all monitors integration"""
|
|
# Setup
|
|
mock_args = Mock()
|
|
mock_args.monitor_action = "resume"
|
|
mock_args.monitor = None
|
|
mock_args.group = None
|
|
mock_args.all = True
|
|
|
|
mock_client.api.get_monitors.return_value = mock_monitors
|
|
mock_client.api.resume_monitor.return_value = {"msg": "Resumed Successfully."}
|
|
|
|
# Execute
|
|
result = handle_monitor_command(mock_args, mock_client)
|
|
|
|
# Verify
|
|
assert result is True
|
|
mock_client.api.get_monitors.assert_called_once()
|
|
# Should resume only paused monitors (ID 2 and 4 from mock_monitors)
|
|
assert mock_client.api.resume_monitor.call_count == 2
|
|
mock_client.api.resume_monitor.assert_any_call(2)
|
|
mock_client.api.resume_monitor.assert_any_call(4)
|
|
|
|
|
|
class TestArgumentParsing:
|
|
def test_monitor_list_arguments(self):
|
|
"""Test monitor list command argument parsing"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
setup_monitor_parser(subparsers)
|
|
|
|
# Test with monitor patterns
|
|
args = parser.parse_args(
|
|
["monitor", "list", "--monitor", "web*", "--monitor", "api*"]
|
|
)
|
|
assert args.resource == "monitor"
|
|
assert args.monitor_action == "list"
|
|
assert args.monitor == ["web*", "api*"]
|
|
|
|
def test_monitor_pause_arguments(self):
|
|
"""Test monitor pause command argument parsing"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
setup_monitor_parser(subparsers)
|
|
|
|
# Test with group patterns
|
|
args = parser.parse_args(["monitor", "pause", "--group", "production"])
|
|
assert args.resource == "monitor"
|
|
assert args.monitor_action == "pause"
|
|
assert args.group == ["production"]
|
|
|
|
def test_monitor_resume_all_arguments(self):
|
|
"""Test monitor resume all command argument parsing"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
setup_monitor_parser(subparsers)
|
|
|
|
# Test with --all flag
|
|
args = parser.parse_args(["monitor", "resume", "--all"])
|
|
assert args.resource == "monitor"
|
|
assert args.monitor_action == "resume"
|
|
assert args.all is True
|
|
|
|
def test_maintenance_add_arguments(self):
|
|
"""Test maintenance add command argument parsing"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
setup_maintenance_parser(subparsers)
|
|
|
|
# Test maintenance add
|
|
args = parser.parse_args(
|
|
[
|
|
"maintenance",
|
|
"add",
|
|
"--title",
|
|
"Server Update",
|
|
"--description",
|
|
"Updating server software",
|
|
"--duration",
|
|
"2h",
|
|
"--monitor",
|
|
"server*",
|
|
]
|
|
)
|
|
assert args.resource == "maintenance"
|
|
assert args.maintenance_action == "add"
|
|
assert args.title == "Server Update"
|
|
assert args.description == "Updating server software"
|
|
assert args.duration == "2h"
|
|
assert args.monitor == ["server*"]
|
|
|
|
def test_maintenance_delete_arguments(self):
|
|
"""Test maintenance delete command argument parsing"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
setup_maintenance_parser(subparsers)
|
|
|
|
# Test delete by ID
|
|
args = parser.parse_args(["maintenance", "delete", "--id", "123"])
|
|
assert args.resource == "maintenance"
|
|
assert args.maintenance_action == "delete"
|
|
assert args.id == 123
|
|
|
|
# Test delete all
|
|
args = parser.parse_args(["maintenance", "delete", "--all"])
|
|
assert args.resource == "maintenance"
|
|
assert args.maintenance_action == "delete"
|
|
assert args.all is True
|
|
|
|
def test_info_arguments(self):
|
|
"""Test info command argument parsing"""
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="resource")
|
|
setup_info_parser(subparsers)
|
|
|
|
# Test info command
|
|
args = parser.parse_args(["info"])
|
|
assert args.resource == "info"
|
|
|
|
|
|
class TestErrorHandling:
|
|
def test_monitor_command_resilience(self, mock_client, capsys):
|
|
"""Test monitor command handles various error conditions"""
|
|
# Setup
|
|
mock_args = Mock()
|
|
mock_args.monitor_action = "pause"
|
|
mock_args.monitor = ["nonexistent*"]
|
|
mock_args.group = None
|
|
|
|
# Mock no matches found
|
|
def mock_find_and_get_monitors(*args, **kwargs):
|
|
print("Error: No monitors found matching the specified patterns or groups")
|
|
return []
|
|
|
|
mock_client.find_and_get_monitors.side_effect = mock_find_and_get_monitors
|
|
|
|
# Execute
|
|
result = handle_monitor_command(mock_args, mock_client)
|
|
|
|
# Verify error handling
|
|
assert result is True # Command completes even with no matches
|
|
captured = capsys.readouterr()
|
|
assert (
|
|
"Error: No monitors found matching the specified patterns or groups"
|
|
in captured.out
|
|
)
|
|
|
|
def test_maintenance_command_resilience(self, mock_client, capsys):
|
|
"""Test maintenance command handles API errors"""
|
|
# Setup
|
|
mock_args = Mock()
|
|
mock_args.maintenance_action = "list"
|
|
|
|
# Mock API error
|
|
from uptime_kuma_api import UptimeKumaException
|
|
|
|
mock_client.api.get_maintenances.side_effect = UptimeKumaException(
|
|
"Connection timeout"
|
|
)
|
|
|
|
# Execute
|
|
result = handle_maintenance_command(mock_args, mock_client)
|
|
|
|
# Verify error handling
|
|
assert result is True # Command completes even with error
|
|
captured = capsys.readouterr()
|
|
assert "Error listing maintenances: Connection timeout" in captured.out
|