import json import re import unittest from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] CRM_FRONTEND = REPO_ROOT / "salesforce-crm-standard" / "frontend" UI_POLICY = CRM_FRONTEND / "src" / "ui-field-surface-policy.ts" METADATA_POLICY = CRM_FRONTEND / "src" / "metadata-field-type-policy.ts" def read_text(path: Path) -> str: return path.read_text(encoding="utf-8") def load_json(path: Path): with path.open(encoding="utf-8") as handle: return json.load(handle) def ts_string_array(source: str, name: str) -> list[str]: match = re.search( rf"export const {re.escape(name)} = \[(.*?)\] as const", source, flags=re.DOTALL, ) if not match: raise AssertionError(f"missing array export {name}") return re.findall(r"'([^']*)'", match.group(1)) def ts_string_const(source: str, name: str) -> str: match = re.search(rf"export const {re.escape(name)} = '([^']*)';", source) if not match: raise AssertionError(f"missing string export {name}") return match.group(1) class CrmFrontendFieldMetadataPolicyTest(unittest.TestCase): def test_package_exports_and_manifest_entrypoints_include_field_metadata_sources(self): package_json = load_json(CRM_FRONTEND / "package.json") manifest = load_json(CRM_FRONTEND / "source-manifest.json") self.assertEqual( package_json["exports"]["./ui-field-surface-policy"], "./src/ui-field-surface-policy.ts", ) self.assertEqual( package_json["exports"]["./metadata-field-type-policy"], "./src/metadata-field-type-policy.ts", ) self.assertIn( "src/ui-field-surface-policy.ts", manifest["packageBuild"]["entrypoints"], ) self.assertIn( "src/metadata-field-type-policy.ts", manifest["packageBuild"]["entrypoints"], ) def test_ui_field_surface_policy_preserves_current_crm_field_identity_facts(self): source = read_text(UI_POLICY) self.assertEqual( ts_string_array(source, "CRM_UI_FIELD_RENDERER_TYPES"), [ "boolean", "picklist", "multipicklist", "url", "email", "phone", "reference", "currency", "date", "datetime", "double", "percent", "richtextarea", "textarea", ], ) self.assertEqual( ts_string_array(source, "CRM_UI_FIELD_INPUT_TYPES"), ["picklist", "multipicklist", "reference", "textarea", "boolean"], ) self.assertEqual(ts_string_const(source, "CRM_CURRENCY_CODE_FIELD"), "CurrencyIsoCode") self.assertEqual(ts_string_const(source, "CRM_FIELD_DISPLAY_VALUE_SUFFIX"), "_Display") self.assertEqual(ts_string_const(source, "CRM_URL_VALUE_SUFFIX"), "_url") self.assertEqual(ts_string_const(source, "CRM_LOOKUP_NAME_SUFFIX"), "_Name") self.assertEqual(ts_string_const(source, "CRM_LOOKUP_ID_SUFFIX"), "Id") self.assertEqual(ts_string_const(source, "CRM_LOOKUP_TYPE_SUFFIX"), "_type") self.assertEqual( ts_string_array(source, "CRM_NON_NAVIGABLE_TABLE_LOOKUP_TARGETS"), ["user", "group", "recordtype"], ) self.assertEqual(ts_string_const(source, "CRM_MULTIPICKLIST_DELIMITER"), ";") self.assertIn("export const CRM_EMPTY_FIELD_DISPLAY = '\\u2014';", source) def test_metadata_policy_preserves_current_field_type_and_operator_catalog_shape(self): source = read_text(METADATA_POLICY) field_type_ids = ts_string_array(source, "CRM_METADATA_FIELD_TYPE_IDS") operator_ids = ts_string_array(source, "CRM_METADATA_OPERATOR_IDS") self.assertEqual( field_type_ids, [ "autonumber", "boolean", "currency", "date", "datetime", "double", "email", "encryptedstring", "formula", "json", "masterdetail", "multipicklist", "password", "percent", "phone", "picklist", "reference", "richtextarea", "rollupsummary", "string", "textarea", "url", ], ) self.assertEqual( operator_ids, [ "between", "contains", "ends_with", "equals", "greater_or_equal", "greater_than", "in", "is_not_null", "is_null", "less_or_equal", "less_than", "not_contains", "not_equals", "not_in", "starts_with", ], ) for field_type in field_type_ids: self.assertRegex(source, rf"\n {field_type}: \{{") for operator in operator_ids: self.assertRegex(source, rf"\n {operator}: \{{") self.assertIn( "CRM metadata for frontend display and authoring only.", source, ) self.assertIn( "query lowering remain owned by the platform schema/query resolvers.", source, ) self.assertNotIn("sqlType", source) self.assertNotIn("sqlOperator", source) self.assertNotIn("sqlPattern", source) for sql_lowering_token in ( "'BETWEEN'", "'LIKE'", "'IN'", "'IS NOT NULL'", "'IS NULL'", "'NOT LIKE'", "'NOT IN'", "'%{value}%'", "'%{value}'", "'{value}%'", ): self.assertNotIn(sql_lowering_token, source) self.assertIn("multipicklist: {", source) self.assertIn("operators: ['includes', 'excludes', 'is_null', 'is_not_null']", source) self.assertIn("| 'includes'", source) self.assertIn("| 'excludes'", source) self.assertNotRegex(source, r"\n includes: \{") self.assertNotRegex(source, r"\n excludes: \{") if __name__ == "__main__": unittest.main()