fix: update remaining tests and session_to_tree for title field rename

- test_tree_validation.py: replace "action"/"solution" content fields with "title"
- test_procedural_flows.py: update solution node fixtures to use "title"
- test_save_session_as_tree.py: update fixtures and assertions for "title" field
- session_to_tree.py: generate "title" instead of "action"/"solution" on converted nodes;
  fall back to legacy field names when reading from old tree snapshots for compatibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-22 23:55:37 -05:00
parent 5acf94b6c2
commit 8475f780d1
4 changed files with 47 additions and 47 deletions

View File

@@ -28,7 +28,7 @@ def convert_session_to_tree(
return { return {
"id": str(uuid.uuid4()), "id": str(uuid.uuid4()),
"type": "solution", "type": "solution",
"solution": "Session had no recorded path", "title": "Session had no recorded path",
"children": [] "children": []
} }
@@ -63,7 +63,7 @@ def convert_session_to_tree(
new_node = { new_node = {
"id": node_id, "id": node_id,
"type": "action", "type": "action",
"action": f"Step from original tree (node {node_id})", "title": f"Step from original tree (node {node_id})",
"children": [] "children": []
} }
@@ -130,15 +130,15 @@ def _create_node_from_original(
if decision and decision.get("answer"): if decision and decision.get("answer"):
new_node["question"] += f"\n\nAnswer: {decision['answer']}" new_node["question"] += f"\n\nAnswer: {decision['answer']}"
elif node_type == "action": elif node_type == "action":
new_node["action"] = original_node.get("action", "") new_node["title"] = original_node.get("title", original_node.get("action", ""))
if decision and decision.get("action_performed"): if decision and decision.get("action_performed"):
new_node["action"] = decision["action_performed"] new_node["title"] = decision["action_performed"]
if decision and decision.get("command_output"): if decision and decision.get("command_output"):
output = decision["command_output"].strip() output = decision["command_output"].strip()
if output: if output:
new_node["action"] += f"\n\nCommand Output:\n{output}" new_node["title"] += f"\n\nCommand Output:\n{output}"
elif node_type == "solution": elif node_type == "solution":
new_node["solution"] = original_node.get("solution", "") new_node["title"] = original_node.get("title", original_node.get("solution", ""))
return new_node return new_node
@@ -169,18 +169,18 @@ def _create_node_from_custom_step(
if step_type == "decision": if step_type == "decision":
new_node["question"] = content new_node["question"] = content
elif step_type == "action": elif step_type == "action":
new_node["action"] = content new_node["title"] = content
elif step_type == "solution": elif step_type == "solution":
new_node["solution"] = content new_node["title"] = content
# Add notes if present # Add notes if present
if custom_step.get("notes"): if custom_step.get("notes"):
if step_type == "decision": if step_type == "decision":
new_node["question"] += f"\n\nNotes: {custom_step['notes']}" new_node["question"] += f"\n\nNotes: {custom_step['notes']}"
elif step_type == "action": elif step_type == "action":
new_node["action"] += f"\n\nNotes: {custom_step['notes']}" new_node["title"] += f"\n\nNotes: {custom_step['notes']}"
elif step_type == "solution": elif step_type == "solution":
new_node["solution"] += f"\n\nNotes: {custom_step['notes']}" new_node["title"] += f"\n\nNotes: {custom_step['notes']}"
return new_node return new_node

View File

@@ -228,8 +228,8 @@ class TestCanPublishTreeDispatch:
"type": "decision", "type": "decision",
"question": "Test?", "question": "Test?",
"children": [ "children": [
{"id": "y", "type": "solution", "solution": "Yes"}, {"id": "y", "type": "solution", "title": "Yes"},
{"id": "n", "type": "solution", "solution": "No"}, {"id": "n", "type": "solution", "title": "No"},
] ]
} }
can, errors = can_publish_tree(structure, "My Tree", tree_type="troubleshooting") can, errors = can_publish_tree(structure, "My Tree", tree_type="troubleshooting")

View File

@@ -20,7 +20,7 @@ class TestSessionToTreeConversion:
"""Test converting a session with no path.""" """Test converting a session with no path."""
tree_structure = convert_session_to_tree([], {}, [], []) tree_structure = convert_session_to_tree([], {}, [], [])
assert tree_structure["type"] == "solution" assert tree_structure["type"] == "solution"
assert "no recorded path" in tree_structure["solution"].lower() assert "no recorded path" in tree_structure["title"].lower()
def test_convert_simple_linear_path(self): def test_convert_simple_linear_path(self):
"""Test converting a simple linear path.""" """Test converting a simple linear path."""
@@ -29,8 +29,8 @@ class TestSessionToTreeConversion:
"type": "decision", "type": "decision",
"question": "Is it working?", "question": "Is it working?",
"children": [ "children": [
{"id": "yes", "type": "solution", "solution": "Great!"}, {"id": "yes", "type": "solution", "title": "Great!"},
{"id": "no", "type": "action", "action": "Fix it"} {"id": "no", "type": "action", "title": "Fix it"}
] ]
} }
path_taken = ["root", "no"] path_taken = ["root", "no"]
@@ -51,7 +51,7 @@ class TestSessionToTreeConversion:
tree_snapshot = { tree_snapshot = {
"id": "root", "id": "root",
"type": "solution", "type": "solution",
"solution": "Done" "title": "Done"
} }
custom_step_id = "custom-123" custom_step_id = "custom-123"
path_taken = ["root", custom_step_id] path_taken = ["root", custom_step_id]
@@ -70,7 +70,7 @@ class TestSessionToTreeConversion:
assert len(result["children"]) == 1 assert len(result["children"]) == 1
custom_node = result["children"][0] custom_node = result["children"][0]
assert custom_node["type"] == "action" assert custom_node["type"] == "action"
assert "Custom troubleshooting step" in custom_node["action"] assert "Custom troubleshooting step" in custom_node["title"]
def test_find_node_in_tree(self): def test_find_node_in_tree(self):
"""Test finding a node in nested tree structure.""" """Test finding a node in nested tree structure."""
@@ -142,7 +142,7 @@ class TestSaveSessionAsTreeAPI:
tree = Tree( tree = Tree(
name="Test Tree", name="Test Tree",
description="Test", description="Test",
tree_structure={"id": "root", "type": "solution", "solution": "Fix"}, tree_structure={"id": "root", "type": "solution", "title": "Fix"},
author_id=UUID(test_user["user_data"]["id"]), author_id=UUID(test_user["user_data"]["id"]),
account_id=UUID(test_user["user_data"]["account_id"]), account_id=UUID(test_user["user_data"]["account_id"]),
status='published' status='published'
@@ -187,7 +187,7 @@ class TestSaveSessionAsTreeAPI:
tree = Tree( tree = Tree(
name="Original Tree", name="Original Tree",
tree_structure={"id": "root", "type": "solution", "solution": "Fix"}, tree_structure={"id": "root", "type": "solution", "title": "Fix"},
author_id=UUID(test_user["user_data"]["id"]), author_id=UUID(test_user["user_data"]["id"]),
account_id=UUID(test_user["user_data"]["account_id"]), account_id=UUID(test_user["user_data"]["account_id"]),
status='published' status='published'
@@ -227,7 +227,7 @@ class TestSaveSessionAsTreeAPI:
# Create a simple tree with just a solution (will convert to valid linear tree) # Create a simple tree with just a solution (will convert to valid linear tree)
tree = Tree( tree = Tree(
name="Test Tree", name="Test Tree",
tree_structure={"id": "root", "type": "solution", "solution": "Fixed"}, tree_structure={"id": "root", "type": "solution", "title": "Fixed"},
author_id=UUID(test_user["user_data"]["id"]), author_id=UUID(test_user["user_data"]["id"]),
account_id=UUID(test_user["user_data"]["account_id"]), account_id=UUID(test_user["user_data"]["account_id"]),
status='published' status='published'
@@ -267,7 +267,7 @@ class TestSaveSessionAsTreeAPI:
tree = Tree( tree = Tree(
name="Original Tree", name="Original Tree",
tree_structure={"id": "root", "type": "solution", "solution": "Fix"}, tree_structure={"id": "root", "type": "solution", "title": "Fix"},
author_id=UUID(test_user["user_data"]["id"]), author_id=UUID(test_user["user_data"]["id"]),
account_id=UUID(test_user["user_data"]["account_id"]), account_id=UUID(test_user["user_data"]["account_id"]),
status='published' status='published'
@@ -326,7 +326,7 @@ class TestSaveSessionAsTreeAPI:
# Create a tree # Create a tree
tree = Tree( tree = Tree(
name="Test Tree", name="Test Tree",
tree_structure={"id": "root", "type": "solution", "solution": "Fix"}, tree_structure={"id": "root", "type": "solution", "title": "Fix"},
author_id=UUID(test_user["user_data"]["id"]), author_id=UUID(test_user["user_data"]["id"]),
account_id=UUID(test_user["user_data"]["account_id"]), account_id=UUID(test_user["user_data"]["account_id"]),
status='published' status='published'

View File

@@ -15,7 +15,7 @@ class TestValidateTreeStructure:
def test_valid_solution_tree(self): def test_valid_solution_tree(self):
valid, errors = validate_tree_structure({ valid, errors = validate_tree_structure({
"id": "root", "type": "solution", "solution": "Done" "id": "root", "type": "solution", "title": "Done"
}) })
assert valid assert valid
assert errors == [] assert errors == []
@@ -26,8 +26,8 @@ class TestValidateTreeStructure:
"type": "decision", "type": "decision",
"question": "Is it on?", "question": "Is it on?",
"children": [ "children": [
{"id": "yes", "type": "solution", "solution": "Great"}, {"id": "yes", "type": "solution", "title": "Great"},
{"id": "no", "type": "action", "action": "Turn it on"}, {"id": "no", "type": "action", "title": "Turn it on"},
], ],
}) })
assert valid assert valid
@@ -39,7 +39,7 @@ class TestValidateTreeStructure:
assert any("empty" in e["message"].lower() for e in errors) assert any("empty" in e["message"].lower() for e in errors)
def test_missing_id_on_root(self): def test_missing_id_on_root(self):
valid, errors = validate_tree_structure({"type": "solution", "solution": "X"}) valid, errors = validate_tree_structure({"type": "solution", "title": "X"})
assert not valid assert not valid
assert any("id" in e["field"] for e in errors) assert any("id" in e["field"] for e in errors)
@@ -67,7 +67,7 @@ class TestValidateTreeStructure:
"type": "decision", "type": "decision",
"question": "Q?", "question": "Q?",
"children": [ "children": [
{"id": "only", "type": "solution", "solution": "S"}, {"id": "only", "type": "solution", "title": "S"},
], ],
}) })
assert not valid assert not valid
@@ -80,29 +80,29 @@ class TestValidateTreeStructure:
}) })
assert valid assert valid
def test_action_missing_action_field(self): def test_action_missing_title_field(self):
valid, errors = validate_tree_structure({ valid, errors = validate_tree_structure({
"id": "root", "type": "action" "id": "root", "type": "action"
}) })
assert not valid assert not valid
assert any("action" in e["message"].lower() for e in errors) assert any("title" in e["message"].lower() for e in errors)
def test_action_with_empty_action(self): def test_action_with_empty_title(self):
valid, errors = validate_tree_structure({ valid, errors = validate_tree_structure({
"id": "root", "type": "action", "action": "" "id": "root", "type": "action", "title": ""
}) })
assert not valid assert not valid
def test_solution_missing_solution_field(self): def test_solution_missing_title_field(self):
valid, errors = validate_tree_structure({ valid, errors = validate_tree_structure({
"id": "root", "type": "solution" "id": "root", "type": "solution"
}) })
assert not valid assert not valid
assert any("solution" in e["message"].lower() for e in errors) assert any("title" in e["message"].lower() for e in errors)
def test_solution_with_empty_solution(self): def test_solution_with_empty_title(self):
valid, errors = validate_tree_structure({ valid, errors = validate_tree_structure({
"id": "root", "type": "solution", "solution": "" "id": "root", "type": "solution", "title": ""
}) })
assert not valid assert not valid
@@ -119,8 +119,8 @@ class TestValidateTreeStructure:
"type": "decision", "type": "decision",
"question": "Q?", "question": "Q?",
"children": [ "children": [
{"type": "solution", "solution": "S1"}, {"type": "solution", "title": "S1"},
{"id": "c2", "type": "solution", "solution": "S2"}, {"id": "c2", "type": "solution", "title": "S2"},
], ],
}) })
assert not valid assert not valid
@@ -133,7 +133,7 @@ class TestValidateTreeStructure:
"question": "Q?", "question": "Q?",
"children": [ "children": [
{"id": "c1"}, {"id": "c1"},
{"id": "c2", "type": "solution", "solution": "S2"}, {"id": "c2", "type": "solution", "title": "S2"},
], ],
}) })
assert not valid assert not valid
@@ -151,11 +151,11 @@ class TestValidateTreeStructure:
"type": "decision", "type": "decision",
"question": "Level 2?", "question": "Level 2?",
"children": [ "children": [
{"id": "l3a", "type": "solution", "solution": "Deep"}, {"id": "l3a", "type": "solution", "title": "Deep"},
{"id": "l3b", "type": "solution"}, # Missing solution {"id": "l3b", "type": "solution"}, # Missing title
], ],
}, },
{"id": "l2b", "type": "solution", "solution": "Shallow"}, {"id": "l2b", "type": "solution", "title": "Shallow"},
], ],
}) })
assert not valid assert not valid
@@ -167,8 +167,8 @@ class TestValidateTreeStructure:
"type": "decision", "type": "decision",
"question": "Q?", "question": "Q?",
"children": [ "children": [
{"id": "c1", "type": "solution"}, # missing solution {"id": "c1", "type": "solution"}, # missing title
{"id": "c2", "type": "action"}, # missing action {"id": "c2", "type": "action"}, # missing title
], ],
}) })
assert not valid assert not valid
@@ -179,7 +179,7 @@ class TestCanPublishTree:
def test_valid_tree_can_publish(self): def test_valid_tree_can_publish(self):
can, errors = can_publish_tree( can, errors = can_publish_tree(
{"id": "root", "type": "solution", "solution": "Done"}, {"id": "root", "type": "solution", "title": "Done"},
"My Tree" "My Tree"
) )
assert can assert can
@@ -187,7 +187,7 @@ class TestCanPublishTree:
def test_empty_name_cannot_publish(self): def test_empty_name_cannot_publish(self):
can, errors = can_publish_tree( can, errors = can_publish_tree(
{"id": "root", "type": "solution", "solution": "Done"}, {"id": "root", "type": "solution", "title": "Done"},
"" ""
) )
assert not can assert not can
@@ -195,14 +195,14 @@ class TestCanPublishTree:
def test_whitespace_name_cannot_publish(self): def test_whitespace_name_cannot_publish(self):
can, errors = can_publish_tree( can, errors = can_publish_tree(
{"id": "root", "type": "solution", "solution": "Done"}, {"id": "root", "type": "solution", "title": "Done"},
" " " "
) )
assert not can assert not can
def test_none_name_cannot_publish(self): def test_none_name_cannot_publish(self):
can, errors = can_publish_tree( can, errors = can_publish_tree(
{"id": "root", "type": "solution", "solution": "Done"}, {"id": "root", "type": "solution", "title": "Done"},
None None
) )
assert not can assert not can