Files
netbox-librenms-plugin/netbox_librenms_plugin/tests/test_import_validation_helpers.py
Vlastislav Svatek 673e67106e
Some checks failed
ci / deploy (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
first commit
2026-06-05 10:39:05 +02:00

369 lines
12 KiB
Python

"""
Tests for netbox_librenms_plugin.import_validation_helpers module.
Phase 2 tests covering validation state updates, model retrieval,
and selection extraction functions.
"""
from unittest.mock import MagicMock
# =============================================================================
# TestGetModelById - 4 tests
# =============================================================================
class TestFetchModelById:
"""Test generic model retrieval helper."""
def test_fetch_model_by_id_success(self):
"""Return model instance when found."""
mock_model_class = MagicMock()
mock_instance = MagicMock(id=1, name="Access Switch")
mock_model_class.objects.get.return_value = mock_instance
from netbox_librenms_plugin.import_validation_helpers import fetch_model_by_id
result = fetch_model_by_id(mock_model_class, 1)
assert result == mock_instance
mock_model_class.objects.get.assert_called_once_with(pk=1)
def test_fetch_model_by_id_not_found(self):
"""Return None when ID doesn't exist."""
mock_model_class = MagicMock()
mock_model_class.DoesNotExist = Exception
mock_model_class.objects.get.side_effect = mock_model_class.DoesNotExist
from netbox_librenms_plugin.import_validation_helpers import fetch_model_by_id
result = fetch_model_by_id(mock_model_class, 999)
assert result is None
def test_fetch_model_by_id_invalid_id(self):
"""Handle invalid ID gracefully."""
mock_model_class = MagicMock()
mock_model_class.DoesNotExist = type("DoesNotExist", (Exception,), {})
from netbox_librenms_plugin.import_validation_helpers import fetch_model_by_id
result = fetch_model_by_id(mock_model_class, "not-a-number")
assert result is None
def test_fetch_model_by_id_none_id(self):
"""Handle None ID gracefully."""
mock_model_class = MagicMock()
from netbox_librenms_plugin.import_validation_helpers import fetch_model_by_id
result = fetch_model_by_id(mock_model_class, None)
assert result is None
mock_model_class.objects.get.assert_not_called()
# =============================================================================
# TestExtractSelections - 4 tests
# =============================================================================
class TestExtractDeviceSelections:
"""Test extraction of device selections from request."""
def test_extract_selections_all_present(self):
"""All selections extracted from POST request."""
from netbox_librenms_plugin.import_validation_helpers import (
extract_device_selections,
)
mock_request = MagicMock()
mock_request.method = "POST"
mock_request.POST = {
"cluster_1234": "5",
"role_1234": "10",
"rack_1234": "15",
}
result = extract_device_selections(mock_request, device_id=1234)
assert result["cluster_id"] == "5"
assert result["role_id"] == "10"
assert result["rack_id"] == "15"
def test_extract_selections_partial(self):
"""Missing fields return None."""
from netbox_librenms_plugin.import_validation_helpers import (
extract_device_selections,
)
mock_request = MagicMock()
mock_request.method = "POST"
mock_request.POST = {
"role_1234": "10",
}
result = extract_device_selections(mock_request, device_id=1234)
assert result["cluster_id"] is None
assert result["role_id"] == "10"
assert result["rack_id"] is None
def test_extract_selections_from_get(self):
"""Selections extracted from GET request."""
from netbox_librenms_plugin.import_validation_helpers import (
extract_device_selections,
)
mock_request = MagicMock()
mock_request.method = "GET"
mock_request.GET = {
"cluster_999": "3",
"role_999": "7",
"rack_999": "11",
}
result = extract_device_selections(mock_request, device_id=999)
assert result["cluster_id"] == "3"
assert result["role_id"] == "7"
assert result["rack_id"] == "11"
def test_extract_selections_empty_values(self):
"""Empty strings handled correctly."""
from netbox_librenms_plugin.import_validation_helpers import (
extract_device_selections,
)
mock_request = MagicMock()
mock_request.method = "POST"
mock_request.POST = {
"cluster_1234": "",
"role_1234": "",
"rack_1234": "",
}
result = extract_device_selections(mock_request, device_id=1234)
# Empty strings are returned as-is (caller decides meaning)
assert result["cluster_id"] == ""
assert result["role_id"] == ""
assert result["rack_id"] == ""
# =============================================================================
# TestValidationStateUpdates - 10 tests
# =============================================================================
class TestValidationStateUpdates:
"""Test validation state mutation functions."""
def test_apply_role_to_validation_success(self):
"""Role selection updates state correctly."""
from netbox_librenms_plugin.import_validation_helpers import (
apply_role_to_validation,
)
mock_role = MagicMock(id=1, name="Access Switch")
validation = {
"device_role": {"found": False, "role": None},
"issues": ["Device role must be manually selected before import"],
"can_import": False,
"is_ready": False,
"site": {"found": True},
"device_type": {"found": True},
}
apply_role_to_validation(validation, mock_role, is_vm=False)
assert validation["device_role"]["found"] is True
assert validation["device_role"]["role"] == mock_role
def test_apply_role_to_validation_clears_issue(self):
"""Selecting role should clear 'role' related validation issue."""
from netbox_librenms_plugin.import_validation_helpers import (
apply_role_to_validation,
)
mock_role = MagicMock(id=1, name="Access Switch")
validation = {
"device_role": {"found": False, "role": None},
"issues": ["Device role must be manually selected before import"],
"can_import": False,
"is_ready": False,
"site": {"found": True},
"device_type": {"found": True},
}
apply_role_to_validation(validation, mock_role, is_vm=False)
assert len(validation["issues"]) == 0
def test_apply_cluster_to_validation_success(self):
"""Cluster selection updates state for VM import."""
from netbox_librenms_plugin.import_validation_helpers import (
apply_cluster_to_validation,
)
mock_cluster = MagicMock(id=1, name="VMware Cluster 1")
validation = {
"cluster": {"found": False, "cluster": None},
"issues": ["Cluster must be manually selected before import"],
"can_import": False,
"is_ready": False,
}
apply_cluster_to_validation(validation, mock_cluster)
assert validation["cluster"]["found"] is True
assert validation["cluster"]["cluster"] == mock_cluster
def test_apply_rack_to_validation_success(self):
"""Rack selection updates state for device import."""
from netbox_librenms_plugin.import_validation_helpers import (
apply_rack_to_validation,
)
mock_rack = MagicMock(id=1, name="Rack A1")
validation = {
"issues": [],
"can_import": True,
"is_ready": True,
}
apply_rack_to_validation(validation, mock_rack)
assert validation["rack"]["found"] is True
assert validation["rack"]["rack"] == mock_rack
def test_remove_validation_issue_single(self):
"""Remove single issue by keyword."""
from netbox_librenms_plugin.import_validation_helpers import (
remove_validation_issue,
)
validation = {
"issues": [
"Device role must be manually selected before import",
"Site not found for location 'DC1'",
]
}
remove_validation_issue(validation, "role")
assert len(validation["issues"]) == 1
assert "Site not found" in validation["issues"][0]
def test_remove_validation_issue_multiple(self):
"""Remove multiple matching issues."""
from netbox_librenms_plugin.import_validation_helpers import (
remove_validation_issue,
)
validation = {
"issues": [
"Device role must be selected",
"Role is required for import",
"Site not found",
]
}
remove_validation_issue(validation, "role")
assert len(validation["issues"]) == 1
assert "Site not found" in validation["issues"][0]
def test_remove_validation_issue_no_match(self):
"""No change when keyword not found."""
from netbox_librenms_plugin.import_validation_helpers import (
remove_validation_issue,
)
validation = {
"issues": [
"Site not found for location 'DC1'",
"Device type not matched",
]
}
remove_validation_issue(validation, "cluster")
assert len(validation["issues"]) == 2
def test_recalculate_can_import_all_ready_device(self):
"""can_import=True when all requirements met for device."""
from netbox_librenms_plugin.import_validation_helpers import (
recalculate_validation_status,
)
validation = {
"issues": [],
"can_import": False,
"is_ready": False,
"site": {"found": True},
"device_type": {"found": True},
"device_role": {"found": True},
}
recalculate_validation_status(validation, is_vm=False)
assert validation["can_import"] is True
assert validation["is_ready"] is True
def test_recalculate_can_import_missing_required_device(self):
"""can_import=False when required field missing for device."""
from netbox_librenms_plugin.import_validation_helpers import (
recalculate_validation_status,
)
validation = {
"issues": ["Site not found"],
"can_import": True, # Should become False
"is_ready": True,
"site": {"found": False},
"device_type": {"found": True},
"device_role": {"found": True},
}
recalculate_validation_status(validation, is_vm=False)
assert validation["can_import"] is False
assert validation["is_ready"] is False
def test_recalculate_can_import_vm_cluster_required(self):
"""VM import requires cluster to be ready."""
from netbox_librenms_plugin.import_validation_helpers import (
recalculate_validation_status,
)
validation = {
"issues": [],
"can_import": False,
"is_ready": False,
"cluster": {"found": True},
}
recalculate_validation_status(validation, is_vm=True)
assert validation["can_import"] is True
assert validation["is_ready"] is True
def test_recalculate_can_import_vm_missing_cluster(self):
"""VM import not ready without cluster."""
from netbox_librenms_plugin.import_validation_helpers import (
recalculate_validation_status,
)
validation = {
"issues": [],
"can_import": False,
"is_ready": False,
"cluster": {"found": False},
}
recalculate_validation_status(validation, is_vm=True)
assert validation["can_import"] is True # No issues
assert validation["is_ready"] is False # But not ready without cluster