mirror of
https://github.com/azaion/missions.git
synced 2026-06-21 08:41:07 +00:00
6b2c2d998e
Adds 26 blackbox tests (FT-P-01..18, FT-N-01..08) covering full AC
matrices for Vehicles/Missions/Waypoints/Health/Errors. Three
spec-vs-code carry-forwards documented in batch_02_report.md and
pinned with [Trait("carry_forward", ...)].
Shared scaffolding: ApiDtos.cs, AssertProblemEnvelopeAsync helper,
Seeds.cs, StubSchema.cs, CascadeF3/F4 fixtures, PostgresStopStart
fixture (gated by COMPOSE_RESTART_ENABLED). Removes the 4 placeholder
Sanity.cs files (now superseded). docker-compose.test.yml gains the
expected_results volume mount + FIXTURE_SQL_DIR for the consumer.
Co-authored-by: Cursor <cursoragent@cursor.com>
100 lines
3.7 KiB
C#
100 lines
3.7 KiB
C#
using System.Net;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http.Json;
|
|
using Azaion.Missions.E2E.Fixtures;
|
|
using Azaion.Missions.E2E.Helpers;
|
|
using Xunit;
|
|
|
|
namespace Azaion.Missions.E2E.Tests.Vehicles;
|
|
|
|
/// <summary>
|
|
/// FT-N-01..03 — vehicle negative scenarios from
|
|
/// <c>_docs/02_document/tests/blackbox-tests.md § Negative</c>.
|
|
/// FT-N-08 (generic 500 redacted body) lives in Tests/Errors because it
|
|
/// owns its own destructive xUnit collection.
|
|
/// Traces: AC-1.6 (no-match) / AC-1.7 (404) / AC-1.8 (409 in-use).
|
|
/// </summary>
|
|
[Collection("Vehicles")]
|
|
[Trait("Category", "Blackbox")]
|
|
[Trait("db_access", "seed-or-assert-only")]
|
|
public sealed class NegativeTests : TestBase, IClassFixture<DbResetFixture>
|
|
{
|
|
[Fact]
|
|
[Trait("Traces", "AC-1.6")]
|
|
[Trait("max_ms", "2000")]
|
|
public async Task FT_N_01_filter_no_match_returns_empty_array_for_both_casings()
|
|
{
|
|
// Arrange
|
|
DbResetFixture.ResetDatabase(TestEnvironment.DbSideChannel);
|
|
Seeds.Apply(Seeds.Three_BR01_BR02_MQ9.Sql);
|
|
var token = await Tokens.MintDefaultAsync();
|
|
|
|
async Task<List<VehicleDto>> FetchAsync(string query)
|
|
{
|
|
using var http = new HttpRequestMessage(HttpMethod.Get, "/vehicles?" + query);
|
|
http.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Jwt);
|
|
using var resp = await Missions.SendAsync(http);
|
|
await HttpAssertions.AssertStatusAsync(resp, HttpStatusCode.OK);
|
|
return await resp.Content.ReadFromJsonAsync<List<VehicleDto>>() ?? throw new InvalidOperationException("body deserialized to null");
|
|
}
|
|
|
|
// Act
|
|
var upper = await FetchAsync("name=ZZ");
|
|
var lower = await FetchAsync("name=zz");
|
|
|
|
// Assert
|
|
Assert.Empty(upper);
|
|
Assert.Empty(lower);
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Traces", "AC-1.7,AC-8.2")]
|
|
[Trait("max_ms", "2000")]
|
|
public async Task FT_N_02_get_vehicle_returns_404_with_problem_envelope()
|
|
{
|
|
// Arrange
|
|
DbResetFixture.ResetDatabase(TestEnvironment.DbSideChannel);
|
|
var token = await Tokens.MintDefaultAsync();
|
|
var randomId = Guid.NewGuid();
|
|
|
|
// Act
|
|
using var http = new HttpRequestMessage(HttpMethod.Get, $"/vehicles/{randomId}");
|
|
http.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Jwt);
|
|
using var response = await Missions.SendAsync(http);
|
|
|
|
// Assert
|
|
await HttpAssertions.AssertProblemEnvelopeAsync(response, HttpStatusCode.NotFound)
|
|
;
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Traces", "AC-1.8,AC-8.5")]
|
|
[Trait("max_ms", "2000")]
|
|
public async Task FT_N_03_delete_in_use_vehicle_returns_409_and_row_remains()
|
|
{
|
|
// Arrange
|
|
DbResetFixture.ResetDatabase(TestEnvironment.DbSideChannel);
|
|
Seeds.Apply(Seeds.OneDefaultVehicle.Sql);
|
|
var vehicleId = Seeds.OneDefaultVehicle.Id;
|
|
var missionId = Guid.NewGuid();
|
|
Seeds.Apply($"""
|
|
INSERT INTO missions (id, created_date, name, vehicle_id)
|
|
VALUES ('{missionId}', '2026-05-14T00:00:00Z', 'in-use', '{vehicleId}');
|
|
""");
|
|
var token = await Tokens.MintDefaultAsync();
|
|
|
|
// Act
|
|
using var http = new HttpRequestMessage(HttpMethod.Delete, $"/vehicles/{vehicleId}");
|
|
http.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Jwt);
|
|
using var response = await Missions.SendAsync(http);
|
|
|
|
// Assert
|
|
await HttpAssertions.AssertProblemEnvelopeAsync(response, HttpStatusCode.Conflict)
|
|
;
|
|
var remaining = DbAssertions.ScalarCount(
|
|
"SELECT COUNT(*) FROM vehicles WHERE id = @id",
|
|
("id", vehicleId));
|
|
Assert.Equal(1L, remaining);
|
|
}
|
|
}
|