Приоритет владельца: sysadmin проверяет весы/принтер/сканер на ноутбуке магазина без входа в кассу. Отдельный exe (food-market.pos.hwcheck), ссылается ТОЛЬКО на pos.core ради Hardware/* — не умеет быть кассой (нет логина, сервера, БД, токенов, сетевых запросов). - pos.core/Hardware/HardwareProbe.cs: детект COM-портов (занят/свободен, VID/PID, описание) и принтеров Windows (имя/порт/в сети/число заданий) — только чтение, очередь не трогаем. WMI под OperatingSystem.IsWindows(); на Linux — базовый COM. - pos.core/Hardware/BarcodeScan.cs: контрольная цифра EAN-13/EAN-8 и оценка «сканер vs ручной набор» по среднему интервалу между символами (чистая логика). - food-market.pos.hwcheck: окно на Avalonia (код, без XAML), светлая тема, русский. Весы (Найти/Прочитать/Запустить-Остановить, live-вес ~350 мс, сырой hex, ручной выбор порта/скорости/протокола), COM-порты с пометкой «занят», принтеры (только чтение), сканер (EAN + тип ввода), «Сохранить/Копировать отчёт». Тестовая печать ВЫКЛ по умолчанию, включается только --allow-test-print. - tests: EAN контрольная цифра (13/8, валид/битый) + классификация ввода. 50/50. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
47 lines
1.6 KiB
C#
47 lines
1.6 KiB
C#
using System.Collections.Generic;
|
|
using FluentAssertions;
|
|
using foodmarket.Pos.Core.Hardware;
|
|
using Xunit;
|
|
|
|
namespace foodmarket.UnitTests;
|
|
|
|
public class BarcodeScanTests
|
|
{
|
|
[Theory]
|
|
[InlineData("4600051000057", true)] // валидный EAN-13
|
|
[InlineData("4607034170011", true)]
|
|
[InlineData("96385074", true)] // валидный EAN-8
|
|
[InlineData("4600051000058", false)] // битая контрольная
|
|
[InlineData("1234567890123", false)]
|
|
[InlineData("12345", false)] // не EAN-длина
|
|
[InlineData("abcdefghabcde", false)] // не цифры
|
|
public void IsValidEan_checks_control_digit(string code, bool expected)
|
|
=> BarcodeScan.IsValidEan(code).Should().Be(expected);
|
|
|
|
[Fact]
|
|
public void Fast_even_input_is_classified_as_scanner()
|
|
{
|
|
// 13 символов, ~15 мс между ними
|
|
var ts = new List<long>();
|
|
for (int i = 0; i < 13; i++) ts.Add(i * 15);
|
|
var a = BarcodeScan.Analyze("4600051000057", ts);
|
|
a.Kind.Should().Be(BarcodeScan.InputKind.Scanner);
|
|
a.IsEan.Should().BeTrue();
|
|
a.EanValid.Should().BeTrue();
|
|
a.AvgIntervalMs.Should().BeLessThan(40);
|
|
}
|
|
|
|
[Fact]
|
|
public void Slow_input_is_classified_as_manual()
|
|
{
|
|
var ts = new List<long>();
|
|
for (int i = 0; i < 8; i++) ts.Add(i * 250);
|
|
var a = BarcodeScan.Analyze("96385074", ts);
|
|
a.Kind.Should().Be(BarcodeScan.InputKind.Manual);
|
|
}
|
|
|
|
[Fact]
|
|
public void Empty_input_is_empty()
|
|
=> BarcodeScan.Analyze("", null).Kind.Should().Be(BarcodeScan.InputKind.Empty);
|
|
}
|