templates support
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
using Inspectron.Epson.Templates.Configuration;
|
||||
using Inspectron.Epson.Templates.Interpreter;
|
||||
using Inspectron.Epson.Templates.Language;
|
||||
using Inspectron.Epson.Templates.Language.Nodes;
|
||||
using Inspectron.Epson.Templates.Tests.Helpers;
|
||||
|
||||
namespace Inspectron.Epson.Templates.Tests.Integration;
|
||||
|
||||
public class KitchenReceiptTests
|
||||
{
|
||||
private readonly PrinterProfile _profile = new("tm-t30iii", "TM-T30III", 48, 24, false);
|
||||
|
||||
private const string KitchenReceiptJson = """
|
||||
{
|
||||
"Title": "Restaurant Test",
|
||||
"TransactionDateTime": "2024-03-15T14:30:00",
|
||||
"ReceiptNumber": "12345",
|
||||
"WaiterName": "John Doe",
|
||||
"WaiterId": "W001",
|
||||
"TableNumber": "5",
|
||||
"SpecialInstruction": "Rush Order",
|
||||
"Gangs": [
|
||||
{
|
||||
"Id": 1,
|
||||
"Name": "Starters",
|
||||
"Dishes": [
|
||||
{
|
||||
"Number": 2,
|
||||
"Name": "Caesar Salad",
|
||||
"Modifications": {
|
||||
"Removed": ["Croutons"],
|
||||
"Added": ["Extra Dressing"]
|
||||
},
|
||||
"Comment": "No anchovies"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Dishes": [
|
||||
{
|
||||
"Number": 1,
|
||||
"Name": "Grilled Salmon",
|
||||
"Modifications": {
|
||||
"Removed": [],
|
||||
"Added": []
|
||||
},
|
||||
"Comment": null
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
|
||||
private const string KitchenTemplate = """
|
||||
#red,big,tall,center# {Title} #
|
||||
---
|
||||
|
||||
#center# {TransactionDateTime:dd-MMM-yy HH:mm} Nr.:{ReceiptNumber} #
|
||||
#center# {WaiterName} #
|
||||
#center# {WaiterId} #
|
||||
#big,bold,center# Tisch: {TableNumber} #
|
||||
|
||||
@if SpecialInstruction
|
||||
|
||||
#big,bold,center# {SpecialInstruction} #
|
||||
|
||||
@end
|
||||
---
|
||||
@foreach gang in Gangs
|
||||
#red,big,tall,center# {gang.Id}. {gang.Name} #
|
||||
@foreach dish in gang.Dishes
|
||||
#tall# {dish.Number}x {dish.Name} #
|
||||
@if dish.Modifications.Removed.count > 0
|
||||
@foreach removed in dish.Modifications.Removed
|
||||
#bold,tall# - {removed} #
|
||||
@end
|
||||
@end
|
||||
@if dish.Modifications.Added.count > 0
|
||||
@foreach added in dish.Modifications.Added
|
||||
#bold,tall# + {added} #
|
||||
@end
|
||||
@end
|
||||
@if dish.Comment
|
||||
#bold,tall# Comment: {dish.Comment} #
|
||||
@end
|
||||
@end
|
||||
@end
|
||||
@if Gangs.count > 0
|
||||
---
|
||||
@end
|
||||
@foreach dish in Dishes
|
||||
#tall# {dish.Number}x {dish.Name} #
|
||||
@end
|
||||
""";
|
||||
|
||||
private TemplateNode Parse(string source)
|
||||
{
|
||||
var lexer = new Lexer(source);
|
||||
var parser = new Parser(lexer.Tokenize().Tokens);
|
||||
return parser.Parse().Template;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KitchenReceipt_RendersFully()
|
||||
{
|
||||
var template = Parse(KitchenTemplate);
|
||||
var interpreter = new TemplateInterpreter(_profile);
|
||||
var commands = interpreter.Interpret(template, KitchenReceiptJson);
|
||||
|
||||
// Verify key elements are present
|
||||
Assert.Contains(commands, c => c.Text.Contains("Restaurant Test"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("John Doe"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("Tisch: 5"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("Rush Order"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("1. Starters"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("2x Caesar Salad"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("- Croutons"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("+ Extra Dressing"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("Comment: No anchovies"));
|
||||
Assert.Contains(commands, c => c.Text.Contains("1x Grilled Salmon"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KitchenReceipt_AppliesStyles()
|
||||
{
|
||||
var template = Parse(KitchenTemplate);
|
||||
var interpreter = new TemplateInterpreter(_profile);
|
||||
var commands = interpreter.Interpret(template, KitchenReceiptJson);
|
||||
|
||||
// Title should be big and tall
|
||||
var titleCmd = commands.FirstOrDefault(c => c.Text.Contains("Restaurant Test"));
|
||||
Assert.NotNull(titleCmd);
|
||||
Assert.True(titleCmd.IsBig);
|
||||
Assert.True(titleCmd.IsTall);
|
||||
|
||||
// Table should be bold and big
|
||||
var tableCmd = commands.FirstOrDefault(c => c.Text.Contains("Tisch: 5"));
|
||||
Assert.NotNull(tableCmd);
|
||||
Assert.True(tableCmd.IsBold);
|
||||
Assert.True(tableCmd.IsBig);
|
||||
|
||||
// Modifications should be bold and tall
|
||||
var modCmd = commands.FirstOrDefault(c => c.Text.Contains("- Croutons"));
|
||||
Assert.NotNull(modCmd);
|
||||
Assert.True(modCmd.IsBold);
|
||||
Assert.True(modCmd.IsTall);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KitchenReceipt_GeneratesSeparators()
|
||||
{
|
||||
var template = Parse(KitchenTemplate);
|
||||
var interpreter = new TemplateInterpreter(_profile);
|
||||
var commands = interpreter.Interpret(template, KitchenReceiptJson);
|
||||
|
||||
var separatorCount = commands.Count(c => c.Text.All(ch => ch == '-') && c.Text.Length == 48);
|
||||
Assert.True(separatorCount >= 2, $"Expected at least 2 separators, found {separatorCount}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KitchenReceipt_FormatsDateTime()
|
||||
{
|
||||
var template = Parse(KitchenTemplate);
|
||||
var interpreter = new TemplateInterpreter(_profile);
|
||||
var commands = interpreter.Interpret(template, KitchenReceiptJson);
|
||||
|
||||
Assert.Contains(commands, c => c.Text.Contains("15-Mar-24") || c.Text.Contains("15-Mär-24"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KitchenReceipt_WithoutSpecialInstruction_OmitsSection()
|
||||
{
|
||||
var jsonWithoutInstruction = """
|
||||
{
|
||||
"Title": "Test",
|
||||
"TransactionDateTime": "2024-03-15T14:30:00",
|
||||
"ReceiptNumber": "123",
|
||||
"WaiterName": "John",
|
||||
"WaiterId": "W001",
|
||||
"TableNumber": "1",
|
||||
"SpecialInstruction": null,
|
||||
"Gangs": [],
|
||||
"Dishes": []
|
||||
}
|
||||
""";
|
||||
|
||||
var template = Parse(KitchenTemplate);
|
||||
var interpreter = new TemplateInterpreter(_profile);
|
||||
var commands = interpreter.Interpret(template, jsonWithoutInstruction);
|
||||
|
||||
// Should not have any content that looks like special instruction
|
||||
Assert.DoesNotContain(commands, c => c.Text.Contains("Rush"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user