Make the tests pass
- Remove baseline tests. Those live with tooling - Unskip tests that should have been fixed years ago - Fix rendering test infrastructure
This commit is contained in:
parent
bdb5982dbd
commit
0dd1bf8cd3
|
|
@ -2,14 +2,19 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class BindRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
public BindRazorIntegrationTest(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
internal override bool UseTwoPhaseCompilation => true;
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Components.Razor;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
|
|
@ -84,6 +82,11 @@ namespace Test
|
|||
}
|
||||
");
|
||||
|
||||
public ChildContentRazorIntegrationTest(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
internal override bool UseTwoPhaseCompilation => true;
|
||||
|
||||
[Fact]
|
||||
|
|
@ -410,174 +413,5 @@ namespace Test
|
|||
frame => AssertFrame.Text(frame, " Content", 9),
|
||||
frame => AssertFrame.Text(frame, "Bye!", 11));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_ChildContent_AttributeAndBody_ProducesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
@{ RenderFragment<string> template = @<div>@context.ToLowerInvariant()</div>; }
|
||||
<RenderChildContent ChildContent=""@template.WithValue(""HI"")"">
|
||||
Some Content
|
||||
</RenderChildContent>");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.ChildContentSetByAttributeAndBody.Id, diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_ChildContent_AttributeAndExplicitChildContent_ProducesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
@{ RenderFragment<string> template = @<div>@context.ToLowerInvariant()</div>; }
|
||||
<RenderChildContent ChildContent=""@template.WithValue(""HI"")"">
|
||||
<ChildContent>
|
||||
Some Content
|
||||
</ChildContent>
|
||||
</RenderChildContent>");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.ChildContentSetByAttributeAndBody.Id, diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_ChildContent_ExplicitChildContent_UnrecogizedContent_ProducesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<RenderChildContent>
|
||||
<ChildContent>
|
||||
</ChildContent>
|
||||
@somethingElse
|
||||
</RenderChildContent>");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.ChildContentMixedWithExplicitChildContent.Id, diagnostic.Id);
|
||||
Assert.Equal(
|
||||
"Unrecognized child content inside component 'RenderChildContent'. The component 'RenderChildContent' accepts " +
|
||||
"child content through the following top-level items: 'ChildContent'.",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_ChildContent_ExplicitChildContent_UnrecogizedElement_ProducesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<RenderChildContent>
|
||||
<ChildContent>
|
||||
</ChildContent>
|
||||
<UnrecognizedChildContent></UnrecognizedChildContent>
|
||||
</RenderChildContent>");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.ChildContentMixedWithExplicitChildContent.Id, diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_ChildContent_ExplicitChildContent_UnrecogizedAttribute_ProducesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<RenderChildContent>
|
||||
<ChildContent attr>
|
||||
</ChildContent>
|
||||
</RenderChildContent>");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.ChildContentHasInvalidAttribute.Id, diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_ChildContent_ExplicitChildContent_InvalidParameterName_ProducesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(RenderChildContentStringComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<RenderChildContentString>
|
||||
<ChildContent Context=""@(""HI"")"">
|
||||
</ChildContent>
|
||||
</RenderChildContentString>");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.ChildContentHasInvalidParameter.Id, diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_ChildContent_ExplicitChildContent_RepeatedParameterName_GeneratesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(RenderChildContentStringComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<RenderChildContentString>
|
||||
<ChildContent>
|
||||
<RenderChildContentString>
|
||||
<ChildContent Context=""context"">
|
||||
</ChildContent>
|
||||
</RenderChildContentString>
|
||||
</ChildContent>
|
||||
</RenderChildContentString>");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.ChildContentRepeatedParameterName.Id, diagnostic.Id);
|
||||
Assert.Equal(
|
||||
"The child content element 'ChildContent' of component 'RenderChildContentString' uses the same parameter name ('context') as enclosing child content " +
|
||||
"element 'ChildContent' of component 'RenderChildContentString'. Specify the parameter name like: '<ChildContent Context=\"another_name\"> to resolve the ambiguity",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_ChildContent_ContextParameterNameOnComponent_Invalid_ProducesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(RenderChildContentStringComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<RenderChildContentString Context=""@Foo()"">
|
||||
</RenderChildContentString>");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.ChildContentHasInvalidParameterOnComponent.Id, diagnostic.Id);
|
||||
Assert.Equal(
|
||||
"Invalid parameter name. The parameter name attribute 'Context' on component 'RenderChildContentString' can only include literal text.",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,127 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class ComponentDiscoveryRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
internal override bool UseTwoPhaseCompilation => true;
|
||||
|
||||
[Fact]
|
||||
public void ComponentDiscovery_CanFindComponent_DefinedinCSharp()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent : ComponentBase
|
||||
{
|
||||
}
|
||||
}
|
||||
"));
|
||||
|
||||
// Act
|
||||
var result = CompileToCSharp("@addTagHelper *, TestAssembly");
|
||||
|
||||
// Assert
|
||||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Test.MyComponent");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentDiscovery_CanFindComponent_WithNamespace_DefinedinCSharp()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test.AnotherNamespace
|
||||
{
|
||||
public class MyComponent : ComponentBase
|
||||
{
|
||||
}
|
||||
}
|
||||
"));
|
||||
|
||||
// Act
|
||||
var result = CompileToCSharp("@addTagHelper *, TestAssembly");
|
||||
|
||||
// Assert
|
||||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Test.AnotherNamespace.MyComponent");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentDiscovery_CanFindComponent_DefinedinCshtml()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = CompileToCSharp("UniqueName.cshtml", "@addTagHelper *, TestAssembly");
|
||||
|
||||
// Assert
|
||||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Test.UniqueName");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentDiscovery_CanFindComponent_BuiltIn()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = CompileToCSharp("@addTagHelper *, Microsoft.AspNetCore.Components");
|
||||
|
||||
// Assert
|
||||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Microsoft.AspNetCore.Components.Routing.NavLink");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentDiscovery_CanFindComponent_WithTypeParameter()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = CompileToCSharp("UniqueName.cshtml", @"
|
||||
@addTagHelper *, TestAssembly
|
||||
@typeparam TItem
|
||||
@functions {
|
||||
[Parameter] TItem Item { get; set; }
|
||||
}");
|
||||
|
||||
// Assert
|
||||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Test.UniqueName<TItem>");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentDiscovery_CanFindComponent_WithMultipleTypeParameters()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = CompileToCSharp("UniqueName.cshtml", @"
|
||||
@addTagHelper *, TestAssembly
|
||||
@typeparam TItem1
|
||||
@typeparam TItem2
|
||||
@typeparam TItem3
|
||||
@functions {
|
||||
[Parameter] TItem1 Item { get; set; }
|
||||
}");
|
||||
|
||||
// Assert
|
||||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Test.UniqueName<TItem1, TItem2, TItem3>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,15 +3,20 @@
|
|||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class ComponentRenderingRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
public ComponentRenderingRazorIntegrationTest(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
internal override bool UseTwoPhaseCompilation => true;
|
||||
|
||||
[Fact]
|
||||
|
|
@ -469,12 +474,11 @@ namespace Test
|
|||
frame => AssertFrame.Attribute(frame, "style", "background: #FFFFFF;", 2));
|
||||
}
|
||||
|
||||
// Text nodes decode HTML entities
|
||||
[Fact]
|
||||
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/6185")]
|
||||
public void Render_Component_HtmlEncoded()
|
||||
{
|
||||
// Arrange
|
||||
var component = CompileToComponent(@"<span>Hi</span>");
|
||||
var component = CompileToComponent(@"<span>Hi</span>");
|
||||
|
||||
// Act
|
||||
var frames = GetRenderTree(component);
|
||||
|
|
@ -485,8 +489,23 @@ namespace Test
|
|||
frame => AssertFrame.Text(frame, "<span>Hi</span>"));
|
||||
}
|
||||
|
||||
// Integration test for HTML block rewriting
|
||||
[Fact]
|
||||
public void Render_Component_HtmlBlockEncoded()
|
||||
{
|
||||
// Arrange
|
||||
var component = CompileToComponent(@"<div><span>Hi</span></div>");
|
||||
|
||||
// Act
|
||||
var frames = GetRenderTree(component);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
frames,
|
||||
frame => AssertFrame.Markup(frame, "<div><span>Hi</span></div>"));
|
||||
}
|
||||
|
||||
// Integration test for HTML block rewriting
|
||||
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/6183")]
|
||||
public void Render_HtmlBlock_Integration()
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -1,168 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Razor;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class DeclarationRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
internal override RazorConfiguration Configuration => BlazorExtensionInitializer.DeclarationConfiguration;
|
||||
|
||||
[Fact]
|
||||
public void DeclarationConfiguration_IncludesFunctions()
|
||||
{
|
||||
// Arrange & Act
|
||||
var component = CompileToComponent(@"
|
||||
@functions {
|
||||
public string Value { get; set; }
|
||||
}");
|
||||
|
||||
// Assert
|
||||
var property = component.GetType().GetProperty("Value");
|
||||
Assert.NotNull(property);
|
||||
Assert.Same(typeof(string), property.PropertyType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeclarationConfiguration_IncludesInject()
|
||||
{
|
||||
// Arrange & Act
|
||||
var component = CompileToComponent(@"
|
||||
@inject string Value
|
||||
");
|
||||
|
||||
// Assert
|
||||
var property = component.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
Assert.NotNull(property);
|
||||
Assert.Same(typeof(string), property.PropertyType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeclarationConfiguration_IncludesUsings()
|
||||
{
|
||||
// Arrange & Act
|
||||
var component = CompileToComponent(@"
|
||||
@using System.Text
|
||||
@inject StringBuilder Value
|
||||
");
|
||||
|
||||
// Assert
|
||||
var property = component.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
Assert.NotNull(property);
|
||||
Assert.Same(typeof(StringBuilder), property.PropertyType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeclarationConfiguration_IncludesInherits()
|
||||
{
|
||||
// Arrange & Act
|
||||
var component = CompileToComponent($@"
|
||||
@inherits {FullTypeName<BaseClass>()}
|
||||
");
|
||||
|
||||
// Assert
|
||||
Assert.Same(typeof(BaseClass), component.GetType().BaseType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeclarationConfiguration_IncludesImplements()
|
||||
{
|
||||
// Arrange & Act
|
||||
var component = CompileToComponent($@"
|
||||
@implements {FullTypeName<IDoCoolThings>()}
|
||||
");
|
||||
|
||||
// Assert
|
||||
var type = component.GetType();
|
||||
Assert.Contains(typeof(IDoCoolThings), component.GetType().GetInterfaces());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeclarationConfiguration_RenderMethodIsEmpty()
|
||||
{
|
||||
// Arrange & Act
|
||||
var component = CompileToComponent(@"
|
||||
<html>
|
||||
@{ var message = ""hi""; }
|
||||
<span class=""@(5 + 7)"">@message</span>
|
||||
</html>
|
||||
");
|
||||
|
||||
var frames = GetRenderTree(component);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(frames);
|
||||
}
|
||||
|
||||
[Fact] // Regression test for https://github.com/aspnet/Blazor/issues/453
|
||||
public void DeclarationConfiguration_FunctionsBlockHasLineMappings_MappingsApplyToError()
|
||||
{
|
||||
// Arrange & Act 1
|
||||
var generated = CompileToCSharp(@"
|
||||
@functions {
|
||||
public StringBuilder Builder { get; set; }
|
||||
}
|
||||
");
|
||||
|
||||
// Assert 1
|
||||
AssertSourceEquals(@"
|
||||
// <auto-generated/>
|
||||
#pragma warning disable 1591
|
||||
#pragma warning disable 0414
|
||||
#pragma warning disable 0649
|
||||
#pragma warning disable 0169
|
||||
|
||||
namespace Test
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 1 ""x:\dir\subdir\Test\TestComponent.cshtml""
|
||||
|
||||
public StringBuilder Builder { get; set; }
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
", generated);
|
||||
|
||||
// Act 2
|
||||
var assembly = CompileToAssembly(generated, throwOnFailure: false);
|
||||
|
||||
// Assert 2
|
||||
var diagnostic = Assert.Single(assembly.Diagnostics);
|
||||
|
||||
// This error should map to line 2 of the generated file, the test
|
||||
// says 1 because Roslyn's line/column data structures are 0-based.
|
||||
var position = diagnostic.Location.GetMappedLineSpan();
|
||||
Assert.EndsWith(".cshtml", position.Path);
|
||||
Assert.Equal(1, position.StartLinePosition.Line);
|
||||
}
|
||||
|
||||
public class BaseClass : ComponentBase
|
||||
{
|
||||
}
|
||||
|
||||
public interface IDoCoolThings
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class DesignTimeCodeGenerationTest : CodeGenerationTestBase
|
||||
{
|
||||
internal override bool DesignTime => true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class DiagnosticRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void RejectsEndTagWithNoStartTag()
|
||||
{
|
||||
// Arrange/Act
|
||||
var result = CompileToCSharp(
|
||||
"Line1\nLine2\nLine3</mytag>");
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result.Diagnostics,
|
||||
item =>
|
||||
{
|
||||
Assert.Equal("BL9981", item.Id);
|
||||
Assert.Equal("Unexpected closing tag 'mytag' with no matching start tag.", item.GetMessage());
|
||||
});
|
||||
}
|
||||
|
||||
// This used to be a sugar syntax for lambdas, but we don't support that anymore
|
||||
[Fact]
|
||||
public void OldCodeBlockAttributeSyntax_ReportsError()
|
||||
{
|
||||
// Arrange/Act
|
||||
var generated = CompileToCSharp(@"
|
||||
<elem attr=@{ DidInvokeCode = true; } />
|
||||
@functions {
|
||||
public bool DidInvokeCode { get; set; } = false;
|
||||
}");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Equal("BL9979", diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RejectsScriptTag()
|
||||
{
|
||||
// Arrange/Act
|
||||
var result = CompileToCSharp(@"Hello
|
||||
<div>
|
||||
<script src='anything'>
|
||||
something
|
||||
</script>
|
||||
</div>
|
||||
Goodbye");
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result.Diagnostics,
|
||||
item =>
|
||||
{
|
||||
Assert.Equal("BL9992", item.Id);
|
||||
Assert.Equal("Script tags should not be placed inside components because they cannot be updated dynamically. To fix this, move the script tag to the 'index.html' file or another static location. For more information see https://go.microsoft.com/fwlink/?linkid=872131", item.GetMessage());
|
||||
Assert.Equal(2, item.Span.LineIndex);
|
||||
Assert.Equal(4, item.Span.CharacterIndex);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,16 +4,21 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Layouts;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
// Integration tests for Blazor's directives
|
||||
public class DirectiveRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
public DirectiveRazorIntegrationTest(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentsDoNotHaveLayoutAttributeByDefault()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
// Integration tests focused on file path handling for class/namespace names
|
||||
public class FilePathRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void FileNameIsInvalidClassName_SanitizesInvalidClassName()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = CompileToAssembly("Filename with spaces.cshtml", "");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
|
||||
var type = Assert.Single(result.Assembly.GetTypes());
|
||||
Assert.Equal(DefaultBaseNamespace, type.Namespace);
|
||||
Assert.Equal("Filename_with_spaces", type.Name);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("ItemAtRoot.cs", "Test", "ItemAtRoot")]
|
||||
[InlineData("Dir1\\MyFile.cs", "Test.Dir1", "MyFile")]
|
||||
[InlineData("Dir1\\Dir2\\MyFile.cs", "Test.Dir1.Dir2", "MyFile")]
|
||||
public void CreatesClassWithCorrectNameAndNamespace(string relativePath, string expectedNamespace, string expectedClassName)
|
||||
{
|
||||
// Arrange
|
||||
relativePath = relativePath.Replace('\\', Path.DirectorySeparatorChar);
|
||||
|
||||
// Act
|
||||
var result = CompileToAssembly(relativePath, "");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
|
||||
var type = Assert.Single(result.Assembly.GetTypes());
|
||||
Assert.Equal(expectedNamespace, type.Namespace);
|
||||
Assert.Equal(expectedClassName, type.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Components.Razor;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
|
|
@ -81,6 +80,11 @@ namespace Test
|
|||
}
|
||||
");
|
||||
|
||||
public GenericComponentRazorIntegrationTest(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
internal override bool UseTwoPhaseCompilation => true;
|
||||
|
||||
[Fact]
|
||||
|
|
@ -313,45 +317,5 @@ namespace Test
|
|||
frame => AssertFrame.Text(frame, "FOO", 1),
|
||||
frame => AssertFrame.Text(frame, "39", 2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenericComponent_WithoutAnyTypeParameters_TriggersDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(GenericContextComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<GenericContext />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.GenericComponentTypeInferenceUnderspecified.Id, diagnostic.Id);
|
||||
Assert.Equal(
|
||||
"The type of component 'GenericContext' cannot be inferred based on the values provided. Consider " +
|
||||
"specifying the type arguments directly using the following attributes: 'TItem'.",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenericComponent_WithMissingTypeParameters_TriggersDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(MultipleGenericParameterComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MultipleGenericParameter TItem1=int />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.GenericComponentMissingTypeArgument.Id, diagnostic.Id);
|
||||
Assert.Equal(
|
||||
"The component 'MultipleGenericParameter' is missing required type arguments. " +
|
||||
"Specify the missing types using the attributes: 'TItem2', 'TItem3'.",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Components.Build.Test;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||
{
|
||||
public class InitializeTestFileAttribute : BeforeAfterTestAttribute
|
||||
{
|
||||
public override void Before(MethodInfo methodUnderTest)
|
||||
{
|
||||
if (typeof(RazorBaselineIntegrationTestBase).GetTypeInfo().IsAssignableFrom(methodUnderTest.ReflectedType.GetTypeInfo()))
|
||||
{
|
||||
var typeName = methodUnderTest.ReflectedType.Name;
|
||||
RazorBaselineIntegrationTestBase.DirectoryPath = $"TestFiles/{typeName}/{methodUnderTest.Name}";
|
||||
}
|
||||
}
|
||||
|
||||
public override void After(MethodInfo methodUnderTest)
|
||||
{
|
||||
if (typeof(RazorBaselineIntegrationTestBase).GetTypeInfo().IsAssignableFrom(methodUnderTest.ReflectedType.GetTypeInfo()))
|
||||
{
|
||||
RazorBaselineIntegrationTestBase.DirectoryPath = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||
{
|
||||
public static class IntermediateNodeSerializer
|
||||
{
|
||||
public static string Serialize(IntermediateNode node)
|
||||
{
|
||||
using (var writer = new StringWriter())
|
||||
{
|
||||
var walker = new Walker(writer);
|
||||
walker.Visit(node);
|
||||
|
||||
return writer.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private class Walker : IntermediateNodeWalker
|
||||
{
|
||||
private readonly IntermediateNodeWriter _visitor;
|
||||
private readonly TextWriter _writer;
|
||||
|
||||
public Walker(TextWriter writer)
|
||||
{
|
||||
_visitor = new IntermediateNodeWriter(writer);
|
||||
_writer = writer;
|
||||
}
|
||||
|
||||
public TextWriter Writer { get; }
|
||||
|
||||
public override void VisitDefault(IntermediateNode node)
|
||||
{
|
||||
_visitor.Visit(node);
|
||||
_writer.WriteLine();
|
||||
|
||||
_visitor.Depth++;
|
||||
base.VisitDefault(node);
|
||||
_visitor.Depth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,275 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||
{
|
||||
public static class IntermediateNodeVerifier
|
||||
{
|
||||
public static void Verify(IntermediateNode node, string[] baseline)
|
||||
{
|
||||
var walker = new Walker(baseline);
|
||||
walker.Visit(node);
|
||||
walker.AssertReachedEndOfBaseline();
|
||||
}
|
||||
|
||||
private class Walker : IntermediateNodeWalker
|
||||
{
|
||||
private readonly string[] _baseline;
|
||||
private readonly IntermediateNodeWriter _visitor;
|
||||
private readonly StringWriter _writer;
|
||||
|
||||
private int _index;
|
||||
|
||||
public Walker(string[] baseline)
|
||||
{
|
||||
_writer = new StringWriter();
|
||||
|
||||
_visitor = new IntermediateNodeWriter(_writer);
|
||||
_baseline = baseline;
|
||||
|
||||
}
|
||||
|
||||
public TextWriter Writer { get; }
|
||||
|
||||
public override void VisitDefault(IntermediateNode node)
|
||||
{
|
||||
var expected = _index < _baseline.Length ? _baseline[_index++] : null;
|
||||
|
||||
// Write the node as text for comparison
|
||||
_writer.GetStringBuilder().Clear();
|
||||
_visitor.Visit(node);
|
||||
var actual = _writer.GetStringBuilder().ToString();
|
||||
|
||||
AssertNodeEquals(node, Ancestors, expected, actual);
|
||||
|
||||
_visitor.Depth++;
|
||||
base.VisitDefault(node);
|
||||
_visitor.Depth--;
|
||||
}
|
||||
|
||||
public void AssertReachedEndOfBaseline()
|
||||
{
|
||||
// Since we're walking the nodes of our generated code there's the chance that our baseline is longer.
|
||||
Assert.True(_baseline.Length == _index, "Not all lines of the baseline were visited!");
|
||||
}
|
||||
|
||||
private void AssertNodeEquals(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual)
|
||||
{
|
||||
if (string.Equals(expected, actual))
|
||||
{
|
||||
// YAY!!! everything is great.
|
||||
return;
|
||||
}
|
||||
|
||||
if (expected == null)
|
||||
{
|
||||
var message = "The node is missing from baseline.";
|
||||
throw new IntermediateNodeBaselineException(node, Ancestors.ToArray(), expected, actual, message);
|
||||
}
|
||||
|
||||
int charsVerified = 0;
|
||||
AssertNestingEqual(node, ancestors, expected, actual, ref charsVerified);
|
||||
AssertNameEqual(node, ancestors, expected, actual, ref charsVerified);
|
||||
AssertDelimiter(node, expected, actual, true, ref charsVerified);
|
||||
AssertLocationEqual(node, ancestors, expected, actual, ref charsVerified);
|
||||
AssertDelimiter(node, expected, actual, false, ref charsVerified);
|
||||
AssertContentEqual(node, ancestors, expected, actual, ref charsVerified);
|
||||
|
||||
throw new InvalidOperationException("We can't figure out HOW these two things are different. This is a bug.");
|
||||
}
|
||||
|
||||
private void AssertNestingEqual(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual, ref int charsVerified)
|
||||
{
|
||||
var i = 0;
|
||||
for (; i < expected.Length; i++)
|
||||
{
|
||||
if (expected[i] != ' ')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var failed = false;
|
||||
var j = 0;
|
||||
for (; j < i; j++)
|
||||
{
|
||||
if (actual.Length <= j || actual[j] != ' ')
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (actual.Length <= j + 1 || actual[j] == ' ')
|
||||
{
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
var message = "The node is at the wrong level of nesting. This usually means a child is missing.";
|
||||
throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message);
|
||||
}
|
||||
|
||||
charsVerified = j;
|
||||
}
|
||||
|
||||
private void AssertNameEqual(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual, ref int charsVerified)
|
||||
{
|
||||
var expectedName = GetName(expected, charsVerified);
|
||||
var actualName = GetName(actual, charsVerified);
|
||||
|
||||
if (!string.Equals(expectedName, actualName))
|
||||
{
|
||||
var message = $"Node names are not equal.";
|
||||
throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message);
|
||||
}
|
||||
|
||||
charsVerified += expectedName.Length;
|
||||
}
|
||||
|
||||
// Either both strings need to have a delimiter next or neither should.
|
||||
private void AssertDelimiter(IntermediateNode node, string expected, string actual, bool required, ref int charsVerified)
|
||||
{
|
||||
if (charsVerified == expected.Length && required)
|
||||
{
|
||||
throw new InvalidOperationException($"Baseline text is not well-formed: '{expected}'.");
|
||||
}
|
||||
|
||||
if (charsVerified == actual.Length && required)
|
||||
{
|
||||
throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'.");
|
||||
}
|
||||
|
||||
if (charsVerified == expected.Length && charsVerified == actual.Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var expectedDelimiter = expected.IndexOf(" - ", charsVerified);
|
||||
if (expectedDelimiter != charsVerified && expectedDelimiter != -1)
|
||||
{
|
||||
throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'.");
|
||||
}
|
||||
|
||||
var actualDelimiter = actual.IndexOf(" - ", charsVerified);
|
||||
if (actualDelimiter != charsVerified && actualDelimiter != -1)
|
||||
{
|
||||
throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'.");
|
||||
}
|
||||
|
||||
Assert.Equal(expectedDelimiter, actualDelimiter);
|
||||
|
||||
charsVerified += 3;
|
||||
}
|
||||
|
||||
private void AssertLocationEqual(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual, ref int charsVerified)
|
||||
{
|
||||
var expectedLocation = GetLocation(expected, charsVerified);
|
||||
var actualLocation = GetLocation(actual, charsVerified);
|
||||
|
||||
if (!string.Equals(expectedLocation, actualLocation))
|
||||
{
|
||||
var message = $"Locations are not equal.";
|
||||
throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message);
|
||||
}
|
||||
|
||||
charsVerified += expectedLocation.Length;
|
||||
}
|
||||
|
||||
private void AssertContentEqual(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual, ref int charsVerified)
|
||||
{
|
||||
var expectedContent = GetContent(expected, charsVerified);
|
||||
var actualContent = GetContent(actual, charsVerified);
|
||||
|
||||
if (!string.Equals(expectedContent, actualContent))
|
||||
{
|
||||
var message = $"Contents are not equal.";
|
||||
throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message);
|
||||
}
|
||||
|
||||
charsVerified += expectedContent.Length;
|
||||
}
|
||||
|
||||
private string GetName(string text, int start)
|
||||
{
|
||||
var delimiter = text.IndexOf(" - ", start);
|
||||
if (delimiter == -1)
|
||||
{
|
||||
throw new InvalidOperationException($"Baseline text is not well-formed: '{text}'.");
|
||||
}
|
||||
|
||||
return text.Substring(start, delimiter - start);
|
||||
}
|
||||
|
||||
private string GetLocation(string text, int start)
|
||||
{
|
||||
var delimiter = text.IndexOf(" - ", start);
|
||||
return delimiter == -1 ? text.Substring(start) : text.Substring(start, delimiter - start);
|
||||
}
|
||||
|
||||
private string GetContent(string text, int start)
|
||||
{
|
||||
return start == text.Length ? string.Empty : text.Substring(start);
|
||||
}
|
||||
|
||||
private class IntermediateNodeBaselineException : XunitException
|
||||
{
|
||||
public IntermediateNodeBaselineException(IntermediateNode node, IntermediateNode[] ancestors, string expected, string actual, string userMessage)
|
||||
: base(Format(node, ancestors, expected, actual, userMessage))
|
||||
{
|
||||
Node = node;
|
||||
Expected = expected;
|
||||
Actual = actual;
|
||||
}
|
||||
|
||||
public IntermediateNode Node { get; }
|
||||
|
||||
public string Actual { get; }
|
||||
|
||||
public string Expected { get; }
|
||||
|
||||
private static string Format(IntermediateNode node, IntermediateNode[] ancestors, string expected, string actual, string userMessage)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendLine(userMessage);
|
||||
builder.AppendLine();
|
||||
|
||||
if (expected != null)
|
||||
{
|
||||
builder.Append("Expected: ");
|
||||
builder.AppendLine(expected);
|
||||
}
|
||||
|
||||
if (actual != null)
|
||||
{
|
||||
builder.Append("Actual: ");
|
||||
builder.AppendLine(actual);
|
||||
}
|
||||
|
||||
if (ancestors != null)
|
||||
{
|
||||
builder.AppendLine();
|
||||
builder.AppendLine("Path:");
|
||||
|
||||
foreach (var ancestor in ancestors)
|
||||
{
|
||||
builder.AppendLine(ancestor.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,316 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Components.Razor;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||
{
|
||||
// Serializes single IR nodes (shallow).
|
||||
public class IntermediateNodeWriter :
|
||||
IntermediateNodeVisitor,
|
||||
IExtensionIntermediateNodeVisitor<HtmlElementIntermediateNode>,
|
||||
IExtensionIntermediateNodeVisitor<HtmlBlockIntermediateNode>,
|
||||
IExtensionIntermediateNodeVisitor<ComponentExtensionNode>,
|
||||
IExtensionIntermediateNodeVisitor<ComponentAttributeExtensionNode>,
|
||||
IExtensionIntermediateNodeVisitor<ComponentChildContentIntermediateNode>,
|
||||
IExtensionIntermediateNodeVisitor<ComponentTypeArgumentExtensionNode>,
|
||||
IExtensionIntermediateNodeVisitor<ComponentTypeInferenceMethodIntermediateNode>,
|
||||
IExtensionIntermediateNodeVisitor<RouteAttributeExtensionNode>,
|
||||
IExtensionIntermediateNodeVisitor<RefExtensionNode>
|
||||
{
|
||||
private readonly TextWriter _writer;
|
||||
|
||||
public IntermediateNodeWriter(TextWriter writer)
|
||||
{
|
||||
_writer = writer;
|
||||
}
|
||||
|
||||
public int Depth { get; set; }
|
||||
|
||||
public override void VisitDefault(IntermediateNode node)
|
||||
{
|
||||
WriteBasicNode(node);
|
||||
}
|
||||
|
||||
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, string.Join(" ", node.Modifiers), node.ClassName, node.BaseType, string.Join(", ", node.Interfaces ?? new List<string>()));
|
||||
}
|
||||
|
||||
public override void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Prefix);
|
||||
}
|
||||
|
||||
public override void VisitCSharpCodeAttributeValue(CSharpCodeAttributeValueIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Prefix);
|
||||
}
|
||||
|
||||
public override void VisitToken(IntermediateToken node)
|
||||
{
|
||||
WriteContentNode(node, node.Kind.ToString(), node.Content);
|
||||
}
|
||||
|
||||
public override void VisitMalformedDirective(MalformedDirectiveIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.DirectiveName);
|
||||
}
|
||||
|
||||
public override void VisitDirective(DirectiveIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.DirectiveName);
|
||||
}
|
||||
|
||||
public override void VisitDirectiveToken(DirectiveTokenIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Content);
|
||||
}
|
||||
|
||||
public override void VisitFieldDeclaration(FieldDeclarationIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, string.Join(" ", node.Modifiers), node.FieldType, node.FieldName);
|
||||
}
|
||||
|
||||
public override void VisitHtmlAttribute(HtmlAttributeIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Prefix, node.Suffix);
|
||||
}
|
||||
|
||||
public override void VisitHtmlAttributeValue(HtmlAttributeValueIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Prefix);
|
||||
}
|
||||
|
||||
public override void VisitNamespaceDeclaration(NamespaceDeclarationIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Content);
|
||||
}
|
||||
|
||||
public override void VisitMethodDeclaration(MethodDeclarationIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, string.Join(" ", node.Modifiers), node.ReturnType, node.MethodName);
|
||||
}
|
||||
|
||||
public override void VisitUsingDirective(UsingDirectiveIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Content);
|
||||
}
|
||||
|
||||
public override void VisitTagHelper(TagHelperIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.TagName, string.Format("{0}.{1}", nameof(TagMode), node.TagMode));
|
||||
}
|
||||
|
||||
public override void VisitTagHelperProperty(TagHelperPropertyIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.AttributeName, node.BoundAttribute.DisplayName, string.Format("HtmlAttributeValueStyle.{0}", node.AttributeStructure));
|
||||
}
|
||||
|
||||
public override void VisitTagHelperHtmlAttribute(TagHelperHtmlAttributeIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.AttributeName, string.Format("HtmlAttributeValueStyle.{0}", node.AttributeStructure));
|
||||
}
|
||||
|
||||
public override void VisitExtension(ExtensionIntermediateNode node)
|
||||
{
|
||||
// This will be called for nodes that are internal implementation details of Razor,
|
||||
// like the design time directive nodes.
|
||||
if (node.GetType().Assembly == typeof(RazorCodeDocument).Assembly)
|
||||
{
|
||||
WriteBasicNode(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Unknown node type: " + node.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteBasicNode(IntermediateNode node)
|
||||
{
|
||||
WriteIndent();
|
||||
WriteName(node);
|
||||
WriteSeparator();
|
||||
WriteSourceRange(node);
|
||||
}
|
||||
|
||||
protected void WriteContentNode(IntermediateNode node, params string[] content)
|
||||
{
|
||||
WriteIndent();
|
||||
WriteName(node);
|
||||
WriteSeparator();
|
||||
WriteSourceRange(node);
|
||||
|
||||
for (var i = 0; i < content.Length; i++)
|
||||
{
|
||||
WriteSeparator();
|
||||
WriteContent(content[i]);
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteIndent()
|
||||
{
|
||||
for (var i = 0; i < Depth; i++)
|
||||
{
|
||||
for (var j = 0; j < 4; j++)
|
||||
{
|
||||
_writer.Write(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteSeparator()
|
||||
{
|
||||
_writer.Write(" - ");
|
||||
}
|
||||
|
||||
protected void WriteNewLine()
|
||||
{
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
protected void WriteName(IntermediateNode node)
|
||||
{
|
||||
var typeName = node.GetType().Name;
|
||||
if (typeName.EndsWith("IntermediateNode"))
|
||||
{
|
||||
_writer.Write(typeName.Substring(0, typeName.Length - "IntermediateNode".Length));
|
||||
}
|
||||
else
|
||||
{
|
||||
_writer.Write(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteSourceRange(IntermediateNode node)
|
||||
{
|
||||
if (node.Source != null)
|
||||
{
|
||||
WriteSourceRange(node.Source.Value);
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteSourceRange(SourceSpan sourceRange)
|
||||
{
|
||||
_writer.Write("(");
|
||||
_writer.Write(sourceRange.AbsoluteIndex);
|
||||
_writer.Write(":");
|
||||
_writer.Write(sourceRange.LineIndex);
|
||||
_writer.Write(",");
|
||||
_writer.Write(sourceRange.CharacterIndex);
|
||||
_writer.Write(" [");
|
||||
_writer.Write(sourceRange.Length);
|
||||
_writer.Write("] ");
|
||||
|
||||
if (sourceRange.FilePath != null)
|
||||
{
|
||||
var fileName = sourceRange.FilePath.Substring(sourceRange.FilePath.LastIndexOf('/') + 1);
|
||||
_writer.Write(fileName);
|
||||
}
|
||||
|
||||
_writer.Write(")");
|
||||
}
|
||||
|
||||
protected void WriteDiagnostics(IntermediateNode node)
|
||||
{
|
||||
if (node.HasDiagnostics)
|
||||
{
|
||||
_writer.Write("| ");
|
||||
for (var i = 0; i < node.Diagnostics.Count; i++)
|
||||
{
|
||||
var diagnostic = node.Diagnostics[i];
|
||||
_writer.Write("{");
|
||||
WriteSourceRange(diagnostic.Span);
|
||||
_writer.Write(": ");
|
||||
_writer.Write(diagnostic.Severity);
|
||||
_writer.Write(" ");
|
||||
_writer.Write(diagnostic.Id);
|
||||
_writer.Write(": ");
|
||||
|
||||
// Purposefully not writing out the entire message to ensure readable IR and because messages
|
||||
// can span multiple lines. Not using string.GetHashCode because we can't have any collisions.
|
||||
using (var md5 = MD5.Create())
|
||||
{
|
||||
var diagnosticMessage = diagnostic.GetMessage();
|
||||
var messageBytes = Encoding.UTF8.GetBytes(diagnosticMessage);
|
||||
var messageHash = md5.ComputeHash(messageBytes);
|
||||
var stringHashBuilder = new StringBuilder();
|
||||
|
||||
for (var j = 0; j < messageHash.Length; j++)
|
||||
{
|
||||
stringHashBuilder.Append(messageHash[j].ToString("x2"));
|
||||
}
|
||||
|
||||
var stringHash = stringHashBuilder.ToString();
|
||||
_writer.Write(stringHash);
|
||||
}
|
||||
_writer.Write("} ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteContent(string content)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We explicitly escape newlines in node content so that the IR can be compared line-by-line. The escaped
|
||||
// newline cannot be platform specific so we need to drop the windows \r.
|
||||
// Also, escape our separator so we can search for ` - `to find delimiters.
|
||||
_writer.Write(content.Replace("\r", string.Empty).Replace("\n", "\\n").Replace(" - ", "\\-"));
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<HtmlElementIntermediateNode>.VisitExtension(HtmlElementIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.TagName);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<HtmlBlockIntermediateNode>.VisitExtension(HtmlBlockIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Content);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<ComponentExtensionNode>.VisitExtension(ComponentExtensionNode node)
|
||||
{
|
||||
WriteContentNode(node, node.TagName, node.TypeName);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<ComponentAttributeExtensionNode>.VisitExtension(ComponentAttributeExtensionNode node)
|
||||
{
|
||||
WriteContentNode(node, node.AttributeName, node.PropertyName);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<ComponentChildContentIntermediateNode>.VisitExtension(ComponentChildContentIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.AttributeName);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<ComponentTypeArgumentExtensionNode>.VisitExtension(ComponentTypeArgumentExtensionNode node)
|
||||
{
|
||||
WriteContentNode(node, node.TypeParameterName);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<ComponentTypeInferenceMethodIntermediateNode>.VisitExtension(ComponentTypeInferenceMethodIntermediateNode node)
|
||||
{
|
||||
WriteContentNode(node, node.FullTypeName, node.MethodName);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<RouteAttributeExtensionNode>.VisitExtension(RouteAttributeExtensionNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Template);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<RefExtensionNode>.VisitExtension(RefExtensionNode node)
|
||||
{
|
||||
WriteContentNode(node, node.IdentifierToken.Content, node.IsComponentCapture ? node.ComponentCaptureTypeName : "Element");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
public class RazorDiagnosticSerializer
|
||||
{
|
||||
public static string Serialize(RazorDiagnostic diagnostic)
|
||||
{
|
||||
return diagnostic.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||
{
|
||||
public static class SourceMappingsSerializer
|
||||
{
|
||||
public static string Serialize(RazorCSharpDocument csharpDocument, RazorSourceDocument sourceDocument)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
var charBuffer = new char[sourceDocument.Length];
|
||||
sourceDocument.CopyTo(0, charBuffer, 0, sourceDocument.Length);
|
||||
var sourceContent = new string(charBuffer);
|
||||
|
||||
for (var i = 0; i < csharpDocument.SourceMappings.Count; i++)
|
||||
{
|
||||
var sourceMapping = csharpDocument.SourceMappings[i];
|
||||
|
||||
builder.Append("Source Location: ");
|
||||
AppendMappingLocation(builder, sourceMapping.OriginalSpan, sourceContent);
|
||||
|
||||
builder.Append("Generated Location: ");
|
||||
AppendMappingLocation(builder, sourceMapping.GeneratedSpan, csharpDocument.GeneratedCode);
|
||||
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static void AppendMappingLocation(StringBuilder builder, SourceSpan location, string content)
|
||||
{
|
||||
builder
|
||||
.AppendLine(location.ToString())
|
||||
.Append("|");
|
||||
|
||||
for (var i = 0; i < location.Length; i++)
|
||||
{
|
||||
builder.Append(content[location.AbsoluteIndex + i]);
|
||||
}
|
||||
|
||||
builder.AppendLine("|");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
|
|
@ -9,19 +9,30 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
{
|
||||
private readonly byte[] _content;
|
||||
|
||||
public VirtualProjectItem(string basePath, string filePath, string physicalPath, string relativePhysicalPath, byte[] content)
|
||||
public VirtualProjectItem(
|
||||
string basePath,
|
||||
string filePath,
|
||||
string physicalPath,
|
||||
string relativePhysicalPath,
|
||||
string fileKind,
|
||||
byte[] content)
|
||||
{
|
||||
BasePath = basePath;
|
||||
FilePath = filePath;
|
||||
PhysicalPath = physicalPath;
|
||||
RelativePhysicalPath = relativePhysicalPath;
|
||||
_content = content;
|
||||
|
||||
// Base class will detect based on file-extension.
|
||||
FileKind = fileKind ?? base.FileKind;
|
||||
}
|
||||
|
||||
public override string BasePath { get; }
|
||||
|
||||
public override string RelativePhysicalPath { get; }
|
||||
|
||||
public override string FileKind { get; }
|
||||
|
||||
public override string FilePath { get; }
|
||||
|
||||
public override string PhysicalPath { get; }
|
||||
|
|
|
|||
|
|
@ -1,211 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.IntegrationTests;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
[InitializeTestFile]
|
||||
public abstract class RazorBaselineIntegrationTestBase : RazorIntegrationTestBase
|
||||
{
|
||||
private static readonly AsyncLocal<string> _directoryPath = new AsyncLocal<string>();
|
||||
|
||||
protected RazorBaselineIntegrationTestBase(bool? generateBaselines = null)
|
||||
{
|
||||
TestProjectRoot = TestProject.GetProjectDirectory(GetType());
|
||||
|
||||
if (generateBaselines.HasValue)
|
||||
{
|
||||
GenerateBaselines = generateBaselines.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Used by the test framework to set the directory for test files.
|
||||
public static string DirectoryPath
|
||||
{
|
||||
get { return _directoryPath.Value; }
|
||||
set { _directoryPath.Value = value; }
|
||||
}
|
||||
|
||||
#if GENERATE_BASELINES
|
||||
protected bool GenerateBaselines { get; } = true;
|
||||
#else
|
||||
protected bool GenerateBaselines { get; } = false;
|
||||
#endif
|
||||
|
||||
protected string TestProjectRoot { get; }
|
||||
|
||||
// For consistent line endings because the character counts are going to be recorded in files.
|
||||
internal override string LineEnding => "\r\n";
|
||||
|
||||
internal override bool NormalizeSourceLineEndings => true;
|
||||
|
||||
internal override string PathSeparator => "\\";
|
||||
|
||||
// Force consistent paths since they are going to be recorded in files.
|
||||
internal override string WorkingDirectory => ArbitraryWindowsPath;
|
||||
|
||||
[Fact]
|
||||
public void GenerateBaselinesMustBeFalse()
|
||||
{
|
||||
Assert.False(GenerateBaselines, "GenerateBaselines should be set back to false before you check in!");
|
||||
}
|
||||
|
||||
protected void AssertDocumentNodeMatchesBaseline(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var document = codeDocument.GetDocumentIntermediateNode();
|
||||
var baselineFilePath = GetBaselineFilePath(codeDocument, ".ir.txt");
|
||||
|
||||
if (GenerateBaselines)
|
||||
{
|
||||
var baselineFullPath = Path.Combine(TestProjectRoot, baselineFilePath);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(baselineFullPath));
|
||||
WriteBaseline(IntermediateNodeSerializer.Serialize(document), baselineFullPath);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var irFile = TestFile.Create(baselineFilePath, GetType().Assembly);
|
||||
if (!irFile.Exists())
|
||||
{
|
||||
throw new XunitException($"The resource {baselineFilePath} was not found.");
|
||||
}
|
||||
|
||||
// Normalize newlines by splitting into an array.
|
||||
var baseline = irFile.ReadAllText().Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
IntermediateNodeVerifier.Verify(document, baseline);
|
||||
}
|
||||
|
||||
protected void AssertCSharpDocumentMatchesBaseline(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var document = codeDocument.GetCSharpDocument();
|
||||
|
||||
// Normalize newlines to match those in the baseline.
|
||||
var actualCode = document.GeneratedCode.Replace("\r", "").Replace("\n", "\r\n");
|
||||
|
||||
var baselineFilePath = GetBaselineFilePath(codeDocument, ".codegen.cs");
|
||||
var baselineDiagnosticsFilePath = GetBaselineFilePath(codeDocument, ".diagnostics.txt");
|
||||
var baselineMappingsFilePath = GetBaselineFilePath(codeDocument, ".mappings.txt");
|
||||
|
||||
var serializedMappings = SourceMappingsSerializer.Serialize(document, codeDocument.Source);
|
||||
|
||||
if (GenerateBaselines)
|
||||
{
|
||||
var baselineFullPath = Path.Combine(TestProjectRoot, baselineFilePath);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(baselineFullPath));
|
||||
WriteBaseline(actualCode, baselineFullPath);
|
||||
|
||||
var baselineDiagnosticsFullPath = Path.Combine(TestProjectRoot, baselineDiagnosticsFilePath);
|
||||
var lines = document.Diagnostics.Select(RazorDiagnosticSerializer.Serialize).ToArray();
|
||||
if (lines.Any())
|
||||
{
|
||||
WriteBaseline(lines, baselineDiagnosticsFullPath);
|
||||
}
|
||||
else if (File.Exists(baselineDiagnosticsFullPath))
|
||||
{
|
||||
File.Delete(baselineDiagnosticsFullPath);
|
||||
}
|
||||
|
||||
var baselineMappingsFullPath = Path.Combine(TestProjectRoot, baselineMappingsFilePath);
|
||||
var text = SourceMappingsSerializer.Serialize(document, codeDocument.Source);
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
WriteBaseline(text, baselineMappingsFullPath);
|
||||
}
|
||||
else if (File.Exists(baselineMappingsFullPath))
|
||||
{
|
||||
File.Delete(baselineMappingsFullPath);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var codegenFile = TestFile.Create(baselineFilePath, GetType().Assembly);
|
||||
if (!codegenFile.Exists())
|
||||
{
|
||||
throw new XunitException($"The resource {baselineFilePath} was not found.");
|
||||
}
|
||||
|
||||
var baseline = codegenFile.ReadAllText();
|
||||
Assert.Equal(baseline, actualCode);
|
||||
|
||||
var baselineDiagnostics = string.Empty;
|
||||
var diagnosticsFile = TestFile.Create(baselineDiagnosticsFilePath, GetType().Assembly);
|
||||
if (diagnosticsFile.Exists())
|
||||
{
|
||||
baselineDiagnostics = diagnosticsFile.ReadAllText();
|
||||
}
|
||||
|
||||
var actualDiagnostics = string.Concat(document.Diagnostics.Select(d => RazorDiagnosticSerializer.Serialize(d) + "\r\n"));
|
||||
Assert.Equal(baselineDiagnostics, actualDiagnostics);
|
||||
|
||||
var baselineMappings = string.Empty;
|
||||
var mappingsFile = TestFile.Create(baselineMappingsFilePath, GetType().Assembly);
|
||||
if (mappingsFile.Exists())
|
||||
{
|
||||
baselineMappings = mappingsFile.ReadAllText();
|
||||
}
|
||||
|
||||
var actualMappings = SourceMappingsSerializer.Serialize(document, codeDocument.Source);
|
||||
actualMappings = actualMappings.Replace("\r", "").Replace("\n", "\r\n");
|
||||
Assert.Equal(baselineMappings, actualMappings);
|
||||
}
|
||||
|
||||
private string GetBaselineFilePath(RazorCodeDocument codeDocument, string extension)
|
||||
{
|
||||
if (codeDocument == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocument));
|
||||
}
|
||||
|
||||
if (extension == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(extension));
|
||||
}
|
||||
|
||||
var lastSlash = codeDocument.Source.FilePath.LastIndexOfAny(new []{ '/', '\\' });
|
||||
var fileName = lastSlash == -1 ? null : codeDocument.Source.FilePath.Substring(lastSlash + 1);
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
var message = "Integration tests require a filename";
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
if (DirectoryPath == null)
|
||||
{
|
||||
var message = $"{nameof(AssertDocumentNodeMatchesBaseline)} should only be called from an integration test..";
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
return Path.Combine(DirectoryPath, Path.ChangeExtension(fileName, extension));
|
||||
}
|
||||
|
||||
private static void WriteBaseline(string text, string filePath)
|
||||
{
|
||||
var lines = text.Replace("\r", "").Replace("\n", "\r\n");
|
||||
File.WriteAllText(filePath, text);
|
||||
}
|
||||
|
||||
private static void WriteBaseline(string[] lines, string filePath)
|
||||
{
|
||||
using (var writer = new StreamWriter(File.Open(filePath, FileMode.Create)))
|
||||
{
|
||||
// Force windows-style line endings so that we're consistent. This isn't
|
||||
// required for correctness, but will prevent churn when developing on OSX.
|
||||
writer.NewLine = "\r\n";
|
||||
|
||||
for (var i = 0; i < lines.Length; i++)
|
||||
{
|
||||
writer.WriteLine(lines[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,9 +8,8 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Razor;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
|
|
@ -20,12 +19,15 @@ using Microsoft.CodeAnalysis;
|
|||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class RazorIntegrationTestBase
|
||||
{
|
||||
private static readonly AsyncLocal<ITestOutputHelper> _output = new AsyncLocal<ITestOutputHelper>();
|
||||
|
||||
internal const string ArbitraryWindowsPath = "x:\\dir\\subdir\\Test";
|
||||
internal const string ArbitraryMacLinuxPath = "/dir/subdir/Test";
|
||||
|
||||
|
|
@ -59,17 +61,23 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
CSharpParseOptions = new CSharpParseOptions(LanguageVersion.CSharp7_3);
|
||||
}
|
||||
|
||||
public RazorIntegrationTestBase()
|
||||
public RazorIntegrationTestBase(ITestOutputHelper output)
|
||||
{
|
||||
_output.Value = output;
|
||||
|
||||
AdditionalSyntaxTrees = new List<SyntaxTree>();
|
||||
AdditionalRazorItems = new List<RazorProjectItem>();
|
||||
|
||||
|
||||
Configuration = BlazorExtensionInitializer.DefaultConfiguration;
|
||||
Configuration = RazorConfiguration.Create(RazorLanguageVersion.Latest, "MVC-3.0", Array.Empty<RazorExtension>());
|
||||
FileKind = FileKinds.Component; // Treat input files as components by default.
|
||||
FileSystem = new VirtualRazorProjectFileSystem();
|
||||
PathSeparator = Path.DirectorySeparatorChar.ToString();
|
||||
WorkingDirectory = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ArbitraryWindowsPath : ArbitraryMacLinuxPath;
|
||||
|
||||
// Many of the rendering tests include line endings in the output.
|
||||
LineEnding = "\n";
|
||||
NormalizeSourceLineEndings = true;
|
||||
|
||||
DefaultBaseNamespace = "Test"; // Matches the default working directory
|
||||
DefaultFileName = "TestComponent.cshtml";
|
||||
}
|
||||
|
|
@ -85,6 +93,8 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
internal virtual string DefaultFileName { get; }
|
||||
|
||||
internal virtual bool DesignTime { get; }
|
||||
|
||||
internal virtual string FileKind { get; }
|
||||
|
||||
internal virtual VirtualRazorProjectFileSystem FileSystem { get; }
|
||||
|
||||
|
|
@ -97,14 +107,15 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
internal virtual string PathSeparator { get; }
|
||||
|
||||
internal virtual bool NormalizeSourceLineEndings { get; }
|
||||
|
||||
|
||||
internal virtual bool UseTwoPhaseCompilation { get; }
|
||||
|
||||
internal virtual string WorkingDirectory { get; }
|
||||
|
||||
internal RazorProjectEngine CreateProjectEngine(RazorConfiguration configuration, MetadataReference[] references)
|
||||
// Intentionally private, we don't want tests messing with this because it's fragile.
|
||||
private RazorProjectEngine CreateProjectEngine(MetadataReference[] references)
|
||||
{
|
||||
return RazorProjectEngine.Create(configuration, FileSystem, b =>
|
||||
return RazorProjectEngine.Create(Configuration, FileSystem, b =>
|
||||
{
|
||||
// Turn off checksums, we're testing code generation.
|
||||
b.Features.Add(new SuppressChecksum());
|
||||
|
|
@ -114,7 +125,11 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
b.Phases.Insert(0, new ForceLineEndingPhase(LineEnding));
|
||||
}
|
||||
|
||||
BlazorExtensionInitializer.Register(b);
|
||||
// Including MVC here so that we can find any issues that arise from mixed MVC + Components.
|
||||
Microsoft.AspNetCore.Mvc.Razor.Extensions.RazorExtensions.Register(b);
|
||||
|
||||
// Features that use Roslyn are mandatory for components
|
||||
Microsoft.CodeAnalysis.Razor.CompilerFeatures.Register(b);
|
||||
|
||||
b.Features.Add(new CompilationTagHelperFeature());
|
||||
b.Features.Add(new DefaultMetadataReferenceFeature()
|
||||
|
|
@ -141,10 +156,11 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
}
|
||||
|
||||
return new VirtualProjectItem(
|
||||
WorkingDirectory,
|
||||
filePath,
|
||||
WorkingDirectory,
|
||||
filePath,
|
||||
fullPath,
|
||||
cshtmlRelativePath,
|
||||
FileKind,
|
||||
Encoding.UTF8.GetBytes(cshtmlContent.TrimStart()));
|
||||
}
|
||||
|
||||
|
|
@ -159,13 +175,13 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
{
|
||||
// The first phase won't include any metadata references for component discovery. This mirrors
|
||||
// what the build does.
|
||||
var projectEngine = CreateProjectEngine(BlazorExtensionInitializer.DeclarationConfiguration, Array.Empty<MetadataReference>());
|
||||
var projectEngine = CreateProjectEngine(Array.Empty<MetadataReference>());
|
||||
|
||||
RazorCodeDocument codeDocument;
|
||||
foreach (var item in AdditionalRazorItems)
|
||||
{
|
||||
// Result of generating declarations
|
||||
codeDocument = projectEngine.Process(item);
|
||||
codeDocument = projectEngine.ProcessDeclarationOnly(item);
|
||||
Assert.Empty(codeDocument.GetCSharpDocument().Diagnostics);
|
||||
|
||||
var syntaxTree = Parse(codeDocument.GetCSharpDocument().GeneratedCode, path: item.FilePath);
|
||||
|
|
@ -174,7 +190,7 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
|
||||
// Result of generating declarations
|
||||
var projectItem = CreateProjectItem(cshtmlRelativePath, cshtmlContent);
|
||||
codeDocument = projectEngine.Process(projectItem);
|
||||
codeDocument = projectEngine.ProcessDeclarationOnly(projectItem);
|
||||
var declaration = new CompileToCSharpResult
|
||||
{
|
||||
BaseCompilation = BaseCompilation.AddSyntaxTrees(AdditionalSyntaxTrees),
|
||||
|
|
@ -188,13 +204,13 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
|
||||
// Add the 'temp' compilation as a metadata reference
|
||||
var references = BaseCompilation.References.Concat(new[] { tempAssembly.Compilation.ToMetadataReference() }).ToArray();
|
||||
projectEngine = CreateProjectEngine(BlazorExtensionInitializer.DefaultConfiguration, references);
|
||||
projectEngine = CreateProjectEngine(references);
|
||||
|
||||
// Now update the any additional files
|
||||
foreach (var item in AdditionalRazorItems)
|
||||
{
|
||||
// Result of generating declarations
|
||||
codeDocument = projectEngine.Process(item);
|
||||
codeDocument = DesignTime ? projectEngine.ProcessDesignTime(item) : projectEngine.Process(item);
|
||||
Assert.Empty(codeDocument.GetCSharpDocument().Diagnostics);
|
||||
|
||||
// Replace the 'declaration' syntax tree
|
||||
|
|
@ -205,6 +221,30 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
|
||||
// Result of real code generation for the document under test
|
||||
codeDocument = DesignTime ? projectEngine.ProcessDesignTime(projectItem) : projectEngine.Process(projectItem);
|
||||
|
||||
_output.Value.WriteLine("Use this output when opening an issue");
|
||||
_output.Value.WriteLine(string.Empty);
|
||||
|
||||
_output.Value.WriteLine($"## Main source file ({projectItem.FileKind}):");
|
||||
_output.Value.WriteLine("```");
|
||||
_output.Value.WriteLine(ReadProjectItem(projectItem));
|
||||
_output.Value.WriteLine("```");
|
||||
_output.Value.WriteLine(string.Empty);
|
||||
|
||||
foreach (var item in AdditionalRazorItems)
|
||||
{
|
||||
_output.Value.WriteLine($"### Additional source file ({item.FileKind}):");
|
||||
_output.Value.WriteLine("```");
|
||||
_output.Value.WriteLine(ReadProjectItem(item));
|
||||
_output.Value.WriteLine("```");
|
||||
_output.Value.WriteLine(string.Empty);
|
||||
}
|
||||
|
||||
_output.Value.WriteLine("## Generated C#:");
|
||||
_output.Value.WriteLine("```C#");
|
||||
_output.Value.WriteLine(codeDocument.GetCSharpDocument().GeneratedCode);
|
||||
_output.Value.WriteLine("```");
|
||||
|
||||
return new CompileToCSharpResult
|
||||
{
|
||||
BaseCompilation = BaseCompilation.AddSyntaxTrees(AdditionalSyntaxTrees),
|
||||
|
|
@ -217,10 +257,26 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
{
|
||||
// For single phase compilation tests just use the base compilation's references.
|
||||
// This will include the built-in Blazor components.
|
||||
var projectEngine = CreateProjectEngine(Configuration, BaseCompilation.References.ToArray());
|
||||
var projectEngine = CreateProjectEngine(BaseCompilation.References.ToArray());
|
||||
|
||||
var projectItem = CreateProjectItem(cshtmlRelativePath, cshtmlContent);
|
||||
var codeDocument = DesignTime ? projectEngine.ProcessDesignTime(projectItem) : projectEngine.Process(projectItem);
|
||||
|
||||
// Log the generated code for test results.
|
||||
_output.Value.WriteLine("Use this output when opening an issue");
|
||||
_output.Value.WriteLine(string.Empty);
|
||||
|
||||
_output.Value.WriteLine($"## Main source file ({projectItem.FileKind}):");
|
||||
_output.Value.WriteLine("```");
|
||||
_output.Value.WriteLine(ReadProjectItem(projectItem));
|
||||
_output.Value.WriteLine("```");
|
||||
_output.Value.WriteLine(string.Empty);
|
||||
|
||||
_output.Value.WriteLine("## Generated C#:");
|
||||
_output.Value.WriteLine("```");
|
||||
_output.Value.WriteLine(codeDocument.GetCSharpDocument().GeneratedCode);
|
||||
_output.Value.WriteLine("```");
|
||||
|
||||
return new CompileToCSharpResult
|
||||
{
|
||||
BaseCompilation = BaseCompilation.AddSyntaxTrees(AdditionalSyntaxTrees),
|
||||
|
|
@ -343,6 +399,14 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
Assert.Equal(expected, generated.Code.Trim(), ignoreLineEndingDifferences: true);
|
||||
}
|
||||
|
||||
private static string ReadProjectItem(RazorProjectItem item)
|
||||
{
|
||||
using (var reader = new StreamReader(item.Read()))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
protected class CompileToCSharpResult
|
||||
{
|
||||
// A compilation that can be used *with* this code to compile an assembly
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
|
|
@ -14,6 +14,11 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
// Includes running the component code to verify the output.
|
||||
public class RenderingRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
public RenderingRazorIntegrationTest(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SupportsPlainText()
|
||||
{
|
||||
|
|
@ -83,7 +88,7 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
frame => AssertFrame.Text(frame, "there", 2));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Temporarily disable compiling markup frames in 0.5.1")]
|
||||
[Fact]
|
||||
public void SupportsElementsAsStaticBlock()
|
||||
{
|
||||
// Arrange/Act
|
||||
|
|
@ -144,28 +149,28 @@ namespace Microsoft.AspNetCore.Components.Build.Test
|
|||
frame => AssertFrame.Attribute(frame, "myattr", "val", 2));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Temporarily disable compiling markup frames in 0.5.1")]
|
||||
[Fact]
|
||||
public void SupportsSelfClosingElementsAsStaticBlock()
|
||||
{
|
||||
// Arrange/Act
|
||||
var component = CompileToComponent("Some text so elem isn't at position 0 <input attr='123' />");
|
||||
|
||||
// Assert
|
||||
Assert.Collection(GetRenderTree(component),
|
||||
frame => AssertFrame.Text(frame, "Some text so elem isn't at position 0 ", 0),
|
||||
frame => AssertFrame.Markup(frame, "<input attr=\"123\">", 1));
|
||||
Assert.Collection(
|
||||
GetRenderTree(component),
|
||||
frame => AssertFrame.Markup(frame, "Some text so elem isn't at position 0 <input attr=\"123\">", 0));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Temporarily disable compiling markup frames in 0.5.1")]
|
||||
[Fact]
|
||||
public void SupportsVoidHtmlElements()
|
||||
{
|
||||
// Arrange/Act
|
||||
var component = CompileToComponent("Some text so elem isn't at position 0 <img>");
|
||||
|
||||
// Assert
|
||||
Assert.Collection(GetRenderTree(component),
|
||||
frame => AssertFrame.Text(frame, "Some text so elem isn't at position 0 ", 0),
|
||||
frame => AssertFrame.Markup(frame, "<img>", 1));
|
||||
Assert.Collection(
|
||||
GetRenderTree(component),
|
||||
frame => AssertFrame.Markup(frame, "Some text so elem isn't at position 0 <img>", 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class RuntimeCodeGenerationTest : CodeGenerationTestBase
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
public class TemplateRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
// Razor doesn't parse this as a template, we don't need much special handling for
|
||||
// it because it will just be invalid in general.
|
||||
[Fact]
|
||||
public void Template_ImplicitExpressionInMarkupAttribute_CreatesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"<div attr=""@<div></div>"" />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Equal("RZ1005", diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Template_ExplicitExpressionInMarkupAttribute_CreatesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"<div attr=""@(@<div></div>)"" />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Equal("BL9994", diagnostic.Id);
|
||||
}
|
||||
|
||||
// Razor doesn't parse this as a template, we don't need much special handling for
|
||||
// it because it will just be invalid in general.
|
||||
[Fact]
|
||||
public void Template_ImplicitExpressionInComponentAttribute_CreatesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent : ComponentBase
|
||||
{
|
||||
}
|
||||
}
|
||||
"));
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"<MyComponent attr=""@<div></div>"" />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Equal("RZ1005", diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Template_ExplicitExpressionInComponentAttribute_CreatesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent : ComponentBase
|
||||
{
|
||||
}
|
||||
}
|
||||
"));
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"<MyComponent attr=""@(@<div></div>)"" />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Equal("BL9994", diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Template_ExplicitExpressionInRef_CreatesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"<div ref=""@(@<div></div>)"" />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Equal("BL9994", diagnostic.Id);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Template_ExplicitExpressionInBind_CreatesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"<input type=""text"" bind=""@(@<div></div>)"" />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Equal("BL9994", diagnostic.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Template_ExplicitExpressionInEventHandler_CreatesDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"<input type=""text"" onchange=""@(@<div></div>)"" />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Equal("BL9994", diagnostic.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
// Similar to design time code generation tests, but goes a character at a time.
|
||||
// Don't add many of these since they are slow - instead add features to existing
|
||||
// tests here, and use these as smoke tests, not for detailed regression testing.
|
||||
public class TypingTest : RazorIntegrationTestBase
|
||||
{
|
||||
internal override bool DesignTime => true;
|
||||
|
||||
internal override bool UseTwoPhaseCompilation => false;
|
||||
|
||||
[Fact]
|
||||
public void DoSomeTyping()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent : ComponentBase
|
||||
{
|
||||
[Parameter] int Value { get; set; }
|
||||
[Parameter] Action<int> ValueChanged { get; set; }
|
||||
[Parameter] string AnotherValue { get; set; }
|
||||
}
|
||||
|
||||
public class ModelState
|
||||
{
|
||||
public Action<string> Bind(Func<string, string> func) => throw null;
|
||||
}
|
||||
}
|
||||
"));
|
||||
var text = @"
|
||||
@addTagHelper *, TestAssembly
|
||||
<div>
|
||||
<MyComponent bind-Value=""myValue"" AnotherValue=""hi""/>
|
||||
<input type=""text"" bind=""@this.ModelState.Bind(x => x)"" />
|
||||
<button ref=""_button"" onsubmit=""@FormSubmitted"">Click me</button>
|
||||
</div>
|
||||
<MyComponent
|
||||
IntProperty=""123""
|
||||
BoolProperty=""true""
|
||||
StringProperty=""My string""
|
||||
ObjectProperty=""new SomeType()""/>
|
||||
@functions {
|
||||
Test.ModelState ModelState { get; set; }
|
||||
}";
|
||||
|
||||
for (var i = 0; i <= text.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
CompileToCSharp(text.Substring(0, i));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new XunitException($@"
|
||||
Code generation failed on iteration {i} with source text:
|
||||
{text.Substring(0, i)}
|
||||
|
||||
Exception:
|
||||
{ex}
|
||||
");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact] // Regression test for #1068
|
||||
public void Regression_1068()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
<input type=""text"" bind="" />
|
||||
@functions {
|
||||
Test.ModelState ModelState { get; set; }
|
||||
}
|
||||
");
|
||||
|
||||
// Assert
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Build.Test
|
||||
{
|
||||
// Integration tests focused on file path handling for class/namespace names
|
||||
public class WorkingDirectoryRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
public WorkingDirectoryRazorIntegrationTest()
|
||||
{
|
||||
WorkingDirectory = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ArbitraryWindowsPath : ArbitraryMacLinuxPath;
|
||||
WorkingDirectory += "-Dir";
|
||||
}
|
||||
|
||||
internal override string WorkingDirectory { get; }
|
||||
|
||||
[Theory]
|
||||
[InlineData("ItemAtRoot.cs", "Test_Dir", "ItemAtRoot")]
|
||||
[InlineData("Dir1\\MyFile.cs", "Test_Dir.Dir1", "MyFile")]
|
||||
[InlineData("Dir1\\Dir2\\MyFile.cs", "Test_Dir.Dir1.Dir2", "MyFile")]
|
||||
public void CreatesClassWithCorrectNameAndNamespace(string relativePath, string expectedNamespace, string expectedClassName)
|
||||
{
|
||||
// Arrange
|
||||
relativePath = relativePath.Replace('\\', Path.DirectorySeparatorChar);
|
||||
|
||||
// Act
|
||||
var result = CompileToAssembly(relativePath, "");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Diagnostics);
|
||||
|
||||
var type = Assert.Single(result.Assembly.GetTypes());
|
||||
Assert.Equal(expectedNamespace, type.Namespace);
|
||||
Assert.Equal(expectedClassName, type.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
|
|
|||
Loading…
Reference in New Issue