from __future__ import annotations import json from pathlib import Path import pytest from kontextual_engine import ( Actor, ActorType, CMISAccessPoint, CMISAccessProfile, CMISAction, OperationContext, ) pytestmark = pytest.mark.cmis ROOT = Path(__file__).resolve().parents[2] FIXTURE_PATH = ROOT / "examples" / "cmis" / "capability-fixtures.json" TCK_MAP_PATH = ROOT / "tests" / "cmis" / "opencmis-tck" / "tck-subset-map.json" TCK_RESULT_TEMPLATE = ROOT / "tests" / "cmis" / "opencmis-tck" / "tck-result-template.json" ACTION_MAP = { "create_document": CMISAction.CREATE_DOCUMENT, "update_properties": CMISAction.UPDATE_PROPERTIES, "delete_object": CMISAction.DELETE_OBJECT, "set_content_stream": CMISAction.SET_CONTENT_STREAM, "append_content_stream": CMISAction.SET_CONTENT_STREAM, } def _catalog() -> dict: return json.loads(FIXTURE_PATH.read_text(encoding="utf-8")) def _tck_map() -> dict: return json.loads(TCK_MAP_PATH.read_text(encoding="utf-8")) def _profiles() -> dict[str, CMISAccessProfile]: return { profile.name: profile for profile in ( CMISAccessProfile.readonly_browser(), CMISAccessProfile.governed_authoring(), CMISAccessProfile.admin_export(), CMISAccessProfile.compat_tck(), ) } def _context(actor_type: ActorType = ActorType.HUMAN) -> OperationContext: return OperationContext.create( Actor.create(actor_type, actor_id=f"fixture-{actor_type.value}"), correlation_id="corr-cmis-fixture-integration", ) def test_fixture_profiles_match_implemented_access_profiles() -> None: catalog = _catalog() implemented = _profiles() assert set(catalog["profiles"]) == set(implemented) for profile_name, fixture in catalog["profiles"].items(): profile = implemented[profile_name] assert profile.binding.value == fixture["binding"] assert profile.allow_mutations is fixture["mutations"] assert [item.value for item in profile.visible_sensitivities] == fixture["visibility"] assert [item.value for item in profile.denied_sensitivities] == fixture["deny"] def test_fixture_mutation_expectations_match_profile_decisions() -> None: catalog = _catalog() implemented = _profiles() for profile_name, expectations in catalog["profile_expectations"].items(): profile = implemented[profile_name] context = _context( ActorType.SERVICE_ACCOUNT if profile.required_actor_types else ActorType.HUMAN ) for action_name in expectations.get("must_authorize_actions", []): assert profile.decide_action(ACTION_MAP[action_name], context).allowed is True for action_name in expectations.get("must_reject_actions", []): assert profile.decide_action(ACTION_MAP[action_name], context).allowed is False def test_every_fixture_profile_has_a_browser_access_point_shape() -> None: for profile in _profiles().values(): access_point = CMISAccessPoint( access_point_id=profile.name, repository_id=f"kontextual-{profile.name}", profile=profile, base_path=f"/cmis/{profile.name}/browser", ) serialized = access_point.to_dict() assert serialized["base_path"] == f"/cmis/{profile.name}/browser" assert serialized["repository_id"] == f"kontextual-{profile.name}" assert serialized["profile"]["binding"] == "browser" def test_optional_opencmis_tck_map_covers_fixture_capability_groups() -> None: catalog = _catalog() tck_map = _tck_map() fixture_groups = {group["id"] for group in catalog["capability_groups"]} mapped_groups = {group["capability_group"] for group in tck_map["groups"]} assert tck_map["tck"]["execution"] == "optional" assert tck_map["target"]["profile"] == "compat-tck" assert mapped_groups == fixture_groups assert all(group["tck_groups"] for group in tck_map["groups"]) def test_optional_tck_result_template_can_capture_gap_mapping() -> None: template = json.loads(TCK_RESULT_TEMPLATE.read_text(encoding="utf-8")) assert template["run"]["profile"] == "compat-tck" assert template["summary"] == {"passed": 0, "failed": 0, "skipped": 0, "known_gap": 0} assert "capability_gaps" in template assert template["groups"][0]["status"] == "not_run"