template engine

This commit is contained in:
EugeneTes
2026-02-03 14:27:13 +01:00
parent 46b648d753
commit ec5decb12e
31 changed files with 4640 additions and 946 deletions

View File

@@ -0,0 +1,298 @@
using Inspectron.Epson.PrintServer.Printers.Utils;
using Inspectron.Epson.PrintServer.Printers.Utils.KitchenReceipt;
using System.Text.Json;
namespace Inspectron.Epson.TemplateEngine.Tests;
public class KitchenReceiptTemplateTests
{
private const int LineWidth = 42;
private const int BigLineWidth = 22;
private readonly ReceiptTemplateEngine _engine = new();
private static string GetTemplatePath()
{
return Path.Combine(AppContext.BaseDirectory, "Templates", "KitchenReceipt.xml");
}
[Fact]
public void RenderKitchenReceipt_BasicStructure()
{
var template = File.ReadAllText(GetTemplatePath());
var json = """
{
"Title": "Test Restaurant",
"TransactionDateTime": "2024-03-15T14:30:00Z",
"ReceiptNumber": "42",
"WaiterName": "Max",
"TableNumber": "5",
"SpecialInstruction": null,
"HasGangs": false,
"HasDishes": false,
"Gangs": [],
"Dishes": []
}
""";
var commands = _engine.Render(template, json, LineWidth, BigLineWidth);
Assert.True(commands.Count > 0);
// First line: title centered in big font, red
Assert.True(commands[0].IsBig);
Assert.True(commands[0].IsTall);
Assert.True(commands[0].IsRed);
Assert.Contains("Test Restaurant", commands[0].Text);
// Second line: separator
Assert.Equal(new string('-', LineWidth), commands[1].Text);
// Empty line
Assert.Equal("", commands[2].Text);
}
[Fact]
public void RenderKitchenReceipt_WithSpecialInstruction()
{
var template = File.ReadAllText(GetTemplatePath());
var json = """
{
"Title": "Test Restaurant",
"TransactionDateTime": "2024-03-15T14:30:00Z",
"ReceiptNumber": "42",
"WaiterName": "Max",
"TableNumber": "5",
"SpecialInstruction": "RUSH ORDER",
"HasGangs": false,
"HasDishes": false,
"Gangs": [],
"Dishes": []
}
""";
var commands = _engine.Render(template, json, LineWidth, BigLineWidth);
// Should contain the special instruction
var specialCommands = commands.Where(c => c.Text.Contains("RUSH ORDER")).ToList();
Assert.NotEmpty(specialCommands);
Assert.True(specialCommands[0].IsBig);
Assert.True(specialCommands[0].IsBold);
}
[Fact]
public void RenderKitchenReceipt_WithGangs()
{
var template = File.ReadAllText(GetTemplatePath());
var json = """
{
"Title": "Test Restaurant",
"TransactionDateTime": "2024-03-15T14:30:00Z",
"ReceiptNumber": "42",
"WaiterName": "Max",
"TableNumber": "5",
"SpecialInstruction": null,
"HasGangs": true,
"HasDishes": false,
"Gangs": [
{
"Id": 1,
"Name": "Vorspeise",
"Dishes": [
{
"Number": 2,
"Name": "Caesar Salad",
"GuestPrefix": "",
"GuestId": null,
"Modifications": { "Removed": [], "Added": [], "HasModifications": false },
"Comment": null
}
]
},
{
"Id": 2,
"Name": "Hauptgang",
"Dishes": [
{
"Number": 1,
"Name": "Wiener Schnitzel",
"GuestPrefix": "",
"GuestId": null,
"Modifications": { "Removed": ["Pommes"], "Added": ["Reis"], "HasModifications": true },
"Comment": "Well done"
}
]
}
],
"Dishes": []
}
""";
var commands = _engine.Render(template, json, LineWidth, BigLineWidth);
// Should contain gang names
Assert.Contains(commands, c => c.Text.Contains("1. Vorspeise"));
Assert.Contains(commands, c => c.Text.Contains("2. Hauptgang"));
// Should contain dish names
Assert.Contains(commands, c => c.Text.Contains("2x Caesar Salad"));
Assert.Contains(commands, c => c.Text.Contains("1x Wiener Schnitzel"));
// Should contain modifications
Assert.Contains(commands, c => c.Text.Contains("- Pommes") && c.IsBold);
Assert.Contains(commands, c => c.Text.Contains("+ Reis") && c.IsBold);
// Should contain comment
Assert.Contains(commands, c => c.Text.Contains("Comment: Well done") && c.IsBold);
// Should have cut between gangs (not after last)
var cutCommands = commands.Where(c => c.IsCut).ToList();
Assert.Single(cutCommands);
// Gang headers should be red and big
var gangHeaders = commands.Where(c => c.Text.Contains("Vorspeise") || c.Text.Contains("Hauptgang")).ToList();
Assert.All(gangHeaders, c =>
{
Assert.True(c.IsRed);
Assert.True(c.IsBig);
Assert.True(c.IsTall);
});
}
[Fact]
public void RenderKitchenReceipt_DishesAreTall()
{
var template = File.ReadAllText(GetTemplatePath());
var json = """
{
"Title": "Test",
"TransactionDateTime": "2024-01-01T00:00:00Z",
"ReceiptNumber": "1",
"WaiterName": "W",
"TableNumber": "1",
"SpecialInstruction": null,
"HasGangs": true,
"HasDishes": false,
"Gangs": [
{
"Id": 1,
"Name": "Gang1",
"Dishes": [
{
"Number": 1,
"Name": "Item",
"GuestPrefix": "",
"GuestId": null,
"Modifications": { "Removed": [], "Added": [], "HasModifications": false },
"Comment": null
}
]
}
],
"Dishes": []
}
""";
var commands = _engine.Render(template, json, LineWidth, BigLineWidth);
// Dish line should be tall
var dishCmd = commands.First(c => c.Text.Contains("1x Item"));
Assert.True(dishCmd.IsTall);
}
[Fact]
public void RenderKitchenReceipt_TableLineCenteredBigBold()
{
var template = File.ReadAllText(GetTemplatePath());
var json = """
{
"Title": "Test",
"TransactionDateTime": "2024-01-01T00:00:00Z",
"ReceiptNumber": "1",
"WaiterName": "W",
"TableNumber": "12",
"SpecialInstruction": null,
"HasGangs": false,
"HasDishes": false,
"Gangs": [],
"Dishes": []
}
""";
var commands = _engine.Render(template, json, LineWidth, BigLineWidth);
var tableCmd = commands.First(c => c.Text.Contains("Tisch: 12"));
Assert.True(tableCmd.IsBig);
Assert.True(tableCmd.IsBold);
// Should be centered in big font width
Assert.True(tableCmd.Text.StartsWith(" "));
}
[Fact]
public void CompareWithExistingConverter_BasicReceipt()
{
// Create a KitchenReceipt via the existing converter
var receipt = new KitchenReceipt
{
Title = "Test Restaurant",
TransactionDateTime = new DateTime(2024, 3, 15, 14, 30, 0),
ReceiptNumber = "42",
WaiterName = "Max Mustermann",
WaiterId = "W001",
TableNumber = "5",
SpecialInstruction = null,
Gangs = new List<Gang>(),
Dishes = new List<Dish>()
};
var existingConverter = new KitchenReceiptConverter(LineWidth, BigLineWidth);
var existingCommands = existingConverter.ConvertToPrintCommands(receipt);
// Render with template engine
var template = File.ReadAllText(GetTemplatePath());
var jsonData = JsonSerializer.Serialize(new
{
receipt.Title,
TransactionDateTime = receipt.TransactionDateTime.ToString("o"),
receipt.ReceiptNumber,
receipt.WaiterName,
receipt.TableNumber,
receipt.SpecialInstruction,
HasGangs = receipt.Gangs.Count > 0,
HasDishes = receipt.Dishes != null && receipt.Dishes.Any(),
receipt.Gangs,
receipt.Dishes
});
var templateCommands = _engine.Render(template, jsonData, LineWidth, BigLineWidth);
// Compare key structural elements
// Title should match
Assert.Equal(existingCommands[0].Text, templateCommands[0].Text);
Assert.Equal(existingCommands[0].IsRed, templateCommands[0].IsRed);
Assert.Equal(existingCommands[0].IsBig, templateCommands[0].IsBig);
Assert.Equal(existingCommands[0].IsTall, templateCommands[0].IsTall);
// Separator should match
Assert.Equal(existingCommands[1].Text, templateCommands[1].Text);
// Empty line
Assert.Equal(existingCommands[2].Text, templateCommands[2].Text);
// Date/receipt number line should match formatting
Assert.Equal(existingCommands[3].Text, templateCommands[3].Text);
// Waiter name
Assert.Equal(existingCommands[4].Text, templateCommands[4].Text);
// Table number
Assert.Equal(existingCommands[5].Text, templateCommands[5].Text);
Assert.Equal(existingCommands[5].IsBig, templateCommands[5].IsBig);
Assert.Equal(existingCommands[5].IsBold, templateCommands[5].IsBold);
}
}