Files
Print_server/Inspectron.Epson.Tests/PrinterRegistrationTests.cs
EugeneTes 51792fcd20 add reflection-based test coverage for DiscoveryService.GetModelNameFromId
Ensures the 0x20 => "POS895" registration is actually tested. Without this,
the line could be deleted and the whole suite would still pass.

Claude-Session: https://claude.ai/code/session_01E6N3P4nSZLtp4BC2LXVref
2026-09-03 12:19:34 +02:00

123 lines
4.1 KiB
C#

using Inspectron.Epson;
using Inspectron.Epson.PrintServer.Printers;
using Inspectron.Epson.PrintServer.Printers.Utils;
namespace Inspectron.Epson.Tests;
public class PrinterRegistrationTests
{
[Fact]
public void WrapperFactory_returns_a_POS895_for_id_0x20()
{
var factory = new PrinterWrapperFactory();
var printer = factory.CreatePrinterFromId(0x20, new RecordingEpsonPrinter());
Assert.IsType<POS895>(printer);
}
[Fact]
public void WrapperFactory_still_returns_a_TM_T30III_for_id_0x01()
{
var factory = new PrinterWrapperFactory();
var printer = factory.CreatePrinterFromId(0x01, new RecordingEpsonPrinter());
Assert.IsType<TM_T30IIITranslated>(printer);
}
[Fact]
public void WorkareaTicket_uses_48_columns_for_the_POS895()
{
// The switch defaults to the 33-column TM-U220 layout. Without an
// explicit 0x20 case a POS895 prints kitchen tickets far too narrow -
// wrong, but not obviously broken.
//
// Both branches return the same converter type and only the constructor
// argument differs, so comparing types would pass even unfixed. Reading
// the private field is the only way to observe it.
var factory = new ReceiptConverterFactory();
var pos895 = factory.Create((int)ReceiptConverterFactory.EReceiptType.WorkareaTicket, 0x20);
Assert.Equal(48, LineWidthOf(pos895));
}
[Fact]
public void WorkareaTicket_still_uses_33_columns_for_the_narrow_printer()
{
var factory = new ReceiptConverterFactory();
var u220 = factory.Create((int)ReceiptConverterFactory.EReceiptType.WorkareaTicket, 0x13);
Assert.Equal(33, LineWidthOf(u220));
}
/// <summary>
/// Reads KitchenReceiptConverterAdapter._lineWidth. Brittle by design: if the
/// field is renamed this fails loudly rather than silently passing.
/// </summary>
private static int LineWidthOf(IReceiptConverter converter)
{
var field = converter.GetType().GetField("_lineWidth",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
Assert.NotNull(field);
return (int)field!.GetValue(converter)!;
}
[Fact]
public void Receipt_types_resolve_for_the_POS895()
{
var factory = new ReceiptConverterFactory();
foreach (var type in new[]
{
ReceiptConverterFactory.EReceiptType.Receipt,
ReceiptConverterFactory.EReceiptType.WorkareaTicket,
ReceiptConverterFactory.EReceiptType.OrdersOverview,
ReceiptConverterFactory.EReceiptType.Invoice,
ReceiptConverterFactory.EReceiptType.MoneyReturn
})
{
Assert.NotNull(factory.Create((int)type, 0x20));
}
}
[Fact]
public void GetModelNameFromId_maps_0x20_to_POS895()
{
Assert.Equal("POS895", ModelNameFor(0x20));
}
[Fact]
public void GetModelNameFromId_still_maps_the_existing_epson_ids()
{
// Guards against a change that makes every id report as POS895.
Assert.Equal("TM-T30III", ModelNameFor(0x01));
Assert.Equal("TM-U220II", ModelNameFor(0x0D));
Assert.Equal("TM-U220II", ModelNameFor(0x13));
}
[Fact]
public void GetModelNameFromId_falls_back_for_an_unknown_id()
{
Assert.Equal("Unknown (0x99)", ModelNameFor(0x99));
}
/// <summary>
/// Invokes DiscoveryService.GetModelNameFromId, which is private static and
/// otherwise reachable only through a live TCP connection. Reflection keeps the
/// production code untouched; if the method is renamed this fails loudly rather
/// than silently passing.
/// </summary>
private static string ModelNameFor(byte printerId)
{
var method = typeof(DiscoveryService).GetMethod("GetModelNameFromId",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
Assert.NotNull(method);
return (string)method!.Invoke(null, new object[] { printerId })!;
}
}