mtg_python_deckbuilder/code/tests/test_multi_face_merge.py
matt 88cf832bf2 Finalize MDFC follow-ups, docs, and diagnostics tooling
document deck summary DFC badges, exporter annotations, and per-face metadata across README/DOCKER/release notes

record completion of all MDFC roadmap follow-ups and add the authoring guide for multi-face CSV entries

wire in optional DFC_PER_FACE_SNAPSHOT env support, exporter regression tests, and diagnostics updates noted in the changelog
2025-10-02 15:31:05 -07:00

192 lines
No EOL
6.9 KiB
Python

from __future__ import annotations
import pandas as pd
from code.tagging.multi_face_merger import merge_multi_face_rows
def _build_dataframe() -> pd.DataFrame:
return pd.DataFrame(
[
{
"name": "Eddie Brock // Venom, Lethal Protector",
"faceName": "Eddie Brock",
"edhrecRank": 12345.0,
"colorIdentity": "B",
"colors": "B",
"manaCost": "{3}{B}{B}",
"manaValue": 5.0,
"type": "Legendary Creature — Human",
"creatureTypes": ["Human"],
"text": "When Eddie Brock enters...",
"power": 3,
"toughness": 4,
"keywords": "Transform",
"themeTags": ["Aggro", "Control"],
"layout": "transform",
"side": "a",
"roleTags": ["Value Engine"],
},
{
"name": "Eddie Brock // Venom, Lethal Protector",
"faceName": "Venom, Lethal Protector",
"edhrecRank": 12345.0,
"colorIdentity": "B",
"colors": "B",
"manaCost": "",
"manaValue": 5.0,
"type": "Legendary Creature — Symbiote",
"creatureTypes": ["Symbiote"],
"text": "Whenever Venom attacks...",
"power": 5,
"toughness": 5,
"keywords": "Menace, Transform",
"themeTags": ["Menace", "Legends Matter"],
"layout": "transform",
"side": "b",
"roleTags": ["Finisher"],
},
{
"name": "Bonecrusher Giant // Stomp",
"faceName": "Bonecrusher Giant",
"edhrecRank": 6789.0,
"colorIdentity": "R",
"colors": "R",
"manaCost": "{2}{R}",
"manaValue": 3.0,
"type": "Creature — Giant",
"creatureTypes": ["Giant"],
"text": "Whenever this creature becomes the target...",
"power": 4,
"toughness": 3,
"keywords": "",
"themeTags": ["Aggro"],
"layout": "adventure",
"side": "a",
"roleTags": [],
},
{
"name": "Bonecrusher Giant // Stomp",
"faceName": "Stomp",
"edhrecRank": 6789.0,
"colorIdentity": "R",
"colors": "R",
"manaCost": "{1}{R}",
"manaValue": 2.0,
"type": "Instant — Adventure",
"creatureTypes": [],
"text": "Stomp deals 2 damage to any target.",
"power": None,
"toughness": None,
"keywords": "Instant",
"themeTags": ["Removal"],
"layout": "adventure",
"side": "b",
"roleTags": [],
},
{
"name": "Expansion // Explosion",
"faceName": "Expansion",
"edhrecRank": 4321.0,
"colorIdentity": "U, R",
"colors": "U, R",
"manaCost": "{U/R}{U/R}",
"manaValue": 2.0,
"type": "Instant",
"creatureTypes": [],
"text": "Copy target instant or sorcery spell...",
"power": None,
"toughness": None,
"keywords": "",
"themeTags": ["Spell Copy"],
"layout": "split",
"side": "a",
"roleTags": ["Copy Enabler"],
},
{
"name": "Expansion // Explosion",
"faceName": "Explosion",
"edhrecRank": 4321.0,
"colorIdentity": "U, R",
"colors": "U, R",
"manaCost": "{X}{X}{U}{R}",
"manaValue": 4.0,
"type": "Instant",
"creatureTypes": [],
"text": "Explosion deals X damage to any target...",
"power": None,
"toughness": None,
"keywords": "",
"themeTags": ["Burn", "Card Draw"],
"layout": "split",
"side": "b",
"roleTags": ["Finisher"],
},
{
"name": "Persistent Petitioners",
"faceName": "Persistent Petitioners",
"edhrecRank": 5555.0,
"colorIdentity": "U",
"colors": "U",
"manaCost": "{1}{U}",
"manaValue": 2.0,
"type": "Creature — Human Advisor",
"creatureTypes": ["Human", "Advisor"],
"text": "{1}{U}, Tap four untapped Advisors you control: Mill 12.",
"power": 1,
"toughness": 3,
"keywords": "",
"themeTags": ["Mill"],
"layout": "normal",
"side": "",
"roleTags": ["Mill Enabler"],
},
]
)
def test_merge_multi_face_rows_combines_themes_and_keywords():
df = _build_dataframe()
merged = merge_multi_face_rows(df, "grixis", logger=None)
# Eddie Brock merge assertions
eddie = merged[merged["name"] == "Eddie Brock // Venom, Lethal Protector"].iloc[0]
assert set(eddie["themeTags"]) == {
"Aggro",
"Control",
"Legends Matter",
"Menace",
}
assert set(eddie["creatureTypes"]) == {"Human", "Symbiote"}
assert eddie["keywords"] == "Menace, Transform"
assert (merged["faceName"] == "Venom, Lethal Protector").sum() == 0
# Bonecrusher Giant adventure merge assertions
bonecrusher = merged[merged["name"] == "Bonecrusher Giant // Stomp"].iloc[0]
assert set(bonecrusher["themeTags"]) == {"Aggro", "Removal"}
assert set(bonecrusher["creatureTypes"]) == {"Giant"}
assert bonecrusher["keywords"] == "Instant"
assert (merged["faceName"] == "Stomp").sum() == 0
# Split card merge assertions
explosion = merged[merged["name"] == "Expansion // Explosion"].iloc[0]
assert set(explosion["themeTags"]) == {"Spell Copy", "Burn", "Card Draw"}
assert set(explosion["roleTags"]) == {"Copy Enabler", "Finisher"}
assert (merged["faceName"] == "Explosion").sum() == 0
# Persistent Petitioners should remain untouched
petitioners = merged[merged["name"] == "Persistent Petitioners"].iloc[0]
assert petitioners["themeTags"] == ["Mill"]
assert petitioners["roleTags"] == ["Mill Enabler"]
assert "faceDetails" not in merged.columns
assert len(merged) == 4
def test_merge_multi_face_rows_is_idempotent():
df = _build_dataframe()
once = merge_multi_face_rows(df, "izzet", logger=None)
twice = merge_multi_face_rows(once, "izzet", logger=None)
pd.testing.assert_frame_equal(once, twice)