using System.Text.Json; using FluentAssertions; using foodmarket.Shared.Pos.V1; using Xunit; namespace foodmarket.UnitTests; /// Контракт POS — public API: ломая его, мы ломаем все Windows-кассы /// в поле. Тестируем сериализацию round-trip + наличие required-полей. /// При попытке убрать поле или поменять тип компиляция этих тестов упадёт. public class PosContractsTests { [Fact] public void Product_sync_dto_round_trips() { var dto = new ProductSyncDto { Id = Guid.NewGuid(), Name = "Молоко 1л", Article = "M-001", Barcodes = new[] { "1234567890123", "2345678901234" }, UnitCode = "л", Packaging = 1, VatPercent = 12m, VatEnabled = true, IsMarked = false, IsArchived = false, UpdatedAt = DateTime.UtcNow, }; var json = JsonSerializer.Serialize(dto); var back = JsonSerializer.Deserialize(json)!; back.Should().BeEquivalentTo(dto); } [Fact] public void Batch_dto_carries_idempotency_key() { var batch = new PosSaleBatchDto { IdempotencyKey = Guid.NewGuid(), Sales = new[] { new PosSaleDto { ClientSaleId = Guid.NewGuid(), OccurredAt = DateTime.UtcNow, Payment = 0, PaidCash = 1000m, PaidCard = 0m, Lines = new[] { new PosSaleLineDto { ProductId = Guid.NewGuid(), Quantity = 1m, UnitPrice = 1000m, Discount = 0m, VatPercent = 12m, }, }, }, }, }; var json = JsonSerializer.Serialize(batch); var back = JsonSerializer.Deserialize(json)!; back.IdempotencyKey.Should().Be(batch.IdempotencyKey); back.Sales.Should().HaveCount(1); back.Sales[0].Lines.Should().HaveCount(1); } [Fact] public void Sync_response_collects_all_groups() { var resp = new PosSyncResponse { ServerTime = DateTime.UtcNow, Products = Array.Empty(), Prices = Array.Empty(), Stocks = Array.Empty(), Counterparties = Array.Empty(), DeletedProductIds = Array.Empty(), }; var json = JsonSerializer.Serialize(resp); var back = JsonSerializer.Deserialize(json)!; back.Should().BeEquivalentTo(resp); } }