template engine
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user