#!/usr/bin/env python3 """ Unit tests for JSON utilities in jsonUtils.py Tests parseJsonWithModel, extractJsonString, tryParseJson, repairBrokenJson. """ import pytest import json from modules.shared.jsonUtils import ( parseJsonWithModel, extractJsonString, tryParseJson, repairBrokenJson ) from modules.datamodels.datamodelWorkflow import ActionDefinition, AiResponse class TestExtractJsonString: """Test extractJsonString function""" def test_extractJsonString_plain_json(self): """Test extracting plain JSON""" text = '{"key": "value"}' result = extractJsonString(text) assert result == '{"key": "value"}' def test_extractJsonString_with_code_fences(self): """Test extracting JSON from code fences""" text = '```json\n{"key": "value"}\n```' result = extractJsonString(text) assert result == '{"key": "value"}' def test_extractJsonString_with_extra_text(self): """Test extracting JSON with extra text""" text = 'Some text before {"key": "value"} some text after' result = extractJsonString(text) assert result == '{"key": "value"}' class TestTryParseJson: """Test tryParseJson function""" def test_tryParseJson_valid_json(self): """Test parsing valid JSON""" obj, error, cleaned = tryParseJson('{"key": "value"}') assert error is None assert isinstance(obj, dict) assert obj["key"] == "value" def test_tryParseJson_invalid_json(self): """Test parsing invalid JSON""" obj, error, cleaned = tryParseJson('{"key": "value"') assert error is not None assert obj is None def test_tryParseJson_with_code_fences(self): """Test parsing JSON with code fences""" obj, error, cleaned = tryParseJson('```json\n{"key": "value"}\n```') assert error is None assert isinstance(obj, dict) assert obj["key"] == "value" class TestParseJsonWithModel: """Test parseJsonWithModel function""" def test_parseJsonWithModel_valid_json(self): """Test parsing valid JSON into Pydantic model""" jsonStr = '{"action": "ai.process", "actionObjective": "Process documents"}' result = parseJsonWithModel(jsonStr, ActionDefinition) assert isinstance(result, ActionDefinition) assert result.action == "ai.process" assert result.actionObjective == "Process documents" def test_parseJsonWithModel_with_code_fences(self): """Test parsing JSON with code fences""" jsonStr = '```json\n{"action": "ai.process", "actionObjective": "Process"}\n```' result = parseJsonWithModel(jsonStr, ActionDefinition) assert isinstance(result, ActionDefinition) assert result.action == "ai.process" def test_parseJsonWithModel_invalid_json_raises(self): """Test that invalid JSON raises ValueError""" jsonStr = '{"action": "ai.process"' with pytest.raises(ValueError): parseJsonWithModel(jsonStr, ActionDefinition) def test_parseJsonWithModel_empty_string_raises(self): """Test that empty string raises ValueError""" with pytest.raises(ValueError): parseJsonWithModel("", ActionDefinition) def test_parseJsonWithModel_list_wraps_first_item(self): """Test that list JSON wraps first item""" jsonStr = '[{"action": "ai.process", "actionObjective": "Process"}]' result = parseJsonWithModel(jsonStr, ActionDefinition) assert isinstance(result, ActionDefinition) assert result.action == "ai.process" def test_parseJsonWithModel_aiResponse(self): """Test parsing AiResponse model""" jsonStr = '{"content": "Test content", "metadata": {"title": "Test"}}' result = parseJsonWithModel(jsonStr, AiResponse) assert isinstance(result, AiResponse) assert result.content == "Test content" assert result.metadata is not None assert result.metadata.title == "Test" class TestRepairBrokenJson: """Test repairBrokenJson function""" def test_repairBrokenJson_incomplete_json(self): """Test repairing incomplete JSON""" brokenJson = '{"key": "value"' repaired = repairBrokenJson(brokenJson) # Should attempt to repair or return None assert repaired is None or isinstance(repaired, dict) def test_repairBrokenJson_missing_closing_brace(self): """Test repairing JSON with missing closing brace""" brokenJson = '{"documents": [{"sections": [{"id": "section_1"}]}' repaired = repairBrokenJson(brokenJson) # Should attempt to repair assert repaired is None or isinstance(repaired, dict) if __name__ == "__main__": pytest.main([__file__, "-v"])