test_validate_endpoint.py
1 """ 2 Integration tests for the FastAPI /validate/kind-2003 endpoint. 3 4 These tests use FastAPI's TestClient to test the actual validation endpoint 5 with real rule execution (subprocess calls). 6 7 IMPORTANT: The validate endpoint uses PUT method (not POST) as defined in main.py. 8 IMPORTANT: The Nip35Kind2003Event Pydantic model validates event structure strictly. 9 """ 10 11 import pytest 12 13 14 def create_valid_nip35_event(): 15 """Create a valid NIP-35 event that passes Pydantic validation.""" 16 return { 17 "id": "0000000000000000000000000000000000000000000000000000000000000001", 18 "pubkey": "0000000000000000000000000000000000000000000000000000000000000002", 19 "created_at": 1234567890, 20 "kind": 2003, 21 "tags": [ 22 ["title", "Test Torrent"], 23 ["x", "abc123abc123abc123abc123abc123abc123abc1"], # 40-char hex btih 24 ["file", "test.mkv", "1073741824"], # name, size in bytes 25 ], 26 "content": "Test torrent description", 27 "sig": "0" * 128, # 128-char hex signature (64 bytes) 28 } 29 30 31 @pytest.mark.integration 32 @pytest.mark.slow 33 def test_validate_accepts_valid_event(): 34 """Test that validate endpoint accepts a valid NIP-35 event.""" 35 try: 36 from fastapi.testclient import TestClient 37 38 from main import app 39 except Exception as e: 40 pytest.skip(f"Failed to import app (venv generation issue?): {e}") 41 42 client = TestClient(app) 43 event = create_valid_nip35_event() 44 45 response = client.put("/validate/kind-2003", json=event) 46 47 assert response.status_code == 200 48 data = response.json() 49 assert "passed" in data 50 assert "rules" in data 51 assert isinstance(data["passed"], bool) 52 assert isinstance(data["rules"], dict) 53 54 55 @pytest.mark.integration 56 @pytest.mark.slow 57 def test_validate_returns_rule_results(): 58 """Test that validate endpoint returns rule IDs and results.""" 59 try: 60 from fastapi.testclient import TestClient 61 62 from main import app 63 except Exception as e: 64 pytest.skip(f"Failed to import app (venv generation issue?): {e}") 65 66 client = TestClient(app) 67 event = create_valid_nip35_event() 68 69 response = client.put("/validate/kind-2003", json=event) 70 71 assert response.status_code == 200 72 data = response.json() 73 74 # Should have rules in response (at least the 3 POC rules if enabled) 75 # Rules format: {"D-SCHEMA-03": {"passed": true/false}, ...} 76 if len(data["rules"]) > 0: 77 # Check that each rule has expected structure 78 for _rule_id, rule_result in data["rules"].items(): 79 assert isinstance(rule_result, dict) 80 # Rule should have either "passed" (deterministic) or "score" (probabilistic) 81 assert "passed" in rule_result or "score" in rule_result 82 83 84 @pytest.mark.integration 85 def test_validate_rejects_invalid_event_format(): 86 """Test that validate endpoint rejects malformed JSON.""" 87 try: 88 from fastapi.testclient import TestClient 89 90 from main import app 91 except Exception as e: 92 pytest.skip(f"Failed to import app (venv generation issue?): {e}") 93 94 client = TestClient(app) 95 96 # Send invalid JSON (missing required fields) 97 response = client.put("/validate/kind-2003", json={"invalid": "data"}) 98 99 # Should return 422 Unprocessable Entity (Pydantic validation error) 100 assert response.status_code == 422 101 102 103 @pytest.mark.integration 104 def test_validate_rejects_wrong_kind(): 105 """Test that validate endpoint rejects events with wrong kind.""" 106 try: 107 from fastapi.testclient import TestClient 108 109 from main import app 110 except Exception as e: 111 pytest.skip(f"Failed to import app (venv generation issue?): {e}") 112 113 client = TestClient(app) 114 event = create_valid_nip35_event() 115 event["kind"] = 1 # Wrong kind (should be 2003) 116 117 response = client.put("/validate/kind-2003", json=event) 118 119 # Should return 422 Unprocessable Entity (kind must be 2003) 120 assert response.status_code == 422 121 122 123 @pytest.mark.integration 124 def test_validate_rejects_missing_required_tags(): 125 """Test that validate endpoint rejects events without required tags.""" 126 try: 127 from fastapi.testclient import TestClient 128 129 from main import app 130 except Exception as e: 131 pytest.skip(f"Failed to import app (venv generation issue?): {e}") 132 133 client = TestClient(app) 134 135 # Event missing title tag (remove it from valid event) 136 event = create_valid_nip35_event() 137 # Remove title tag from tags list 138 event["tags"] = [ 139 tag for tag in event["tags"] if tag[0] != "title" 140 ] 141 142 response = client.put("/validate/kind-2003", json=event) 143 144 # Should return 422 Unprocessable Entity (missing title tag) 145 assert response.status_code == 422 146 # Error message should mention title or missing 147 error_detail = response.json().get("detail", "") 148 assert "title" in str(error_detail).lower() or "missing" in str(error_detail).lower()