#!/usr/bin/env python3 # Copyright (c) 2025 Patrick Motsch # All rights reserved. """ End-to-End Validation Tests for New Architecture Validates that the new architecture works correctly in real scenarios. """ import pytest import sys import os # Add gateway to path sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) from modules.datamodels.datamodelWorkflow import ActionDefinition, AiResponse from modules.datamodels.datamodelDocref import DocumentReferenceList, DocumentListReference from modules.aichat.datamodelFeatureAiChat import ChatWorkflow from modules.shared.jsonUtils import parseJsonWithModel class TestArchitectureValidation: """End-to-end validation of new architecture""" def test_actionDefinition_stage1_to_stage2_flow(self): """Validate Stage 1 → Stage 2 flow""" # Stage 1: Action selection with resources stage1 = ActionDefinition( action="ai.process", actionObjective="Process documents", documentList=DocumentReferenceList(references=[ DocumentListReference(label="input_docs") ]) ) assert stage1.needsStage2() is True # Parameters not set # Stage 2: Add parameters stage1.parameters = {"resultType": "pdf", "aiPrompt": "Generate report"} assert stage1.needsStage2() is False # Parameters now set def test_documentReferenceList_round_trip(self): """Validate DocumentReferenceList string conversion round-trip""" # Create typed references refList = DocumentReferenceList(references=[ DocumentListReference(messageId="msg123", label="task1_results"), DocumentListReference(label="task2_results") ]) # Convert to strings stringList = refList.to_string_list() assert len(stringList) == 2 assert "docList:msg123:task1_results" in stringList assert "docList:task2_results" in stringList # Parse back from strings parsedList = DocumentReferenceList.from_string_list(stringList) assert len(parsedList.references) == 2 assert parsedList.references[0].messageId == "msg123" assert parsedList.references[1].messageId is None def test_parseJsonWithModel_actionDefinition(self): """Validate parseJsonWithModel with ActionDefinition""" jsonStr = ''' { "action": "ai.process", "actionObjective": "Process documents", "documentList": { "references": [ {"messageId": "msg123", "label": "task1_results"} ] } } ''' # Should parse successfully result = parseJsonWithModel(jsonStr, ActionDefinition) assert isinstance(result, ActionDefinition) assert result.action == "ai.process" assert result.actionObjective == "Process documents" def test_workflow_state_management(self): """Validate workflow state management""" workflow = ChatWorkflow( id="test123", name="Test", mandateId="test_mandate" ) # Test state increments workflow.incrementAction() assert workflow.getActionIndex() == 1 workflow.incrementTask() assert workflow.getTaskIndex() == 1 assert workflow.getActionIndex() == 0 # Reset workflow.incrementRound() assert workflow.getRoundIndex() == 1 assert workflow.getTaskIndex() == 0 # Reset assert workflow.getActionIndex() == 0 # Reset def test_aiResponse_structure(self): """Validate AiResponse structure""" response = AiResponse( content='{"result": "success"}', metadata=None, documents=None ) # Test toJson conversion jsonResult = response.toJson() assert isinstance(jsonResult, dict) assert jsonResult["result"] == "success" class TestBackwardCompatibilityRemoved: """Validate that backward compatibility has been removed""" def test_no_string_document_references(self): """Validate that string document references are not supported""" # DocumentReferenceList.from_string_list() should work # But direct string usage should be converted stringList = ["docList:task1_results"] refList = DocumentReferenceList.from_string_list(stringList) assert isinstance(refList, DocumentReferenceList) assert len(refList.references) == 1 def test_no_snake_case_fields(self): """Validate that only camelCase fields are used""" actionDef = ActionDefinition( action="ai.process", actionObjective="Test objective" ) # Should use camelCase assert hasattr(actionDef, "actionObjective") assert not hasattr(actionDef, "action_objective") # snake_case removed if __name__ == "__main__": pytest.main([__file__, "-v"])