using Npgsql; namespace Azaion.Missions.E2E.Fixtures; /// /// Inline seed-data definitions referenced by name from /// _docs/02_document/tests/test-data.md § Seed Data Sets. Each seed /// is idempotent against a freshly-reset DB (callers must run /// first; the /// base does this automatically). /// /// /// UUIDs are deterministic so assertions can reference them directly without /// having to first read them back. Seeds insert rows that satisfy every /// schema constraint — including the partial unique index /// ux_vehicles_one_default (a fixture cannot stage two /// is_default=true rows even though the test name suggests it). /// public static class Seeds { /// seed_one_default_vehicle: a single Bayraktar with is_default=true. public static class OneDefaultVehicle { public static readonly Guid Id = Guid.Parse("11111111-1111-1111-1111-000000000001"); public const string Sql = """ INSERT INTO vehicles (id, type, model, name, fuel_type, battery_capacity, engine_consumption, engine_consumption_idle, is_default) VALUES ('11111111-1111-1111-1111-000000000001', 0, 'Bayraktar', 'BR-default', 1, 0, 5, 1, true); """; } /// /// seed_3_vehicles_2_default — name-misleading: only ONE row is default /// because the partial unique index ux_vehicles_one_default rejects /// two. The "2" in the name historically referred to a pre-B12 variant /// allowing two defaults; today only BR-01 carries the flag. This still /// satisfies every consumer scenario (FT-P-04 ordering, FT-P-05 filter, /// FT-N-01 no-match) — none of them require >1 default. /// /// Insert order is reverse-alphabetic ([MQ-9, BR-02, BR-01]) so an /// ordering bug in the SUT (missing OrderBy) would surface immediately /// — see Risk #2 in _docs/tasks/done/AZ-577_test_vehicles_positive.md. /// public static class Three_BR01_BR02_MQ9 { public static readonly Guid IdBr01 = Guid.Parse("11111111-2222-3333-4444-000000000001"); public static readonly Guid IdBr02 = Guid.Parse("11111111-2222-3333-4444-000000000002"); public static readonly Guid IdMq9 = Guid.Parse("11111111-2222-3333-4444-000000000003"); public const string Sql = """ INSERT INTO vehicles (id, type, model, name, fuel_type, battery_capacity, engine_consumption, engine_consumption_idle, is_default) VALUES ('11111111-2222-3333-4444-000000000003', 0, 'Bayraktar', 'MQ-9', 1, 0, 5, 1, false), ('11111111-2222-3333-4444-000000000002', 0, 'Bayraktar', 'BR-02', 1, 0, 5, 1, false), ('11111111-2222-3333-4444-000000000001', 0, 'Bayraktar', 'BR-01', 1, 0, 5, 1, true); """; } /// /// seed_25_missions: 5 in January 2026, 20 in February 2026; CreatedDate /// values are spaced ≥ 1 second apart so DESC ordering is deterministic /// (FT-P-08 risk #2). Names alternate between "Recon-N" and "OPS-N" so /// the case-INSENSITIVE name=re filter returns >0 rows. /// public static class TwentyFiveMissions { public static readonly Guid VehicleId = Guid.Parse("11111111-aaaa-aaaa-aaaa-000000000001"); // The 5 January CreatedDate values are 2026-01-15T10:00:[00..04]Z so // every mission has a distinct, deterministic CreatedDate. public static string Sql { get { var sb = new System.Text.StringBuilder(); sb.AppendLine(""" INSERT INTO vehicles (id, type, model, name, fuel_type, battery_capacity, engine_consumption, engine_consumption_idle, is_default) VALUES ('11111111-aaaa-aaaa-aaaa-000000000001', 0, 'Bayraktar', 'BR-fixture-25', 1, 0, 5, 1, false); """); sb.AppendLine("INSERT INTO missions (id, created_date, name, vehicle_id) VALUES"); for (var i = 0; i < 25; i++) { var month = i < 5 ? "01" : "02"; var day = i < 5 ? (15 + i).ToString("D2") : (1 + (i - 5)).ToString("D2"); var second = (i % 60).ToString("D2"); var minute = ((i / 60) % 60).ToString("D2"); var name = (i % 2 == 0) ? $"Recon-{i:D2}" : $"OPS-{i:D2}"; var idHex = (i + 1).ToString("D12"); sb.Append("('22222222-bbbb-bbbb-bbbb-").Append(idHex).Append("', "); sb.Append("'2026-").Append(month).Append('-').Append(day); sb.Append('T').Append("10:").Append(minute).Append(':').Append(second).Append("Z', "); sb.Append('\'').Append(name).Append("', "); sb.Append("'11111111-aaaa-aaaa-aaaa-000000000001')"); sb.AppendLine(i == 24 ? ";" : ","); } return sb.ToString(); } } } /// /// seed_5_waypoints_unordered: 5 waypoints under one mission with /// OrderNum values [3, 1, 2, 5, 4] inserted in that order. The shuffled /// insert order forces FT-P-13 to fail loudly if the SUT forgets the /// OrderBy(w => w.OrderNum) clause. /// public static class FiveWaypointsUnordered { public static readonly Guid VehicleId = Guid.Parse("11111111-cccc-cccc-cccc-000000000001"); public static readonly Guid MissionId = Guid.Parse("22222222-cccc-cccc-cccc-000000000001"); public const string Sql = """ INSERT INTO vehicles (id, type, model, name, fuel_type, battery_capacity, engine_consumption, engine_consumption_idle, is_default) VALUES ('11111111-cccc-cccc-cccc-000000000001', 0, 'Bayraktar', 'BR-wp-fixture', 1, 0, 5, 1, false); INSERT INTO missions (id, created_date, name, vehicle_id) VALUES ('22222222-cccc-cccc-cccc-000000000001', '2026-05-14T00:00:00Z', 'wp-fixture', '11111111-cccc-cccc-cccc-000000000001'); INSERT INTO waypoints (id, mission_id, lat, lon, mgrs, waypoint_source, waypoint_objective, order_num, height) VALUES ('33333333-cccc-cccc-cccc-000000000001', '22222222-cccc-cccc-cccc-000000000001', 50.45, 30.52, NULL, 0, 0, 3, 100), ('33333333-cccc-cccc-cccc-000000000002', '22222222-cccc-cccc-cccc-000000000001', 50.46, 30.53, NULL, 0, 0, 1, 110), ('33333333-cccc-cccc-cccc-000000000003', '22222222-cccc-cccc-cccc-000000000001', 50.47, 30.54, NULL, 0, 0, 2, 120), ('33333333-cccc-cccc-cccc-000000000004', '22222222-cccc-cccc-cccc-000000000001', 50.48, 30.55, NULL, 0, 0, 5, 130), ('33333333-cccc-cccc-cccc-000000000005', '22222222-cccc-cccc-cccc-000000000001', 50.49, 30.56, NULL, 0, 0, 4, 140); """; } public static void Apply(string sql) { using var conn = new NpgsqlConnection(TestEnvironment.DbSideChannel); conn.Open(); using var cmd = conn.CreateCommand(); cmd.CommandText = sql; cmd.ExecuteNonQuery(); } }