using System.Net.Http.Json; using FluentAssertions; using foodmarket.IntegrationTests.Support; using Microsoft.Extensions.DependencyInjection; using Xunit; namespace foodmarket.IntegrationTests; /// Тест рендеринга ежедневной сводки OwnerDailySummaryJob. /// Сравниваем text-output с ожидаемым: заголовок org-name, цифры, /// топ-3 + low-stock. Не отправляем реальное сообщение — тестируем /// чистую функцию RenderSummaryAsync (она publicна именно ради тестов). [Collection(ApiCollection.Name)] public class TelegramOwnerSummaryTests { private readonly ApiFactory _factory; public TelegramOwnerSummaryTests(ApiFactory factory) => _factory = factory; [Fact] public async Task Render_summary_contains_org_name_and_metrics() { var actor = new ApiActor(_factory.CreateClient()); var email = $"tg-{Guid.NewGuid():N}@example.kz"; (await actor.SignupAsync(email, "Passw0rd!", "Telegram Test Org")).EnsureSuccessStatusCode(); var token = await actor.TokenAsync(email, "Passw0rd!"); actor.UseToken(token); var meDoc = await actor.GetJsonAsync("/api/me"); var orgId = Guid.Parse(meDoc.GetProperty("orgId").GetString()!); // Засеем демо-данные чтобы было что показать (50 товаров + 30 продаж за // последние 30 дней + пара low-stock). (await actor.Http.PostAsync("/api/admin/seed-demo", null)).EnsureSuccessStatusCode(); // Вытащим джоб напрямую из DI и сгенерируем текст. using var scope = _factory.Services.CreateScope(); var job = scope.ServiceProvider.GetRequiredService(); var text = await job.RenderSummaryAsync(orgId, "Telegram Test Org", CancellationToken.None); // Базовые поля text.Should().Contain("Food Market"); text.Should().Contain("Telegram Test Org"); text.Should().Contain("Выручка"); text.Should().Contain("Чеков"); // HTML-форматирование parse_mode=HTML text.Should().Contain(""); // На свежей орге за «вчера» может ничего не быть (demo сеется на даты // сегодня-30..сегодня). В разном таймзоне может попасть, может нет — // главное чтобы render не падал и базовая структура была. } }