From db4ac0c1c8827a475cfff20a0d8b9afea8c2ab3a Mon Sep 17 00:00:00 2001 From: Renn F Date: Tue, 12 May 2026 06:35:43 +0200 Subject: [PATCH] =?UTF-8?q?test(integration):=20E2=20anti-regression=20?= =?UTF-8?q?=E2=80=94=20agents.role=20binds=20to=20'agentrole'=20enum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../test_agent_role_enum_naming.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/integration/test_agent_role_enum_naming.py diff --git a/tests/integration/test_agent_role_enum_naming.py b/tests/integration/test_agent_role_enum_naming.py new file mode 100644 index 00000000..348d6756 --- /dev/null +++ b/tests/integration/test_agent_role_enum_naming.py @@ -0,0 +1,54 @@ +"""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." + )