Files
the-other-dude/backend/tests/test_config_change_parser.py
Jason Staack 7fddf35fc5 test(05-02): add failing tests for config change parser
- 6 tests covering component extraction, summaries, multi-section, removals, modifications, fallback, raw_line

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:35:19 -05:00

114 lines
4.3 KiB
Python

"""Tests for config change parser.
Tests the parse_diff_changes function that extracts structured RouterOS
component changes from unified diffs.
"""
import pytest
from app.services.config_change_parser import parse_diff_changes
class TestParseDiffChanges:
"""Tests for parse_diff_changes()."""
def test_firewall_filter_additions(self):
"""Test 1: Diff with additions under /ip firewall filter produces correct component and summary."""
diff_text = (
"--- a/config\n"
"+++ b/config\n"
"@@ -1,3 +1,5 @@\n"
" /ip firewall filter\n"
" add chain=input action=accept\n"
"+add chain=forward action=accept protocol=tcp dst-port=80\n"
"+add chain=forward action=accept protocol=tcp dst-port=443\n"
)
changes = parse_diff_changes(diff_text)
assert len(changes) == 1
assert changes[0]["component"] == "ip/firewall/filter"
assert "Added" in changes[0]["summary"]
assert "2" in changes[0]["summary"]
assert changes[0]["raw_line"] is not None
def test_multiple_sections(self):
"""Test 2: Diff with changes under multiple sections produces two change entries."""
diff_text = (
"--- a/config\n"
"+++ b/config\n"
"@@ -1,4 +1,6 @@\n"
" /ip address\n"
"+add address=10.0.0.1/24 interface=ether1\n"
" /ip dns\n"
"+set servers=8.8.8.8,8.8.4.4\n"
)
changes = parse_diff_changes(diff_text)
assert len(changes) == 2
components = [c["component"] for c in changes]
assert "ip/address" in components
assert "ip/dns" in components
def test_removals_only(self):
"""Test 3: Diff with only removals produces summary like 'Removed 1 NAT rule'."""
diff_text = (
"--- a/config\n"
"+++ b/config\n"
"@@ -1,3 +1,2 @@\n"
" /ip firewall nat\n"
" add chain=srcnat action=masquerade\n"
"-add chain=dstnat action=dst-nat to-addresses=192.168.1.100\n"
)
changes = parse_diff_changes(diff_text)
assert len(changes) == 1
assert changes[0]["component"] == "ip/firewall/nat"
assert "Removed" in changes[0]["summary"]
assert "1" in changes[0]["summary"]
def test_modifications_both_add_and_remove(self):
"""Test 4: Diff with both + and - lines under same component produces 'Modified' summary."""
diff_text = (
"--- a/config\n"
"+++ b/config\n"
"@@ -1,3 +1,3 @@\n"
" /ip firewall filter\n"
"-add chain=input action=accept protocol=tcp dst-port=22\n"
"-add chain=input action=accept protocol=tcp dst-port=23\n"
"+add chain=input action=accept protocol=tcp dst-port=22 comment=ssh\n"
"+add chain=input action=accept protocol=tcp dst-port=443 comment=https\n"
)
changes = parse_diff_changes(diff_text)
assert len(changes) == 1
assert "Modified" in changes[0]["summary"]
assert "2" in changes[0]["summary"]
def test_no_path_header_fallback(self):
"""Test 5: Diff with no RouterOS path headers uses system/general as fallback."""
diff_text = (
"--- a/config\n"
"+++ b/config\n"
"@@ -1,3 +1,3 @@\n"
" # RouterOS config\n"
"-# version 6.48\n"
"+# version 6.49\n"
)
changes = parse_diff_changes(diff_text)
assert len(changes) == 1
assert changes[0]["component"] == "system/general"
def test_raw_line_contains_diff_lines(self):
"""Test 6: raw_line field contains actual changed diff lines joined with newlines."""
diff_text = (
"--- a/config\n"
"+++ b/config\n"
"@@ -1,3 +1,4 @@\n"
" /ip address\n"
"+add address=10.0.0.1/24 interface=ether1\n"
"-add address=192.168.1.1/24 interface=ether2\n"
)
changes = parse_diff_changes(diff_text)
assert len(changes) == 1
raw = changes[0]["raw_line"]
assert "+add address=10.0.0.1/24 interface=ether1" in raw
assert "-add address=192.168.1.1/24 interface=ether2" in raw
# Lines are joined with newlines
assert "\n" in raw