diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/storage/SchemaBootstrapIT.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/storage/SchemaBootstrapIT.java index 5c547c77..4ec6fe08 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/storage/SchemaBootstrapIT.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/storage/SchemaBootstrapIT.java @@ -52,10 +52,14 @@ class SchemaBootstrapIT extends AbstractPostgresIT { @Test void alerting_enums_exist() { + // Scope to current schema's namespace — Testcontainers reuse can otherwise + // expose enums from a previous run's tenant_default schema alongside public. var enums = jdbcTemplate.queryForList(""" - SELECT typname FROM pg_type - WHERE typname IN ('severity_enum','condition_kind_enum','alert_state_enum', - 'target_kind_enum','notification_status_enum') + SELECT t.typname FROM pg_type t + JOIN pg_namespace n ON n.oid = t.typnamespace + WHERE t.typname IN ('severity_enum','condition_kind_enum','alert_state_enum', + 'target_kind_enum','notification_status_enum') + AND n.nspname = current_schema() """, String.class); assertThat(enums).containsExactlyInAnyOrder( "severity_enum", "condition_kind_enum", "alert_state_enum", @@ -86,6 +90,7 @@ class SchemaBootstrapIT extends AbstractPostgresIT { SELECT column_name FROM information_schema.columns WHERE table_name = 'alert_instances' AND column_name IN ('read_at','deleted_at') + AND table_schema = current_schema() """, String.class); assertThat(cols).containsExactlyInAnyOrder("read_at", "deleted_at"); } @@ -96,13 +101,16 @@ class SchemaBootstrapIT extends AbstractPostgresIT { SELECT COUNT(*)::int FROM pg_indexes WHERE indexname = 'alert_instances_open_rule_uq' AND tablename = 'alert_instances' + AND schemaname = current_schema() """, Integer.class); assertThat(count).isEqualTo(1); Boolean isUnique = jdbcTemplate.queryForObject(""" SELECT indisunique FROM pg_index - JOIN pg_class ON pg_class.oid = pg_index.indexrelid - WHERE pg_class.relname = 'alert_instances_open_rule_uq' + JOIN pg_class c ON c.oid = pg_index.indexrelid + JOIN pg_namespace n ON n.oid = c.relnamespace + WHERE c.relname = 'alert_instances_open_rule_uq' + AND n.nspname = current_schema() """, Boolean.class); assertThat(isUnique).isTrue(); } diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/outbound/controller/OutboundConnectionAdminControllerIT.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/outbound/controller/OutboundConnectionAdminControllerIT.java index 00fd8158..dd81092e 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/outbound/controller/OutboundConnectionAdminControllerIT.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/outbound/controller/OutboundConnectionAdminControllerIT.java @@ -34,6 +34,10 @@ class OutboundConnectionAdminControllerIT extends AbstractPostgresIT { @org.junit.jupiter.api.AfterEach void cleanupRows() { jdbcTemplate.update("DELETE FROM outbound_connections WHERE tenant_id = 'default'"); + // Clear deployments.created_by for our test users — sibling ITs + // (DeploymentControllerIT etc.) may have left rows that FK-block user deletion. + jdbcTemplate.update( + "DELETE FROM deployments WHERE created_by IN ('test-admin','test-operator','test-viewer')"); jdbcTemplate.update("DELETE FROM users WHERE user_id IN ('test-admin','test-operator','test-viewer')"); } diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/storage/V4DeploymentCreatedByMigrationIT.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/storage/V4DeploymentCreatedByMigrationIT.java index fa3568b4..e19d0e71 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/storage/V4DeploymentCreatedByMigrationIT.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/storage/V4DeploymentCreatedByMigrationIT.java @@ -16,10 +16,13 @@ class V4DeploymentCreatedByMigrationIT extends AbstractPostgresIT { @Test void created_by_column_exists_with_correct_type_and_nullable() { + // Scope to current schema — Testcontainers reuse can otherwise leave + // a previous run's tenant_default schema visible alongside public. List> cols = jdbc.queryForList( "SELECT column_name, data_type, is_nullable " + "FROM information_schema.columns " + - "WHERE table_name = 'deployments' AND column_name = 'created_by'" + "WHERE table_name = 'deployments' AND column_name = 'created_by' " + + " AND table_schema = current_schema()" ); assertThat(cols).hasSize(1); assertThat(cols.get(0)).containsEntry("data_type", "text"); @@ -30,7 +33,8 @@ class V4DeploymentCreatedByMigrationIT extends AbstractPostgresIT { void created_by_index_exists() { Integer count = jdbc.queryForObject( "SELECT count(*)::int FROM pg_indexes " + - "WHERE tablename = 'deployments' AND indexname = 'idx_deployments_created_by'", + "WHERE tablename = 'deployments' AND indexname = 'idx_deployments_created_by' " + + " AND schemaname = current_schema()", Integer.class ); assertThat(count).isEqualTo(1); @@ -45,7 +49,8 @@ class V4DeploymentCreatedByMigrationIT extends AbstractPostgresIT { "WHERE tc.table_name = 'deployments' " + " AND tc.constraint_type = 'FOREIGN KEY' " + " AND ccu.table_name = 'users' " + - " AND ccu.column_name = 'user_id'", + " AND ccu.column_name = 'user_id' " + + " AND tc.table_schema = current_schema()", Integer.class ); assertThat(count).isGreaterThanOrEqualTo(1);