using MeterVault.Core.Domain; using MeterVault.Infrastructure.Backup; using MeterVault.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; namespace MeterVault.Integration.Tests; /// /// JSON config export/import (SDD §10): a round-trip through an emptied database preserves the /// relationships (meter → energy type, meter-scoped tariff, category membership) after id remapping. /// [Collection("Timescale")] public sealed class ExportRoundTripTests(TimescaleFixture fx) { [Fact] public async Task Export_then_import_preserves_relationships() { string json; await using (var db = fx.CreateContext()) { await WipeAllAsync(db); await DatabaseSeeder.SeedAsync(db); var elec = await db.EnergyTypes.FirstAsync(t => t.Key == "electricity"); var strom = await db.CostCategories.FirstAsync(c => c.Name == "Strom"); var meter = new Meter { Name = "Export Meter", EnergyTypeId = elec.Id, Mode = MeterMode.CumulativeCounter, Unit = "kWh" }; db.Meters.Add(meter); await db.SaveChangesAsync(); db.Tariffs.Add(new Tariff { ScopeType = TariffScope.Meter, ScopeId = meter.Id, Component = TariffComponent.UnitPrice, Value = 0.30, Unit = "EUR/kWh", ValidFrom = new DateOnly(2024, 1, 1) }); db.CostCategoryMembers.Add(new CostCategoryMember { CategoryId = strom.Id, MeterId = meter.Id }); await db.SaveChangesAsync(); json = await new ExportService(db).ExportJsonAsync(); } await using (var db = fx.CreateContext()) { await WipeAllAsync(db); await new ExportService(db).ImportJsonAsync(json); } await using (var db = fx.CreateContext()) { var meter = await db.Meters.SingleAsync(m => m.Name == "Export Meter"); Assert.True(await db.EnergyTypes.AnyAsync(t => t.Id == meter.EnergyTypeId)); var tariff = await db.Tariffs.SingleAsync(t => t.ScopeType == TariffScope.Meter); Assert.Equal(meter.Id, tariff.ScopeId); var member = await db.CostCategoryMembers.SingleAsync(); Assert.Equal(meter.Id, member.MeterId); Assert.True(await db.CostCategories.AnyAsync(c => c.Id == member.CategoryId)); await WipeAllAsync(db); } } private static async Task WipeAllAsync(MeterVaultDbContext db) { await db.Consumption.ExecuteDeleteAsync(); await db.Readings.ExecuteDeleteAsync(); await db.MeterEvents.ExecuteDeleteAsync(); await db.ManualCosts.ExecuteDeleteAsync(); await db.CostCategoryMembers.ExecuteDeleteAsync(); await db.Tariffs.ExecuteDeleteAsync(); await db.Tanks.ExecuteDeleteAsync(); await db.MeterSources.ExecuteDeleteAsync(); await db.Meters.ExecuteDeleteAsync(); await db.IngestionEndpoints.ExecuteDeleteAsync(); await db.CostCategories.ExecuteDeleteAsync(); await db.EnergyTypes.ExecuteDeleteAsync(); await db.AppSettings.ExecuteDeleteAsync(); } }