using System.Net; using MeterVault.Infrastructure.Import; using MeterVault.Infrastructure.Persistence; using MeterVault.Integration.Tests.Costing; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using static MeterVault.Integration.Tests.Costing.CostSandbox; namespace MeterVault.Integration.Tests.Overview; /// /// The Overview page (brief §7.1) rendered by the real app on the frozen clock of /// (server prerender, which reads the initial load): this month to date of the seeded instance says there is no data /// and offers the latest month as its own period instead of showing it; the previous year shows the sheet's bill with /// the energy type cards, the attention item with its tariff link, the change table and the composition, in English and /// German; a manual-cost-only instance shows its month without a meter. Interactive behaviour (chart, toggles) is covered /// by the pure tests and the browser check. /// [Collection("Timescale")] public sealed class OverviewPageTests(TimescaleFixture fx) : IAsyncLifetime { public async Task InitializeAsync() { await using var db = fx.CreateContext(); await ClearDataAsync(db); } public async Task DisposeAsync() { await using var db = fx.CreateContext(); await ClearDataAsync(db); } [Fact] public async Task The_seeded_overview_explains_an_empty_month_and_shows_the_previous_year_s_bill() { await LoadReferenceDataAsync(); int strom; await using (var db = fx.CreateContext()) { strom = await db.EnergyTypes.Where(t => t.Key == "electricity").Select(t => (int)t.Id).FirstAsync(); } using var app = new FrozenApp(fx.ConnectionString); // Month to date (the default): no data, the dates that have data, and the latest month as its own period — the // panels are not silently switched to May. var empty = await app.GetAsync("/"); Assert.Contains("The app on the frozen clock of ; pages come back HTML-decoded. private sealed class FrozenApp : IDisposable { private readonly MeterVaultAppFactory _root; private readonly WebApplicationFactory _app; public FrozenApp(string connectionString) { _root = new MeterVaultAppFactory(connectionString); _app = _root.WithWebHostBuilder(builder => builder.ConfigureTestServices(services => services.AddSingleton(new FixedTimeProvider(Now)))); } public async Task GetAsync(string path, string culture = "en") { using var client = _app.CreateClient(); client.DefaultRequestHeaders.Add( "Cookie", CookieRequestCultureProvider.DefaultCookieName + "=" + Uri.EscapeDataString(CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)))); using var response = await client.GetAsync(new Uri(path, UriKind.Relative)); response.EnsureSuccessStatusCode(); return WebUtility.HtmlDecode(await response.Content.ReadAsStringAsync()); } public void Dispose() { _app.Dispose(); _root.Dispose(); } } }