Prompt_Squirrel_RAG / scripts /smoke_ui_state.py
Food Desert
Fix UI tag-button desync and add regression smoke coverage
827e786
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import app
def _assert(cond: bool, msg: str) -> None:
if not cond:
raise AssertionError(msg)
def test_prompt_uses_visible_rows_only() -> None:
# If selected state contains stale hidden tags, prompt should still reflect visible-row selections only.
row_defs = [
{"name": "r1", "label": "R1", "tags": ["solo", "female"], "tag_meta": {}},
{"name": "r2", "label": "R2", "tags": ["cub"], "tag_meta": {}},
]
payload = app._build_ui_payload(
console_text="x",
row_defs=row_defs,
selected_tags=["solo", "rosalina_(mario)"],
)
prompt_text = payload[2]
selected_state = payload[3]
_assert("rosalina \\(mario\\)" not in prompt_text, "stale hidden tag leaked into prompt")
_assert("solo" in prompt_text, "visible selected tag missing from prompt")
_assert("rosalina_(mario)" not in selected_state, "stale hidden tag leaked into selected state")
def test_row_deduping() -> None:
row_defs = [
{
"name": "other_retrieved",
"label": "Other (Retrieved)",
"tags": ["cub", "expressions", "invalid_tag", "cub", "expressions"],
"tag_meta": {},
}
]
prompt_text, row_values_state, _, checkbox_updates = app._build_row_component_updates(
row_defs=row_defs,
selected_tags=["cub", "expressions"],
max_rows=app.display_max_rows_default,
)
_assert(prompt_text == "cub, expressions", "prompt should be deduped and ordered from row")
_assert(row_values_state[0] == ["cub", "expressions"], "row selected values should be deduped")
first_choices = checkbox_updates[0]["choices"]
first_values = [v for _, v in first_choices]
_assert(first_values == ["cub", "expressions", "invalid_tag"], "row choices should be deduped")
def test_rebuild_ignores_stale_selected_state() -> None:
row_defs = [
{"name": "selected_other", "label": "Selected (Other)", "tags": ["solo", "female", "anthro"], "tag_meta": {}},
{"name": "other_retrieved", "label": "Other (Retrieved)", "tags": ["cub", "expressions"], "tag_meta": {}},
]
# Simulate UI state where user has deselected anthro, but stale selected state still contains it.
selected_state = ["solo", "female", "anthro", "cub"]
row_values_state = [["solo", "female"], ["cub"]]
out = app._rebuild_rows_from_selected(
selected_state,
row_defs,
row_values_state,
app.display_top_groups_default,
app.display_top_tags_per_group_default,
app.display_rank_top_k_default,
)
prompt = out[1]
selected_after = out[2]
_assert("anthro" not in selected_after, "rebuild should not resurrect stale deselected tags")
_assert("anthro" not in prompt, "prompt should not include stale deselected tags")
_assert("solo" in prompt and "female" in prompt and "cub" in prompt, "rebuild should retain current row selections")
def test_toggle_then_rebuild_does_not_resurrect_removed_tag() -> None:
row_defs = [
{"name": "selected_other", "label": "Selected (Other)", "tags": ["solo", "anthro", "female"], "tag_meta": {}},
{"name": "other_retrieved", "label": "Other (Retrieved)", "tags": ["cub", "expressions"], "tag_meta": {}},
]
selected_state = ["solo", "anthro", "female", "cub"]
row_values_state = [["solo", "anthro", "female"], ["cub"]]
# User unchecks anthro in row 0.
toggle_out = app._on_toggle_row(
0,
["solo", "female"],
selected_state,
False,
row_defs,
row_values_state,
app.display_max_rows_default,
)
selected_after_toggle = toggle_out[0]
row_values_after_toggle = toggle_out[3]
_assert("anthro" not in selected_after_toggle, "toggle should remove anthro from selected state")
# Rebuild from current row values must preserve the user-toggle result.
rebuild_out = app._rebuild_rows_from_selected(
selected_after_toggle,
row_defs,
row_values_after_toggle,
app.display_top_groups_default,
app.display_top_tags_per_group_default,
app.display_rank_top_k_default,
)
prompt_after_rebuild = rebuild_out[1]
selected_after_rebuild = rebuild_out[2]
_assert("anthro" not in selected_after_rebuild, "rebuild should not resurrect deselected anthro")
_assert("anthro" not in prompt_after_rebuild, "prompt should not contain deselected anthro after rebuild")
_assert("solo" in prompt_after_rebuild and "female" in prompt_after_rebuild, "kept selections should remain")
_assert("cub" in prompt_after_rebuild, "other retrieved selection should remain")
def test_toggle_does_not_cross_activate_unrelated_row_tag() -> None:
row_defs = [
{"name": "organization", "label": "Organization", "tags": ["pinup", "close-up"], "tag_meta": {}},
{"name": "color_markings", "label": "Color Markings", "tags": ["shoulder_markings", "black_markings"], "tag_meta": {}},
]
selected_state = []
row_values_state = [[], []]
# User enables close-up in organization row.
out = app._on_toggle_row(
0,
["close-up"],
selected_state,
False,
row_defs,
row_values_state,
app.display_max_rows_default,
)
selected_after = out[0]
row_values_after = out[3]
_assert("close-up" in selected_after, "close-up should be selected")
_assert("shoulder_markings" not in selected_after, "unrelated row tag should not be auto-selected")
_assert(row_values_after[0] == ["close-up"], "organization row values should include close-up only")
_assert(row_values_after[1] == [], "color markings row should remain unselected")
def test_shared_tag_mirrors_without_unrelated_cross_toggle() -> None:
row_defs = [
{"name": "objects_props", "label": "Objects Props", "tags": ["holding_face", "holding_clothing"], "tag_meta": {}},
{"name": "expression_detail", "label": "Expression Detail", "tags": ["open_mouth", "closed_smile"], "tag_meta": {}},
{"name": "pose_action_detail", "label": "Pose Action Detail", "tags": ["holding_face", "walking"], "tag_meta": {}},
]
selected_state = []
row_values_state = [[], [], []]
# Enable open_mouth; should not affect holding_face rows.
out1 = app._on_toggle_row(
1,
["open_mouth"],
selected_state,
False,
row_defs,
row_values_state,
app.display_max_rows_default,
)
sel1 = out1[0]
vals1 = out1[3]
_assert("open_mouth" in sel1, "open_mouth should be selected")
_assert("holding_face" not in sel1, "holding_face must remain unselected")
_assert(vals1[0] == [], "objects props row should remain unselected")
_assert(vals1[1] == ["open_mouth"], "expression row should select open_mouth")
_assert(vals1[2] == [], "pose row should remain unselected")
# Enable holding_face in objects row; should mirror only to pose row, not expression row.
out2 = app._on_toggle_row(
0,
["holding_face"],
sel1,
True,
row_defs,
vals1,
app.display_max_rows_default,
)
sel2 = out2[0]
vals2 = out2[3]
_assert("holding_face" in sel2 and "open_mouth" in sel2, "both explicitly selected tags should be present")
_assert(vals2[0] == ["holding_face"], "objects row should select holding_face")
_assert(vals2[1] == ["open_mouth"], "expression row should keep open_mouth only")
_assert(vals2[2] == ["holding_face"], "pose row should mirror holding_face")
def main() -> None:
test_prompt_uses_visible_rows_only()
test_row_deduping()
test_rebuild_ignores_stale_selected_state()
test_toggle_then_rebuild_does_not_resurrect_removed_tag()
test_toggle_does_not_cross_activate_unrelated_row_tag()
test_shared_tag_mirrors_without_unrelated_cross_toggle()
print("ui state smoke: ok")
if __name__ == "__main__":
main()