from __future__ import annotations import json from pathlib import Path FIXTURE_PATH = ( Path(__file__).resolve().parents[2] / "examples" / "cmis" / "capability-fixtures.json" ) REQUIRED_GROUPS = { "repository-type", "navigation", "object-content", "versioning", "discovery-query", "relationships", "acl-policy", "change-log", "retention-renditions-bulk", } REQUIRED_PROFILES = {"readonly-browser", "governed-authoring", "admin-export", "compat-tck"} def _catalog() -> dict: return json.loads(FIXTURE_PATH.read_text(encoding="utf-8")) def test_cmis_fixture_catalog_declares_target_standard_and_profiles() -> None: catalog = _catalog() assert catalog["standard"] == { "name": "CMIS", "version": "1.1", "primary_binding": "browser", "deferred_bindings": ["atompub", "web_services"], } assert set(catalog["profiles"]) == REQUIRED_PROFILES assert all(profile["binding"] == "browser" for profile in catalog["profiles"].values()) def test_cmis_fixture_groups_cover_required_capabilities() -> None: catalog = _catalog() groups = {group["id"]: group for group in catalog["capability_groups"]} assert set(groups) == REQUIRED_GROUPS for group in groups.values(): assert group["examples"], group["id"] assert group["must_validate"], group["id"] assert set(group["supported_profiles"]).issubset(REQUIRED_PROFILES) def test_unsupported_cmis_features_have_structured_diagnostics() -> None: catalog = _catalog() diagnostics = catalog["unsupported_diagnostics"] unsupported = { feature for group in catalog["capability_groups"] for feature in group.get("unsupported", []) } unsupported.update(catalog["standard"]["deferred_bindings"]) assert unsupported <= set(diagnostics) assert all(diagnostics[feature] for feature in unsupported) def test_profile_visibility_and_mutation_expectations_are_explicit() -> None: catalog = _catalog() groups = {group["id"] for group in catalog["capability_groups"]} for profile_name, profile in catalog["profiles"].items(): expectations = catalog["profile_expectations"][profile_name] assert set(expectations["must_expose"]).issubset(groups) assert "must_not_expose_objects" in expectations if profile["mutations"]: assert expectations["must_authorize_actions"] == [ "create_document", "update_properties", "delete_object", "set_content_stream", "append_content_stream", ] else: assert expectations["must_reject_actions"] == [ "create_document", "update_properties", "delete_object", "set_content_stream", "append_content_stream", ] def test_readonly_and_governed_profiles_hide_confidential_fixture_objects() -> None: catalog = _catalog() objects = {item["id"]: item for item in catalog["objects"]} confidential = { object_id for object_id, item in objects.items() if item.get("sensitivity") == "confidential" } assert confidential for profile_name in ["readonly-browser", "governed-authoring", "compat-tck"]: denied = set(catalog["profile_expectations"][profile_name]["must_not_expose_objects"]) assert confidential <= denied def test_admin_export_is_the_only_profile_for_deferred_extension_group() -> None: catalog = _catalog() extension = next( group for group in catalog["capability_groups"] if group["id"] == "retention-renditions-bulk" ) assert extension["supported_profiles"] == ["admin-export"] for profile_name, expectations in catalog["profile_expectations"].items(): exposes_extension = "retention-renditions-bulk" in expectations["must_expose"] assert exposes_extension is (profile_name == "admin-export")