"""Tests for variable extraction and resolution service.""" import pytest from app.services.variable_service import extract_variables, resolve_variables TREE_WITH_VARIABLES = { "id": "root", "type": "decision", "question": "What is the hostname of [USER_INPUT:hostname]?", "help_text": "Enter the server hostname", "options": [ {"id": "opt1", "label": "Check [VAR:hostname]", "next_node_id": "action1"}, ], "children": [ { "id": "action1", "type": "action", "title": "Ping [VAR:hostname]", "description": "Run diagnostics on [VAR:hostname].\n\n[SAVE_AS:test_results]", "commands": ["ping [VAR:hostname]"], "expected_outcome": "Replies from [VAR:hostname]", "next_node_id": "solution1", "children": [ { "id": "solution1", "type": "solution", "title": "Resolved", "description": "Issue on [VAR:hostname] resolved.", "resolution_steps": [ "Document results for [VAR:hostname]", "Save as [SAVE_AS:final_result]" ], "solution": "Resolved", } ], } ], } TREE_WITHOUT_VARIABLES = { "id": "root", "type": "solution", "title": "Simple Fix", "description": "Just restart it.", "solution": "Restart", } class TestExtractVariables: def test_extracts_user_input(self): variables = extract_variables(TREE_WITH_VARIABLES) user_inputs = [v for v in variables if v.kind == "user_input"] assert len(user_inputs) == 1 assert user_inputs[0].name == "hostname" assert user_inputs[0].node_id == "root" def test_extracts_var_references(self): variables = extract_variables(TREE_WITH_VARIABLES) refs = [v for v in variables if v.kind == "reference"] assert len(refs) >= 4 # hostname used in multiple places def test_extracts_save_as(self): variables = extract_variables(TREE_WITH_VARIABLES) saves = [v for v in variables if v.kind == "save_as"] assert len(saves) == 2 names = {v.name for v in saves} assert "test_results" in names assert "final_result" in names def test_no_variables(self): variables = extract_variables(TREE_WITHOUT_VARIABLES) assert len(variables) == 0 def test_extracts_from_commands(self): variables = extract_variables(TREE_WITH_VARIABLES) cmd_vars = [v for v in variables if v.node_id == "action1" and v.kind == "reference"] # hostname in title, description, commands, expected_outcome assert len(cmd_vars) >= 3 class TestResolveVariables: def test_resolves_var_reference(self): text = "Ping [VAR:hostname] now" result = resolve_variables(text, {"hostname": "server01"}) assert result == "Ping server01 now" def test_resolves_user_input(self): text = "Server: [USER_INPUT:hostname]" result = resolve_variables(text, {"hostname": "server01"}) assert result == "Server: server01" def test_removes_save_as(self): text = "Done [SAVE_AS:result] here" result = resolve_variables(text, {}) assert result == "Done here" def test_unresolved_var_preserved(self): text = "Server: [VAR:unknown_var]" result = resolve_variables(text, {}) assert result == "Server: [VAR:unknown_var]" def test_multiple_variables(self): text = "[VAR:hostname] ([VAR:ip]) - [USER_INPUT:ticket]" result = resolve_variables(text, { "hostname": "server01", "ip": "10.0.0.1", "ticket": "INC001", }) assert result == "server01 (10.0.0.1) - INC001" def test_empty_variables_dict(self): text = "No vars here" result = resolve_variables(text, {}) assert result == "No vars here" def test_empty_text(self): result = resolve_variables("", {"hostname": "server01"}) assert result == ""