import json from pathlib import Path import tempfile import unittest from unittest.mock import patch import hint_library as lib class HintLibraryTests(unittest.TestCase): def setUp(self): self.temp=tempfile.TemporaryDirectory() self.path=Path(self.temp.name)/"hints.json" self.patch=patch.object(lib,"PATH",self.path); self.patch.start() def tearDown(self): self.patch.stop(); self.temp.cleanup() def hint(self): return {"title":"Find the records","text":"Look at the sleeve — then the record.","categories":["Records","Discovery"], "phase":"ARCADE","target":"P03","condition":"incomplete","level":1} def test_persists_and_updates_with_stable_id(self): data=lib.save({"revision":0,"hint":self.hint()}) self.assertEqual(lib.read(),data) added=data["hints"][-1] added["text"]="A clearer hint" updated=lib.save({"revision":1,"hint":added}) self.assertEqual(len(data["hints"]),len(updated["hints"])) self.assertEqual(lib.read()["hints"][-1]["text"],"A clearer hint") self.assertTrue(self.path.with_suffix(".bak").exists()) def test_conflict_preserves_other_device_edits(self): lib.save({"revision":0,"hint":self.hint()}) before=self.path.read_bytes() with self.assertRaises(lib.Conflict): lib.save({"revision":0,"hint":self.hint()}) self.assertEqual(self.path.read_bytes(),before) def test_bad_input_and_corrupt_file_are_not_overwritten(self): hint=self.hint(); hint["text"]="x"*1501 with self.assertRaises(ValueError): lib.save({"revision":0,"hint":hint}) self.path.write_text("broken",encoding="utf-8") with self.assertRaises(ValueError): lib.save({"revision":0,"hint":self.hint()}) self.assertEqual(self.path.read_text(),"broken") if __name__=="__main__": unittest.main()