#!/usr/bin/env python3 """Keep existing PMG guidance tied to the actual navigation and read limits. Static source/document checks only: no gateway, mail, credentials, network, service, notification or live diagnostic operation is performed. """ from pathlib import Path import re import unittest ROOT = Path(__file__).resolve().parents[2] DOC = ROOT / "docs/MAIL_GATEWAY.md" def frontend(path): return (ROOT / "frontend-modern/src" / path).read_text(encoding="utf-8") def plain(text): return " ".join(text.replace("**", "").split()) def go_block(text, opening): """Read one known source block, including its nested bodies.""" start = text.index(opening) + len(opening) depth = 1 for end in range(start, len(text)): depth += (text[end] == "{") - (text[end] == "}") if depth == 0: return text[start:end] raise AssertionError(f"Unclosed source block: {opening}") class PMGDocsTest(unittest.TestCase): def setUp(self): self.text = DOC.read_text(encoding="utf-8") self.guide = plain(self.text) def test_shipped_guide_matches(self): self.assertEqual(DOC.read_bytes(), (ROOT / "frontend-modern/public/docs/MAIL_GATEWAY.md").read_bytes()) def test_connection_instructions_match_existing_picker_and_form(self): picker = frontend("components/Settings/InfrastructureSourcePicker.tsx") authentication = frontend("components/Settings/NodeModalAuthenticationSection.tsx") self.assertIn("Show more sources", picker) self.assertIn("Show more sources", self.guide) self.assertIn("Settings → Infrastructure → Add infrastructure", self.guide) self.assertNotIn("**Add Node**", self.text) self.assertIn("Username & Password", authentication) self.assertIn("Username & Password", self.guide) self.assertIn("modalProps.nodeType !== 'pmg'", authentication) for phrase in ("not the PVE/PBS API-token setup", "minimum read permissions", "password only in the private settings form", "do not put it in a command, URL or issue report", "Keep HTTPS and certificate verification enabled"): self.assertIn(phrase, self.guide) def test_navigation_and_dataset_detail_match_the_current_surface(self): model = frontend("features/proxmox/proxmoxPageModel.ts") route = re.search(r"id: 'mail', label: '([^']+)', path: '([^']+)'", model) self.assertIsNotNone(route) self.assertIn(f"**Proxmox → {route[1]}** (`{route[2]}`)", self.text) table = frontend("features/proxmox/ProxmoxMailGatewayTable.tsx") self.assertIn("No instances match current filters", table) self.assertIn("clear its search and status filters", self.guide) self.assertNotIn("on the **Infrastructure** page", self.text) drawer = frontend("features/proxmox/ProxmoxMailGatewayDrawer.tsx") self.assertIn(".slice(0, 8)", drawer) self.assertIn("top eight reported domains, not the entire domain inventory", self.guide) # The mail-flow card names the window its counts cover. self.assertRegex(drawer, r"stats(?:\(\))?\??\.timeframe") self.assertIn("compare the same window in PMG", self.guide) self.assertIn("Expand the intended gateway's row", self.guide) def test_documented_thresholds_exist_and_keep_their_units(self): config = (ROOT / "internal/alerts/config/types.go").read_text() fields = config.split("type PMGThresholdConfig struct {", 1)[1].split("\n}", 1)[0] for key in ("queueTotalWarning", "deferredQueueWarn", "holdQueueWarn", "oldestMessageWarnMins", "quarantineSpamWarn", "quarantineVirusWarn", "quarantineGrowthWarnPct", "quarantineGrowthWarnMin"): self.assertIn(f'json:"{key}"', fields) self.assertNotRegex(fields, r'json:"(?:spamRate|deliveryFailures)') self.assertIn("