import asyncio from services.rpg_plot import ( prune_beats_for_done_quests, process_arc_beats, should_advance_arc_keywords, pop_matching_beats, dice_outcome_to_beat_trigger, ) def test_prune_removes_beat_when_quest_done(): arc = { "beats": [ {"id": "b2", "title": "Highway Howl", "trigger": "event_driven:travel", "choices": []}, ] } quests = [{"title": "Highway Howl", "status": "done"}] arc, removed = prune_beats_for_done_quests(arc, quests) assert removed[0]["title"] == "Highway Howl" assert arc["beats"] == [] def test_stuck_recovery_fires_when_no_active_quests(): arc = { "beats": [ {"id": "b3", "title": "New Beat", "trigger": "event_driven:rest", "choices": [{"id": "a", "label": "A"}]}, ] } quests = [{"title": "Old", "status": "done"}] async def run(): return await process_arc_beats(arc, quests, "hello") arc2, fired, pruned, mode = asyncio.run(run()) assert mode == "stuck_recovery" assert fired[0]["title"] == "New Beat" assert arc2["beats"] == [] def test_dice_outcome_maps_to_after_fail(): assert dice_outcome_to_beat_trigger("failure") == "event_driven:after_fail" assert dice_outcome_to_beat_trigger("critical failure") == "event_driven:after_fail" assert dice_outcome_to_beat_trigger("success") == "event_driven:after_success" def test_after_fail_beat_fires_on_dice_failure(): arc = { "beats": [ { "id": "b_fail", "title": "Dust Yourself Off", "trigger": "event_driven:after_fail", "injection": "The stumble leaves you both shaken.", "choices": [{"id": "a", "label": "Try again"}], }, { "id": "b_ok", "title": "Victory Lap", "trigger": "event_driven:after_success", "choices": [], }, ] } async def run(): return await process_arc_beats( arc, [], "продолжаем разговор", last_dice_outcome="failure" ) arc2, fired, _, mode = asyncio.run(run()) assert mode == "after_dice" assert fired[0]["id"] == "b_fail" assert len(arc2["beats"]) == 1 assert arc2["beats"][0]["id"] == "b_ok" def test_keyword_fallback_travel(): arc = { "beats": [ {"id": "b2", "title": "Highway Howl", "trigger": "event_driven:travel", "choices": []}, ] } trig = should_advance_arc_keywords("едем на стадион") assert trig == "event_driven:travel" arc, fired = pop_matching_beats(arc, trig, max_beats=1) assert fired[0]["title"] == "Highway Howl"