public void TreesAreDifferentReturnsFalseIfTreeStructureIsSame() { var factory = SpanFactory.CreateCsHtml(); Block original = new MarkupBlock( factory.Markup("<p>"), new ExpressionBlock( factory.CodeTransition(), factory.Code("f") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)), factory.Markup("</p>")); factory.Reset(); Block modified = new MarkupBlock( factory.Markup("<p>"), new ExpressionBlock( factory.CodeTransition(), factory.Code("foo") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)), factory.Markup("</p>")); original.LinkNodes(); modified.LinkNodes(); ITextBuffer oldBuffer = new StringTextBuffer("<p>@f</p>"); ITextBuffer newBuffer = new StringTextBuffer("<p>@foo</p>"); Assert.False(BackgroundParser.TreesAreDifferent( original, modified, new[] { new TextChange(position: 5, oldLength: 0, oldBuffer: oldBuffer, newLength: 2, newBuffer: newBuffer) })); }
public void Rewrite_Moves_Whitespace_Preceeding_ExpressionBlock_To_Parent_Block() { // Arrange var factory = SpanFactory.CreateCsHtml(); Block start = new MarkupBlock( factory.Markup("test"), new ExpressionBlock( factory.Code(" ").AsExpression(), factory.CodeTransition(SyntaxConstants.TransitionString), factory.Code("foo").AsExpression() ), factory.Markup("test") ); WhiteSpaceRewriter rewriter = new WhiteSpaceRewriter(new HtmlMarkupParser().BuildSpan); // Act Block actual = rewriter.Rewrite(start); factory.Reset(); // Assert ParserTestBase.EvaluateParseTree(actual, new MarkupBlock( factory.Markup("test"), factory.Markup(" "), new ExpressionBlock( factory.CodeTransition(SyntaxConstants.TransitionString), factory.Code("foo").AsExpression() ), factory.Markup("test") )); }
public void TreesAreDifferentReturnsTrueIfTreeStructureIsDifferent() { var factory = SpanFactory.CreateCsHtml(); var original = new MarkupBlock( factory.Markup("<p>"), new ExpressionBlock( factory.CodeTransition()), factory.Markup("</p>")); var modified = new MarkupBlock( factory.Markup("<p>"), new ExpressionBlock( factory.CodeTransition("@"), factory.Code("f") .AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)), factory.Markup("</p>")); var oldBuffer = new StringTextBuffer("<p>@</p>"); var newBuffer = new StringTextBuffer("<p>@f</p>"); Assert.True(BackgroundParser.TreesAreDifferent( original, modified, new[] { new TextChange(position: 4, oldLength: 0, oldBuffer: oldBuffer, newLength: 1, newBuffer: newBuffer) })); }
public void TreesAreDifferentReturnsFalseForAddedContent(string content) { // Arrange var factory = SpanFactory.CreateCsHtml(); var blockFactory = new BlockFactory(factory); var original = new MarkupBlock( blockFactory.MarkupTagBlock("<p>"), blockFactory.TagHelperBlock( tagName: "div", tagMode: TagMode.StartTagAndEndTag, start: new SourceLocation(3, 0, 3), startTag: blockFactory.MarkupTagBlock("<div>"), children: new SyntaxTreeNode[] { factory.Markup($"{Environment.NewLine}{Environment.NewLine}") }, endTag: blockFactory.MarkupTagBlock("</div>")), blockFactory.MarkupTagBlock("</p>")); factory.Reset(); var modified = new MarkupBlock( blockFactory.MarkupTagBlock("<p>"), blockFactory.TagHelperBlock( tagName: "div", tagMode: TagMode.StartTagAndEndTag, start: new SourceLocation(3, 0, 3), startTag: blockFactory.MarkupTagBlock("<div>"), children: new SyntaxTreeNode[] { factory.Markup($"{Environment.NewLine}{content}{Environment.NewLine}") }, endTag: blockFactory.MarkupTagBlock("</div>")), blockFactory.MarkupTagBlock("</p>")); original.LinkNodes(); modified.LinkNodes(); var oldBuffer = new StringTextBuffer($"<p><div>{Environment.NewLine}{Environment.NewLine}</div></p>"); var newBuffer = new StringTextBuffer( $"<p><div>{Environment.NewLine}{content}{Environment.NewLine}</div></p>"); // Act var treesAreDifferent = BackgroundParser.TreesAreDifferent( original, modified, new[] { new TextChange( position: 8 + Environment.NewLine.Length, oldLength: 0, oldBuffer: oldBuffer, newLength: content.Length, newBuffer: newBuffer) }); // Assert Assert.False(treesAreDifferent); }
public void RunParseTreeRewriterTest( string documentContent, MarkupBlock expectedOutput, IEnumerable<RazorError> errors, params string[] tagNames) { var providerContext = BuildProviderContext(tagNames); EvaluateData(providerContext, documentContent, expectedOutput, errors); }
public void RunParseTreeRewriterTest( string documentContent, MarkupBlock expectedOutput, params string[] tagNames) { RunParseTreeRewriterTest( documentContent, expectedOutput, errors: Enumerable.Empty<RazorError>(), tagNames: tagNames); }
public void Rewrite_CanHandleInvalidChildrenWithWhitespace() { // Arrange var factory = CreateDefaultSpanFactory(); var blockFactory = new BlockFactory(factory); var documentContent = $"<p>{Environment.NewLine} <strong>{Environment.NewLine} Hello" + $"{Environment.NewLine} </strong>{Environment.NewLine}</p>"; var newLineLength = Environment.NewLine.Length; var expectedErrors = new[] { new RazorError( RazorResources.FormatTagHelperParseTreeRewriter_InvalidNestedTag("strong", "p", "br"), absoluteIndex: 7 + newLineLength, lineIndex: 1, columnIndex: 9 + newLineLength, length: 8), new RazorError( RazorResources.FormatTagHelperParseTreeRewriter_CannotHaveNonTagContent("p", "br"), absoluteIndex: 23 + newLineLength * 2, lineIndex: 2, columnIndex: 23 + newLineLength * 2, length: 5), new RazorError( RazorResources.FormatTagHelperParseTreeRewriter_InvalidNestedTag("strong", "p", "br"), absoluteIndex: 32 + newLineLength * 3, lineIndex: 3, columnIndex: 32 + newLineLength * 3, length: 9), }; var expectedOutput = new MarkupBlock( new MarkupTagHelperBlock("p", factory.Markup(Environment.NewLine + " "), blockFactory.MarkupTagBlock("<strong>"), factory.Markup(Environment.NewLine + " Hello" + Environment.NewLine + " "), blockFactory.MarkupTagBlock("</strong>"), factory.Markup(Environment.NewLine))); var descriptors = new TagHelperDescriptor[] { new TagHelperDescriptor { TagName = "p", TypeName = "PTagHelper", AssemblyName = "SomeAssembly", AllowedChildren = new[] { "br" }, } }; var descriptorProvider = new TagHelperDescriptorProvider(descriptors); // Act & Assert EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors); }
public void EvaluateData( TagHelperDescriptorProvider provider, string documentContent, MarkupBlock expectedOutput, IEnumerable<RazorError> expectedErrors) { var errorSink = new ErrorSink(); var results = ParseDocument(documentContent, errorSink); var rewritingContext = new RewritingContext(results.Document, errorSink); new TagHelperParseTreeRewriter(provider).Rewrite(rewritingContext); var rewritten = rewritingContext.SyntaxTree; var actualErrors = errorSink.Errors.OrderBy(error => error.Location.AbsoluteIndex) .ToList(); EvaluateRazorErrors(actualErrors, expectedErrors.ToList()); EvaluateParseTree(rewritten, expectedOutput); }
public void Rewrite_CanHandleWithoutEndTagTagStructure(string documentContent, MarkupBlock expectedOutput) { // Arrange var descriptors = new TagHelperDescriptor[] { new TagHelperDescriptor { TagName = "input", TypeName = "InputTagHelper", AssemblyName = "SomeAssembly", TagStructure = TagStructure.WithoutEndTag, } }; var descriptorProvider = new TagHelperDescriptorProvider(descriptors); // Act & Assert EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors: new RazorError[0]); }
public void LocateOwnerReturnsNullIfNoSpanReturnsTrueForOwnsSpan() { // Arrange var factory = SpanFactory.CreateCsHtml(); var block = new MarkupBlock( factory.Markup("Foo "), new StatementBlock( factory.CodeTransition(), factory.Code("bar").AsStatement()), factory.Markup(" Baz")); var change = new TextChange(128, 1, new StringTextBuffer("Foo @bar Baz"), 1, new StringTextBuffer("Foo @bor Baz")); // Act var actual = block.LocateOwner(change); // Assert Assert.Null(actual); }
public void TagHelperParseTreeRewriter_RewritesNestedTagHelperTagBlocks( string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "div"); }
public void TagHelperParseTreeRewriter_RewritesTagHelpersWithPlainAttributes( string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, "p"); }
public void TagHelperParseTreeRewriter_RewritesSelfClosingTagHelpers( string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, "p"); }
public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlocks( string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, "p"); }
public void Rewrite_AllowsTagHelperElementOptForIncompleteTextTagInCSharpBlock( string documentContent, MarkupBlock expectedOutput, RazorError[] expectedErrors) { RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors, "text"); }
public void Rewrite_CreatesErrorForMalformedTagHelpersWithAttributes( string documentContent, MarkupBlock expectedOutput, RazorError[] expectedErrors) { RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors, "strong", "p"); }
public void TagHelperParseTreeRewriter_CreatesMarkupCodeSpansForNonStringTagHelperAttributes( string documentContent, MarkupBlock expectedOutput) { // Arrange var descriptors = new TagHelperDescriptor[] { new TagHelperDescriptor("person", "PersonTagHelper", "personAssembly", attributes: new[] { new TagHelperAttributeDescriptor("age", "Age", typeof(int).FullName, isIndexer: false), new TagHelperAttributeDescriptor( "birthday", "BirthDay", typeof(DateTime).FullName, isIndexer: false), new TagHelperAttributeDescriptor("name", "Name", typeof(string).FullName, isIndexer: false), }) }; var providerContext = new TagHelperDescriptorProvider(descriptors); // Act & Assert EvaluateData(providerContext, documentContent, expectedOutput, expectedErrors: Enumerable.Empty<RazorError>()); }
public void Rewrite_UnderstandsEmptyAttributeTagHelpers(string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, new RazorError[0], "p"); }
public void Rewrite_AllowsTagHelperElementOptOutHTML( string documentContent, MarkupBlock expectedOutput, RazorError[] expectedErrors) { RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors, "strong", "p"); }
public void Rewrite_AllowsTagHelperElementOptForIncompleteHTML( string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, new RazorError[0], "strong", "p"); }
public void Rewrite_RequiredAttributeDescriptorsCreateMalformedTagHelperBlocksCorrectly( string documentContent, MarkupBlock expectedOutput, RazorError[] expectedErrors) { // Arrange var descriptors = new TagHelperDescriptor[] { new TagHelperDescriptor( tagName: "p", typeName: "pTagHelper", assemblyName: "SomeAssembly", attributes: new TagHelperAttributeDescriptor[0], requiredAttributes: new[] { "class" }) }; var descriptorProvider = new TagHelperDescriptorProvider(descriptors); // Act & Assert EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors); }
public void Rewrite_AllowsPrefixedTagHelpers( string documentContent, MarkupBlock expectedOutput, IEnumerable<TagHelperDescriptor> availableDescriptors) { // Arrange var descriptorProvider = new TagHelperDescriptorProvider(availableDescriptors); // Act & Assert EvaluateData( descriptorProvider, documentContent, expectedOutput, expectedErrors: Enumerable.Empty<RazorError>()); }
public void Rewrite_UnderstandsMinimizedAttributes( string documentContent, MarkupBlock expectedOutput, RazorError[] expectedErrors) { // Arrange var descriptors = new TagHelperDescriptor[] { new TagHelperDescriptor( tagName: "input", typeName: "InputTagHelper1", assemblyName: "SomeAssembly", attributes: new[] { new TagHelperAttributeDescriptor( "bound-required-string", "BoundRequiredString", typeof(string).FullName, isIndexer: false, designTimeDescriptor: null) }, requiredAttributes: new[] { "unbound-required" }), new TagHelperDescriptor( tagName: "input", typeName: "InputTagHelper1", assemblyName: "SomeAssembly", attributes: new[] { new TagHelperAttributeDescriptor( "bound-required-string", "BoundRequiredString", typeof(string).FullName, isIndexer: false, designTimeDescriptor: null) }, requiredAttributes: new[] { "bound-required-string" }), new TagHelperDescriptor( tagName: "input", typeName: "InputTagHelper2", assemblyName: "SomeAssembly", attributes: new[] { new TagHelperAttributeDescriptor( "bound-required-int", "BoundRequiredInt", typeof(int).FullName, isIndexer: false, designTimeDescriptor: null) }, requiredAttributes: new[] { "bound-required-int" }), new TagHelperDescriptor( tagName: "input", typeName: "InputTagHelper3", assemblyName: "SomeAssembly", attributes: new[] { new TagHelperAttributeDescriptor( "int-dictionary", "DictionaryOfIntProperty", typeof(IDictionary<string, int>).FullName, isIndexer: false, designTimeDescriptor: null), new TagHelperAttributeDescriptor( "string-dictionary", "DictionaryOfStringProperty", typeof(IDictionary<string, string>).FullName, isIndexer: false, designTimeDescriptor: null), new TagHelperAttributeDescriptor( "int-prefix-", "DictionaryOfIntProperty", typeof(int).FullName, isIndexer: true, designTimeDescriptor: null), new TagHelperAttributeDescriptor( "string-prefix-", "DictionaryOfStringProperty", typeof(string).FullName, isIndexer: true, designTimeDescriptor: null), }, requiredAttributes: Enumerable.Empty<string>()), new TagHelperDescriptor( tagName: "p", typeName: "PTagHelper", assemblyName: "SomeAssembly", attributes: new[] { new TagHelperAttributeDescriptor( "bound-string", "BoundRequiredString", typeof(string).FullName, isIndexer: false, designTimeDescriptor: null), new TagHelperAttributeDescriptor( "bound-int", "BoundRequiredString", typeof(int).FullName, isIndexer: false, designTimeDescriptor: null) }, requiredAttributes: Enumerable.Empty<string>()), }; var descriptorProvider = new TagHelperDescriptorProvider(descriptors); // Act & Assert EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors); }
public void TagHelperParseTreeRewriter_DoesNotRewriteTextTagTransitionTagHelpers( string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "text"); }
public void LocateOwnerReturnsNullIfChangeCrossesMultipleSpans() { // Arrange var factory = SpanFactory.CreateCsHtml(); Block block = new MarkupBlock( factory.Markup("Foo "), new StatementBlock( factory.CodeTransition(), factory.Code("bar").AsStatement()), factory.Markup(" Baz")); TextChange change = new TextChange(4, 10, new StringTextBuffer("Foo @bar Baz"), 10, new StringTextBuffer("Foo @bor Baz")); // Act Span actual = block.LocateOwner(change); // Assert Assert.Null(actual); }
public void TagHelperParseTreeRewriter_DoesNotRewriteSpecialTagTagHelpers( string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, "!--", "?xml", "![CDATA[", "!DOCTYPE"); }
public void TagHelperParseTreeRewriter_CreatesErrorForIncompleteTagHelper( string documentContent, MarkupBlock expectedOutput, RazorError[] expectedErrors) { RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors, "strong", "p"); }
public void Rewrite_CreatesErrorForEmptyTagHelperBoundAttributes( string documentContent, MarkupBlock expectedOutput, RazorError[] expectedErrors) { // Arrange var descriptors = new TagHelperDescriptor[] { new TagHelperDescriptor( tagName: "myth", typeName: "mythTagHelper", assemblyName: "SomeAssembly", attributes: new[] { new TagHelperAttributeDescriptor( name: "bound", propertyName: "Bound", typeName: typeof(bool).FullName, isIndexer: false), new TagHelperAttributeDescriptor( name: "name", propertyName: "Name", typeName: typeof(string).FullName, isIndexer: false) }) }; var descriptorProvider = new TagHelperDescriptorProvider(descriptors); // Act & Assert EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors); }
public void ParseDocument_WithUnexpectedTransitionsInAttributeValue_Throws() { // Arrange var expected = new MarkupBlock( new MarkupTagBlock( Factory.Markup("<span"), new MarkupBlock( new AttributeBlockCodeGenerator("foo", new LocationTagged<string>(" foo='", 5, 0, 5), new LocationTagged<string>("'", 14, 0, 14)), Factory.Markup(" foo='").With(SpanCodeGenerator.Null), new MarkupBlock( new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(string.Empty, 11, 0, 11), 11, 0, 11), new ExpressionBlock( Factory.CodeTransition(), Factory.EmptyCSharp().AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace))), new MarkupBlock( new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(" ", 12, 0, 12), 12, 0, 12), Factory.Markup(" ").With(SpanCodeGenerator.Null), new ExpressionBlock( Factory.CodeTransition().Accepts(AcceptedCharacters.None).With(SpanCodeGenerator.Null), Factory.EmptyCSharp().AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace))), Factory.Markup("'").With(SpanCodeGenerator.Null)), Factory.Markup(" />"))); var expectedErrors = new RazorError[] { new RazorError(@"A space or line break was encountered after the ""@"" character. Only valid identifiers, keywords, comments, ""("" and ""{"" are valid at the start of a code block and they must occur immediately following ""@"" with no space in between.", new SourceLocation(12, 0, 12)), new RazorError(@"""' />"" is not valid at the start of a code block. Only identifiers, keywords, comments, ""("" and ""{"" are valid.", new SourceLocation(14, 0, 14)), }; // Act & Assert ParseDocumentTest("<span foo='@ @' />", expected, expectedErrors); }
public void TagHelperParseTreeRewriter_AllowsInvalidHtml(string documentContent, MarkupBlock expectedOutput) { RunParseTreeRewriterTest(documentContent, expectedOutput, "p"); }