using Inspectron.Epson.Templates.Configuration; using Inspectron.Epson.Templates.Interpreter; using Inspectron.Epson.Templates.Language; using Inspectron.Epson.Templates.Language.Nodes; namespace Inspectron.Epson.Templates.Tests.Interpreter; public class InterpreterLoopTests { private readonly PrinterProfile _profile = new("test", "Test Printer", 48, 24, false); private TemplateNode Parse(string source) { var lexer = new Lexer(source); var parser = new Parser(lexer.Tokenize().Tokens); return parser.Parse().Template; } [Fact] public void Interpret_Foreach_IteratesOverArray() { var template = Parse("@foreach item in Items\n{item}\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Items": ["A", "B", "C"]}"""); Assert.Contains(commands, c => c.Text == "A"); Assert.Contains(commands, c => c.Text == "B"); Assert.Contains(commands, c => c.Text == "C"); } [Fact] public void Interpret_Foreach_AccessesObjectProperties() { var template = Parse("@foreach item in Items\n{item.Name}\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Items": [{"Name": "First"}, {"Name": "Second"}]}"""); Assert.Contains(commands, c => c.Text == "First"); Assert.Contains(commands, c => c.Text == "Second"); } [Fact] public void Interpret_Foreach_EmptyArray_NoOutput() { var template = Parse("@foreach item in Items\n{item}\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Items": []}"""); Assert.DoesNotContain(commands, c => !string.IsNullOrWhiteSpace(c.Text)); } [Fact] public void Interpret_Foreach_IndexMetadata_Works() { var template = Parse("@foreach item in Items\n{_index}:{item}\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Items": ["A", "B"]}"""); Assert.Contains(commands, c => c.Text == "0"); Assert.Contains(commands, c => c.Text == "1"); } [Fact] public void Interpret_Foreach_NumberMetadata_Works() { var template = Parse("@foreach item in Items\n{_number}. {item}\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Items": ["A", "B"]}"""); Assert.Contains(commands, c => c.Text == "1"); Assert.Contains(commands, c => c.Text == "2"); } [Fact] public void Interpret_Foreach_FirstMetadata_Works() { var template = Parse("@foreach item in Items\n@if _first\nFirst: {item}\n@end\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Items": ["A", "B", "C"]}"""); var firstCmds = commands.Where(c => c.Text.Contains("First")).ToList(); Assert.Single(firstCmds); Assert.Contains(commands, c => c.Text == "A"); } [Fact] public void Interpret_Foreach_LastMetadata_Works() { var template = Parse("@foreach item in Items\n@if _last\nLast: {item}\n@end\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Items": ["A", "B", "C"]}"""); Assert.Contains(commands, c => c.Text.Contains("Last")); Assert.Contains(commands, c => c.Text == "C"); } [Fact] public void Interpret_NestedForeach_Works() { var template = Parse("@foreach group in Groups\n@foreach item in group.Items\n{item}\n@end\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Groups": [{"Items": ["A", "B"]}, {"Items": ["C", "D"]}]}"""); Assert.Contains(commands, c => c.Text == "A"); Assert.Contains(commands, c => c.Text == "B"); Assert.Contains(commands, c => c.Text == "C"); Assert.Contains(commands, c => c.Text == "D"); } [Fact] public void Interpret_Foreach_AccessesParentContext() { var template = Parse("@foreach item in Items\n{Title}: {item}\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Title": "List", "Items": ["A", "B"]}"""); Assert.Contains(commands, c => c.Text == "List"); Assert.Contains(commands, c => c.Text == "A"); Assert.Contains(commands, c => c.Text == "B"); } [Fact] public void Interpret_Foreach_NestedPath_Works() { var template = Parse("@foreach item in Data.Items\n{item.Name}\n@end"); var interpreter = new TemplateInterpreter(_profile); var commands = interpreter.Interpret(template, """{"Data": {"Items": [{"Name": "First"}, {"Name": "Second"}]}}"""); Assert.Contains(commands, c => c.Text == "First"); Assert.Contains(commands, c => c.Text == "Second"); } }