using foodmarket.Shared.Barcodes; using FluentAssertions; using Xunit; namespace foodmarket.UnitTests; public class InternalBarcodeTests { [Fact] public void Generated_is_valid_ean13_with_correct_check_digit() { for (int i = 0; i < 100; i++) { var code = InternalBarcode.Generate(); code.Should().HaveLength(13); code.Should().MatchRegex("^[0-9]{13}$"); var body = code[..12]; InternalBarcode.Ean13CheckDigit(body).Should().Be(code[12] - '0'); } } [Fact] public void Default_prefix_is_2x_not_leading_zero() { var code = InternalBarcode.Generate(WeightedBarcodeSettings.Default); // Внутренний код — зона restricted circulation 20–29 (не «02»: с ведущим нулём // 13-значный код выглядит как UPC-A и может совпасть с реальным товаром). code.Should().StartWith("2"); code[1].Should().BeInRange('0', '9'); code[0].Should().NotBe('0'); // По умолчанию (разбор этикеток выключен) как весовая не распознаётся. WeightedBarcode.Parse(code, WeightedBarcodeSettings.Default).IsWeighted.Should().BeFalse(); } [Fact] public void Prefix_avoids_weight_and_price_prefixes() { // Орг. заняла и 02 под вес — генератор должен уйти на другой свободный префикс. var settings = new WeightedBarcodeSettings { Enabled = true, WeightPrefixes = new[] { 2, 20, 21, 22, 23, 24 }, PricePrefixes = new[] { 25, 26, 27, 28, 29 }, }; var prefix = InternalBarcode.PickPrefix(settings); new[] { 2, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }.Should().NotContain(prefix); var code = InternalBarcode.Generate(settings); WeightedBarcode.Parse(code, settings).IsWeighted.Should().BeFalse(); } }