krona-staff/apps/KronaStaffTerminal.Tests/Mocks/MockFingerprintScanner.cs

144 lines
4.4 KiB
C#

using KronaStaffTerminal.Services;
namespace KronaStaffTerminal.Tests.Mocks;
public sealed class MockFingerprintScanner : IFingerprintScanner
{
private readonly List<ScannerDeviceInfo> _devices = new();
private readonly Dictionary<int, string> _loadedTemplates = new();
private int _registrationTargetId;
private int _registrationStep;
public ScannerState State { get; private set; } = ScannerState.Disconnected;
public int DeviceCount => _devices.Count;
public int ReaderIndex { get; private set; } = -1;
public IReadOnlyList<ScannerDeviceInfo> DiscoveredDevices => _devices;
public bool IsConnected => State == ScannerState.Connected || State == ScannerState.Busy;
public int SkippedTemplateCount { get; set; } = 0;
public int ConnectCallCount { get; private set; } = 0;
public event Action<int, int>? FingerRecognized;
public event Action<int>? RegistrationProgress;
public event Action<int, string>? RegistrationCompleted;
public event Action<string>? StatusChanged;
public event Action<ScannerState, string>? StateChanged;
public event Action? ConnectionLost;
public event Action? RegistrationCancelled;
public MockFingerprintScanner()
{
// Default with 1 virtual SLK20R
_devices.Add(new ScannerDeviceInfo(0, "SLK20R-Virtual", "ZK-VIRT-001", "SLK20R [ZK-VIRT-001]"));
}
public void AddVirtualDevice(int index, string model, string serial)
{
_devices.Add(new ScannerDeviceInfo(index, model, serial, $"{model} [{serial}]"));
}
public void ClearDevices()
{
_devices.Clear();
}
public IReadOnlyList<ScannerDeviceInfo> DiscoverDevices()
{
return _devices;
}
public void Connect(int readerIndex, IEnumerable<(int FingerprintId, string Template)> templates)
{
ConnectCallCount++;
if (_devices.Count == 0)
{
State = ScannerState.DriverError;
StateChanged?.Invoke(ScannerState.DriverError, "No devices found");
return;
}
ReaderIndex = readerIndex;
_loadedTemplates.Clear();
foreach (var (id, tpl) in templates)
{
_loadedTemplates[id] = tpl;
}
State = ScannerState.Connected;
StateChanged?.Invoke(ScannerState.Connected, "Scanner ready");
StatusChanged?.Invoke("Scanner ready");
}
public void Disconnect()
{
State = ScannerState.Disconnected;
ReaderIndex = -1;
_loadedTemplates.Clear();
StateChanged?.Invoke(ScannerState.Disconnected, "Scanner disconnected");
StatusChanged?.Invoke("Scanner disconnected");
}
public void BeginRegistration(int fingerprintId)
{
_registrationTargetId = fingerprintId;
_registrationStep = 0;
State = ScannerState.Busy;
StateChanged?.Invoke(ScannerState.Busy, "Enrolling finger");
}
public void CancelRegistration()
{
_registrationTargetId = 0;
_registrationStep = 0;
if (State == ScannerState.Busy)
{
State = ScannerState.Connected;
StateChanged?.Invoke(ScannerState.Connected, "Registration cancelled");
}
RegistrationCancelled?.Invoke();
}
public void SimulateFingerScan(int fingerprintId, int score = 85)
{
if (State != ScannerState.Connected)
{
return;
}
FingerRecognized?.Invoke(fingerprintId, score);
}
public void SimulateEnrollmentSample(string? finalTemplate = null)
{
if (State != ScannerState.Busy) return;
_registrationStep++;
RegistrationProgress?.Invoke(_registrationStep);
if (_registrationStep >= 3)
{
string tpl = finalTemplate ?? Convert.ToBase64String(new byte[512]);
_loadedTemplates[_registrationTargetId] = tpl;
State = ScannerState.Connected;
StateChanged?.Invoke(ScannerState.Connected, "Registration complete");
RegistrationCompleted?.Invoke(_registrationTargetId, tpl);
}
}
public void SimulateDisconnect()
{
State = ScannerState.Disconnected;
StateChanged?.Invoke(ScannerState.Disconnected, "Device unplugged");
ConnectionLost?.Invoke();
}
public void SimulateReconnect()
{
State = ScannerState.Connected;
StateChanged?.Invoke(ScannerState.Connected, "Device reconnected");
}
public void Dispose()
{
Disconnect();
}
}