using System.Text.Json;
using Dapper;
using JdeScoping.Core.Models.Search;
using Microsoft.Data.SqlClient;
namespace JdeScoping.Database.Tests.Infrastructure;
///
/// xUnit Collection definition to disable parallel execution for database tests.
/// All test classes using [Collection("DatabaseTests")] run sequentially.
///
[CollectionDefinition("DatabaseTests")]
public class DatabaseTestCollection : ICollectionFixture
{
}
///
/// Shared fixture for database tests. Ensures database is available.
///
public class DatabaseTestFixture : IAsyncLifetime
{
///
/// Connection string for the test database.
/// Uses SA credentials from db_info.md for local development.
///
public const string ConnectionString =
"Server=localhost,1434;Database=ScopingTool;User Id=sa;Password=ScopingTool_SA_2024Dev;TrustServerCertificate=true";
public async Task InitializeAsync()
{
// Verify database is accessible
using var connection = new SqlConnection(ConnectionString);
await connection.OpenAsync();
}
public Task DisposeAsync() => Task.CompletedTask;
}
///
/// Base class for database function tests.
/// Each test gets its own connection and cleans up created data.
///
[Collection("DatabaseTests")]
public abstract class DatabaseTestBase : IAsyncLifetime
{
protected SqlConnection Connection { get; private set; } = null!;
private readonly List _createdSearchIds = [];
public async Task InitializeAsync()
{
Connection = new SqlConnection(DatabaseTestFixture.ConnectionString);
await Connection.OpenAsync();
}
public async Task DisposeAsync()
{
// Clean up test data
foreach (var id in _createdSearchIds)
{
await Connection.ExecuteAsync("DELETE FROM dbo.Search WHERE ID = @Id", new { Id = id });
}
await Connection.DisposeAsync();
}
///
/// Insert a test search with the given criteria and return the ID.
///
protected async Task InsertTestSearchAsync(SearchCriteria criteria, string userName = "testuser", string name = "Test Search")
{
var criteriaJson = JsonSerializer.Serialize(criteria);
var id = await Connection.QuerySingleAsync(
@"INSERT INTO dbo.Search (UserName, Name, Status, Criteria)
OUTPUT INSERTED.ID
VALUES (@UserName, @Name, 0, @Criteria)",
new { UserName = userName, Name = name, Criteria = criteriaJson });
_createdSearchIds.Add(id);
return id;
}
///
/// Insert a test search with raw criteria JSON (for testing invalid JSON scenarios).
///
protected async Task InsertTestSearchWithRawCriteriaAsync(string? criteriaJson, string userName = "testuser", string name = "Test Search")
{
var id = await Connection.QuerySingleAsync(
@"INSERT INTO dbo.Search (UserName, Name, Status, Criteria)
OUTPUT INSERTED.ID
VALUES (@UserName, @Name, 0, @Criteria)",
new { UserName = userName, Name = name, Criteria = criteriaJson });
_createdSearchIds.Add(id);
return id;
}
}