import copy import importlib.util from pathlib import Path import unittest spec = importlib.util.spec_from_file_location("office_access", Path(__file__).with_name("2026-10-07-office-access.py")) migration = importlib.util.module_from_spec(spec) spec.loader.exec_module(migration) class OfficeAccessMigrationTests(unittest.TestCase): def collection(self): return {"type": "auth", "fields": [ {"id": "role-id", "name": "role", "type": "select", "maxSelect": 1, "values": ["admin", "site_user", "clock_only"]}, {"id": "sites-id", "name": "sites", "type": "relation", "collectionId": "sites", "maxSelect": 99}, ]} def test_adds_office_role_and_fields_without_changing_existing_fields(self): original = self.collection() snapshot = copy.deepcopy(original) fields = migration.prepare_fields(original) by_name = {field["name"]: field for field in fields} self.assertEqual(by_name["role"]["values"], ["admin", "site_user", "clock_only", "office_user"]) self.assertEqual(by_name["role"]["id"], "role-id") self.assertEqual(by_name["sites"], snapshot["fields"][1]) self.assertEqual(by_name["modules"]["values"], ["overview", "sites", "workforce", "plant", "financial"]) self.assertEqual(by_name["modules"]["maxSelect"], 5) self.assertEqual(by_name["all_sites"]["type"], "bool") self.assertEqual(original, snapshot) def test_second_run_leaves_schema_unchanged(self): collection = self.collection() collection["fields"] = migration.prepare_fields(collection) self.assertEqual(migration.prepare_fields(collection), collection["fields"]) def test_rejects_incompatible_existing_module_field(self): collection = self.collection() collection["fields"].append({"name": "modules", "type": "text"}) with self.assertRaises(RuntimeError): migration.prepare_fields(collection) def test_requires_an_auth_collection_and_existing_role(self): with self.assertRaises(RuntimeError): migration.prepare_fields({"type": "base", "fields": []}) if __name__ == "__main__": unittest.main()