""" Phase 9: External Integrations Tests ==================================== Tests for webhook delivery and notification paths. Required tests: - github_webhook: Verify GitHub event handling in dry-run - slack_notification: Verify Slack notification dispatch in dry-run - webhook_delivery: Verify IntegrationManager broadcast delivery """ import os import sys from pathlib import Path # Add integrations to path sys.path.insert(0, str(Path(__file__).parent.parent.parent / "integrations")) PASSED = 0 FAILED = 0 def log(msg: str, status: str = "info"): icons = {"pass": "\033[92m✓\033[0m", "fail": "\033[91m✗\033[0m", "info": "→"} print(f" {icons.get(status, '•')} {msg}") def load_module(name: str, path: Path): import importlib.util spec = importlib.util.spec_from_file_location(name, path) if spec is None or spec.loader is None: raise ImportError(f"Module spec missing for {name}") module = importlib.util.module_from_spec(spec) sys.modules[name] = module spec.loader.exec_module(module) return module def test_github_webhook(): """Test GitHub webhook handling in dry-run mode""" global PASSED, FAILED print("\n[TEST] github_webhook") os.environ["INTEGRATION_DRY_RUN"] = "true" os.environ["GITHUB_TOKEN"] = "ghp_test_token" os.environ["GITHUB_REPO"] = "example/repo" try: base = load_module( "common.base", Path(__file__).parent.parent.parent / "integrations" / "common" / "base.py", ) github = load_module( "github.github", Path(__file__).parent.parent.parent / "integrations" / "github" / "github.py", ) except ImportError as e: log(f"GitHub import failed: {e}", "fail") FAILED += 1 return False gh = github.GitHubIntegration() event = base.IntegrationEvent( event_type="plan_created", source="agent-001", data={"plan": {"title": "Test Plan", "objective": "Verify webhook"}}, ) if gh.send_event(event): log("GitHub plan event handled", "pass") PASSED += 1 else: log("GitHub plan event failed", "fail") FAILED += 1 audit = gh.get_audit_log() if any(entry.get("operation") == "create_pr" for entry in audit): log("GitHub create_pr audit recorded", "pass") PASSED += 1 else: log("GitHub create_pr audit missing", "fail") FAILED += 1 return True def test_slack_notification(): """Test Slack notification dispatch in dry-run mode""" global PASSED, FAILED print("\n[TEST] slack_notification") os.environ["INTEGRATION_DRY_RUN"] = "true" os.environ["SLACK_BOT_TOKEN"] = "xoxb-test-token" os.environ["SLACK_WEBHOOK_URL"] = "https://hooks.slack.com/test" try: base = load_module( "common.base", Path(__file__).parent.parent.parent / "integrations" / "common" / "base.py", ) slack_module = load_module( "slack.slack", Path(__file__).parent.parent.parent / "integrations" / "slack" / "slack.py", ) except ImportError as e: log(f"Slack import failed: {e}", "fail") FAILED += 1 return False slack = slack_module.SlackIntegration() event = base.IntegrationEvent( event_type="violation_detected", source="agent-002", data={ "violation": {"type": "policy", "severity": "high", "description": "Test"} }, priority="high", ) if slack.send_event(event): log("Slack violation notification dispatched", "pass") PASSED += 1 else: log("Slack notification failed", "fail") FAILED += 1 audit = slack.get_audit_log() if any(entry.get("operation") == "send_message" for entry in audit): log("Slack send_message audit recorded", "pass") PASSED += 1 else: log("Slack send_message audit missing", "fail") FAILED += 1 return True def test_webhook_delivery(): """Test IntegrationManager broadcast delivery""" global PASSED, FAILED print("\n[TEST] webhook_delivery") os.environ["INTEGRATION_DRY_RUN"] = "true" os.environ["SLACK_BOT_TOKEN"] = "xoxb-test-token" os.environ["GITHUB_TOKEN"] = "ghp_test_token" os.environ["GITHUB_REPO"] = "example/repo" try: base = load_module( "common.base", Path(__file__).parent.parent.parent / "integrations" / "common" / "base.py", ) slack_module = load_module( "slack.slack", Path(__file__).parent.parent.parent / "integrations" / "slack" / "slack.py", ) github = load_module( "github.github", Path(__file__).parent.parent.parent / "integrations" / "github" / "github.py", ) except ImportError as e: log(f"Integration import failed: {e}", "fail") FAILED += 1 return False manager = base.IntegrationManager() manager.register( slack_module.SlackIntegration( webhook_url="https://hooks.slack.com/test", bot_token="xoxb-test-token", ) ) manager.register( github.GitHubIntegration( token="ghp_test_token", repo="example/repo", ) ) event = base.IntegrationEvent( event_type="execution_complete", source="agent-003", data={"result": {"success": True, "duration": 4.2}, "commit_sha": "HEAD"}, ) results = manager.broadcast(event) if results.get("slack") and results.get("github"): log("Broadcast delivered to Slack and GitHub", "pass") PASSED += 1 else: log(f"Broadcast results missing: {results}", "fail") FAILED += 1 return True def main(): global PASSED, FAILED print("\n" + "=" * 60) print("PHASE 9: EXTERNAL INTEGRATIONS TESTS") print("=" * 60) try: test_github_webhook() test_slack_notification() test_webhook_delivery() except Exception as e: print(f"\n\033[91mTest execution error: {e}\033[0m") FAILED += 1 print("\n" + "=" * 60) print(f"RESULTS: {PASSED} passed, {FAILED} failed") print("=" * 60 + "\n") return FAILED == 0 if __name__ == "__main__": success = main() sys.exit(0 if success else 1)