import importlib.util import unittest from pathlib import Path spec = importlib.util.spec_from_file_location("site_map", Path(__file__).with_name("2026-10-14-site-map.py")) migration = importlib.util.module_from_spec(spec) spec.loader.exec_module(migration) class SiteMapMigrationTests(unittest.TestCase): def defs(self): return {d["name"]: d for d in migration.definitions("SITES_ID", "MODELS_ID")} def test_three_private_collections(self): defs = self.defs() self.assertEqual(set(defs), {"site_models", "site_progress_events", "site_survey_imports"}) for d in defs.values(): for rule in ("listRule", "viewRule", "createRule", "updateRule", "deleteRule"): self.assertIsNone(d[rule], f"{d['name']}.{rule} must stay private") def test_model_files_are_protected_json(self): files = {f["name"]: f for f in self.defs()["site_models"]["fields"]}["files"] self.assertTrue(files["protected"]) self.assertEqual(files["mimeTypes"], ["application/json"]) self.assertGreaterEqual(files["maxSelect"], 5) def test_events_relate_to_site_and_model_and_are_indexed(self): d = self.defs()["site_progress_events"] fields = {f["name"]: f for f in d["fields"]} self.assertEqual(fields["site"]["collectionId"], "SITES_ID") self.assertEqual(fields["model"]["collectionId"], "MODELS_ID") self.assertEqual(fields["source"]["values"], ["manual", "survey_import", "admin_clear"]) self.assertIn("(site, key, created)", d["indexes"][0]) def test_events_need_the_model_id(self): names = [d["name"] for d in migration.definitions("SITES_ID", None)] self.assertEqual(names, ["site_models"]) # second pass adds the others once site_models exists if __name__ == "__main__": unittest.main() class SurveyFileTypes(unittest.TestCase): def test_survey_file_accepts_tab_separated(self): defs = {d["name"]: d for d in migration.definitions("sites0", "models0")} f = next(x for x in defs["site_survey_imports"]["fields"] if x["name"] == "file") self.assertIn("text/tab-separated-values", f["mimeTypes"])