Files
roboco/tests/integration/test_agent_role_enum_naming.py
T
Renn F db4ac0c1c8 test(integration): E2 anti-regression — agents.role binds to 'agentrole' enum
Pin the SQLAlchemy enum-naming invariant: every column typed Role
(aliased as AgentRole) MUST bind to the postgres enum named
'agentrole', not 'role'. Wave A5's smoke regression came from the
inferred 'role' type colliding with migration 001's 'agentrole'.

The fix already shipped (roboco/db/tables.py::_PG_ENUM_NAME_OVERRIDES);
this test locks it in. Two assertions: agents.role.udt_name == agentrole;
no stray 'role' enum type exists in pg_type.
2026-05-12 06:35:43 +02:00

55 lines
2.0 KiB
Python

"""Wave E2: agents.role column is typed as the postgres enum named 'agentrole'.
Anti-regression for the SQLAlchemy enum-naming binding. Without the
`_PG_ENUM_NAME_OVERRIDES["Role"] = "agentrole"` entry in
`roboco/db/tables.py`, SQLAlchemy infers the postgres type name from the
Python class name (`Role` → `role`), producing the `operator does not
exist: agentrole = role` regression smoke run 2 hit.
This test pins the invariant — every column typed `Role`/`AgentRole`
binds to the canonical `agentrole` postgres type.
"""
from __future__ import annotations
import pytest
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
@pytest.mark.asyncio
async def test_agents_role_uses_agentrole_type(db_session: AsyncSession) -> None:
"""agents.role.udt_name == 'agentrole' — never 'role'."""
result = await db_session.execute(
text(
"SELECT udt_name FROM information_schema.columns "
"WHERE table_name = 'agents' AND column_name = 'role'"
)
)
row = result.first()
assert row is not None, "agents.role column missing from test DB"
assert row[0] == "agentrole", (
f"agents.role typed as {row[0]!r}, expected 'agentrole' — "
f"the SQLAlchemy enum binding is missing the name='agentrole' "
f"override in roboco/db/tables.py::_PG_ENUM_NAME_OVERRIDES"
)
@pytest.mark.asyncio
async def test_no_stray_role_enum_type_exists(db_session: AsyncSession) -> None:
"""No postgres enum named 'role' should exist — only 'agentrole'."""
result = await db_session.execute(
text(
"SELECT typname FROM pg_type "
"WHERE typname IN ('role', 'agentrole') "
"ORDER BY typname"
)
)
typenames = [row[0] for row in result]
assert "agentrole" in typenames, "agentrole enum type missing"
assert "role" not in typenames, (
"stray 'role' enum type exists — Base.metadata.create_all "
"produced both 'role' and 'agentrole'. Check "
"roboco/db/tables.py::_str_enum for missing name= override."
)