test(secciones): cobertura cascada de inactividad — issue #16

This commit is contained in:
2026-04-17 11:46:14 -03:00
parent 4fb25356a3
commit 3829c93af6
5 changed files with 274 additions and 3 deletions

View File

@@ -389,6 +389,156 @@ public sealed class SeccionesControllerTests : IAsyncLifetime
Assert.Equal("seccion_not_found", json.GetProperty("error").GetString());
}
// ── CASCADA INACTIVIDAD (issue #16) ──────────────────────────────────────
[Fact]
public async Task UpdateSeccion_WhenMedioInactive_Returns409()
{
const string medioCodigo = "TSEC_UPD_INACT";
var token = await GetAdminTokenAsync();
try
{
var medioId = await CreateMedioAsync(medioCodigo, "Medio Inactivo Update", token);
using var createReq = BuildRequest(HttpMethod.Post, Endpoint, new
{
medioId,
codigo = "SECUPDINACT",
nombre = "Seccion Update Inactivo",
tipo = "clasificados"
}, token);
var createResp = await _client.SendAsync(createReq);
Assert.Equal(HttpStatusCode.Created, createResp.StatusCode);
var created = await createResp.Content.ReadFromJsonAsync<JsonElement>();
var secId = created.GetProperty("id").GetInt32();
// Deactivate the medio
using var deactMedioReq = BuildRequest(HttpMethod.Post, $"{MediosEndpoint}/{medioId}/deactivate", bearerToken: token);
var deactMedioResp = await _client.SendAsync(deactMedioReq);
Assert.Equal(HttpStatusCode.NoContent, deactMedioResp.StatusCode);
var auditBefore = await CountAuditEventsAsync("seccion.update", "Seccion", secId.ToString());
// Try to update seccion with inactive medio
using var updateReq = BuildRequest(HttpMethod.Put, $"{Endpoint}/{secId}", new
{
nombre = "Nombre Cambiado",
tipo = "notables"
}, token);
var updateResp = await _client.SendAsync(updateReq);
Assert.Equal(HttpStatusCode.Conflict, updateResp.StatusCode);
var json = await updateResp.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal("medio_inactivo", json.GetProperty("error").GetString());
var auditAfter = await CountAuditEventsAsync("seccion.update", "Seccion", secId.ToString());
Assert.Equal(auditBefore, auditAfter);
}
finally
{
await DeleteMedioIfExistsAsync(medioCodigo);
}
}
[Fact]
public async Task DeactivateSeccion_WhenMedioInactive_Returns409()
{
const string medioCodigo = "TSEC_DEACT_INACT";
var token = await GetAdminTokenAsync();
try
{
var medioId = await CreateMedioAsync(medioCodigo, "Medio Inactivo Deactivate", token);
using var createReq = BuildRequest(HttpMethod.Post, Endpoint, new
{
medioId,
codigo = "SECDEACTINACT",
nombre = "Seccion Deactivate Inactivo",
tipo = "clasificados"
}, token);
var createResp = await _client.SendAsync(createReq);
Assert.Equal(HttpStatusCode.Created, createResp.StatusCode);
var created = await createResp.Content.ReadFromJsonAsync<JsonElement>();
var secId = created.GetProperty("id").GetInt32();
// Deactivate the medio
using var deactMedioReq = BuildRequest(HttpMethod.Post, $"{MediosEndpoint}/{medioId}/deactivate", bearerToken: token);
var deactMedioResp = await _client.SendAsync(deactMedioReq);
Assert.Equal(HttpStatusCode.NoContent, deactMedioResp.StatusCode);
var auditBefore = await CountAuditEventsAsync("seccion.deactivate", "Seccion", secId.ToString());
// Try to deactivate seccion with inactive medio
using var deactReq = BuildRequest(HttpMethod.Post, $"{Endpoint}/{secId}/deactivate", bearerToken: token);
var deactResp = await _client.SendAsync(deactReq);
Assert.Equal(HttpStatusCode.Conflict, deactResp.StatusCode);
var json = await deactResp.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal("medio_inactivo", json.GetProperty("error").GetString());
var auditAfter = await CountAuditEventsAsync("seccion.deactivate", "Seccion", secId.ToString());
Assert.Equal(auditBefore, auditAfter);
}
finally
{
await DeleteMedioIfExistsAsync(medioCodigo);
}
}
[Fact]
public async Task ReactivateSeccion_WhenMedioInactive_Returns409()
{
const string medioCodigo = "TSEC_REACT_INACT";
var token = await GetAdminTokenAsync();
try
{
var medioId = await CreateMedioAsync(medioCodigo, "Medio Inactivo Reactivate", token);
// Create seccion then deactivate it (while medio is still active)
using var createReq = BuildRequest(HttpMethod.Post, Endpoint, new
{
medioId,
codigo = "SECREACTINACT",
nombre = "Seccion Reactivate Inactivo",
tipo = "clasificados"
}, token);
var createResp = await _client.SendAsync(createReq);
Assert.Equal(HttpStatusCode.Created, createResp.StatusCode);
var created = await createResp.Content.ReadFromJsonAsync<JsonElement>();
var secId = created.GetProperty("id").GetInt32();
// Deactivate seccion while medio is still active
using var deactSecReq = BuildRequest(HttpMethod.Post, $"{Endpoint}/{secId}/deactivate", bearerToken: token);
var deactSecResp = await _client.SendAsync(deactSecReq);
Assert.Equal(HttpStatusCode.NoContent, deactSecResp.StatusCode);
// Now deactivate the medio
using var deactMedioReq = BuildRequest(HttpMethod.Post, $"{MediosEndpoint}/{medioId}/deactivate", bearerToken: token);
var deactMedioResp = await _client.SendAsync(deactMedioReq);
Assert.Equal(HttpStatusCode.NoContent, deactMedioResp.StatusCode);
var auditBefore = await CountAuditEventsAsync("seccion.reactivate", "Seccion", secId.ToString());
// Try to reactivate seccion with inactive medio
using var reactReq = BuildRequest(HttpMethod.Post, $"{Endpoint}/{secId}/reactivate", bearerToken: token);
var reactResp = await _client.SendAsync(reactReq);
Assert.Equal(HttpStatusCode.Conflict, reactResp.StatusCode);
var json = await reactResp.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal("medio_inactivo", json.GetProperty("error").GetString());
var auditAfter = await CountAuditEventsAsync("seccion.reactivate", "Seccion", secId.ToString());
Assert.Equal(auditBefore, auditAfter);
}
finally
{
await DeleteMedioIfExistsAsync(medioCodigo);
}
}
// ── DEACTIVATE ────────────────────────────────────────────────────────────
[Fact]