// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Web.Razor.Generator; using System.Web.Razor.Parser; using System.Web.Razor.Parser.SyntaxTree; using System.Web.Razor.Resources; using System.Web.Razor.Test.Framework; using Xunit; namespace System.Web.Razor.Test.Parser.VB { public class VBSectionTest : VBHtmlMarkupParserTestBase { [Fact] public void ParseSectionBlockCapturesNewlineImmediatelyFollowing() { ParseDocumentTest(@"@Section ", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator(String.Empty), Factory.CodeTransition(), Factory.MetaCode("Section\r\n"), new MarkupBlock())), new RazorError( String.Format( RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start, RazorResources.ErrorComponent_EndOfFile), 10, 1, 0), new RazorError( String.Format( RazorResources.ParseError_BlockNotTerminated, "Section", "End Section"), 1, 0, 1)); } [Fact] public void ParseSectionRequiresNameBeOnSameLineAsSectionKeyword() { ParseDocumentTest(@"@Section Foo <p>Body</p> End Section", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator(String.Empty), Factory.CodeTransition(), Factory.MetaCode("Section "), new MarkupBlock( Factory.Markup("\r\nFoo\r\n <p>Body</p>\r\n")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml()), new RazorError( String.Format( RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start, RazorResources.ErrorComponent_Newline), 9, 0, 9)); } [Fact] public void ParseSectionAllowsNameToBeOnDifferentLineAsSectionKeywordIfUnderscoresUsed() { ParseDocumentTest(@"@Section _ _ Foo <p>Body</p> End Section", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("Foo"), Factory.CodeTransition(), Factory.MetaCode("Section _\r\n_\r\nFoo"), new MarkupBlock( Factory.Markup("\r\n <p>Body</p>\r\n")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml())); } [Fact] public void ParseSectionReportsErrorAndTerminatesSectionBlockIfKeywordNotFollowedByIdentifierStartCharacter() { ParseDocumentTest(@"@Section 9 <p>Foo</p> End Section", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator(String.Empty), Factory.CodeTransition(), Factory.MetaCode("Section "), new MarkupBlock( Factory.Markup("9\r\n <p>Foo</p>\r\n")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml()), new RazorError( String.Format( RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start, String.Format(RazorResources.ErrorComponent_Character, "9")), 9, 0, 9)); } [Fact] public void ParserOutputsErrorOnNestedSections() { ParseDocumentTest(@"@Section foo @Section bar <p>Foo</p> End Section End Section", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("foo"), Factory.CodeTransition(), Factory.MetaCode("Section foo"), new MarkupBlock( Factory.Markup("\r\n"), new SectionBlock(new SectionCodeGenerator("bar"), Factory.Code(" ").AsStatement(), Factory.CodeTransition(), Factory.MetaCode("Section bar"), new MarkupBlock( Factory.Markup("\r\n <p>Foo</p>\r\n ")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.Markup("\r\n")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml()), new RazorError( String.Format( RazorResources.ParseError_Sections_Cannot_Be_Nested, RazorResources.SectionExample_VB), 26, 1, 12)); } [Fact] public void ParseSectionHandlesEOFAfterIdentifier() { ParseDocumentTest("@Section foo", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("foo"), Factory.CodeTransition(), Factory.MetaCode("Section foo") .AutoCompleteWith(SyntaxConstants.VB.EndSectionKeyword), new MarkupBlock())), new RazorError( String.Format( RazorResources.ParseError_BlockNotTerminated, "Section", "End Section"), 1, 0, 1)); } [Fact] public void ParseSectionHandlesUnterminatedSection() { ParseDocumentTest(@"@Section foo <p>Foo</p>", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("foo"), Factory.CodeTransition(), Factory.MetaCode("Section foo") .AutoCompleteWith(SyntaxConstants.VB.EndSectionKeyword), new MarkupBlock( Factory.Markup("\r\n <p>Foo</p>")))), new RazorError( String.Format( RazorResources.ParseError_BlockNotTerminated, "Section", "End Section"), 1, 0, 1)); } [Fact] public void ParseDocumentParsesNamedSectionCorrectly() { ParseDocumentTest(@"@Section foo <p>Foo</p> End Section", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("foo"), Factory.CodeTransition(), Factory.MetaCode("Section foo"), new MarkupBlock( Factory.Markup("\r\n <p>Foo</p>\r\n")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml())); } [Fact] public void ParseSectionTerminatesOnFirstEndSection() { ParseDocumentTest(@"@Section foo <p>End Section</p>", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("foo"), Factory.CodeTransition(), Factory.MetaCode("Section foo"), new MarkupBlock( Factory.Markup("\r\n <p>")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.Markup("</p>"))); } [Fact] public void ParseSectionAllowsEndSectionInVBExpression() { ParseDocumentTest(@"@Section foo I really want to render the word @(""End Section""), so this is how I do it End Section", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("foo"), Factory.CodeTransition(), Factory.MetaCode("Section foo"), new MarkupBlock( Factory.Markup("\r\n I really want to render the word "), new ExpressionBlock( Factory.CodeTransition(), Factory.MetaCode("(").Accepts(AcceptedCharacters.None), Factory.Code("\"End Section\"").AsExpression(), Factory.MetaCode(")").Accepts(AcceptedCharacters.None)), Factory.Markup(", so this is how I do it\r\n")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml())); } // These are tests that are normally in HtmlToCodeSwitchTest, but we want to verify them for VB // since VB has slightly different section terminating behavior which follow slightly different // code paths [Fact] public void SectionBodyTreatsTwoAtSignsAsEscapeSequence() { ParseDocumentTest(@"@Section Foo <foo>@@bar</foo> End Section", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("Foo"), Factory.CodeTransition(), Factory.MetaCode("Section Foo").AutoCompleteWith(null), new MarkupBlock( Factory.Markup("\r\n <foo>"), Factory.Markup("@").Hidden(), Factory.Markup("@bar</foo>\r\n")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml())); } [Fact] public void SectionBodyTreatsPairsOfAtSignsAsEscapeSequence() { ParseDocumentTest(@"@Section Foo <foo>@@@@@bar</foo> End Section", new MarkupBlock( Factory.EmptyHtml(), new SectionBlock(new SectionCodeGenerator("Foo"), Factory.CodeTransition(), Factory.MetaCode("Section Foo").AutoCompleteWith(null), new MarkupBlock( Factory.Markup("\r\n <foo>"), Factory.Markup("@").Hidden(), Factory.Markup("@"), Factory.Markup("@").Hidden(), Factory.Markup("@"), new ExpressionBlock( Factory.CodeTransition(), Factory.Code("bar") .AsImplicitExpression(VBCodeParser.DefaultKeywords) .Accepts(AcceptedCharacters.NonWhiteSpace)), Factory.Markup("</foo>\r\n")), Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml())); } } }