109 lines
4.3 KiB
Python
109 lines
4.3 KiB
Python
"""End-to-end tests for the dependency-free EQL spell CLI."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
CLI = ROOT / "scripts" / "eql-spells"
|
|
FIXTURE = ROOT / "tests" / "fixtures" / "eql-spells"
|
|
|
|
|
|
class EqlSpellsCliTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.temporary = tempfile.TemporaryDirectory()
|
|
self.work = Path(self.temporary.name)
|
|
self.game = self.work / "game"
|
|
shutil.copytree(FIXTURE, self.game)
|
|
self.db = self.work / "cache" / "spells.sqlite"
|
|
|
|
def tearDown(self) -> None:
|
|
self.temporary.cleanup()
|
|
|
|
def run_cli(self, *arguments: str) -> subprocess.CompletedProcess[str]:
|
|
return subprocess.run(
|
|
[sys.executable, str(CLI), "--game-path", str(self.game), "--db", str(self.db), *arguments],
|
|
cwd=ROOT,
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
|
|
def json_stdout(self, *arguments: str) -> dict:
|
|
result = self.run_cli(*arguments)
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
return json.loads(result.stdout)
|
|
|
|
def test_build_and_exact_lookup_by_id_and_name(self) -> None:
|
|
built = self.json_stdout("build")
|
|
self.assertEqual(built["built"], {"descriptions": 3, "messages": 3, "spells": 3})
|
|
self.assertTrue(self.db.is_file())
|
|
|
|
by_id = self.json_stdout("get", "1")
|
|
self.assertEqual(by_id["spell"]["name"], "Fire Bolt")
|
|
self.assertEqual(by_id["spell"]["description"], "Launches a bolt of fire at your target.")
|
|
self.assertEqual(by_id["spell"]["messages"]["caster_me"], "You cast Fire Bolt.")
|
|
self.assertIn("fingerprint", by_id["source"])
|
|
|
|
by_name = self.json_stdout("get", "water breathing")
|
|
self.assertEqual(by_name["spell"]["id"], 2)
|
|
|
|
def test_find_search_and_raw_output(self) -> None:
|
|
found = self.json_stdout("find", "fire")
|
|
self.assertEqual([spell["name"] for spell in found["results"]], ["Fire Bolt", "Fireball"])
|
|
|
|
searched = self.json_stdout("search", "breathing underwater")
|
|
self.assertEqual([spell["id"] for spell in searched["results"]], [2])
|
|
|
|
raw = self.json_stdout("get", "1", "--raw")
|
|
self.assertEqual(raw["spell"]["raw"]["line"], "1^Fire Bolt^0^alpha")
|
|
self.assertEqual(raw["spell"]["raw"]["fields"], ["1", "Fire Bolt", "0", "alpha"])
|
|
|
|
def test_query_automatically_rebuilds_after_source_change(self) -> None:
|
|
self.json_stdout("build")
|
|
descriptions = self.game / "dbstr_us.txt"
|
|
with descriptions.open("a", encoding="utf-8") as handle:
|
|
handle.write("2^6^Lets your target breathe underwater indefinitely.^0^\n")
|
|
|
|
result = self.run_cli("search", "indefinitely")
|
|
self.assertEqual(result.returncode, 1)
|
|
self.assertIn("Duplicate spell description", json.loads(result.stderr)["error"]["message"])
|
|
|
|
# Replace the existing description rather than adding a duplicate.
|
|
descriptions.write_text(
|
|
"1^6^Launches a bolt of fire at your target.^0^\n"
|
|
"2^6^Lets your target breathe underwater indefinitely.^0^\n"
|
|
"3^6^Launches a ball of fire at your target.^0^\n"
|
|
"1^5^Fire^0^\n",
|
|
encoding="utf-8",
|
|
)
|
|
rebuilt = self.json_stdout("search", "indefinitely")
|
|
self.assertTrue(rebuilt["index_rebuilt"])
|
|
self.assertEqual(rebuilt["results"][0]["id"], 2)
|
|
|
|
def test_malformed_data_and_invalid_query_return_structured_errors(self) -> None:
|
|
(self.game / "spells_us.txt").write_text("bad row\n", encoding="utf-8")
|
|
malformed = self.run_cli("build")
|
|
self.assertEqual(malformed.returncode, 1)
|
|
self.assertEqual(json.loads(malformed.stderr)["error"]["code"], "data")
|
|
|
|
shutil.copy2(FIXTURE / "spells_us.txt", self.game / "spells_us.txt")
|
|
invalid_limit = self.run_cli("find", "fire", "--limit", "101")
|
|
self.assertEqual(invalid_limit.returncode, 2)
|
|
self.assertEqual(json.loads(invalid_limit.stderr)["error"]["code"], "usage")
|
|
|
|
missing = self.run_cli("get", "999")
|
|
self.assertEqual(missing.returncode, 1)
|
|
self.assertEqual(json.loads(missing.stderr)["error"]["code"], "data")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|