테스트 DB 계약과 실행 안전성 정렬
ci / backend (push) Failing after 0s
ci / static (push) Failing after 6s
ci / backend (pull_request) Failing after 1s
ci / static (pull_request) Failing after 7s
Build & Test with Secrets / build (pull_request) Failing after 1s
ci / frontend (push) Failing after 48s
Build & Test with Secrets / security-scan (pull_request) Successful in 5s
Build & Test with Secrets / frontend (pull_request) Failing after 1m23s
ci / frontend (pull_request) Failing after 1m32s
Build & Test with Secrets / notification (pull_request) Failing after 2s
ci / backend (push) Failing after 0s
ci / static (push) Failing after 6s
ci / backend (pull_request) Failing after 1s
ci / static (pull_request) Failing after 7s
Build & Test with Secrets / build (pull_request) Failing after 1s
ci / frontend (push) Failing after 48s
Build & Test with Secrets / security-scan (pull_request) Successful in 5s
Build & Test with Secrets / frontend (pull_request) Failing after 1m23s
ci / frontend (pull_request) Failing after 1m32s
Build & Test with Secrets / notification (pull_request) Failing after 2s
This commit is contained in:
@@ -26,8 +26,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
|
||||
public ApprovalWorkflowTests()
|
||||
{
|
||||
_connectionString = Environment.GetEnvironmentVariable("KARTSELL_POSTGRES")
|
||||
?? "Host=localhost;Port=5432;Database=kartselldb;Username=kartsell;Password=kartsell4321@!";
|
||||
_connectionString = TestDatabaseConnection.GetConnectionString();
|
||||
_dataSource = new NpgsqlDataSourceBuilder(_connectionString).Build();
|
||||
_connectionFactory = new NpgsqlConnectionFactory(_dataSource);
|
||||
}
|
||||
@@ -67,8 +66,8 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
""",
|
||||
new[]
|
||||
{
|
||||
new { RunId = runId1, ModelId = modelId, Start = new DateOnly(2024, 1, 2), End = new DateOnly(2024, 8, 31) },
|
||||
new { RunId = runId2, ModelId = modelId, Start = new DateOnly(2024, 1, 2), End = new DateOnly(2024, 8, 31) }
|
||||
new { RunId = runId1, ModelId = modelId, Start = new DateTime(2024, 1, 2), End = new DateTime(2024, 8, 31) },
|
||||
new { RunId = runId2, ModelId = modelId, Start = new DateTime(2024, 1, 2), End = new DateTime(2024, 8, 31) }
|
||||
});
|
||||
|
||||
// Create approvals: one Pending, one Approved
|
||||
@@ -115,7 +114,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
INSERT INTO model_operations.shadow_run (run_id, model_id, window_start, window_end, status)
|
||||
VALUES (@RunId, @ModelId, @Start, @End, 'EvaluationComplete')
|
||||
""",
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateOnly(2024, 1, 2), End = new DateOnly(2024, 8, 31) });
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateTime(2024, 1, 2), End = new DateTime(2024, 8, 31) });
|
||||
|
||||
await connection.ExecuteAsync("""
|
||||
INSERT INTO model_operations.approval_queue (run_id, model_id, status)
|
||||
@@ -162,7 +161,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
INSERT INTO model_operations.shadow_run (run_id, model_id, window_start, window_end, status)
|
||||
VALUES (@RunId, @ModelId, @Start, @End, 'EvaluationComplete')
|
||||
""",
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateOnly(2024, 1, 2), End = new DateOnly(2024, 8, 31) });
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateTime(2024, 1, 2), End = new DateTime(2024, 8, 31) });
|
||||
|
||||
await connection.ExecuteAsync("""
|
||||
INSERT INTO model_operations.approval_queue (run_id, model_id, status, approved_by, approval_reason)
|
||||
@@ -198,7 +197,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
INSERT INTO model_operations.shadow_run (run_id, model_id, window_start, window_end, status)
|
||||
VALUES (@RunId, @ModelId, @Start, @End, 'EvaluationComplete')
|
||||
""",
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateOnly(2024, 1, 2), End = new DateOnly(2024, 8, 31) });
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateTime(2024, 1, 2), End = new DateTime(2024, 8, 31) });
|
||||
|
||||
await connection.ExecuteAsync("""
|
||||
INSERT INTO model_operations.approval_queue (run_id, model_id, status)
|
||||
@@ -237,7 +236,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
var runId = Guid.NewGuid();
|
||||
var modelId = Guid.NewGuid();
|
||||
var approverId = Guid.NewGuid();
|
||||
var beforeApproval = _clock.UtcNow.DateTime;
|
||||
var beforeApproval = MarketTime.SeoulDateTime(_clock.UtcNow);
|
||||
|
||||
await using var connection = await _connectionFactory.OpenAsync(CancellationToken.None);
|
||||
|
||||
@@ -245,7 +244,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
INSERT INTO model_operations.shadow_run (run_id, model_id, window_start, window_end, status)
|
||||
VALUES (@RunId, @ModelId, @Start, @End, 'EvaluationComplete')
|
||||
""",
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateOnly(2024, 1, 2), End = new DateOnly(2024, 8, 31) });
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateTime(2024, 1, 2), End = new DateTime(2024, 8, 31) });
|
||||
|
||||
await connection.ExecuteAsync("""
|
||||
INSERT INTO model_operations.approval_queue (run_id, model_id, status)
|
||||
@@ -258,7 +257,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
var request = new ApproveRequest(runId, "Approved");
|
||||
var response = await handler.HandleAsync(request, approverId, CancellationToken.None);
|
||||
|
||||
var afterApproval = _clock.UtcNow.DateTime;
|
||||
var afterApproval = MarketTime.SeoulDateTime(_clock.UtcNow);
|
||||
|
||||
// Assert: Timestamps are within expected range
|
||||
var approval = await connection.QuerySingleAsync<(DateTime RequestedAt, DateTime ApprovedAt)>("""
|
||||
@@ -267,7 +266,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
""",
|
||||
new { RunId = runId });
|
||||
|
||||
Assert.True(approval.RequestedAt < approval.ApprovedAt);
|
||||
Assert.True(approval.RequestedAt <= approval.ApprovedAt);
|
||||
Assert.True(approval.ApprovedAt >= beforeApproval && approval.ApprovedAt <= afterApproval.AddSeconds(1));
|
||||
}
|
||||
|
||||
@@ -287,7 +286,7 @@ public sealed class ApprovalWorkflowTests : IAsyncLifetime
|
||||
INSERT INTO model_operations.shadow_run (run_id, model_id, window_start, window_end, status)
|
||||
VALUES (@RunId, @ModelId, @Start, @End, 'EvaluationComplete')
|
||||
""",
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateOnly(2024, 1, 2), End = new DateOnly(2024, 8, 31) });
|
||||
new { RunId = runId, ModelId = modelId, Start = new DateTime(2024, 1, 2), End = new DateTime(2024, 8, 31) });
|
||||
|
||||
// Insert first approval
|
||||
await connection.ExecuteAsync("""
|
||||
|
||||
@@ -18,7 +18,7 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
var connString = Environment.GetEnvironmentVariable("KARTSELL_POSTGRES") ?? DefaultConnString;
|
||||
var connString = TestDatabaseConnection.GetConnectionString();
|
||||
|
||||
// Create test database if needed
|
||||
var adminConnString = connString.Replace("kartsell_migration_test", "postgres");
|
||||
@@ -51,7 +51,7 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
await _dataSource.DisposeAsync();
|
||||
|
||||
// Cleanup test database
|
||||
var adminConnString = Environment.GetEnvironmentVariable("KARTSELL_POSTGRES") ?? DefaultConnString;
|
||||
var adminConnString = TestDatabaseConnection.GetConnectionString();
|
||||
adminConnString = adminConnString.Replace("kartsell_migration_test", "postgres");
|
||||
|
||||
await using var adminConn = new NpgsqlConnection(adminConnString);
|
||||
@@ -149,13 +149,10 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
|
||||
// Assert: All three tables exist
|
||||
Assert.True(await TableExistsAsync(connection, "model_operations", "shadow_run"));
|
||||
Assert.True(await TableExistsAsync(connection, "outbox", "inbox"));
|
||||
Assert.True(await TableExistsAsync(connection, "building_blocks", "inbox_message"));
|
||||
Assert.True(await TableExistsAsync(connection, "model_operations", "approval_queue"));
|
||||
|
||||
// Assert: Foreign keys exist
|
||||
var fkCount = await CountForeignKeysAsync(connection, "outbox", "inbox");
|
||||
Assert.True(fkCount > 0, "inbox should have FK to outbox");
|
||||
|
||||
var aqFkCount = await CountForeignKeysAsync(connection, "model_operations", "approval_queue");
|
||||
Assert.True(aqFkCount > 0, "approval_queue should have FK to shadow_run");
|
||||
}
|
||||
@@ -191,7 +188,8 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
|
||||
// Assert: Data survived, table is unchanged
|
||||
await using var selectCmd = connection.CreateCommand();
|
||||
selectCmd.CommandText = "SELECT COUNT(*) FROM model_operations.shadow_run;";
|
||||
selectCmd.CommandText = "SELECT COUNT(*) FROM model_operations.shadow_run WHERE run_id = @runId;";
|
||||
selectCmd.Parameters.AddWithValue("@runId", runId);
|
||||
var count = (long?)await selectCmd.ExecuteScalarAsync();
|
||||
|
||||
Assert.Equal(1, count);
|
||||
@@ -268,8 +266,9 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
var outboxId = Guid.NewGuid();
|
||||
await using var outboxCmd = connection.CreateCommand();
|
||||
outboxCmd.CommandText = """
|
||||
INSERT INTO outbox.outbox (id, event_type, payload)
|
||||
VALUES (@id, 'TestEvent', '{"test":"data"}'::jsonb);
|
||||
INSERT INTO building_blocks.outbox_message
|
||||
(message_id, event_type, schema_version, payload_json, correlation_id, occurred_at, payload_hash)
|
||||
VALUES (@id, 'TestEvent', 1, '{"test":"data"}'::jsonb, 'test-correlation', CURRENT_TIMESTAMP, 'test-hash');
|
||||
""";
|
||||
outboxCmd.Parameters.AddWithValue("@id", outboxId);
|
||||
await outboxCmd.ExecuteNonQueryAsync();
|
||||
@@ -278,11 +277,10 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
var inboxId = Guid.NewGuid();
|
||||
await using var invalidCmd = connection.CreateCommand();
|
||||
invalidCmd.CommandText = """
|
||||
INSERT INTO outbox.inbox (id, outbox_id, consumer_id, event_type, payload, status)
|
||||
VALUES (@id, @outboxId, 'TestConsumer', 'TestEvent', '{"test":"data"}'::jsonb, 'Processed');
|
||||
INSERT INTO building_blocks.inbox_message (message_id, consumer, status)
|
||||
VALUES (@id, 'TestConsumer', 'Processed');
|
||||
""";
|
||||
invalidCmd.Parameters.AddWithValue("@id", inboxId);
|
||||
invalidCmd.Parameters.AddWithValue("@outboxId", outboxId);
|
||||
|
||||
// Assert: Trigger violation
|
||||
await Assert.ThrowsAsync<PostgresException>(
|
||||
@@ -304,8 +302,9 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
var outboxId = Guid.NewGuid();
|
||||
await using var outboxCmd = connection.CreateCommand();
|
||||
outboxCmd.CommandText = """
|
||||
INSERT INTO outbox.outbox (id, event_type, payload)
|
||||
VALUES (@id, 'TestEvent', '{"test":"data"}'::jsonb);
|
||||
INSERT INTO building_blocks.outbox_message
|
||||
(message_id, event_type, schema_version, payload_json, correlation_id, occurred_at, payload_hash)
|
||||
VALUES (@id, 'TestEvent', 1, '{"test":"data"}'::jsonb, 'test-correlation', CURRENT_TIMESTAMP, 'test-hash');
|
||||
""";
|
||||
outboxCmd.Parameters.AddWithValue("@id", outboxId);
|
||||
await outboxCmd.ExecuteNonQueryAsync();
|
||||
@@ -313,8 +312,8 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
// Insert first inbox record
|
||||
await using var insertCmd = connection.CreateCommand();
|
||||
insertCmd.CommandText = """
|
||||
INSERT INTO outbox.inbox (outbox_id, consumer_id, event_type, payload, status)
|
||||
VALUES (@outboxId, 'Consumer1', 'TestEvent', '{"test":"data"}'::jsonb, 'Pending');
|
||||
INSERT INTO building_blocks.inbox_message (message_id, consumer, status)
|
||||
VALUES (@outboxId, 'Consumer1', 'Pending');
|
||||
""";
|
||||
insertCmd.Parameters.AddWithValue("@outboxId", outboxId);
|
||||
await insertCmd.ExecuteNonQueryAsync();
|
||||
@@ -322,8 +321,8 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
// Act: Try to insert duplicate (same outbox_id + consumer_id)
|
||||
await using var duplicateCmd = connection.CreateCommand();
|
||||
duplicateCmd.CommandText = """
|
||||
INSERT INTO outbox.inbox (outbox_id, consumer_id, event_type, payload, status)
|
||||
VALUES (@outboxId, 'Consumer1', 'TestEvent', '{"test":"data"}'::jsonb, 'Pending');
|
||||
INSERT INTO building_blocks.inbox_message (message_id, consumer, status)
|
||||
VALUES (@outboxId, 'Consumer1', 'Pending');
|
||||
""";
|
||||
duplicateCmd.Parameters.AddWithValue("@outboxId", outboxId);
|
||||
|
||||
@@ -479,7 +478,7 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
{
|
||||
await using var connection = await _dataSource.OpenConnectionAsync();
|
||||
await using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = File.ReadAllText("src/KArtSell.DbMigrator/0008_CreateShadowRunTable.sql");
|
||||
cmd.CommandText = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "migrations", "0022_model_operations_execution_schema.sql"));
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
@@ -487,7 +486,7 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
{
|
||||
await using var connection = await _dataSource.OpenConnectionAsync();
|
||||
await using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = File.ReadAllText("src/KArtSell.DbMigrator/0009_CreateInboxTable.sql");
|
||||
cmd.CommandText = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "migrations", "0023_inbox_status_contract.sql"));
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
@@ -495,7 +494,7 @@ public sealed class DbUpMigrationTests : IAsyncLifetime
|
||||
{
|
||||
await using var connection = await _dataSource.OpenConnectionAsync();
|
||||
await using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = File.ReadAllText("src/KArtSell.DbMigrator/0010_CreateApprovalQueueTable.sql");
|
||||
cmd.CommandText = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "migrations", "0022_model_operations_execution_schema.sql"));
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,14 @@
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<NoWarn>$(NoWarn);CA1001;CA1859;DAP005</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.Development.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="../../db/migrations/*.sql" Link="migrations/%(Filename)%(Extension)">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../src/KArtSell.BuildingBlocks/KArtSell.BuildingBlocks.csproj" />
|
||||
<ProjectReference Include="../../src/KArtSell.Host/KArtSell.Host.csproj" />
|
||||
|
||||
@@ -26,8 +26,7 @@ public sealed class OutboxInboxCrashRecoveryTests : IAsyncLifetime
|
||||
|
||||
public OutboxInboxCrashRecoveryTests()
|
||||
{
|
||||
_connectionString = Environment.GetEnvironmentVariable("KARTSELL_POSTGRES")
|
||||
?? "Host=localhost;Port=5432;Database=kartselldb;Username=kartsell;Password=kartsell4321@!";
|
||||
_connectionString = TestDatabaseConnection.GetConnectionString();
|
||||
_dataSource = new NpgsqlDataSourceBuilder(_connectionString).Build();
|
||||
_connectionFactory = new NpgsqlConnectionFactory(_dataSource);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ public sealed class OutboxPollerJobTests : IAsyncLifetime
|
||||
|
||||
public OutboxPollerJobTests()
|
||||
{
|
||||
_connectionString = Environment.GetEnvironmentVariable("KARTSELL_POSTGRES")
|
||||
?? "Host=localhost;Port=5432;Database=kartselldb;Username=kartsell;Password=kartsell4321@!";
|
||||
_connectionString = TestDatabaseConnection.GetConnectionString();
|
||||
_dataSource = new NpgsqlDataSourceBuilder(_connectionString).Build();
|
||||
_connectionFactory = new NpgsqlConnectionFactory(_dataSource);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
|
||||
public ShadowRunGate3Tests()
|
||||
{
|
||||
_connectionString = Environment.GetEnvironmentVariable("KARTSELL_POSTGRES")
|
||||
?? "Host=localhost;Port=5432;Database=kartselldb;Username=kartsell;Password=kartsell4321@!";
|
||||
_connectionString = TestDatabaseConnection.GetConnectionString();
|
||||
_dataSource = new NpgsqlDataSourceBuilder(_connectionString).Build();
|
||||
_connectionFactory = new NpgsqlConnectionFactory(_dataSource);
|
||||
}
|
||||
@@ -86,8 +85,8 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
{
|
||||
RunId = runId,
|
||||
ModelId = modelId,
|
||||
Start = new DateOnly(2024, 1, 2),
|
||||
End = new DateOnly(2024, 8, 31),
|
||||
Start = new DateTime(2024, 1, 2),
|
||||
End = new DateTime(2024, 8, 31),
|
||||
Status = "EvaluationComplete",
|
||||
Now = now,
|
||||
Gates = validationGates,
|
||||
@@ -137,8 +136,8 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
{
|
||||
RunId = runId,
|
||||
ModelId = modelId,
|
||||
Start = new DateOnly(2024, 1, 2),
|
||||
End = new DateOnly(2024, 8, 31),
|
||||
Start = new DateTime(2024, 1, 2),
|
||||
End = new DateTime(2024, 8, 31),
|
||||
Status = "EvaluationComplete",
|
||||
Now = now,
|
||||
Gates = validationGates
|
||||
@@ -168,7 +167,7 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
// Arrange: Create shadow run that passes all gates
|
||||
var runId = Guid.NewGuid();
|
||||
var modelId = Guid.NewGuid();
|
||||
var now = _clock.UtcNow.DateTime;
|
||||
var now = MarketTime.SeoulDateTime(_clock.UtcNow);
|
||||
|
||||
var validationGates = """
|
||||
{
|
||||
@@ -190,8 +189,8 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
{
|
||||
RunId = runId,
|
||||
ModelId = modelId,
|
||||
Start = new DateOnly(2024, 1, 2),
|
||||
End = new DateOnly(2024, 8, 31),
|
||||
Start = new DateTime(2024, 1, 2),
|
||||
End = new DateTime(2024, 8, 31),
|
||||
Status = "EvaluationComplete",
|
||||
Now = now,
|
||||
Gates = validationGates
|
||||
@@ -227,7 +226,7 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
var runId = Guid.NewGuid();
|
||||
var modelId = Guid.NewGuid();
|
||||
var correlationId = Guid.NewGuid().ToString();
|
||||
var now = _clock.UtcNow.DateTime;
|
||||
var now = MarketTime.SeoulDateTime(_clock.UtcNow);
|
||||
|
||||
var validationGates = """{"all_gates_passed": true}""";
|
||||
|
||||
@@ -243,8 +242,8 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
{
|
||||
RunId = runId,
|
||||
ModelId = modelId,
|
||||
Start = new DateOnly(2024, 1, 2),
|
||||
End = new DateOnly(2024, 8, 31),
|
||||
Start = new DateTime(2024, 1, 2),
|
||||
End = new DateTime(2024, 8, 31),
|
||||
Status = "EvaluationComplete",
|
||||
Now = now,
|
||||
Gates = validationGates
|
||||
@@ -255,13 +254,13 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
await connection.ExecuteAsync("""
|
||||
INSERT INTO building_blocks.outbox_message
|
||||
(message_id, event_type, schema_version, payload_json, correlation_id, occurred_at, payload_hash, published_at)
|
||||
VALUES (@EventId, @EventType, 1, @Payload, @CorrelationId, @Now, @Hash, @Now)
|
||||
VALUES (@EventId, @EventType, 1, CAST(@Payload AS jsonb), @CorrelationId, @Now, @Hash, @Now)
|
||||
""",
|
||||
new
|
||||
{
|
||||
EventId = eventId,
|
||||
EventType = "ShadowRunCompleted",
|
||||
Payload = $$$"""{{"runId":"{runId}","modelId":"{modelId}"}}""",
|
||||
Payload = $"{{\"runId\":\"{runId}\",\"modelId\":\"{modelId}\"}}",
|
||||
CorrelationId = correlationId,
|
||||
Now = now,
|
||||
Hash = "hash123"
|
||||
@@ -310,8 +309,8 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
{
|
||||
RunId = runId,
|
||||
ModelId = modelId,
|
||||
Start = new DateOnly(2024, 1, 2),
|
||||
End = new DateOnly(2024, 8, 31),
|
||||
Start = new DateTime(2024, 1, 2),
|
||||
End = new DateTime(2024, 8, 31),
|
||||
Status = "EvaluationComplete",
|
||||
Phase = phaseAnalysis
|
||||
});
|
||||
@@ -364,8 +363,8 @@ public sealed class ShadowRunGate3Tests : IAsyncLifetime
|
||||
{
|
||||
RunId = runId,
|
||||
ModelId = modelId,
|
||||
Start = new DateOnly(2024, 1, 2),
|
||||
End = new DateOnly(2024, 8, 31),
|
||||
Start = new DateTime(2024, 1, 2),
|
||||
End = new DateTime(2024, 8, 31),
|
||||
Now = now,
|
||||
Gates = validationGates
|
||||
});
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace KArtSell.Integration.Tests;
|
||||
|
||||
internal static class TestDatabaseConnection
|
||||
{
|
||||
public static string GetConnectionString()
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "appsettings.Development.json");
|
||||
if (!File.Exists(path))
|
||||
throw new InvalidOperationException($"Integration test settings are required: {path}");
|
||||
|
||||
using var document = JsonDocument.Parse(File.ReadAllText(path));
|
||||
if (!document.RootElement.TryGetProperty("ConnectionStrings", out var connectionStrings) ||
|
||||
!connectionStrings.TryGetProperty("Postgres", out var postgres) ||
|
||||
string.IsNullOrWhiteSpace(postgres.GetString()))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"ConnectionStrings:Postgres is required in appsettings.Development.json.");
|
||||
}
|
||||
|
||||
return postgres.GetString()!;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user