194 lines
6.3 KiB
C#
194 lines
6.3 KiB
C#
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"));
|
|
}
|
|
}
|