"""Frontend contract tests for Agent Management.""" import unittest from pathlib import Path from fastapi import FastAPI from fastapi.testclient import TestClient from app.frontend.router import router from app.identity import get_current_user, required_page_permission STATIC_ROOT = Path(__file__).parents[1] / "app" / "frontend" / "static" class AgentManagementFrontendTests(unittest.TestCase): def setUp(self): self.app = FastAPI() self.app.include_router(router) self.client = TestClient(self.app) def authenticate(self, permissions): self.app.dependency_overrides[get_current_user] = lambda: { "id": "00000000-0000-4000-8000-000000009001", "username": "agent-test-user", "display_name": "Agent Test User", "role": "Test Role", "permissions": tuple(permissions), } def test_page_requires_agents_view(self): self.authenticate(("unrelated.permission",)) self.assertEqual( self.client.get("/agent/management").status_code, 403, ) self.authenticate(("agents.view",)) response = self.client.get("/agent/management") self.assertEqual(response.status_code, 200) self.assertIn("Agent Management", response.text) self.assertIn('href="/agent/management"', response.text) def test_manage_controls_follow_agents_manage_permission(self): self.authenticate(("agents.view",)) restricted = self.client.get("/agent/management").text self.assertNotIn('id="agentCreateForm"', restricted) restricted_text = " ".join(restricted.split()) self.assertIn( "cannot create Agent enrollments.", restricted_text, ) self.authenticate(("agents.view", "agents.manage")) managed = self.client.get("/agent/management").text self.assertIn('id="agentCreateForm"', managed) self.assertIn('id="agentSite"', managed) self.assertIn('id="agentZone"', managed) self.assertIn('id="agentDisplayName"', managed) self.assertIn("Linux x64 — coming later", managed) self.assertIn("Linux ARM64 / Raspberry Pi — coming later", managed) def test_route_and_asset_contract(self): self.assertEqual( required_page_permission("/agent/management"), "agents.view", ) self.authenticate(("agents.view",)) page = self.client.get("/agent/management") self.assertIn( "/assets/minerops-agent-management.js", page.text, ) asset = self.client.get( "/assets/minerops-agent-management.js" ) self.assertEqual(asset.status_code, 200) self.assertEqual( asset.headers.get("cache-control"), "no-store", ) def test_javascript_is_secret_conscious_and_safe_dom_only(self): source = ( STATIC_ROOT / "agent-management.js" ).read_text(encoding="utf-8") self.assertIn('api("/api/agents")', source) self.assertIn('api("/api/agent-enrollments")', source) self.assertIn( 'api("/api/agent-enrollments", {', source, ) for unsafe in ( "innerHTML", "outerHTML", "insertAdjacentHTML", "localStorage", "sessionStorage", "console.log", ): self.assertNotIn(unsafe, source) self.assertIn( "el.agentEnrollmentToken.textContent", source, ) self.assertIn( "el.agentEnrollmentToken.textContent = \"\"", source, ) def test_agent_management_quiet_actions_have_visible_text(self): css = (STATIC_ROOT / "app.css").read_text(encoding="utf-8") self.assertIn( ".agent-management-columns .quiet-button,", css, ) self.assertIn( ".agent-enrollment-panel .quiet-button {", css, ) self.assertIn( "color: var(--ink);", css, ) def test_windows_package_download_is_ephemeral(self): self.authenticate(("agents.view", "agents.manage")) page = self.client.get("/agent/management").text self.assertIn('id="agentEnrollmentDownload"', page) self.assertIn("Download Windows package", page) source = ( STATIC_ROOT / "agent-management.js" ).read_text(encoding="utf-8") self.assertIn( '"/api/agent-enrollments/windows-package"', source, ) self.assertIn( 'link.download = "MinerOpsAgent-Windows.zip"', source, ) self.assertIn( "window.URL.revokeObjectURL(downloadUrl)", source, ) self.assertIn("dismissToken();", source) for forbidden in ( "localStorage", "sessionStorage", "agent_secret", "api3_password", ): self.assertNotIn(forbidden, source) if __name__ == "__main__": unittest.main()