"""Tests for POV template engine.""" from dataclasses import dataclass import pytest from mudlib.render.pov import render_pov @dataclass class MockEntity: """Simple entity for testing.""" name: str @pytest.fixture def jared(): """Attacker entity.""" return MockEntity(name="Jared") @pytest.fixture def goku(): """Defender entity.""" return MockEntity(name="Goku") @pytest.fixture def vegeta(): """Bystander entity.""" return MockEntity(name="Vegeta") def test_attacker_pov_basic(jared, goku): """Attacker sees 'You' for self, defender name for target.""" template = "{attacker} hit{s} {defender}" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You hit Goku" def test_defender_pov_basic(jared, goku): """Defender sees attacker name, 'You' for self.""" template = "{attacker} hit{s} {defender}" result = render_pov(template, viewer=goku, attacker=jared, defender=goku) assert result == "Jared hits You" def test_bystander_pov_basic(jared, goku, vegeta): """Bystander sees both entity names.""" template = "{attacker} hits {defender}" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared hits Goku" def test_verb_s_conjugation_you(jared, goku): """Verb with {s} after You gets no suffix.""" template = "{attacker} punch{s} {defender}" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You punch Goku" def test_verb_s_conjugation_third_person(jared, goku, vegeta): """Verb with {s} after name gets 's' suffix.""" template = "{attacker} punch{s} {defender}" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared punches Goku" def test_verb_es_conjugation_you(jared, goku): """Verb with {es} after You gets no suffix.""" template = "{attacker} lurch{es} forward" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You lurch forward" def test_verb_es_conjugation_third_person(jared, goku, vegeta): """Verb with {es} after name gets 'es' suffix.""" template = "{attacker} lurch{es} forward" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared lurches forward" def test_irregular_verb_y_ies_you(jared, goku): """Irregular verb {y|ies} after You uses left form.""" template = "{attacker} parr{y|ies} the blow" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You parry the blow" def test_irregular_verb_y_ies_third_person(jared, goku, vegeta): """Irregular verb {y|ies} after name uses right form.""" template = "{attacker} parr{y|ies} the blow" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared parries the blow" def test_pronoun_his_you(jared, goku): """{his} after You becomes 'your'.""" template = "{attacker} raise{s} {his} fist" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You raise your fist" def test_pronoun_his_third_person(jared, goku, vegeta): """{his} after name becomes 'his'.""" template = "{attacker} raise{s} {his} fist" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared raises his fist" def test_pronoun_him_you(jared, goku): """{him} after You becomes 'you'.""" template = "{attacker} brace{s} {him}self" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You brace yourself" def test_pronoun_him_third_person(jared, goku, vegeta): """{him} after name becomes 'him'.""" template = "{attacker} brace{s} {him}self" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared braces himself" def test_mixed_template_attacker_pov(jared, goku): """Complex template with multiple substitutions, attacker POV.""" template = "{attacker} slam{s} {his} fist into {defender}" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You slam your fist into Goku" def test_mixed_template_defender_pov(jared, goku): """Complex template with multiple substitutions, defender POV.""" template = "{attacker} slam{s} {his} fist into {defender}" result = render_pov(template, viewer=goku, attacker=jared, defender=goku) assert result == "Jared slams his fist into You" def test_mixed_template_bystander_pov(jared, goku, vegeta): """Complex template with multiple substitutions, bystander POV.""" template = "{attacker} slam{s} {his} fist into {defender}" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared slams his fist into Goku" def test_defender_contextual_tags(jared, goku): """Contextual tags apply to defender when they precede them.""" template = "{defender} brace{s} {him}self against {attacker}" result = render_pov(template, viewer=goku, attacker=jared, defender=goku) assert result == "You brace yourself against Jared" def test_defender_contextual_third_person(jared, goku, vegeta): """Contextual tags apply to defender in third person.""" template = "{defender} brace{s} {him}self against {attacker}" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Goku braces himself against Jared" def test_plain_text_passthrough(): """Template with no POV tags passes through unchanged.""" template = "The battle rages on!" result = render_pov(template, viewer=None, attacker=None, defender=None) assert result == "The battle rages on!" def test_you_capitalization_mid_sentence(jared, goku): """'You' is capitalized even when not at start of sentence.""" template = "The blow strikes {defender} hard" result = render_pov(template, viewer=goku, attacker=jared, defender=goku) assert result == "The blow strikes You hard" def test_multiple_entity_references(jared, goku): """Context switches between entities correctly.""" template = "{attacker} throw{s} a punch at {defender}, but {defender} dodge{s} it" result = render_pov(template, viewer=goku, attacker=jared, defender=goku) assert result == "Jared throws a punch at You, but You dodge it" def test_multiple_entity_references_attacker_pov(jared, goku): """Context switches correctly from attacker POV.""" template = "{attacker} throw{s} a punch at {defender}, but {defender} dodg{es} it" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You throw a punch at Goku, but Goku dodges it" def test_you_capitalized_after_comma(jared, goku): """'You' stays capitalized after comma/conjunction.""" template = "{attacker} strikes, and {defender} fall{s}" result = render_pov(template, viewer=goku, attacker=jared, defender=goku) assert result == "Jared strikes, and You fall" def test_s_conjugation_after_ch(jared, goku, vegeta): """{s} after 'ch' should add 'es' for third person.""" template = "{attacker} punch{s} {defender}" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared punches Goku" def test_s_conjugation_after_sh(jared, goku, vegeta): """{s} after 'sh' should add 'es' for third person.""" template = "{attacker} smash{s} into {defender}" result = render_pov(template, viewer=vegeta, attacker=jared, defender=goku) assert result == "Jared smashes into Goku" def test_s_conjugation_you_after_ch(jared, goku): """{s} should not add suffix for 'You' regardless of word ending.""" template = "{attacker} punch{s} {defender}" result = render_pov(template, viewer=jared, attacker=jared, defender=goku) assert result == "You punch Goku" def test_s_conjugation_at_template_start(): """{s} at start of template should not crash when checking prev_text.""" template = "{s}test" result = render_pov(template, viewer=None, attacker=None, defender=None) # Without entity, last_was_you defaults to False, so should add 's' assert result == "stest"