"""Tenant-scoped manager behaviour (TENANCY.md ยง4).""" import pytest from infrasynth.features.models import FeatureFlag from infrasynth.scheduler.models import ScheduledTask from infrasynth.tenancy.context import tenant_context from infrasynth.tenancy.models import Tenant pytestmark = pytest.mark.django_db def _task(tenant, name): return ScheduledTask.all_objects.create( tenant=tenant, name=name, task_path="tests.helpers.noop_task", schedule_type="manual", ) class TestTenantManager: def test_fail_closed_without_context(self, tenant): _task(tenant, "a") with tenant_context(None): assert ScheduledTask.objects.count() == 0 assert list(ScheduledTask.objects.all()) == [] def test_scopes_to_current_tenant(self, tenant): other = Tenant.objects.create(slug="other", name="Other") _task(tenant, "a") _task(other, "b") with tenant_context(tenant): assert list(ScheduledTask.objects.values_list("name", flat=True)) == ["a"] with tenant_context(other): assert list(ScheduledTask.objects.values_list("name", flat=True)) == ["b"] def test_cross_tenant_get_raises_does_not_exist(self, tenant): other = Tenant.objects.create(slug="other", name="Other") _task(tenant, "a") with tenant_context(other), pytest.raises(ScheduledTask.DoesNotExist): ScheduledTask.objects.get(name="a") def test_unsafe_all_sees_every_tenant(self, tenant): other = Tenant.objects.create(slug="other", name="Other") _task(tenant, "a") _task(other, "b") with tenant_context(None): assert ScheduledTask.objects.unsafe_all().count() == 2 def test_save_auto_assigns_current_tenant(self, tenant): with tenant_context(tenant): task = ScheduledTask.objects.create( name="auto", task_path="tests.helpers.noop_task", schedule_type="manual", ) assert task.tenant_id == tenant.id class TestGlobalOrTenantManager: def test_exposes_global_plus_override_only(self, tenant): other = Tenant.objects.create(slug="other", name="Other") FeatureFlag.all_objects.create(slug="f", is_active=True, tenant=None) FeatureFlag.all_objects.create(slug="f", is_active=False, tenant=tenant) FeatureFlag.all_objects.create(slug="f", is_active=True, tenant=other) with tenant_context(tenant): assert FeatureFlag.objects.filter(slug="f").count() == 2 # global + own override resolved = FeatureFlag.objects.resolve(slug="f") assert resolved is not None and resolved.is_active is False with tenant_context(other): assert FeatureFlag.objects.filter(slug="f").count() == 2 def test_resolve_falls_back_to_global(self, tenant): FeatureFlag.all_objects.create(slug="only_global", is_active=True, tenant=None) with tenant_context(tenant): resolved = FeatureFlag.objects.resolve(slug="only_global") assert resolved is not None and resolved.tenant_id is None