From c95bc7fe0194de374b32750f032ae9f7d47a1db0 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Thu, 16 Apr 2026 13:22:56 -0300 Subject: [PATCH] fix(tests): extend Respawn + collection config for UDT-010 temporal tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up of B1 (V010 migration). Issues found when running the full suite cross-assembly: 1. Respawn 'Cannot delete rows from a temporal history table' error: 4 per-class Respawner configs in SIGCM2.Application.Tests did not include the newly-created *_History tables introduced by V010 (Usuario_History / Rol_History / Permiso_History / RolPermiso_History). The engine rejects direct DELETE on system-versioned history tables. Extended TablesToIgnore in all 4 configs. 2. FK_RefreshToken_Usuario violation in RolRepositoryTests.InitializeAsync: Manual 'DELETE FROM Usuario' failed when residual RefreshTokens from prior suites existed. Added 'DELETE FROM RefreshToken' before the Usuario cleanup to respect FK order. Latent bug surfaced by a new test-run ordering — not UDT-010 specific, but fixed in scope. 3. UQ_Usuario_Username duplicate admin race: TransactionScopeSpikeTests (B0) and V010MigrationTests (B1) were missing [Collection("ApiIntegration")], causing them to run in parallel with the rest of SIGCM2.Api.Tests and race on SeedAdmin. Serialized by adding the Collection attribute. Suite now passes cross-assembly: 130/130 Api.Tests + 336/336 Application.Tests. Refs: sdd/udt-010-auditoria-trazabilidad/apply-progress (B1 follow-up) --- tests/SIGCM2.Api.Tests/Audit/TransactionScopeSpikeTests.cs | 1 + tests/SIGCM2.Api.Tests/Audit/V010MigrationTests.cs | 1 + .../Infrastructure/RefreshTokenRepositoryTests.cs | 5 +++++ .../Integration/RolRepositoryTests.cs | 4 +++- .../Integration/UsuarioRepositoryTests.cs | 5 +++++ .../Integration/UsuarioRepository_PermisosTests.cs | 5 +++++ .../Integration/V009MigrationTests.cs | 5 +++++ 7 files changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/SIGCM2.Api.Tests/Audit/TransactionScopeSpikeTests.cs b/tests/SIGCM2.Api.Tests/Audit/TransactionScopeSpikeTests.cs index 32c9ca3..8c7bcf6 100644 --- a/tests/SIGCM2.Api.Tests/Audit/TransactionScopeSpikeTests.cs +++ b/tests/SIGCM2.Api.Tests/Audit/TransactionScopeSpikeTests.cs @@ -9,6 +9,7 @@ namespace SIGCM2.Api.Tests.Audit; /// TransactionScope with AsyncFlowEnabled must NOT escalate to MSDTC when /// multiple SqlConnections share a single connection string. If this fails, /// UDT-010 must pivot to explicit IUnitOfWork. +[Collection("ApiIntegration")] public sealed class TransactionScopeSpikeTests { private const string ConnectionString = diff --git a/tests/SIGCM2.Api.Tests/Audit/V010MigrationTests.cs b/tests/SIGCM2.Api.Tests/Audit/V010MigrationTests.cs index 38ae730..e433d95 100644 --- a/tests/SIGCM2.Api.Tests/Audit/V010MigrationTests.cs +++ b/tests/SIGCM2.Api.Tests/Audit/V010MigrationTests.cs @@ -10,6 +10,7 @@ namespace SIGCM2.Api.Tests.Audit; /// REQ-AUD-1: SYSTEM_VERSIONING active on catalog entities (smoke: Usuario + Usuario_History query). /// REQ-AUD-2: dbo.AuditEvent exists, accepts valid INSERT, CHECK constraints reject invalid data. /// REQ-SEC-1: dbo.SecurityEvent exists, CK_SecurityEvent_Result rejects invalid Result. +[Collection("ApiIntegration")] public sealed class V010MigrationTests : IClassFixture { private const string ConnectionString = diff --git a/tests/SIGCM2.Application.Tests/Infrastructure/RefreshTokenRepositoryTests.cs b/tests/SIGCM2.Application.Tests/Infrastructure/RefreshTokenRepositoryTests.cs index 8758b8e..ccd6313 100644 --- a/tests/SIGCM2.Application.Tests/Infrastructure/RefreshTokenRepositoryTests.cs +++ b/tests/SIGCM2.Application.Tests/Infrastructure/RefreshTokenRepositoryTests.cs @@ -36,6 +36,11 @@ public class RefreshTokenRepositoryTests : IAsyncLifetime new Respawn.Graph.Table("dbo", "Rol"), new Respawn.Graph.Table("dbo", "Permiso"), new Respawn.Graph.Table("dbo", "RolPermiso"), + // UDT-010: *_History tables are system-versioned — engine rejects direct DELETE. + new Respawn.Graph.Table("dbo", "Usuario_History"), + new Respawn.Graph.Table("dbo", "Rol_History"), + new Respawn.Graph.Table("dbo", "Permiso_History"), + new Respawn.Graph.Table("dbo", "RolPermiso_History"), ] }); diff --git a/tests/SIGCM2.Application.Tests/Integration/RolRepositoryTests.cs b/tests/SIGCM2.Application.Tests/Integration/RolRepositoryTests.cs index ee1cf60..17ec627 100644 --- a/tests/SIGCM2.Application.Tests/Integration/RolRepositoryTests.cs +++ b/tests/SIGCM2.Application.Tests/Integration/RolRepositoryTests.cs @@ -19,7 +19,9 @@ public class RolRepositoryTests : IAsyncLifetime _connection = new SqlConnection(ConnectionString); await _connection.OpenAsync(); - // Clean Usuario first (FK), then custom Rol codes created by tests. + // Clean RefreshToken first (FK to Usuario), then Usuario (FK to Rol), then custom Rol codes. + // Residual RefreshTokens from prior test suites would violate FK_RefreshToken_Usuario otherwise. + await _connection.ExecuteAsync("DELETE FROM dbo.RefreshToken;"); await _connection.ExecuteAsync("DELETE FROM dbo.Usuario;"); await _connection.ExecuteAsync("DELETE FROM dbo.Rol WHERE Codigo NOT IN ('admin','cajero','operador_ctacte','picadora','jefe_publicidad','productor','diagramacion','reportes');"); // Ensure canonical Rol seeds exist (idempotent — previous test classes may have wiped them via Respawn). diff --git a/tests/SIGCM2.Application.Tests/Integration/UsuarioRepositoryTests.cs b/tests/SIGCM2.Application.Tests/Integration/UsuarioRepositoryTests.cs index 27b34e9..6eabd33 100644 --- a/tests/SIGCM2.Application.Tests/Integration/UsuarioRepositoryTests.cs +++ b/tests/SIGCM2.Application.Tests/Integration/UsuarioRepositoryTests.cs @@ -28,6 +28,11 @@ public class UsuarioRepositoryTests : IAsyncLifetime new Respawn.Graph.Table("dbo", "Rol"), new Respawn.Graph.Table("dbo", "Permiso"), new Respawn.Graph.Table("dbo", "RolPermiso"), + // UDT-010: *_History tables are system-versioned — engine rejects direct DELETE. + new Respawn.Graph.Table("dbo", "Usuario_History"), + new Respawn.Graph.Table("dbo", "Rol_History"), + new Respawn.Graph.Table("dbo", "Permiso_History"), + new Respawn.Graph.Table("dbo", "RolPermiso_History"), ] }); diff --git a/tests/SIGCM2.Application.Tests/Integration/UsuarioRepository_PermisosTests.cs b/tests/SIGCM2.Application.Tests/Integration/UsuarioRepository_PermisosTests.cs index 6ffe69a..6418293 100644 --- a/tests/SIGCM2.Application.Tests/Integration/UsuarioRepository_PermisosTests.cs +++ b/tests/SIGCM2.Application.Tests/Integration/UsuarioRepository_PermisosTests.cs @@ -32,6 +32,11 @@ public sealed class UsuarioRepository_PermisosTests : IAsyncLifetime new Respawn.Graph.Table("dbo", "Rol"), new Respawn.Graph.Table("dbo", "Permiso"), new Respawn.Graph.Table("dbo", "RolPermiso"), + // UDT-010: *_History tables are system-versioned — engine rejects direct DELETE. + new Respawn.Graph.Table("dbo", "Usuario_History"), + new Respawn.Graph.Table("dbo", "Rol_History"), + new Respawn.Graph.Table("dbo", "Permiso_History"), + new Respawn.Graph.Table("dbo", "RolPermiso_History"), ] }); diff --git a/tests/SIGCM2.Application.Tests/Integration/V009MigrationTests.cs b/tests/SIGCM2.Application.Tests/Integration/V009MigrationTests.cs index 8566027..281b24e 100644 --- a/tests/SIGCM2.Application.Tests/Integration/V009MigrationTests.cs +++ b/tests/SIGCM2.Application.Tests/Integration/V009MigrationTests.cs @@ -31,6 +31,11 @@ public sealed class V009MigrationTests : IAsyncLifetime new Respawn.Graph.Table("dbo", "Rol"), new Respawn.Graph.Table("dbo", "Permiso"), new Respawn.Graph.Table("dbo", "RolPermiso"), + // UDT-010: *_History tables are system-versioned — engine rejects direct DELETE. + new Respawn.Graph.Table("dbo", "Usuario_History"), + new Respawn.Graph.Table("dbo", "Rol_History"), + new Respawn.Graph.Table("dbo", "Permiso_History"), + new Respawn.Graph.Table("dbo", "RolPermiso_History"), ] });