"""Tests for per-shard extension activation (SHARD-WP-0014 T3, ADR-0001).""" from shard_wiki.engine import ( ActivationContext, ActivationResolver, StaticProvider, feature_control_provider, ) CANDIDATES = ["ext.overlay", "ext.views", "ext.struct", "ext.compute"] def test_static_provider_default_off(): r = ActivationResolver(StaticProvider()) # nothing enabled assert r.active_extensions(CANDIDATES, ActivationContext("s")) == set() def test_static_provider_global_flags(): r = ActivationResolver(StaticProvider(flags={"ext.overlay": True, "ext.views": True})) assert r.active_extensions(CANDIDATES, ActivationContext("s")) == {"ext.overlay", "ext.views"} def test_per_shard_scoping_overrides_global(): provider = StaticProvider( flags={"ext.views": True}, per_shard={"engB": {"ext.struct": True, "ext.views": False}}, ) r = ActivationResolver(provider) assert r.active_extensions(CANDIDATES, ActivationContext("engA")) == {"ext.views"} assert r.active_extensions(CANDIDATES, ActivationContext("engB")) == {"ext.struct"} def test_context_carries_tenant(): captured = {} class Spy(StaticProvider): def is_active(self, feature_key, context): captured.update(context) return super().is_active(feature_key, context) ActivationResolver(Spy(flags={"ext.views": True})).active_extensions( ["ext.views"], ActivationContext("s1", tenant_id="acme") ) assert captured["shard_id"] == "s1" and captured["tenant_id"] == "acme" def test_activation_profile_returns_config_for_active(): provider = StaticProvider( flags={"ext.struct": True}, configs={"ext.struct": {"max_fields": 50}}, ) profile = ActivationResolver(provider).activation_profile(CANDIDATES, ActivationContext("s")) assert profile == {"ext.struct": {"max_fields": 50}} def test_feature_control_provider_degrades_gracefully(): # feature_control_sdk is not a dependency of shard-wiki: when absent the factory returns # None (standalone path stays dependency-free, ADR-0001); when present it yields a usable # ActivationProvider. Either way it must not raise. provider = feature_control_provider() assert provider is None or hasattr(provider, "is_active")