115 lines
3.9 KiB
Python
115 lines
3.9 KiB
Python
"""Contract tests for the S4.3 group/persona repository packet."""
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.db import Base, create_db_engine
|
|
from app.repositories import (
|
|
EntityNotFoundError,
|
|
InvalidRepositoryField,
|
|
SqlAlchemyGroupRepository,
|
|
SqlAlchemyOrganizationRepository,
|
|
SqlAlchemyUserRepository,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def repository_session(tmp_path: Path):
|
|
engine = create_db_engine(f"sqlite:///{tmp_path / 'groups.db'}")
|
|
Base.metadata.create_all(engine)
|
|
with Session(engine) as session:
|
|
yield session
|
|
|
|
|
|
def test_group_repository_scopes_groups_and_personas_to_org(repository_session: Session):
|
|
organizations = SqlAlchemyOrganizationRepository(repository_session)
|
|
users = SqlAlchemyUserRepository(repository_session)
|
|
groups = SqlAlchemyGroupRepository(repository_session)
|
|
organizations.create(organization_id="org-a", name="Alpha")
|
|
organizations.create(organization_id="org-b", name="Beta")
|
|
users.create(
|
|
user_id="user-a",
|
|
org_id="org-a",
|
|
username="alice",
|
|
password_hash="hash-a",
|
|
name="Alice",
|
|
role="user",
|
|
)
|
|
repository_session.flush()
|
|
|
|
group_a = groups.create(
|
|
group_id="group-a",
|
|
org_id="org-a",
|
|
name="Alpha Group",
|
|
creator_user_id="user-a",
|
|
input_json={"product": "A"},
|
|
)
|
|
groups.create(group_id="group-b", org_id="org-b", name="Beta Group")
|
|
repository_session.flush()
|
|
|
|
persona_a = groups.create_persona(
|
|
persona_id="persona-a",
|
|
group_id="group-a",
|
|
tier="base",
|
|
public_json={"name": "Customer A"},
|
|
latent_json={"objection": "price"},
|
|
org_id="org-a",
|
|
)
|
|
repository_session.commit()
|
|
|
|
assert groups.get("group-a", org_id="org-a") is group_a
|
|
assert groups.get("group-b", org_id="org-a") is None
|
|
assert [item.id for item in groups.list_for_org("org-a")] == ["group-a"]
|
|
assert groups.get_persona("group-a", "persona-a", org_id="org-a") is persona_a
|
|
assert [item.id for item in groups.list_personas("group-a", org_id="org-a")] == ["persona-a"]
|
|
assert groups.get_persona("group-a", "persona-a", org_id="org-b") is None
|
|
|
|
|
|
def test_group_repository_updates_only_allowed_fields(repository_session: Session):
|
|
organizations = SqlAlchemyOrganizationRepository(repository_session)
|
|
groups = SqlAlchemyGroupRepository(repository_session)
|
|
organizations.create(organization_id="org-a", name="Alpha")
|
|
groups.create(group_id="group-a", org_id="org-a", name="Before")
|
|
repository_session.commit()
|
|
|
|
updated = groups.update(
|
|
"group-a",
|
|
org_id="org-a",
|
|
name="After",
|
|
status="ready",
|
|
report_text="Report",
|
|
)
|
|
repository_session.commit()
|
|
assert updated.name == "After"
|
|
assert updated.status == "ready"
|
|
assert updated.report_text == "Report"
|
|
|
|
with pytest.raises(EntityNotFoundError):
|
|
groups.update("group-a", org_id="org-b", name="cross-tenant mutation")
|
|
|
|
with pytest.raises(EntityNotFoundError):
|
|
groups.update("missing", org_id="org-a", name="nope")
|
|
with pytest.raises(InvalidRepositoryField):
|
|
groups.update("group-a", org_id="org-a", creator_user_id="cannot-change")
|
|
|
|
|
|
def test_group_repository_rejects_cross_org_persona_creation(repository_session: Session):
|
|
organizations = SqlAlchemyOrganizationRepository(repository_session)
|
|
groups = SqlAlchemyGroupRepository(repository_session)
|
|
organizations.create(organization_id="org-a", name="Alpha")
|
|
organizations.create(organization_id="org-b", name="Beta")
|
|
groups.create(group_id="group-a", org_id="org-a", name="Alpha Group")
|
|
repository_session.commit()
|
|
|
|
with pytest.raises(EntityNotFoundError):
|
|
groups.create_persona(
|
|
persona_id="persona-invalid",
|
|
group_id="group-a",
|
|
tier="base",
|
|
public_json={},
|
|
org_id="org-b",
|
|
)
|