"""Tests for HTTP parsers.""" import pytest from http_log_explorer.models import HTTPEntry from http_log_explorer.parsers import get_parser from http_log_explorer.parsers.curl_parser import CurlParser from http_log_explorer.parsers.devtools_parser import DevToolsParser from http_log_explorer.parsers.har_parser import HARParser SAMPLE_HAR = """ { "log": { "version": "1.2", "creator": { "name": "Test", "version": "1.0" }, "entries": [ { "startedDateTime": "2024-01-01T12:00:00Z", "time": 150, "request": { "method": "GET", "url": "https://api.example.com/users/123", "httpVersion": "HTTP/1.1", "headers": [ {"name": "Content-Type", "value": "application/json"}, {"name": "Authorization", "value": "Bearer token123"} ], "queryString": [{"name": "include", "value": "profile"}], "cookies": [] }, "response": { "status": 200, "statusText": "OK", "httpVersion": "HTTP/1.1", "headers": [ {"name": "Content-Type", "value": "application/json"} ], "content": { "mimeType": "application/json", "text": "{\\"id\\": 123, \\"name\\": \\"John\\"}" } }, "serverIPAddress": "192.168.1.1", "connection": "keep-alive" } ] } } """ SAMPLE_CURL = """ > GET /api/users HTTP/1.1 > Host: api.example.com > User-Agent: curl/7.88.1 > Accept: */* > < HTTP/1.1 200 OK < Content-Type: application/json < Content-Length: 45 < {"id": 1, "name": "Test User"} """ SAMPLE_CURL_POST = """ > POST /api/users HTTP/1.1 > Host: api.example.com > Content-Type: application/json > Content-Length: 25 > {"name": "New User"} < HTTP/1.1 201 Created < Content-Type: application/json < Content-Length: 35 < {"id": 2, "name": "New User"} """ SAMPLE_DEVTOOLS = """ { "log": { "version": "1.2", "entries": [ { "startedDateTime": "2024-01-01T12:00:00Z", "time": 100, "request": { "method": "GET", "url": "https://api.example.com/posts", "httpVersion": "HTTP/1.1", "headers": { "Content-Type": "application/json" }, "queryString": [] }, "response": { "status": 200, "statusText": "OK", "httpVersion": "HTTP/1.1", "headers": { "Content-Type": "application/json" }, "content": { "mimeType": "application/json", "text": "[{\\"id\\": 1}]" } }, "serverIPAddress": "10.0.0.1" } ] } } """ class TestHARParser: """Tests for HAR parser.""" def test_can_parse_har(self): """Test HAR detection.""" parser = HARParser() assert parser.can_parse(SAMPLE_HAR) def test_parse_har_entry(self): """Test parsing HAR content.""" parser = HARParser() entries = parser.parse(SAMPLE_HAR) assert len(entries) == 1 entry = entries[0] assert entry.request.method == "GET" assert entry.request.url == "https://api.example.com/users/123" assert entry.response.status == 200 assert entry.request.query_params.get("include") == "profile" def test_parse_invalid_har(self): """Test parsing invalid HAR raises error.""" parser = HARParser() with pytest.raises(ValueError): parser.parse("not valid har content") class TestCurlParser: """Tests for curl parser.""" def test_can_parse_curl(self): """Test curl detection.""" parser = CurlParser() assert parser.can_parse(SAMPLE_CURL) def test_parse_curl_get(self): """Test parsing curl GET output.""" parser = CurlParser() entries = parser.parse(SAMPLE_CURL) assert len(entries) == 1 entry = entries[0] assert entry.request.method == "GET" assert "/api/users" in entry.request.url assert entry.response.status == 200 def test_parse_curl_post(self): """Test parsing curl POST output.""" parser = CurlParser() entries = parser.parse(SAMPLE_CURL_POST) assert len(entries) == 1 entry = entries[0] assert entry.request.method == "POST" assert entry.response.status == 201 def test_cannot_parse_har_as_curl(self): """Test that HAR is not detected as curl.""" parser = CurlParser() assert not parser.can_parse(SAMPLE_HAR) class TestDevToolsParser: """Tests for DevTools parser.""" def test_can_parse_devtools(self): """Test DevTools detection.""" parser = DevToolsParser() assert parser.can_parse(SAMPLE_DEVTOOLS) def test_parse_devtools_entry(self): """Test parsing DevTools content.""" parser = DevToolsParser() entries = parser.parse(SAMPLE_DEVTOOLS) assert len(entries) == 1 entry = entries[0] assert entry.request.method == "GET" assert "posts" in entry.request.url assert entry.response.status == 200 class TestParserFactory: """Tests for parser factory.""" def test_get_parser_har(self): """Test factory returns HARParser for HAR content.""" parser = get_parser(SAMPLE_HAR) assert isinstance(parser, HARParser) def test_get_parser_curl(self): """Test factory returns CurlParser for curl content.""" parser = get_parser(SAMPLE_CURL) assert isinstance(parser, CurlParser) def test_get_parser_devtools(self): """Test factory returns DevToolsParser for DevTools content.""" parser = get_parser(SAMPLE_DEVTOOLS) assert isinstance(parser, DevToolsParser) def test_unsupported_format(self): """Test factory raises error for unsupported format.""" with pytest.raises(ValueError, match="Unsupported format"): get_parser("random garbage content")