< Summary

Information
Class: TestUtilities.FirestoreFixture
Assembly: TestUtilities
File(s): /home/runner/work/KicktippAi/KicktippAi/src/TestUtilities/FirestoreFixture.cs
Line coverage
97%
Covered lines: 38
Uncovered lines: 1
Coverable lines: 39
Total lines: 99
Line coverage: 97.4%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Db()100%11100%
set_Db(...)100%11100%
get_ProjectId()100%11100%
.ctor()100%11100%
InitializeAsync()100%11100%
ClearContextDocumentsAsync()100%11100%
ClearPredictionsAsync()100%11100%
ClearKpiDocumentsAsync()100%11100%
ClearOrchestratorIntegrationAsync()100%11100%
ClearCollectionAsync()100%1185.71%
DisposeAsync()100%11100%

File(s)

/home/runner/work/KicktippAi/KicktippAi/src/TestUtilities/FirestoreFixture.cs

#LineLine coverage
 1using Google.Cloud.Firestore;
 2using Grpc.Core;
 3using Testcontainers.Firestore;
 4using TUnit.Core.Interfaces;
 5
 6namespace TestUtilities;
 7
 8/// <summary>
 9/// Shared Testcontainers-based Firestore emulator fixture for integration tests.
 10/// </summary>
 11/// <remarks>
 12/// This fixture is shared across test projects so repository tests and higher-level
 13/// integration tests use the same emulator lifecycle and collection-clearing behavior.
 14/// </remarks>
 15public sealed class FirestoreFixture : IAsyncInitializer, IAsyncDisposable
 16{
 17    public const string SharedKey = "FirestoreEmulator";
 18    public const string ContextDocumentsParallelKey = "Firestore:ContextDocuments";
 19    public const string PredictionsParallelKey = "Firestore:Predictions";
 20    public const string KpiParallelKey = "Firestore:Kpi";
 21    public const string OrchestratorIntegrationParallelKey = "Firestore:OrchestratorIntegration";
 22
 23    private const string ContextDocumentsCollection = "context-documents";
 24    private const string MatchPredictionsCollection = "match-predictions";
 25    private const string MatchesCollection = "matches";
 26    private const string BonusPredictionsCollection = "bonus-predictions";
 27    private const string KpiDocumentsCollection = "kpi-documents";
 28    private const string EmulatorImageTag = "google/cloud-sdk:550.0.0-emulators";
 29
 30    private readonly FirestoreContainer _container;
 31
 132    public FirestoreDb Db { get; private set; } = null!;
 133    public string ProjectId { get; } = $"test-project-{Guid.NewGuid():N}";
 34
 135    public FirestoreFixture()
 36    {
 137        _container = new FirestoreBuilder()
 138            .WithImage(EmulatorImageTag)
 139            .WithEnvironment("CLOUDSDK_CORE_CHECK_GCE_METADATA", "false")
 140            .Build();
 141    }
 42
 43    public async Task InitializeAsync()
 44    {
 145        await _container.StartAsync();
 46
 147        var firestoreDbBuilder = new FirestoreDbBuilder
 148        {
 149            ProjectId = ProjectId,
 150            Endpoint = _container.GetEmulatorEndpoint(),
 151            ChannelCredentials = ChannelCredentials.Insecure
 152        };
 53
 154        Db = await firestoreDbBuilder.BuildAsync();
 155    }
 56
 57    public async Task ClearContextDocumentsAsync()
 58    {
 159        await ClearCollectionAsync(ContextDocumentsCollection);
 160    }
 61
 62    public async Task ClearPredictionsAsync()
 63    {
 164        await Task.WhenAll(
 165            ClearCollectionAsync(MatchPredictionsCollection),
 166            ClearCollectionAsync(MatchesCollection),
 167            ClearCollectionAsync(BonusPredictionsCollection));
 168    }
 69
 70    public async Task ClearKpiDocumentsAsync()
 71    {
 172        await ClearCollectionAsync(KpiDocumentsCollection);
 173    }
 74
 75    public async Task ClearOrchestratorIntegrationAsync()
 76    {
 177        await Task.WhenAll(
 178            ClearPredictionsAsync(),
 179            ClearContextDocumentsAsync());
 180    }
 81
 82    private async Task ClearCollectionAsync(string collectionName)
 83    {
 184        using var httpClient = new HttpClient();
 185        var endpoint = _container.GetEmulatorEndpoint().TrimEnd('/');
 186        var deleteUrl = $"{endpoint}/emulator/v1/projects/{ProjectId}/databases/(default)/documents/{collectionName}";
 87
 188        var response = await httpClient.DeleteAsync(deleteUrl);
 189        if (!response.IsSuccessStatusCode && response.StatusCode != System.Net.HttpStatusCode.NotFound)
 90        {
 091            response.EnsureSuccessStatusCode();
 92        }
 193    }
 94
 95    public async ValueTask DisposeAsync()
 96    {
 197        await _container.DisposeAsync();
 198    }
 99}