# TDD Plan: godotiq_trace_flow

Companion to `claude-plan.md`. Defines tests to write BEFORE implementing each component.

**Testing setup**: pytest + pytest-asyncio, `asyncio_mode = "auto"`. Session fixture loads from fixture project. Tests import internal helpers directly.

---

## 1. Fixtures (tests/fixtures/trace_flow/)

Before any test code, create the minimal fixture project:

# Test: fixture project.godot declares Events and PrinterManager autoloads
# Test: fixture events.gd defines order_accepted and printer_reserved signals
# Test: fixture order_manager.gd has accept_order() that emits order_accepted
# Test: fixture pipeline_controller.gd connects Events.order_accepted and calls PrinterManager.reserve_printer()
# Test: fixture printer_manager.gd has reserve_printer() with early return and emission

Also add edge-case fixtures:
# Fixture: a .gd file with a lambda connection (e.g. `signal.connect(func(): pass)`)
# Fixture: a .gd file with a `has_node`/`get_node` autoload ref
# Fixture: a .gd file with autoload property access (no parentheses)

Session fixture goes in `tests/test_tools/conftest.py`:
# Fixture: trace_flow_session -> GodotIQSession loaded from tests/fixtures/trace_flow/

---

## 2. Signal Listener Map (_build_signal_listeners)

# Test: builds listener map from connections — Events.order_accepted connects in pipeline_controller.gd
# Test: extracts signal name from qualified signal_source (e.g. "Events.order_accepted" -> "order_accepted")
# Test: extracts signal name from self reference (e.g. "self.my_signal" -> "my_signal")
# Test: skips lambda targets — target starting with "func" is excluded from map
# Test: skips qualified targets — target containing "." is excluded from map
# Test: multiple listeners for same signal all appear in map

---

## 3. Trigger Finding (_find_trigger)

# Test: finds trigger by exact function name — "accept_order" returns (order_manager.gd, "accept_order")
# Test: finds trigger by signal name — "order_accepted" finds the emitting function
# Test: returns empty list for unknown trigger
# Test: returns multiple entries when trigger name exists in multiple files
# Test: _find_containing_function returns correct function for a line within its range
# Test: _find_containing_function returns None for line outside any function

---

## 4. Recursive Tracing (_trace_from_function)

# Test: single step — function with no emissions/calls produces 1 FlowStep
# Test: signal chain — accept_order emits order_accepted, pipeline_controller listens, calls PrinterManager
# Test: autoload call — traces from pipeline_controller into printer_manager.gd reserve_printer
# Test: depth limit — depth=1 stops after first step, does not recurse
# Test: cycle detection — (file, func) already in visited returns empty, no infinite loop
# Test: script not found — unknown file path returns empty
# Test: function not found — unknown function name in known script returns empty
# Test: non-direct autoload ref skipped — has_node/get_node refs do not produce flow steps
# Test: property access not traced — autoload ref without "(" on source line is skipped
# Test: shared visited set — multiple entry points converging on same function don't duplicate steps

---

## 5. Failure Point Detection (_detect_failure_points)

# Test: detects "if not X: return" pattern
# Test: detects "if X == null: return" pattern
# Test: detects "if X.is_empty(): return" pattern
# Test: detects "if not is_instance_valid(X): return" pattern
# Test: function with no failure patterns returns empty list
# Test: uses cached file lines (does not re-read file)

---

## 6. Top-Level Function (_build_trace_flow)

# Test: empty trigger returns error dict
# Test: unknown trigger returns flow=[], error="Trigger not found"
# Test: full chain — accept_order traces through to printer_manager with correct step count
# Test: files_involved count matches unique files in flow
# Test: detail="brief" strips failure_points and extra step fields
# Test: detail="normal" includes all fields
# Test: detail="full" same as normal

---

## 7. Tool Registration

# Test: godotiq_trace_flow appears in mcp registered tools (import from godotiq.server)
# Test: import check — from godotiq.tools.flow import _build_trace_flow succeeds
