< Summary

Information
Class: TestUtilities.FirestoreFixture
Assembly: TestUtilities
File(s): /home/runner/work/KicktippAi/KicktippAi/src/TestUtilities/FirestoreFixture.cs
Line coverage
97%
Covered lines: 40
Uncovered lines: 1
Coverable lines: 41
Total lines: 107
Line coverage: 97.5%
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
.ctor()100%11100%
InitializeAsync()100%11100%
ClearContextDocumentsAsync()100%11100%
ClearPredictionsAsync()100%11100%
ClearKpiDocumentsAsync()100%11100%
ClearMatchOutcomesAsync()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 MatchOutcomesParallelKey = "Firestore:MatchOutcomes";
 22    public const string OrchestratorIntegrationParallelKey = "Firestore:OrchestratorIntegration";
 23
 24    private const string ContextDocumentsCollection = "context-documents";
 25    private const string MatchPredictionsCollection = "match-predictions";
 26    private const string MatchesCollection = "matches";
 27    private const string BonusPredictionsCollection = "bonus-predictions";
 28    private const string KpiDocumentsCollection = "kpi-documents";
 29    private const string MatchOutcomesCollection = "match-outcomes";
 30    private const string EmulatorImageTag = "google/cloud-sdk:550.0.0-emulators";
 31
 32    private readonly FirestoreContainer _container;
 33
 34    public FirestoreDb Db { get; private set; } = null!;
 135    public string ProjectId { get; } = $"test-project-{Guid.NewGuid():N}";
 36
 137    public FirestoreFixture()
 38    {
 139        _container = new FirestoreBuilder()
 140            .WithImage(EmulatorImageTag)
 141            .WithEnvironment("CLOUDSDK_CORE_CHECK_GCE_METADATA", "false")
 142            .Build();
 143    }
 44
 45    public async Task InitializeAsync()
 46    {
 147        await _container.StartAsync();
 48
 149        var firestoreDbBuilder = new FirestoreDbBuilder
 150        {
 151            ProjectId = ProjectId,
 152            Endpoint = _container.GetEmulatorEndpoint(),
 153            ChannelCredentials = ChannelCredentials.Insecure
 154        };
 55
 156        Db = await firestoreDbBuilder.BuildAsync();
 157    }
 58
 59    public async Task ClearContextDocumentsAsync()
 60    {
 161        await ClearCollectionAsync(ContextDocumentsCollection);
 162    }
 63
 64    public async Task ClearPredictionsAsync()
 65    {
 166        await Task.WhenAll(
 167            ClearCollectionAsync(MatchPredictionsCollection),
 168            ClearCollectionAsync(MatchesCollection),
 169            ClearCollectionAsync(BonusPredictionsCollection));
 170    }
 71
 72    public async Task ClearKpiDocumentsAsync()
 73    {
 174        await ClearCollectionAsync(KpiDocumentsCollection);
 175    }
 76
 77    public async Task ClearMatchOutcomesAsync()
 78    {
 179        await ClearCollectionAsync(MatchOutcomesCollection);
 180    }
 81
 82    public async Task ClearOrchestratorIntegrationAsync()
 83    {
 184        await Task.WhenAll(
 185            ClearPredictionsAsync(),
 186            ClearContextDocumentsAsync(),
 187            ClearMatchOutcomesAsync());
 188    }
 89
 90    private async Task ClearCollectionAsync(string collectionName)
 91    {
 192        using var httpClient = new HttpClient();
 193        var endpoint = _container.GetEmulatorEndpoint().TrimEnd('/');
 194        var deleteUrl = $"{endpoint}/emulator/v1/projects/{ProjectId}/databases/(default)/documents/{collectionName}";
 95
 196        var response = await httpClient.DeleteAsync(deleteUrl);
 197        if (!response.IsSuccessStatusCode && response.StatusCode != System.Net.HttpStatusCode.NotFound)
 98        {
 099            response.EnsureSuccessStatusCode();
 100        }
 1101    }
 102
 103    public async ValueTask DisposeAsync()
 104    {
 1105        await _container.DisposeAsync();
 1106    }
 107}