Files
kumacli/tests/test_client.py
Pim van Pelt e2e65add2e Add tests
2025-08-02 20:03:32 +02:00

226 lines
8.0 KiB
Python

#!/usr/bin/env python3
import pytest
from unittest.mock import Mock, patch
from datetime import datetime, timedelta
from kumacli.client import KumaClient
class TestKumaClient:
def test_parse_duration_minutes(self):
"""Test parsing duration in minutes"""
client = KumaClient("http://test.com")
assert client.parse_duration("90m") == 5400 # 90 * 60
assert client.parse_duration("1m") == 60
assert client.parse_duration("120m") == 7200
def test_parse_duration_hours(self):
"""Test parsing duration in hours"""
client = KumaClient("http://test.com")
assert client.parse_duration("1h") == 3600 # 1 * 3600
assert client.parse_duration("2h") == 7200
assert client.parse_duration("24h") == 86400
def test_parse_duration_seconds(self):
"""Test parsing duration in seconds"""
client = KumaClient("http://test.com")
assert client.parse_duration("3600s") == 3600
assert client.parse_duration("60s") == 60
assert client.parse_duration("1s") == 1
def test_parse_duration_default(self):
"""Test parsing duration with default value"""
client = KumaClient("http://test.com")
assert client.parse_duration(None) == 5400 # Default 90 minutes
assert client.parse_duration("") == 5400
def test_parse_duration_invalid(self):
"""Test parsing invalid duration format"""
client = KumaClient("http://test.com")
with pytest.raises(ValueError, match="Invalid duration format"):
client.parse_duration("invalid")
with pytest.raises(ValueError, match="Invalid duration format"):
client.parse_duration("90x")
with pytest.raises(ValueError, match="Invalid duration format"):
client.parse_duration("90")
def test_parse_start_time_none(self):
"""Test parsing start time with None (current time)"""
client = KumaClient("http://test.com")
before = datetime.utcnow()
result = client.parse_start_time(None)
after = datetime.utcnow()
assert before <= result <= after
def test_parse_start_time_iso_format(self):
"""Test parsing ISO format start time"""
client = KumaClient("http://test.com")
# Test ISO format with Z
result = client.parse_start_time("2023-12-25T10:30:00Z")
expected = datetime(2023, 12, 25, 10, 30, 0)
assert result == expected
# Test ISO format with timezone
result = client.parse_start_time("2023-12-25T10:30:00+00:00")
assert result == expected
def test_parse_start_time_common_formats(self):
"""Test parsing common date/time formats"""
client = KumaClient("http://test.com")
# Full datetime
result = client.parse_start_time("2023-12-25 10:30:00")
expected = datetime(2023, 12, 25, 10, 30, 0)
assert result == expected
# Date and hour:minute
result = client.parse_start_time("2023-12-25 10:30")
expected = datetime(2023, 12, 25, 10, 30, 0)
assert result == expected
# Date only
result = client.parse_start_time("2023-12-25")
expected = datetime(2023, 12, 25, 0, 0, 0)
assert result == expected
def test_parse_start_time_invalid(self):
"""Test parsing invalid start time format"""
client = KumaClient("http://test.com")
with pytest.raises(ValueError, match="Invalid start time format"):
client.parse_start_time("invalid-date")
with pytest.raises(ValueError, match="Invalid start time format"):
client.parse_start_time("2023-13-45")
def test_find_monitors_by_pattern_success(self):
"""Test finding monitors by pattern successfully"""
client = KumaClient("http://test.com")
client.api = Mock()
mock_monitors = [
{"id": 1, "name": "Web Server"},
{"id": 2, "name": "API Server"},
{"id": 3, "name": "Database"},
{"id": 4, "name": "Web Frontend"}
]
client.api.get_monitors.return_value = mock_monitors
# Test exact match
result = client.find_monitors_by_pattern(["Web Server"])
assert len(result) == 1
assert result[0]["name"] == "Web Server"
# Test wildcard pattern
result = client.find_monitors_by_pattern(["Web*"])
assert len(result) == 2
names = [m["name"] for m in result]
assert "Web Server" in names
assert "Web Frontend" in names
def test_find_monitors_by_pattern_case_insensitive(self):
"""Test finding monitors by pattern is case insensitive"""
client = KumaClient("http://test.com")
client.api = Mock()
mock_monitors = [
{"id": 1, "name": "Web Server"},
{"id": 2, "name": "API Server"}
]
client.api.get_monitors.return_value = mock_monitors
# Test case insensitive matching
result = client.find_monitors_by_pattern(["web*"])
assert len(result) == 1
assert result[0]["name"] == "Web Server"
def test_find_monitors_by_pattern_no_matches(self):
"""Test finding monitors with no matches"""
client = KumaClient("http://test.com")
client.api = Mock()
mock_monitors = [
{"id": 1, "name": "Web Server"}
]
client.api.get_monitors.return_value = mock_monitors
result = client.find_monitors_by_pattern(["Database*"])
assert len(result) == 0
def test_find_monitors_by_pattern_duplicates(self):
"""Test finding monitors removes duplicates"""
client = KumaClient("http://test.com")
client.api = Mock()
mock_monitors = [
{"id": 1, "name": "Web Server"}
]
client.api.get_monitors.return_value = mock_monitors
# Same monitor should match both patterns
result = client.find_monitors_by_pattern(["Web*", "*Server"])
assert len(result) == 1
assert result[0]["name"] == "Web Server"
def test_find_monitors_by_pattern_api_error(self, capsys):
"""Test finding monitors handles API errors"""
client = KumaClient("http://test.com")
client.api = Mock()
client.api.get_monitors.side_effect = Exception("API Error")
result = client.find_monitors_by_pattern(["Web*"])
assert len(result) == 0
captured = capsys.readouterr()
assert "Error finding monitors: API Error" in captured.out
@patch('kumacli.client.UptimeKumaApi')
def test_connect_success(self, mock_api_class, capsys):
"""Test successful connection"""
mock_api = Mock()
mock_api_class.return_value = mock_api
mock_api.login.return_value = True
client = KumaClient("http://test.com", "user", "pass")
result = client.connect()
assert result is True
assert client.api is mock_api
mock_api_class.assert_called_once_with("http://test.com")
mock_api.login.assert_called_once_with("user", "pass")
captured = capsys.readouterr()
assert "Connected to http://test.com" in captured.out
@patch('kumacli.client.UptimeKumaApi')
def test_connect_failure(self, mock_api_class, capsys):
"""Test connection failure"""
mock_api_class.side_effect = Exception("Connection failed")
client = KumaClient("http://test.com", "user", "pass")
result = client.connect()
assert result is False
captured = capsys.readouterr()
assert "Failed to connect: Connection failed" in captured.out
def test_disconnect(self):
"""Test disconnection"""
client = KumaClient("http://test.com")
client.api = Mock()
client.disconnect()
client.api.disconnect.assert_called_once()