using Inspectron.Epson.Templates.Language; using Inspectron.Epson.Templates.Language.Nodes; namespace Inspectron.Epson.Templates.Tests.Language; public class ParserTests { private ParseResult Parse(string source) { var lexer = new Lexer(source); var lexerResult = lexer.Tokenize(); var parser = new Parser(lexerResult.Tokens); return parser.Parse(); } [Fact] public void Parse_PlainText_ReturnsTextNode() { var result = Parse("Hello World"); Assert.False(result.HasErrors); Assert.Single(result.Template.ChildNodes.OfType()); } [Fact] public void Parse_Binding_ReturnsBindingNode() { var result = Parse("{Name}"); Assert.False(result.HasErrors); var binding = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Equal("Name", binding.Path); Assert.Null(binding.Format); } [Fact] public void Parse_BindingWithFormat_PreservesFormat() { var result = Parse("{Date:yyyy-MM-dd}"); Assert.False(result.HasErrors); var binding = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Equal("Date", binding.Path); Assert.Equal("yyyy-MM-dd", binding.Format); } [Fact] public void Parse_StyledText_ReturnsStyledTextNode() { var result = Parse("#bold,center# text #"); Assert.False(result.HasErrors); var styled = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Contains("bold", styled.Styles); Assert.Contains("center", styled.Styles); } [Fact] public void Parse_DashSeparator_ReturnsSeparatorNode() { var result = Parse("---"); Assert.False(result.HasErrors); var separator = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Equal(SeparatorStyle.Dash, separator.Style); } [Fact] public void Parse_IfBlock_ReturnsIfNode() { var result = Parse("@if condition\ntext\n@end"); Assert.False(result.HasErrors); var ifNode = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Equal("condition", ifNode.IfBranch.Condition); Assert.NotEmpty(ifNode.IfBranch.Body); } [Fact] public void Parse_IfElseBlock_ReturnsIfNodeWithElseBranch() { var result = Parse("@if condition\nif-text\n@else\nelse-text\n@end"); Assert.False(result.HasErrors); var ifNode = Assert.Single(result.Template.ChildNodes.OfType()); Assert.NotNull(ifNode.ElseBranch); } [Fact] public void Parse_IfElseIfElseBlock_ReturnsAllBranches() { var result = Parse("@if cond1\ntext1\n@elseif cond2\ntext2\n@else\ntext3\n@end"); Assert.False(result.HasErrors); var ifNode = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Single(ifNode.ElseIfBranches); Assert.NotNull(ifNode.ElseBranch); } [Fact] public void Parse_ForeachBlock_ReturnsForeachNode() { var result = Parse("@foreach item in items\n{item}\n@end"); Assert.False(result.HasErrors); var foreach_ = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Equal("item", foreach_.ItemVariable); Assert.Equal("items", foreach_.CollectionPath); } [Fact] public void Parse_NestedBlocks_HandlesNestingCorrectly() { var result = Parse("@foreach item in items\n@if item.visible\n{item.name}\n@end\n@end"); Assert.False(result.HasErrors); var foreach_ = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Single(foreach_.Body.OfType()); } [Fact] public void Parse_RowWithColumns_ReturnsRowNode() { var result = Parse("@row\n|20|Name|10,right|Value\n@endrow"); Assert.False(result.HasErrors); var row = Assert.Single(result.Template.ChildNodes.OfType()); Assert.Equal(2, row.Columns.Count); } [Fact] public void Parse_EmptyLine_ReturnsEmptyLineNode() { var result = Parse("line1\n\nline2"); Assert.False(result.HasErrors); Assert.Contains(result.Template.ChildNodes, n => n is NewLineNode); } [Fact] public void Parse_UnclosedIfBlock_ReportsError() { var result = Parse("@if condition\ntext"); Assert.True(result.HasErrors); } [Fact] public void Parse_UnclosedForeachBlock_ReportsError() { var result = Parse("@foreach item in items\ntext"); Assert.True(result.HasErrors); } }