Blazor WebAssembly package renames (#19026)

Fixes https://github.com/dotnet/aspnetcore/issues/18384
This commit is contained in:
Pranav K 2020-02-18 10:54:29 -08:00 committed by GitHub
parent 07098b3d97
commit c935e9aa2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
322 changed files with 322 additions and 4108 deletions

View File

@ -34,8 +34,8 @@
$(RepoRoot)src\Installers\**\*.*proj;
$(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
$(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
$(RepoRoot)src\Components\Blazor\Build\testassets\**\*.*proj;
$(RepoRoot)src\ProjectTemplates\BlazorWasm.ProjectTemplates\content\**\*.csproj;
$(RepoRoot)src\Components\WebAssembly\Build\testassets\**\*.*proj;
$(RepoRoot)src\ProjectTemplates\ComponentsWebAssembly.ProjectTemplates\content\**\*.csproj;
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj;
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj;
$(RepoRoot)src\ProjectTemplates\Web.Spa.ProjectTemplates\content\**\*.csproj;

View File

@ -5,13 +5,12 @@
-->
<Project>
<ItemGroup>
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.Build" ProjectPath="$(RepoRoot)src\Components\Blazor\Build\src\Microsoft.AspNetCore.Blazor.Build.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.HttpClient" ProjectPath="$(RepoRoot)src\Components\Blazor\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj" />
<ProjectReferenceProvider Include="Mono.WebAssembly.Interop" ProjectPath="$(RepoRoot)src\Components\Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.Server" ProjectPath="$(RepoRoot)src\Components\Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.DataAnnotations.Validation" ProjectPath="$(RepoRoot)src\Components\Blazor\Validation\src\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" ProjectPath="$(RepoRoot)src\Components\Blazor\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
<ProjectReferenceProvider Include="BlazorServerApp" ProjectPath="$(RepoRoot)src\Components\Samples\BlazorServerApp\BlazorServerApp.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor" ProjectPath="$(RepoRoot)src\Components\Blazor\Blazor\src\Microsoft.AspNetCore.Blazor.csproj" RefProjectPath="$(RepoRoot)src\Components\Blazor\Blazor\ref\Microsoft.AspNetCore.Blazor.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Build" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Build\src\Microsoft.AspNetCore.Components.WebAssembly.Build.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.HttpClient" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj" />
<ProjectReferenceProvider Include="Mono.WebAssembly.Interop" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Server" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.DataAnnotations.Validation" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Validation\src\Microsoft.AspNetCore.Components.DataAnnotations.Validation.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj" RefProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly\ref\Microsoft.AspNetCore.Components.WebAssembly.csproj" />
</ItemGroup>
</Project>

View File

@ -11,65 +11,65 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.Driver", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.TestApp", "benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj", "{10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{B29FB58D-FAE5-405E-9695-BCF93582BE9A}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly", "WebAssembly", "{B29FB58D-FAE5-405E-9695-BCF93582BE9A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blazor", "Blazor", "{E363191C-6C15-4C40-8698-B0AD5AA09700}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly", "WebAssembly", "{E363191C-6C15-4C40-8698-B0AD5AA09700}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor", "Blazor\Blazor\src\Microsoft.AspNetCore.Blazor.csproj", "{8A585A38-917D-4A7E-8AFD-E860C76878FA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly", "WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj", "{8A585A38-917D-4A7E-8AFD-E860C76878FA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Tests", "Blazor\Blazor\test\Microsoft.AspNetCore.Blazor.Tests.csproj", "{75DA4341-5B7F-419C-8EED-3492013D8EB5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Tests", "WebAssembly\WebAssembly\test\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj", "{75DA4341-5B7F-419C-8EED-3492013D8EB5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A82B9830-447D-4E26-BEB7-C724A3956C0D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Build", "Blazor\Build\src\Microsoft.AspNetCore.Blazor.Build.csproj", "{201D53B3-2D33-40AD-813F-347A0C1998ED}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Build", "WebAssembly\Build\src\Microsoft.AspNetCore.Components.WebAssembly.Build.csproj", "{201D53B3-2D33-40AD-813F-347A0C1998ED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Build.Tests", "Blazor\Build\test\Microsoft.AspNetCore.Blazor.Build.Tests.csproj", "{AB13059F-8F21-48F6-B9F3-EAF260D9CB81}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Build.Tests", "WebAssembly\Build\test\Microsoft.AspNetCore.Components.WebAssembly.Build.Tests.csproj", "{AB13059F-8F21-48F6-B9F3-EAF260D9CB81}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{B4ACD900-27B6-482B-B434-2C1E86E9D8BC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorhosted", "Blazor\Build\testassets\blazorhosted\blazorhosted.csproj", "{5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "blazorhosted", "WebAssembly\Build\testassets\blazorhosted\blazorhosted.csproj", "{5F44DC59-3B4E-4E87-973F-C9FB4BBFD03D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "classlibrarywithsatelliteassemblies", "Blazor\Build\testassets\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj", "{4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "classlibrarywithsatelliteassemblies", "WebAssembly\Build\testassets\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj", "{4BD2D530-83C7-4A86-AF8E-FE1FECBF64C6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorClassLibrary", "Blazor\Build\testassets\razorclasslibrary\RazorClassLibrary.csproj", "{779749F3-8D4F-42BD-9219-37502AD68F0E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorClassLibrary", "WebAssembly\Build\testassets\razorclasslibrary\RazorClassLibrary.csproj", "{779749F3-8D4F-42BD-9219-37502AD68F0E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "standalone", "Blazor\Build\testassets\standalone\standalone.csproj", "{9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "standalone", "WebAssembly\Build\testassets\standalone\standalone.csproj", "{9C41BA92-FBC8-4E11-9A71-0B07906A2D6C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevServer", "DevServer", "{A44FB7D1-78AB-41C4-B1C7-94399396EA6C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DevServer", "Blazor\DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj", "{0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.DevServer", "WebAssembly\DevServer\src\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj", "{0ED336B7-6FAB-4872-8D75-1CDD5A5DDBB2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Http", "Http", "{F4995C96-8D4E-4B26-8FB8-614B020156C2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.HttpClient", "Blazor\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj", "{FAFE3FF2-D36D-47DA-833D-C382A902705E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.HttpClient", "WebAssembly\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj", "{FAFE3FF2-D36D-47DA-833D-C382A902705E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.HttpClient.Tests", "Blazor\Http\test\Microsoft.AspNetCore.Blazor.HttpClient.Tests.csproj", "{2C10DF3B-D138-414A-BB36-02E45A7B6025}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.HttpClient.Tests", "WebAssembly\Http\test\Microsoft.AspNetCore.Blazor.HttpClient.Tests.csproj", "{2C10DF3B-D138-414A-BB36-02E45A7B6025}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{37FA056D-A7B3-4F72-A8B9-8D3C175E831E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{FBD7C733-200E-4BED-8B31-2610C2263F72}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.Interop", "WebAssembly\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{FBD7C733-200E-4BED-8B31-2610C2263F72}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{7920B09F-8016-49CF-A229-E72D0CECDD17}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Server", "Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj", "{BDBEDE12-74C1-466E-B8AE-49EC40F83866}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Server", "WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj", "{BDBEDE12-74C1-466E-B8AE-49EC40F83866}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{CBD2BB24-3EC3-4950-ABE4-8C521D258DCD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "Blazor\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "WebAssembly\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{8276993E-3F54-4D2F-8DDA-E86F2C6BEF1E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Server", "Blazor\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{CFA20A59-F52B-47A2-BD5D-B600D9576BDA}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Server", "WebAssembly\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{CFA20A59-F52B-47A2-BD5D-B600D9576BDA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanity", "Blazor\testassets\MonoSanity\MonoSanity.csproj", "{C97721BB-8D89-4167-9E59-839C237BA270}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanity", "WebAssembly\testassets\MonoSanity\MonoSanity.csproj", "{C97721BB-8D89-4167-9E59-839C237BA270}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanityClient", "Blazor\testassets\MonoSanityClient\MonoSanityClient.csproj", "{7F357E7B-BF33-4055-9A21-37B3507BFF90}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanityClient", "WebAssembly\testassets\MonoSanityClient\MonoSanityClient.csproj", "{7F357E7B-BF33-4055-9A21-37B3507BFF90}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneApp", "Blazor\testassets\StandaloneApp\StandaloneApp.csproj", "{236FC110-FBE0-476D-ADC5-D98E23BAA1EE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneApp", "WebAssembly\testassets\StandaloneApp\StandaloneApp.csproj", "{236FC110-FBE0-476D-ADC5-D98E23BAA1EE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Validation", "Validation", "{09758C93-6707-46E3-9211-470449280C2C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation", "Blazor\Validation\src\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj", "{52F0CF32-9506-4D9C-B715-52900B219BDF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.DataAnnotations.Validation", "WebAssembly\Validation\src\Microsoft.AspNetCore.Components.DataAnnotations.Validation.csproj", "{52F0CF32-9506-4D9C-B715-52900B219BDF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests", "Blazor\Validation\test\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", "{C1CC2480-7925-4391-86F5-60653D864E87}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.DataAnnotations.Validation.Tests", "WebAssembly\Validation\test\Microsoft.AspNetCore.Components.DataAnnotations.Validation.Tests.csproj", "{C1CC2480-7925-4391-86F5-60653D864E87}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{194596E0-E6F5-4728-8A7A-A82EA0893111}"
EndProject

View File

@ -1,3 +0,0 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Build.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View File

@ -1,534 +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 Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class BindRazorIntegrationTest : RazorIntegrationTestBase
{
public BindRazorIntegrationTest(ITestOutputHelper output)
: base(output)
{
}
internal override bool UseTwoPhaseCompilation => true;
[Fact]
public void Render_BindToComponent_SpecifiesValue_WithMatchingProperties()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public int Value { get; set; }
[Parameter]
public Action<int> ValueChanged { get; set; }
}
}"));
var component = CompileToComponent(@"
<MyComponent @bind-Value=""ParentValue"" />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0),
frame => AssertFrame.Attribute(frame, "Value", 42, 1),
frame => AssertFrame.Attribute(frame, "ValueChanged", typeof(Action<int>), 2));
}
[Fact]
public void Render_BindToComponent_SpecifiesValue_WithoutMatchingProperties()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase, IComponent
{
Task IComponent.SetParametersAsync(ParameterView parameters)
{
return Task.CompletedTask;
}
}
}"));
var component = CompileToComponent(@"
<MyComponent @bind-Value=""ParentValue"" />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0),
frame => AssertFrame.Attribute(frame, "Value", 42, 1),
frame => AssertFrame.Attribute(frame, "ValueChanged", typeof(EventCallback<int>), 2));
}
[Fact]
public void Render_BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public int Value { get; set; }
[Parameter]
public Action<int> OnChanged { get; set; }
}
}"));
var component = CompileToComponent(@"
<MyComponent @bind-Value=""ParentValue"" @bind-Value:event=""OnChanged"" />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0),
frame => AssertFrame.Attribute(frame, "Value", 42, 1),
frame => AssertFrame.Attribute(frame, "OnChanged", typeof(Action<int>), 2));
}
[Fact]
public void Render_BindToComponent_SpecifiesValueAndChangeEvent_WithoutMatchingProperties()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase, IComponent
{
Task IComponent.SetParametersAsync(ParameterView parameters)
{
return Task.CompletedTask;
}
}
}"));
var component = CompileToComponent(@"
<MyComponent @bind-Value=""ParentValue"" @bind-Value:event=""OnChanged"" />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0),
frame => AssertFrame.Attribute(frame, "Value", 42, 1),
frame => AssertFrame.Attribute(frame, "OnChanged", typeof(EventCallback<int>), 2));
}
[Fact]
public void Render_BindToElement_WritesAttributes()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using Microsoft.AspNetCore.Components;
namespace Test
{
[BindElement(""div"", null, ""myvalue"", ""myevent"")]
public static class BindAttributes
{
}
}"));
var component = CompileToComponent(@"
<div @bind=""@ParentValue"" />
@code {
public string ParentValue { get; set; } = ""hi"";
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "div", 3, 0),
frame => AssertFrame.Attribute(frame, "myvalue", "hi", 1),
frame => AssertFrame.Attribute(frame, "myevent", typeof(EventCallback), 2));
}
[Fact]
public void Render_BindToElementWithSuffix_WritesAttributes()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using Microsoft.AspNetCore.Components;
namespace Test
{
[BindElement(""div"", ""value"", ""myvalue"", ""myevent"")]
public static class BindAttributes
{
}
}"));
var component = CompileToComponent(@"
<div @bind-value=""@ParentValue"" />
@code {
public string ParentValue { get; set; } = ""hi"";
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "div", 3, 0),
frame => AssertFrame.Attribute(frame, "myvalue", "hi", 1),
frame => AssertFrame.Attribute(frame, "myevent", typeof(EventCallback), 2));
}
[Fact]
public void Render_BindDuplicates_ReportsDiagnostic()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using Microsoft.AspNetCore.Components;
namespace Test
{
[BindElement(""div"", ""value"", ""myvalue2"", ""myevent2"")]
[BindElement(""div"", ""value"", ""myvalue"", ""myevent"")]
public static class BindAttributes
{
}
}"));
// Act
var result = CompileToCSharp(@"
<div @bind-value=""@ParentValue"" />
@code {
public string ParentValue { get; set; } = ""hi"";
}");
// Assert
var diagnostic = Assert.Single(result.Diagnostics);
Assert.Equal("RZ9989", diagnostic.Id);
Assert.Equal(
"The attribute '@bind-value' was matched by multiple bind attributes. Duplicates:" + Environment.NewLine +
"Test.BindAttributes" + Environment.NewLine +
"Test.BindAttributes",
diagnostic.GetMessage());
}
[Fact]
public void Render_BuiltIn_BindToInputWithoutType_WritesAttributes()
{
// Arrange
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<input @bind=""@ParentValue"" />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "value", "42", 1),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 2));
}
[Fact]
public void Render_BuiltIn_BindToInputText_WithFormat_WritesAttributes()
{
// Arrange
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<input type=""text"" @bind=""@CurrentDate"" @bind:format=""MM/dd/yyyy""/>
@code {
public DateTime CurrentDate { get; set; } = new DateTime(2018, 1, 1);
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd/yyyy"), 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
}
[Fact]
public void Render_BuiltIn_BindToInputText_WithFormatFromProperty_WritesAttributes()
{
// Arrange
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<input type=""text"" @bind=""@CurrentDate"" @bind:format=""@Format""/>
@code {
public DateTime CurrentDate { get; set; } = new DateTime(2018, 1, 1);
public string Format { get; set; } = ""MM/dd/yyyy"";
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd/yyyy"), 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
}
[Fact]
public void Render_BuiltIn_BindToInputText_WritesAttributes()
{
// Arrange
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<input type=""text"" @bind=""@ParentValue"" />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", "42", 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
}
[Fact]
public void Render_BuiltIn_BindToInputCheckbox_WritesAttributes()
{
// Arrange
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<input type=""checkbox"" @bind=""@Enabled"" />
@code {
public bool Enabled { get; set; }
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "type", "checkbox", 1),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
}
[Fact]
public void Render_BindToElementFallback_WritesAttributes()
{
// Arrange
var component = CompileToComponent(@"
<input type=""text"" @bind-value=""@ParentValue"" @bind-value:event=""onchange"" />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", "42", 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
}
[Fact]
public void Render_BindToElementFallback_WithFormat_WritesAttributes()
{
// Arrange
var component = CompileToComponent(@"
<input type=""text"" @bind-value=""@CurrentDate"" @bind-value:event=""onchange"" @bind-value:format=""MM/dd"" />
@code {
public DateTime CurrentDate { get; set; } = new DateTime(2018, 1, 1);
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd"), 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
}
[Fact] // Additional coverage of OrphanTagHelperLoweringPass
public void Render_BindToElementFallback_SpecifiesValueAndChangeEvent_WithCSharpAttribute()
{
// Arrange
var component = CompileToComponent(@"
<input type=""@(""text"")"" @bind-value=""@ParentValue"" @bind-value:event=""onchange"" visible />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 5, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "visible", 2),
frame => AssertFrame.Attribute(frame, "value", "42", 3),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 4));
}
[Fact] // See https://github.com/aspnet/Blazor/issues/703
public void Workaround_703()
{
// Arrange
var component = CompileToComponent(@"
<input @bind-value=""@ParentValue"" @bind-value:event=""onchange"" type=""text"" visible />
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
//
// The workaround for 703 is that the value attribute MUST be after the type
// attribute.
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "input", 5, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "visible", 2),
frame => AssertFrame.Attribute(frame, "value", "42", 3),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 4));
}
[Fact] // Additional coverage of OrphanTagHelperLoweringPass
public void Render_BindToElementFallback_SpecifiesValueAndChangeEvent_BodyContent()
{
// Arrange
var component = CompileToComponent(@"
<div @bind-value=""@ParentValue"" @bind-value:event=""onchange"">
<span>@(42.ToString())</span>
</div>
@code {
public int ParentValue { get; set; } = 42;
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "div", 7, 0),
frame => AssertFrame.Attribute(frame, "value", "42", 1),
frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 2),
frame => AssertFrame.MarkupWhitespace(frame, 3),
frame => AssertFrame.Element(frame, "span", 2, 4),
frame => AssertFrame.Text(frame, "42", 5),
frame => AssertFrame.MarkupWhitespace(frame, 6));
}
[Fact]
public void Render_BindFallback_InvalidSyntax_TooManyParts()
{
// Arrange & Act
var generated = CompileToCSharp(@"
<input type=""text"" @bind-first-second-third=""Text"" />
@code {
public string Text { get; set; } = ""text"";
}");
// Assert
var diagnostic = Assert.Single(generated.Diagnostics);
Assert.Equal("RZ9991", diagnostic.Id);
}
[Fact]
public void Render_BindFallback_InvalidSyntax_TrailingDash()
{
// Arrange & Act
var generated = CompileToCSharp(@"
<input type=""text"" @bind-first-=""Text"" />
@code {
public string Text { get; set; } = ""text"";
}");
// Assert
var diagnostic = Assert.Single(generated.Diagnostics);
Assert.Equal("RZ9991", diagnostic.Id);
}
}
}

View File

@ -1,407 +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 Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class ChildContentRazorIntegrationTest : RazorIntegrationTestBase
{
private readonly CSharpSyntaxTree RenderChildContentComponent = Parse(@"
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace Test
{
public class RenderChildContent : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddContent(0, ChildContent);
}
[Parameter]
public RenderFragment ChildContent { get; set; }
}
}
");
private readonly CSharpSyntaxTree RenderChildContentStringComponent = Parse(@"
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace Test
{
public class RenderChildContentString : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddContent(0, ChildContent, Value);
}
[Parameter]
public RenderFragment<string> ChildContent { get; set; }
[Parameter]
public string Value { get; set; }
}
}
");
private readonly CSharpSyntaxTree RenderMultipleChildContent = Parse(@"
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace Test
{
public class RenderMultipleChildContent : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddContent(0, Header, Name);
builder.AddContent(1, ChildContent, Value);
builder.AddContent(2, Footer);
}
[Parameter]
public string Name { get; set; }
[Parameter]
public RenderFragment<string> Header { get; set; }
[Parameter]
public RenderFragment<string> ChildContent { get; set; }
[Parameter]
public RenderFragment Footer { get; set; }
[Parameter]
public string Value { get; set; }
}
}
");
public ChildContentRazorIntegrationTest(ITestOutputHelper output)
: base(output)
{
}
internal override bool UseTwoPhaseCompilation => true;
[Fact]
public void Render_BodyChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
var component = CompileToComponent(@"
<RenderChildContent>
<div></div>
</RenderChildContent>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 0),
frame => AssertFrame.Attribute(frame, "ChildContent", 1),
frame => AssertFrame.Markup(frame, "\n <div></div>\n", 2));
}
[Fact]
public void Render_BodyChildContent_Generic()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentStringComponent);
var component = CompileToComponent(@"
<RenderChildContentString Value=""HI"">
<div>@context.ToLowerInvariant()</div>
</RenderChildContentString>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContentString", 3, 0),
frame => AssertFrame.Attribute(frame, "Value", "HI", 1),
frame => AssertFrame.Attribute(frame, "ChildContent", 2),
frame => AssertFrame.MarkupWhitespace(frame, 3),
frame => AssertFrame.Element(frame, "div", 2, 4),
frame => AssertFrame.Text(frame, "hi", 5),
frame => AssertFrame.MarkupWhitespace(frame, 6));
}
[Fact]
public void Render_ExplicitChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
var component = CompileToComponent(@"
<RenderChildContent>
<ChildContent>
<div></div>
</ChildContent>
</RenderChildContent>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 0),
frame => AssertFrame.Attribute(frame, "ChildContent", 1),
frame => AssertFrame.Markup(frame, "\n <div></div>\n ", 2));
}
[Fact]
public void Render_BodyChildContent_Recursive()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
var component = CompileToComponent(@"
<RenderChildContent>
<RenderChildContent>
<div></div>
</RenderChildContent>
</RenderChildContent>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 0),
frame => AssertFrame.Attribute(frame, "ChildContent", 1),
frame => AssertFrame.MarkupWhitespace(frame, 2),
frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 3),
frame => AssertFrame.Attribute(frame, "ChildContent", 4),
frame => AssertFrame.MarkupWhitespace(frame, 6),
frame => AssertFrame.Markup(frame, "\n <div></div>\n ", 5));
}
[Fact]
public void Render_AttributeChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
var component = CompileToComponent(@"
@{ RenderFragment<string> template = (context) => @<div>@context.ToLowerInvariant()</div>; }
<RenderChildContent ChildContent=""@template(""HI"")"" />");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 2),
frame => AssertFrame.Attribute(frame, "ChildContent", 3),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hi", 1));
}
[Fact]
public void Render_AttributeChildContent_RenderFragmentOfString()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentStringComponent);
var component = CompileToComponent(@"
@{ RenderFragment<string> template = (context) => @<div>@context.ToLowerInvariant()</div>; }
<RenderChildContentString ChildContent=""@template"" Value=""HI"" />");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContentString", 3, 2),
frame => AssertFrame.Attribute(frame, "ChildContent", 3),
frame => AssertFrame.Attribute(frame, "Value", "HI", 4),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hi", 1));
}
[Fact]
public void Render_AttributeChildContent_NoArgTemplate()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
var component = CompileToComponent(@"
@{ RenderFragment template = @<div>@(""HI"".ToLowerInvariant())</div>; }
<RenderChildContent ChildContent=""@template"" />");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 2),
frame => AssertFrame.Attribute(frame, "ChildContent", 3),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hi", 1));
}
[Fact]
public void Render_AttributeChildContent_IgnoresEmptyBody()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
var component = CompileToComponent(@"
@{ RenderFragment<string> template = (context) => @<div>@context.ToLowerInvariant()</div>; }
<RenderChildContent ChildContent=""@template(""HI"")""></RenderChildContent>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 2),
frame => AssertFrame.Attribute(frame, "ChildContent", 3),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hi", 1));
}
[Fact]
public void Render_AttributeChildContent_IgnoresWhitespaceBody()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderChildContentComponent);
var component = CompileToComponent(@"
@{ RenderFragment<string> template = (context) => @<div>@context.ToLowerInvariant()</div>; }
<RenderChildContent ChildContent=""@template(""HI"")"">
</RenderChildContent>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderChildContent", 2, 2),
frame => AssertFrame.Attribute(frame, "ChildContent", 3),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hi", 1));
}
[Fact]
public void Render_MultipleChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderMultipleChildContent);
var component = CompileToComponent(@"
@{ RenderFragment<string> header = context => @<div>@context.ToLowerInvariant()</div>; }
<RenderMultipleChildContent Name=""billg"" Header=@header Value=""HI"">
<ChildContent>Some @context.ToLowerInvariant() Content</ChildContent>
<Footer>Bye!</Footer>
</RenderMultipleChildContent>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderMultipleChildContent", 6, 2),
frame => AssertFrame.Attribute(frame, "Name", "billg", 3),
frame => AssertFrame.Attribute(frame, "Header", typeof(RenderFragment<string>), 4),
frame => AssertFrame.Attribute(frame, "Value", "HI", 5),
frame => AssertFrame.Attribute(frame, "ChildContent", typeof(RenderFragment<string>), 6),
frame => AssertFrame.Attribute(frame, "Footer", typeof(RenderFragment), 10),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "billg", 1),
frame => AssertFrame.Text(frame, "Some ", 7),
frame => AssertFrame.Text(frame, "hi", 8),
frame => AssertFrame.Text(frame, " Content", 9),
frame => AssertFrame.Text(frame, "Bye!", 11));
}
[Fact]
public void Render_MultipleChildContent_ContextParameterOnComponent()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderMultipleChildContent);
var component = CompileToComponent(@"
<RenderMultipleChildContent Name=""billg"" Value=""HI"" Context=""item"">
<Header><div>@item.ToLowerInvariant()</div></Header>
<ChildContent Context=""Context"">Some @Context.ToLowerInvariant() Content</ChildContent>
<Footer>Bye!</Footer>
</RenderMultipleChildContent>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderMultipleChildContent", 6, 0),
frame => AssertFrame.Attribute(frame, "Name", "billg", 1),
frame => AssertFrame.Attribute(frame, "Value", "HI", 2),
frame => AssertFrame.Attribute(frame, "Header", typeof(RenderFragment<string>), 3),
frame => AssertFrame.Attribute(frame, "ChildContent", typeof(RenderFragment<string>), 6),
frame => AssertFrame.Attribute(frame, "Footer", typeof(RenderFragment), 10),
frame => AssertFrame.Element(frame, "div", 2, 4),
frame => AssertFrame.Text(frame, "billg", 5),
frame => AssertFrame.Text(frame, "Some ", 7),
frame => AssertFrame.Text(frame, "hi", 8),
frame => AssertFrame.Text(frame, " Content", 9),
frame => AssertFrame.Text(frame, "Bye!", 11));
}
// Verifies that our check for reuse of parameter names isn't too aggressive.
[Fact]
public void Render_MultipleChildContent_ContextParameterOnComponent_SetsSameName()
{
// Arrange
AdditionalSyntaxTrees.Add(RenderMultipleChildContent);
var component = CompileToComponent(@"
<RenderMultipleChildContent Name=""billg"" Value=""HI"" Context=""item"">
<Header><div>@item.ToLowerInvariant()</div></Header>
<ChildContent Context=""item"">Some @item.ToLowerInvariant() Content</ChildContent>
<Footer>Bye!</Footer>
</RenderMultipleChildContent>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.RenderMultipleChildContent", 6, 0),
frame => AssertFrame.Attribute(frame, "Name", "billg", 1),
frame => AssertFrame.Attribute(frame, "Value", "HI", 2),
frame => AssertFrame.Attribute(frame, "Header", typeof(RenderFragment<string>), 3),
frame => AssertFrame.Attribute(frame, "ChildContent", typeof(RenderFragment<string>), 6),
frame => AssertFrame.Attribute(frame, "Footer", typeof(RenderFragment), 10),
frame => AssertFrame.Element(frame, "div", 2, 4),
frame => AssertFrame.Text(frame, "billg", 5),
frame => AssertFrame.Text(frame, "Some ", 7),
frame => AssertFrame.Text(frame, "hi", 8),
frame => AssertFrame.Text(frame, " Content", 9),
frame => AssertFrame.Text(frame, "Bye!", 11));
}
}
}

View File

@ -1,616 +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 Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.AspNetCore.Components.Web;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class ComponentRenderingRazorIntegrationTest : RazorIntegrationTestBase
{
public ComponentRenderingRazorIntegrationTest(ITestOutputHelper output)
: base(output)
{
}
internal override bool UseTwoPhaseCompilation => true;
[Fact]
public void Render_ChildComponent_Simple()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
}
}
"));
var component = CompileToComponent(@"
<MyComponent/>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 1, 0));
}
[Fact]
public void Render_ChildComponent_WithParameters()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class SomeType
{
}
public class MyComponent : ComponentBase
{
[Parameter] public int IntProperty { get; set; }
[Parameter] public bool BoolProperty { get; set; }
[Parameter] public string StringProperty { get; set; }
[Parameter] public SomeType ObjectProperty { get; set; }
}
}
"));
var component = CompileToComponent(@"
<MyComponent
IntProperty=""123""
BoolProperty=""true""
StringProperty=""My string""
ObjectProperty=""new SomeType()"" />");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 5, 0),
frame => AssertFrame.Attribute(frame, "IntProperty", 123, 1),
frame => AssertFrame.Attribute(frame, "BoolProperty", true, 2),
frame => AssertFrame.Attribute(frame, "StringProperty", "My string", 3),
frame =>
{
AssertFrame.Attribute(frame, "ObjectProperty", 4);
Assert.Equal("Test.SomeType", frame.AttributeValue.GetType().FullName);
});
}
[Fact]
public void Render_ChildComponent_TriesToSetNonParamter()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
public int IntProperty { get; set; }
}
}
"));
var component = CompileToComponent(@"
<MyComponent IntProperty=""123"" />");
// Act
var ex = Assert.Throws<InvalidOperationException>(() => GetRenderTree(component));
// Assert
Assert.Equal(
"Object of type 'Test.MyComponent' has a property matching the name 'IntProperty', " +
"but it does not have [ParameterAttribute] or [CascadingParameterAttribute] applied.",
ex.Message);
}
[Fact]
public void Render_ChildComponent_WithExplicitStringParameter()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public string StringProperty { get; set; }
}
}
"));
var component = CompileToComponent(@"
<MyComponent StringProperty=""@(42.ToString())"" />");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 0),
frame => AssertFrame.Attribute(frame, "StringProperty", "42", 1));
}
[Fact]
public void Render_ChildComponent_WithNonPropertyAttributes()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase, IComponent
{
Task IComponent.SetParametersAsync(ParameterView parameters)
{
return Task.CompletedTask;
}
}
}
"));
var component = CompileToComponent(@"
<MyComponent some-attribute=""foo"" another-attribute=""@(42.ToString())"" />");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0),
frame => AssertFrame.Attribute(frame, "some-attribute", "foo", 1),
frame => AssertFrame.Attribute(frame, "another-attribute", "42", 2));
}
[Theory]
[InlineData("e => Increment(e)")]
[InlineData("(e) => Increment(e)")]
[InlineData("@(e => Increment(e))")]
[InlineData("@(e => { Increment(e); })")]
[InlineData("Increment")]
[InlineData("@Increment")]
[InlineData("@(Increment)")]
public void Render_ChildComponent_WithEventHandler(string expression)
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public Action<MouseEventArgs> OnClick { get; set; }
}
}
"));
var component = CompileToComponent($@"
@using Microsoft.AspNetCore.Components.Web
<MyComponent OnClick=""{expression}""/>
@code {{
private int counter;
private void Increment(MouseEventArgs e) {{
counter++;
}}
}}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 0),
frame =>
{
AssertFrame.Attribute(frame, "OnClick", 1);
// The handler will have been assigned to a lambda
var handler = Assert.IsType<Action<MouseEventArgs>>(frame.AttributeValue);
Assert.Equal("Test.TestComponent", handler.Target.GetType().FullName);
});
}
[Fact]
public void Render_ChildComponent_WithExplicitEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using System;
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public Action<EventArgs> OnClick { get; set; }
}
}
"));
var component = CompileToComponent(@"
<MyComponent OnClick=""@Increment""/>
@code {
private int counter;
private void Increment(EventArgs e) {
counter++;
}
}");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 0),
frame =>
{
AssertFrame.Attribute(frame, "OnClick", 1);
// The handler will have been assigned to a lambda
var handler = Assert.IsType<Action<EventArgs>>(frame.AttributeValue);
Assert.Equal("Test.TestComponent", handler.Target.GetType().FullName);
Assert.Equal("Increment", handler.Method.Name);
});
}
[Fact]
public void Render_ChildComponent_WithMinimizedBoolAttribute()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public bool BoolProperty { get; set; }
}
}"));
var component = CompileToComponent(@"
<MyComponent BoolProperty />");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 0),
frame => AssertFrame.Attribute(frame, "BoolProperty", true, 1));
}
[Fact]
public void Render_ChildComponent_WithChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public string MyAttr { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
}
}
"));
var component = CompileToComponent(@"
<MyComponent MyAttr=""abc"">Some text<some-child a='1'>Nested text @(""Hello"")</some-child></MyComponent>");
// Act
var frames = GetRenderTree(component);
// Assert: component frames are correct
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0),
frame => AssertFrame.Attribute(frame, "MyAttr", "abc", 1),
frame => AssertFrame.Attribute(frame, "ChildContent", 2));
// Assert: Captured ChildContent frames are correct
var childFrames = GetFrames((RenderFragment)frames[2].AttributeValue);
Assert.Collection(
childFrames.AsEnumerable(),
frame => AssertFrame.Text(frame, "Some text", 3),
frame => AssertFrame.Element(frame, "some-child", 4, 4),
frame => AssertFrame.Attribute(frame, "a", "1", 5),
frame => AssertFrame.Text(frame, "Nested text ", 6),
frame => AssertFrame.Text(frame, "Hello", 7));
}
[Fact]
public void Render_ChildComponent_Nested()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
}
}
"));
var component = CompileToComponent(@"
<MyComponent><MyComponent>Some text</MyComponent></MyComponent>");
// Act
var frames = GetRenderTree(component);
// Assert: outer component frames are correct
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 0),
frame => AssertFrame.Attribute(frame, "ChildContent", 1));
// Assert: first level of ChildContent is correct
// Note that we don't really need the sequence numbers to continue on from the
// sequence numbers at the parent level. All that really matters is that they are
// correct relative to each other (i.e., incrementing) within the nesting level.
// As an implementation detail, it happens that they do follow on from the parent
// level, but we could change that part of the implementation if we wanted.
var innerFrames = GetFrames((RenderFragment)frames[1].AttributeValue).AsEnumerable().ToArray();
Assert.Collection(
innerFrames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 2),
frame => AssertFrame.Attribute(frame, "ChildContent", 3));
// Assert: second level of ChildContent is correct
Assert.Collection(
GetFrames((RenderFragment)innerFrames[1].AttributeValue).AsEnumerable(),
frame => AssertFrame.Text(frame, "Some text", 4));
}
[Fact] // https://github.com/aspnet/Blazor/issues/773
public void Regression_773()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class SurveyPrompt : ComponentBase
{
[Parameter] public string Title { get; set; }
}
}
"));
var component = CompileToComponent(@"
@page ""/""
<SurveyPrompt Title=""<div>Test!</div>"" />
");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.SurveyPrompt", 2, 0),
frame => AssertFrame.Attribute(frame, "Title", "<div>Test!</div>", 1));
}
[Fact]
public void Regression_784()
{
// Arrange
// Act
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<p @onmouseover=""OnComponentHover"" style=""background: @ParentBgColor;"" />
@code {
public string ParentBgColor { get; set; } = ""#FFFFFF"";
public void OnComponentHover(MouseEventArgs e)
{
}
}
");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "p", 3, 0),
frame => AssertFrame.Attribute(frame, "onmouseover", 1),
frame => AssertFrame.Attribute(frame, "style", "background: #FFFFFF;", 2));
}
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/6185")]
public void Render_Component_HtmlEncoded()
{
// Arrange
var component = CompileToComponent(@"&lt;span&gt;Hi&lt;/span&gt;");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Text(frame, "<span>Hi</span>"));
}
[Fact]
public void Render_Component_HtmlBlockEncoded()
{
// Arrange
var component = CompileToComponent(@"<div>&lt;span&gt;Hi&lt/span&gt;</div>");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Markup(frame, "<div>&lt;span&gt;Hi&lt/span&gt;</div>"));
}
// Integration test for HTML block rewriting
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/6183")]
public void Render_HtmlBlock_Integration()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
public class MyComponent : ComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
}
}
"));
var component = CompileToComponent(@"
<html>
<head><meta><meta></head>
<body>
<MyComponent>
<div><span></span><span></span></div>
<div>@(""hi"")</div>
<div><span></span><span></span></div>
<div></div>
<div>@(""hi"")</div>
<div></div>
</MyComponent>
</body>
</html>");
// Act
var frames = GetRenderTree(component);
// Assert: component frames are correct
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "html", 9, 0),
frame => AssertFrame.MarkupWhitespace(frame, 1),
frame => AssertFrame.Markup(frame, "<head><meta><meta></head>\n ", 2),
frame => AssertFrame.Element(frame, "body", 5, 3),
frame => AssertFrame.MarkupWhitespace(frame, 4),
frame => AssertFrame.Component(frame, "Test.MyComponent", 2, 5),
frame => AssertFrame.Attribute(frame, "ChildContent", 6),
frame => AssertFrame.MarkupWhitespace(frame, 16),
frame => AssertFrame.MarkupWhitespace(frame, 17));
// Assert: Captured ChildContent frames are correct
var childFrames = GetFrames((RenderFragment)frames[6].AttributeValue);
Assert.Collection(
childFrames.AsEnumerable(),
frame => AssertFrame.MarkupWhitespace(frame, 7),
frame => AssertFrame.Markup(frame, "<div><span></span><span></span></div>\n ", 8),
frame => AssertFrame.Element(frame, "div", 2, 9),
frame => AssertFrame.Text(frame, "hi", 10),
frame => AssertFrame.MarkupWhitespace(frame, 11),
frame => AssertFrame.Markup(frame, "<div><span></span><span></span></div>\n <div></div>\n ", 12),
frame => AssertFrame.Element(frame, "div", 2, 13),
frame => AssertFrame.Text(frame, "hi", 14),
frame => AssertFrame.Markup(frame, "\n <div></div>\n ", 15));
}
[Fact]
public void RazorTemplate_CanBeUsedFromComponent()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace Test
{
public class Repeater : ComponentBase
{
[Parameter] public int Count { get; set; }
[Parameter] public RenderFragment<string> Template { get; set; }
[Parameter] public string Value { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
for (var i = 0; i < Count; i++)
{
builder.AddContent(i, Template, Value);
}
}
}
}
"));
var component = CompileToComponent(@"
@{ RenderFragment<string> template = (context) => @<div>@context.ToLower()</div>; }
<Repeater Count=3 Value=""Hello, World!"" Template=""template"" />
");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.Repeater", 4, 2),
frame => AssertFrame.Attribute(frame, "Count", typeof(int), 3),
frame => AssertFrame.Attribute(frame, "Value", typeof(string), 4),
frame => AssertFrame.Attribute(frame, "Template", typeof(RenderFragment<string>), 5),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1));
}
}
}

View File

@ -1,173 +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 System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
// Integration tests for Blazor's directives
public class DirectiveRazorIntegrationTest : RazorIntegrationTestBase
{
public DirectiveRazorIntegrationTest(ITestOutputHelper output)
: base(output)
{
}
[Fact]
public void ComponentsDoNotHaveLayoutAttributeByDefault()
{
// Arrange/Act
var component = CompileToComponent($"Hello");
// Assert
Assert.Null(component.GetType().GetCustomAttribute<LayoutAttribute>());
}
[Fact]
public void SupportsLayoutDeclarations()
{
// Arrange/Act
var testComponentTypeName = FullTypeName<TestLayout>();
var component = CompileToComponent(
$"@layout {testComponentTypeName}\n" +
$"Hello");
var frames = GetRenderTree(component);
// Assert
var layoutAttribute = component.GetType().GetCustomAttribute<LayoutAttribute>();
Assert.NotNull(layoutAttribute);
Assert.Equal(typeof(TestLayout), layoutAttribute.LayoutType);
Assert.Collection(frames,
frame => AssertFrame.Text(frame, "Hello"));
}
[Fact]
public void SupportsImplementsDeclarations()
{
// Arrange/Act
var testInterfaceTypeName = FullTypeName<ITestInterface>();
var component = CompileToComponent(
$"@implements {testInterfaceTypeName}\n" +
$"Hello");
var frames = GetRenderTree(component);
// Assert
Assert.IsAssignableFrom<ITestInterface>(component);
Assert.Collection(frames,
frame => AssertFrame.Text(frame, "Hello"));
}
[Fact]
public void SupportsMultipleImplementsDeclarations()
{
// Arrange/Act
var testInterfaceTypeName = FullTypeName<ITestInterface>();
var testInterfaceTypeName2 = FullTypeName<ITestInterface2>();
var component = CompileToComponent(
$"@implements {testInterfaceTypeName}\n" +
$"@implements {testInterfaceTypeName2}\n" +
$"Hello");
var frames = GetRenderTree(component);
// Assert
Assert.IsAssignableFrom<ITestInterface>(component);
Assert.IsAssignableFrom<ITestInterface2>(component);
Assert.Collection(frames,
frame => AssertFrame.Text(frame, "Hello"));
}
[Fact]
public void SupportsInheritsDirective()
{
// Arrange/Act
var testBaseClassTypeName = FullTypeName<TestBaseClass>();
var component = CompileToComponent(
$"@inherits {testBaseClassTypeName}" + Environment.NewLine +
$"Hello");
var frames = GetRenderTree(component);
// Assert
Assert.IsAssignableFrom<TestBaseClass>(component);
Assert.Collection(frames,
frame => AssertFrame.Text(frame, "Hello"));
}
[Fact]
public void SupportsInjectDirective()
{
// Arrange/Act 1: Compilation
var componentType = CompileToComponent(
$"@inject {FullTypeName<IMyService1>()} MyService1\n" +
$"@inject {FullTypeName<IMyService2>()} MyService2\n" +
$"Hello from @MyService1 and @MyService2").GetType();
// Assert 1: Compiled type has correct properties
var propertyFlags = BindingFlags.Instance | BindingFlags.NonPublic;
var injectableProperties = componentType.GetProperties(propertyFlags)
.Where(p => p.GetCustomAttribute<InjectAttribute>() != null);
Assert.Collection(injectableProperties.OrderBy(p => p.Name),
property =>
{
Assert.Equal("MyService1", property.Name);
Assert.Equal(typeof(IMyService1), property.PropertyType);
Assert.False(property.GetMethod.IsPublic);
Assert.False(property.SetMethod.IsPublic);
},
property =>
{
Assert.Equal("MyService2", property.Name);
Assert.Equal(typeof(IMyService2), property.PropertyType);
Assert.False(property.GetMethod.IsPublic);
Assert.False(property.SetMethod.IsPublic);
});
// Arrange/Act 2: DI-supplied component has correct behavior
var serviceProvider = new TestServiceProvider();
serviceProvider.AddService<IMyService1>(new MyService1Impl());
serviceProvider.AddService<IMyService2>(new MyService2Impl());
var componentFactory = new ComponentFactory();
var component = componentFactory.InstantiateComponent(serviceProvider, componentType);
var frames = GetRenderTree(component);
// Assert 2: Rendered component behaves correctly
Assert.Collection(frames,
frame => AssertFrame.Text(frame, "Hello from "),
frame => AssertFrame.Text(frame, typeof(MyService1Impl).FullName),
frame => AssertFrame.Text(frame, " and "),
frame => AssertFrame.Text(frame, typeof(MyService2Impl).FullName));
}
public class TestLayout : IComponent
{
[Parameter]
public RenderFragment Body { get; set; }
public void Attach(RenderHandle renderHandle)
{
}
public Task SetParametersAsync(ParameterView parameters)
{
return Task.CompletedTask;
}
}
public interface ITestInterface { }
public interface ITestInterface2 { }
public class TestBaseClass : ComponentBase { }
public interface IMyService1 { }
public interface IMyService2 { }
public class MyService1Impl : IMyService1 { }
public class MyService2Impl : IMyService2 { }
}
}

View File

@ -1,314 +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.Linq;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class GenericComponentRazorIntegrationTest : RazorIntegrationTestBase
{
private readonly CSharpSyntaxTree GenericContextComponent = Parse(@"
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace Test
{
public class GenericContext<TItem> : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
var items = (IReadOnlyList<TItem>)Items ?? Array.Empty<TItem>();
for (var i = 0; i < items.Count; i++)
{
if (ChildContent == null)
{
builder.AddContent(i, Items[i]);
}
else
{
builder.AddContent(i, ChildContent, new Context() { Index = i, Item = items[i], });
}
}
}
[Parameter]
public List<TItem> Items { get; set; }
[Parameter]
public RenderFragment<Context> ChildContent { get; set; }
public class Context
{
public int Index { get; set; }
public TItem Item { get; set; }
}
}
}
");
private readonly CSharpSyntaxTree MultipleGenericParameterComponent = Parse(@"
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace Test
{
public class MultipleGenericParameter<TItem1, TItem2, TItem3> : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddContent(0, Item1);
builder.AddContent(1, Item2);
builder.AddContent(2, Item3);
}
[Parameter]
public TItem1 Item1 { get; set; }
[Parameter]
public TItem2 Item2 { get; set; }
[Parameter]
public TItem3 Item3 { get; set; }
}
}
");
public GenericComponentRazorIntegrationTest(ITestOutputHelper output)
: base(output)
{
}
internal override bool UseTwoPhaseCompilation => true;
[Fact]
public void Render_GenericComponent_WithoutChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(GenericContextComponent);
var component = CompileToComponent(@"
<GenericContext TItem=int Items=""@(new List<int>() { 1, 2, })"" />");
// Act
var frames = GetRenderTree(component);
// Assert
var genericComponentType = component.GetType().Assembly.DefinedTypes
.Where(t => t.Name == "GenericContext`1")
.Single()
.MakeGenericType(typeof(int));
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, genericComponentType.FullName, 2, 0),
frame => AssertFrame.Attribute(frame, "Items", typeof(List<int>), 1),
frame => AssertFrame.Text(frame, "1", 0),
frame => AssertFrame.Text(frame, "2", 1));
}
[Fact]
public void Render_GenericComponent_WithRef()
{
// Arrange
AdditionalSyntaxTrees.Add(GenericContextComponent);
var component = CompileToComponent(@"
<GenericContext TItem=int Items=""@(new List<int>() { 1, 2, })"" @ref=""_my"" />
@code {
GenericContext<int> _my;
void Foo() { GC.KeepAlive(_my); }
}");
// Act
var frames = GetRenderTree(component);
// Assert
var genericComponentType = component.GetType().Assembly.DefinedTypes
.Where(t => t.Name == "GenericContext`1")
.Single()
.MakeGenericType(typeof(int));
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, genericComponentType.FullName, 3, 0),
frame => AssertFrame.Attribute(frame, "Items", typeof(List<int>), 1),
frame => AssertFrame.ComponentReferenceCapture(frame, 2),
frame => AssertFrame.Text(frame, "1", 0),
frame => AssertFrame.Text(frame, "2", 1));
}
[Fact]
public void Render_GenericComponent_WithChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(GenericContextComponent);
var component = CompileToComponent(@"
<GenericContext TItem=int Items=""@(new List<int>() { 1, 2, })"">
<div>@(context.Item * context.Index)</div>
</GenericContext>");
// Act
var frames = GetRenderTree(component);
// Assert
var genericComponentType = component.GetType().Assembly.DefinedTypes
.Where(t => t.Name == "GenericContext`1")
.Single()
.MakeGenericType(typeof(int));
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, genericComponentType.FullName, 3, 0),
frame => AssertFrame.Attribute(frame, "Items", typeof(List<int>), 1),
frame => AssertFrame.Attribute(frame, "ChildContent", 2),
frame => AssertFrame.MarkupWhitespace(frame, 3),
frame => AssertFrame.Element(frame, "div", 2, 4),
frame => AssertFrame.Text(frame, "0", 5),
frame => AssertFrame.MarkupWhitespace(frame, 6),
frame => AssertFrame.MarkupWhitespace(frame, 3),
frame => AssertFrame.Element(frame, "div", 2, 4),
frame => AssertFrame.Text(frame, "2", 5),
frame => AssertFrame.MarkupWhitespace(frame, 6));
}
[Fact]
public void Render_GenericComponent_TypeInference_WithRef()
{
// Arrange
AdditionalSyntaxTrees.Add(GenericContextComponent);
var component = CompileToComponent(@"
<GenericContext Items=""@(new List<int>() { 1, 2, })"" @ref=""_my"" />
@code {
GenericContext<int> _my;
void Foo() { GC.KeepAlive(_my); }
}");
// Act
var frames = GetRenderTree(component);
// Assert
var genericComponentType = component.GetType().Assembly.DefinedTypes
.Where(t => t.Name == "GenericContext`1")
.Single()
.MakeGenericType(typeof(int));
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, genericComponentType.FullName, 3, 0),
frame => AssertFrame.Attribute(frame, "Items", typeof(List<int>), 1),
frame => AssertFrame.ComponentReferenceCapture(frame, 2),
frame => AssertFrame.Text(frame, "1", 0),
frame => AssertFrame.Text(frame, "2", 1));
}
[Fact]
public void Render_GenericComponent_TypeInference_WithRef_Recursive()
{
// Arrange
AdditionalSyntaxTrees.Add(GenericContextComponent);
var assembly = CompileToAssembly("Test.cshtml", @"
@typeparam TItem
<GenericContext Items=""@MyItems"" @ref=""_my"" />
@code {
[Parameter] public List<TItem> MyItems { get; set; }
GenericContext<TItem> _my;
void Foo() { GC.KeepAlive(_my); }
}");
var componentType = assembly.Assembly.DefinedTypes
.Where(t => t.Name == "Test`1")
.Single()
.MakeGenericType(typeof(int));
var component = (IComponent)Activator.CreateInstance(componentType);
// Act
var frames = GetRenderTree(component);
// Assert
var genericComponentType = assembly.Assembly.DefinedTypes
.Where(t => t.Name == "GenericContext`1")
.Single()
.MakeGenericType(typeof(int));
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, genericComponentType.FullName, 3, 0),
frame => AssertFrame.Attribute(frame, "Items", 1),
frame => AssertFrame.ComponentReferenceCapture(frame, 2));
}
[Fact]
public void Render_GenericComponent_TypeInference_WithoutChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(GenericContextComponent);
var component = CompileToComponent(@"
<GenericContext Items=""@(new List<int>() { 1, 2, })"" />");
// Act
var frames = GetRenderTree(component);
// Assert
var genericComponentType = component.GetType().Assembly.DefinedTypes
.Where(t => t.Name == "GenericContext`1")
.Single()
.MakeGenericType(typeof(int));
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, genericComponentType.FullName, 2, 0),
frame => AssertFrame.Attribute(frame, "Items", typeof(List<int>), 1),
frame => AssertFrame.Text(frame, "1", 0),
frame => AssertFrame.Text(frame, "2", 1));
}
[Fact]
public void Render_GenericComponent_MultipleParameters_WithChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(MultipleGenericParameterComponent);
var component = CompileToComponent(@"
<MultipleGenericParameter
TItem1=""int""
TItem2=""string""
TItem3=long
Item1=3
Item2=""@(""FOO"")""
Item3=39L/>");
// Act
var frames = GetRenderTree(component);
// Assert
var genericComponentType = component.GetType().Assembly.DefinedTypes
.Where(t => t.Name == "MultipleGenericParameter`3")
.Single()
.MakeGenericType(typeof(int), typeof(string), typeof(long));
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, genericComponentType.FullName, 4, 0),
frame => AssertFrame.Attribute(frame, "Item1", 3, 1),
frame => AssertFrame.Attribute(frame, "Item2", "FOO", 2),
frame => AssertFrame.Attribute(frame, "Item3", 39L, 3),
frame => AssertFrame.Text(frame, "3", 0),
frame => AssertFrame.Text(frame, "FOO", 1),
frame => AssertFrame.Text(frame, "39", 2));
}
}
}

View File

@ -1,40 +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;
namespace Microsoft.AspNetCore.Razor.Language
{
/// <summary>
/// A <see cref="RazorProjectItem"/> that does not exist.
/// </summary>
internal class NotFoundProjectItem : RazorProjectItem
{
/// <summary>
/// Initializes a new instance of <see cref="NotFoundProjectItem"/>.
/// </summary>
/// <param name="basePath">The base path.</param>
/// <param name="path">The path.</param>
public NotFoundProjectItem(string basePath, string path)
{
BasePath = basePath;
FilePath = path;
}
/// <inheritdoc />
public override string BasePath { get; }
/// <inheritdoc />
public override string FilePath { get; }
/// <inheritdoc />
public override bool Exists => false;
/// <inheritdoc />
public override string PhysicalPath => throw new NotSupportedException();
/// <inheritdoc />
public override Stream Read() => throw new NotSupportedException();
}
}

View File

@ -1,89 +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.Reflection;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language
{
public class TestFile
{
private TestFile(string resourceName, Assembly assembly)
{
Assembly = assembly;
ResourceName = Assembly.GetName().Name + "." + resourceName.Replace('/', '.').Replace('\\', '.');
}
public Assembly Assembly { get; }
public string ResourceName { get; }
public static TestFile Create(string resourceName, Type type)
{
return new TestFile(resourceName, type.GetTypeInfo().Assembly);
}
public static TestFile Create(string resourceName, Assembly assembly)
{
return new TestFile(resourceName, assembly);
}
public Stream OpenRead()
{
var stream = Assembly.GetManifestResourceStream(ResourceName);
if (stream == null)
{
Assert.True(false, string.Format("Manifest resource: {0} not found", ResourceName));
}
return stream;
}
public bool Exists()
{
var resourceNames = Assembly.GetManifestResourceNames();
foreach (var resourceName in resourceNames)
{
// Resource names are case-sensitive.
if (string.Equals(ResourceName, resourceName, StringComparison.Ordinal))
{
return true;
}
}
return false;
}
public string ReadAllText()
{
using (var reader = new StreamReader(OpenRead()))
{
// The .Replace() calls normalize line endings, in case you get \n instead of \r\n
// since all the unit tests rely on the assumption that the files will have \r\n endings.
return reader.ReadToEnd().Replace("\r", "").Replace("\n", "\r\n");
}
}
/// <summary>
/// Saves the file to the specified path.
/// </summary>
public void Save(string filePath)
{
var directory = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
using (var outStream = File.Create(filePath))
{
using (var inStream = OpenRead())
{
inStream.CopyTo(outStream);
}
}
}
}
}

View File

@ -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;
using System.IO;
namespace Microsoft.AspNetCore.Razor.Language
{
public static class TestProject
{
public static string GetProjectDirectory(Type type)
{
var solutionDir = GetSolutionRootDirectory("Components");
var assemblyName = type.Assembly.GetName().Name;
var projectDirectory = Path.Combine(solutionDir, "test", assemblyName);
if (!Directory.Exists(projectDirectory))
{
throw new InvalidOperationException(
$@"Could not locate project directory for type {type.FullName}.
Directory probe path: {projectDirectory}.");
}
return projectDirectory;
}
public static string GetSolutionRootDirectory(string solution)
{
var applicationBasePath = AppContext.BaseDirectory;
var directoryInfo = new DirectoryInfo(applicationBasePath);
do
{
var projectFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, $"{solution}.sln"));
if (projectFileInfo.Exists)
{
return projectFileInfo.DirectoryName;
}
directoryInfo = directoryInfo.Parent;
}
while (directoryInfo.Parent != null);
throw new Exception($"Solution file {solution}.sln could not be found in {applicationBasePath} or its parent directories.");
}
}
}

View File

@ -1,224 +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.Diagnostics;
using System.Linq;
namespace Microsoft.AspNetCore.Razor.Language
{
internal class VirtualRazorProjectFileSystem : RazorProjectFileSystem
{
private readonly DirectoryNode _root = new DirectoryNode("/");
public override IEnumerable<RazorProjectItem> EnumerateItems(string basePath)
{
basePath = NormalizeAndEnsureValidPath(basePath);
var directory = _root.GetDirectory(basePath);
return directory?.EnumerateItems() ?? Enumerable.Empty<RazorProjectItem>();
}
[Obsolete("Use GetItem(string path, string fileKind)] instead")]
public override RazorProjectItem GetItem(string path)
{
return GetItem(path, fileKind: null);
}
public override RazorProjectItem GetItem(string path, string fileKind)
{
// We ignore fileKind here because the _root is pre-filled with project items that already have fileKinds defined. This is
// a unique circumstance where the RazorProjectFileSystem is actually pre-filled with all of its project items on construction.
path = NormalizeAndEnsureValidPath(path);
return _root.GetItem(path) ?? new NotFoundProjectItem(string.Empty, path);
}
public void Add(RazorProjectItem projectItem)
{
if (projectItem == null)
{
throw new ArgumentNullException(nameof(projectItem));
}
var filePath = NormalizeAndEnsureValidPath(projectItem.FilePath);
_root.AddFile(new FileNode(filePath, projectItem));
}
// Internal for testing
[DebuggerDisplay("{Path}")]
internal class DirectoryNode
{
public DirectoryNode(string path)
{
Path = path;
}
public string Path { get; }
public List<DirectoryNode> Directories { get; } = new List<DirectoryNode>();
public List<FileNode> Files { get; } = new List<FileNode>();
public void AddFile(FileNode fileNode)
{
var filePath = fileNode.Path;
if (!filePath.StartsWith(Path, StringComparison.OrdinalIgnoreCase))
{
var message = "Error";
throw new InvalidOperationException(message);
}
// Look for the first / that appears in the path after the current directory path.
var directoryPath = GetDirectoryPath(filePath);
var directory = GetOrAddDirectory(this, directoryPath, createIfNotExists: true);
Debug.Assert(directory != null);
directory.Files.Add(fileNode);
}
public DirectoryNode GetDirectory(string path)
{
if (!path.StartsWith(Path, StringComparison.OrdinalIgnoreCase))
{
var message = "Error";
throw new InvalidOperationException(message);
}
return GetOrAddDirectory(this, path);
}
public IEnumerable<RazorProjectItem> EnumerateItems()
{
foreach (var file in Files)
{
yield return file.ProjectItem;
}
foreach (var directory in Directories)
{
foreach (var file in directory.EnumerateItems())
{
yield return file;
}
}
}
public RazorProjectItem GetItem(string path)
{
if (!path.StartsWith(Path, StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("Error");
}
var directoryPath = GetDirectoryPath(path);
var directory = GetOrAddDirectory(this, directoryPath);
if (directory == null)
{
return null;
}
foreach (var file in directory.Files)
{
var filePath = file.Path;
var directoryLength = directory.Path.Length;
// path, filePath -> /Views/Home/Index.cshtml
// directory.Path -> /Views/Home/
// We only need to match the file name portion since we've already matched the directory segment.
if (string.Compare(path, directoryLength, filePath, directoryLength, path.Length - directoryLength, StringComparison.OrdinalIgnoreCase) == 0)
{
return file.ProjectItem;
}
}
return null;
}
private static string GetDirectoryPath(string path)
{
// /dir1/dir2/file.cshtml -> /dir1/dir2/
var fileNameIndex = path.LastIndexOf('/');
if (fileNameIndex == -1)
{
return path;
}
return path.Substring(0, fileNameIndex + 1);
}
private static DirectoryNode GetOrAddDirectory(
DirectoryNode directory,
string path,
bool createIfNotExists = false)
{
Debug.Assert(!string.IsNullOrEmpty(path));
if (path[path.Length - 1] != '/')
{
path += '/';
}
int index;
while ((index = path.IndexOf('/', directory.Path.Length)) != -1 && index != path.Length)
{
var subDirectory = FindSubDirectory(directory, path);
if (subDirectory == null)
{
if (createIfNotExists)
{
var directoryPath = path.Substring(0, index + 1); // + 1 to include trailing slash
subDirectory = new DirectoryNode(directoryPath);
directory.Directories.Add(subDirectory);
}
else
{
return null;
}
}
directory = subDirectory;
}
return directory;
}
private static DirectoryNode FindSubDirectory(DirectoryNode parentDirectory, string path)
{
for (var i = 0; i < parentDirectory.Directories.Count; i++)
{
// ParentDirectory.Path -> /Views/Home/
// CurrentDirectory.Path -> /Views/Home/SubDir/
// Path -> /Views/Home/SubDir/MorePath/File.cshtml
// Each invocation of FindSubDirectory returns the immediate subdirectory along the path to the file.
var currentDirectory = parentDirectory.Directories[i];
var directoryPath = currentDirectory.Path;
var startIndex = parentDirectory.Path.Length;
var directoryNameLength = directoryPath.Length - startIndex;
if (string.Compare(path, startIndex, directoryPath, startIndex, directoryPath.Length - startIndex, StringComparison.OrdinalIgnoreCase) == 0)
{
return currentDirectory;
}
}
return null;
}
}
// Internal for testing
[DebuggerDisplay("{Path}")]
internal struct FileNode
{
public FileNode(string path, RazorProjectItem projectItem)
{
Path = path;
ProjectItem = projectItem;
}
public string Path { get; }
public RazorProjectItem ProjectItem { get; }
}
}
}

View File

@ -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.IO;
namespace Microsoft.AspNetCore.Razor.Language
{
internal class VirtualProjectItem : RazorProjectItem
{
private readonly 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; }
public override bool Exists => true;
public override Stream Read()
{
return new MemoryStream(_content);
}
}
}

View File

@ -1,542 +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.Reflection;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Blazor.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";
// Creating the initial compilation + reading references is on the order of 250ms without caching
// so making sure it doesn't happen for each test.
private static readonly CSharpCompilation BaseCompilation;
private static CSharpParseOptions CSharpParseOptions { get; }
static RazorIntegrationTestBase()
{
var referenceAssemblyRoots = new[]
{
typeof(System.Runtime.AssemblyTargetedPatchBandAttribute).Assembly, // System.Runtime
typeof(ComponentBase).Assembly,
typeof(RazorIntegrationTestBase).Assembly, // Reference this assembly, so that we can refer to test component types
};
var referenceAssemblies = referenceAssemblyRoots
.SelectMany(assembly => assembly.GetReferencedAssemblies().Concat(new[] { assembly.GetName() }))
.Distinct()
.Select(Assembly.Load)
.Select(assembly => MetadataReference.CreateFromFile(assembly.Location))
.ToList();
BaseCompilation = CSharpCompilation.Create(
"TestAssembly",
Array.Empty<SyntaxTree>(),
referenceAssemblies,
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
CSharpParseOptions = new CSharpParseOptions(LanguageVersion.Preview);
}
public RazorIntegrationTestBase(ITestOutputHelper output)
{
_output.Value = output;
AdditionalSyntaxTrees = new List<SyntaxTree>();
AdditionalRazorItems = new List<RazorProjectItem>();
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;
DefaultRootNamespace = "Test"; // Matches the default working directory
DefaultFileName = "TestComponent.cshtml";
}
internal List<RazorProjectItem> AdditionalRazorItems { get; }
internal List<SyntaxTree> AdditionalSyntaxTrees { get; }
internal virtual RazorConfiguration Configuration { get; }
internal virtual string DefaultRootNamespace { get; }
internal virtual string DefaultFileName { get; }
internal virtual bool DesignTime { get; }
internal virtual string FileKind { get; }
internal virtual VirtualRazorProjectFileSystem FileSystem { get; }
// Used to force a specific style of line-endings for testing. This matters
// for the baseline tests that exercise line mappings. Even though we normalize
// newlines for testing, the difference between platforms affects the data through
// the *count* of characters written.
internal virtual string LineEnding { get; }
internal virtual string PathSeparator { get; }
internal virtual bool NormalizeSourceLineEndings { get; }
internal virtual bool UseTwoPhaseCompilation { get; }
internal virtual string WorkingDirectory { get; }
// 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 =>
{
b.SetRootNamespace(DefaultRootNamespace);
// Turn off checksums, we're testing code generation.
b.Features.Add(new SuppressChecksum());
if (LineEnding != null)
{
b.Phases.Insert(0, new ForceLineEndingPhase(LineEnding));
}
// 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()
{
References = references,
});
});
}
internal RazorProjectItem CreateProjectItem(string cshtmlRelativePath, string cshtmlContent)
{
var fullPath = WorkingDirectory + PathSeparator + cshtmlRelativePath;
// FilePaths in Razor are **always** are of the form '/a/b/c.cshtml'
var filePath = cshtmlRelativePath.Replace('\\', '/');
if (!filePath.StartsWith('/'))
{
filePath = '/' + filePath;
}
if (NormalizeSourceLineEndings)
{
cshtmlContent = cshtmlContent.Replace("\r", "").Replace("\n", LineEnding);
}
return new VirtualProjectItem(
WorkingDirectory,
filePath,
fullPath,
cshtmlRelativePath,
FileKind,
Encoding.UTF8.GetBytes(cshtmlContent.TrimStart()));
}
protected CompileToCSharpResult CompileToCSharp(string cshtmlContent)
{
return CompileToCSharp(DefaultFileName, cshtmlContent);
}
protected CompileToCSharpResult CompileToCSharp(string cshtmlRelativePath, string cshtmlContent)
{
if (UseTwoPhaseCompilation)
{
// The first phase won't include any metadata references for component discovery. This mirrors
// what the build does.
var projectEngine = CreateProjectEngine(Array.Empty<MetadataReference>());
RazorCodeDocument codeDocument;
foreach (var item in AdditionalRazorItems)
{
// Result of generating declarations
codeDocument = projectEngine.ProcessDeclarationOnly(item);
Assert.Empty(codeDocument.GetCSharpDocument().Diagnostics);
var syntaxTree = Parse(codeDocument.GetCSharpDocument().GeneratedCode, path: item.FilePath);
AdditionalSyntaxTrees.Add(syntaxTree);
}
// Result of generating declarations
var projectItem = CreateProjectItem(cshtmlRelativePath, cshtmlContent);
codeDocument = projectEngine.ProcessDeclarationOnly(projectItem);
var declaration = new CompileToCSharpResult
{
BaseCompilation = BaseCompilation.AddSyntaxTrees(AdditionalSyntaxTrees),
CodeDocument = codeDocument,
Code = codeDocument.GetCSharpDocument().GeneratedCode,
Diagnostics = codeDocument.GetCSharpDocument().Diagnostics,
};
// Result of doing 'temp' compilation
var tempAssembly = CompileToAssembly(declaration);
// Add the 'temp' compilation as a metadata reference
var references = BaseCompilation.References.Concat(new[] { tempAssembly.Compilation.ToMetadataReference() }).ToArray();
projectEngine = CreateProjectEngine(references);
// Now update the any additional files
foreach (var item in AdditionalRazorItems)
{
// Result of generating declarations
codeDocument = DesignTime ? projectEngine.ProcessDesignTime(item) : projectEngine.Process(item);
Assert.Empty(codeDocument.GetCSharpDocument().Diagnostics);
// Replace the 'declaration' syntax tree
var syntaxTree = Parse(codeDocument.GetCSharpDocument().GeneratedCode, path: item.FilePath);
AdditionalSyntaxTrees.RemoveAll(st => st.FilePath == item.FilePath);
AdditionalSyntaxTrees.Add(syntaxTree);
}
// 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),
CodeDocument = codeDocument,
Code = codeDocument.GetCSharpDocument().GeneratedCode,
Diagnostics = codeDocument.GetCSharpDocument().Diagnostics,
};
}
else
{
// For single phase compilation tests just use the base compilation's references.
// This will include the built-in Blazor components.
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("```C#");
_output.Value.WriteLine(codeDocument.GetCSharpDocument().GeneratedCode);
_output.Value.WriteLine("```");
return new CompileToCSharpResult
{
BaseCompilation = BaseCompilation.AddSyntaxTrees(AdditionalSyntaxTrees),
CodeDocument = codeDocument,
Code = codeDocument.GetCSharpDocument().GeneratedCode,
Diagnostics = codeDocument.GetCSharpDocument().Diagnostics,
};
}
}
protected CompileToAssemblyResult CompileToAssembly(string cshtmlRelativePath, string cshtmlContent)
{
var cSharpResult = CompileToCSharp(cshtmlRelativePath, cshtmlContent);
return CompileToAssembly(cSharpResult);
}
protected CompileToAssemblyResult CompileToAssembly(CompileToCSharpResult cSharpResult, bool throwOnFailure = true)
{
if (cSharpResult.Diagnostics.Any())
{
var diagnosticsLog = string.Join(Environment.NewLine, cSharpResult.Diagnostics.Select(d => d.ToString()).ToArray());
throw new InvalidOperationException($"Aborting compilation to assembly because RazorCompiler returned nonempty diagnostics: {diagnosticsLog}");
}
var syntaxTrees = new[]
{
Parse(cSharpResult.Code),
};
var compilation = cSharpResult.BaseCompilation.AddSyntaxTrees(syntaxTrees);
var diagnostics = compilation
.GetDiagnostics()
.Where(d => d.Severity != DiagnosticSeverity.Hidden);
if (diagnostics.Any() && throwOnFailure)
{
throw new CompilationFailedException(compilation);
}
else if (diagnostics.Any())
{
return new CompileToAssemblyResult
{
Compilation = compilation,
Diagnostics = diagnostics,
};
}
using (var peStream = new MemoryStream())
{
compilation.Emit(peStream);
return new CompileToAssemblyResult
{
Compilation = compilation,
Diagnostics = diagnostics,
Assembly = diagnostics.Any() ? null : Assembly.Load(peStream.ToArray())
};
}
}
protected IComponent CompileToComponent(string cshtmlSource)
{
var assemblyResult = CompileToAssembly(DefaultFileName, cshtmlSource);
var componentFullTypeName = $"{DefaultRootNamespace}.{Path.GetFileNameWithoutExtension(DefaultFileName)}";
return CompileToComponent(assemblyResult, componentFullTypeName);
}
protected IComponent CompileToComponent(CompileToCSharpResult cSharpResult, string fullTypeName)
{
return CompileToComponent(CompileToAssembly(cSharpResult), fullTypeName);
}
protected IComponent CompileToComponent(CompileToAssemblyResult assemblyResult, string fullTypeName)
{
var componentType = assemblyResult.Assembly.GetType(fullTypeName);
if (componentType == null)
{
throw new XunitException(
$"Failed to find component type '{fullTypeName}'. Found types:" + Environment.NewLine +
string.Join(Environment.NewLine, assemblyResult.Assembly.ExportedTypes.Select(t => t.FullName)));
}
return (IComponent)Activator.CreateInstance(componentType);
}
protected static CSharpSyntaxTree Parse(string text, string path = null)
{
return (CSharpSyntaxTree)CSharpSyntaxTree.ParseText(text, CSharpParseOptions, path: path);
}
protected static string FullTypeName<T>() => typeof(T).FullName.Replace('+', '.');
protected RenderTreeFrame[] GetRenderTree(IComponent component)
{
var renderer = new TestRenderer();
return GetRenderTree(renderer, component);
}
protected private RenderTreeFrame[] GetRenderTree(TestRenderer renderer, IComponent component)
{
renderer.AttachComponent(component);
var task = renderer.Dispatcher.InvokeAsync(() => component.SetParametersAsync(ParameterView.Empty));
// we will have to change this method if we add a test that does actual async work.
Assert.True(task.Status.HasFlag(TaskStatus.RanToCompletion) || task.Status.HasFlag(TaskStatus.Faulted));
if (task.IsFaulted)
{
ExceptionDispatchInfo.Capture(task.Exception.InnerException).Throw();
}
return renderer.LatestBatchReferenceFrames;
}
protected ArrayRange<RenderTreeFrame> GetFrames(RenderFragment fragment)
{
var builder = new RenderTreeBuilder();
fragment(builder);
return builder.GetFrames();
}
protected static void AssertSourceEquals(string expected, CompileToCSharpResult generated)
{
// Normalize the paths inside the expected result to match the OS paths
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var windowsPath = Path.Combine(ArbitraryWindowsPath, generated.CodeDocument.Source.RelativePath).Replace('/', '\\');
expected = expected.Replace(windowsPath, generated.CodeDocument.Source.FilePath);
}
expected = expected.Trim();
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
public Compilation BaseCompilation { get; set; }
public RazorCodeDocument CodeDocument { get; set; }
public string Code { get; set; }
public IEnumerable<RazorDiagnostic> Diagnostics { get; set; }
}
protected class CompileToAssemblyResult
{
public Assembly Assembly { get; set; }
public Compilation Compilation { get; set; }
public string VerboseLog { get; set; }
public IEnumerable<Diagnostic> Diagnostics { get; set; }
}
protected class TestRenderer : Renderer
{
public TestRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance)
{
}
public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault();
public RenderTreeFrame[] LatestBatchReferenceFrames { get; private set; }
public void AttachComponent(IComponent component)
=> AssignRootComponentId(component);
protected override void HandleException(Exception exception)
{
ExceptionDispatchInfo.Capture(exception).Throw();
}
protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
{
LatestBatchReferenceFrames = renderBatch.ReferenceFrames.AsEnumerable().ToArray();
return Task.CompletedTask;
}
}
private class CompilationFailedException : XunitException
{
public CompilationFailedException(Compilation compilation)
{
Compilation = compilation;
}
public Compilation Compilation { get; }
public override string Message
{
get
{
var builder = new StringBuilder();
builder.AppendLine("Compilation failed: ");
var diagnostics = Compilation.GetDiagnostics();
var syntaxTreesWithErrors = new HashSet<SyntaxTree>();
foreach (var diagnostic in diagnostics)
{
builder.AppendLine(diagnostic.ToString());
if (diagnostic.Location.IsInSource)
{
syntaxTreesWithErrors.Add(diagnostic.Location.SourceTree);
}
}
if (syntaxTreesWithErrors.Any())
{
builder.AppendLine();
builder.AppendLine();
foreach (var syntaxTree in syntaxTreesWithErrors)
{
builder.AppendLine($"File {syntaxTree.FilePath ?? "unknown"}:");
builder.AppendLine(syntaxTree.GetText().ToString());
}
}
return builder.ToString();
}
}
}
private class SuppressChecksum : IConfigureRazorCodeGenerationOptionsFeature
{
public int Order => 0;
public RazorEngine Engine { get; set; }
public void Configure(RazorCodeGenerationOptionsBuilder options)
{
options.SuppressChecksum = true;
}
}
private class ForceLineEndingPhase : RazorEnginePhaseBase
{
public ForceLineEndingPhase(string lineEnding)
{
LineEnding = lineEnding;
}
public string LineEnding { get; }
protected override void ExecuteCore(RazorCodeDocument codeDocument)
{
var field = typeof(CodeRenderingContext).GetField("NewLineString", BindingFlags.Static | BindingFlags.NonPublic);
var key = field.GetValue(null);
codeDocument.Items[key] = LineEnding;
}
}
}
}

View File

@ -1,744 +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.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.AspNetCore.Components.Web;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
// Integration tests for the end-to-end of successful Razor compilation of component definitions
// Includes running the component code to verify the output.
public class RenderingRazorIntegrationTest : RazorIntegrationTestBase
{
public RenderingRazorIntegrationTest(ITestOutputHelper output)
: base(output)
{
}
[Fact]
public void SupportsPlainText()
{
// Arrange/Act
var component = CompileToComponent("Some plain text");
var frames = GetRenderTree(component);
// Assert
Assert.Collection(frames,
frame => AssertFrame.Text(frame, "Some plain text", 0));
}
[Fact]
public void SupportsCSharpExpressions()
{
// Arrange/Act
var component = CompileToComponent(@"
@(""Hello"")
@((object)null)
@(123)
@(new object())
");
// Assert
var frames = GetRenderTree(component);
Assert.Collection(frames,
frame => AssertFrame.Text(frame, "Hello", 0),
frame => AssertFrame.MarkupWhitespace(frame, 1),
frame => AssertFrame.TextWhitespace(frame, 2), // @((object)null)
frame => AssertFrame.MarkupWhitespace(frame, 3),
frame => AssertFrame.Text(frame, "123", 4),
frame => AssertFrame.MarkupWhitespace(frame, 5),
frame => AssertFrame.Text(frame, new object().ToString(), 6));
}
[Fact]
public void SupportsCSharpFunctionsBlock()
{
// Arrange/Act
var component = CompileToComponent(@"
@foreach(var item in items) {
@item
}
@code {
string[] items = new[] { ""First"", ""Second"", ""Third"" };
}
");
// Assert
var frames = GetRenderTree(component);
Assert.Collection(frames,
frame => AssertFrame.Text(frame, "First", 0),
frame => AssertFrame.Text(frame, "Second", 0),
frame => AssertFrame.Text(frame, "Third", 0));
}
[Fact]
public void SupportsElementsWithDynamicContent()
{
// Arrange/Act
var component = CompileToComponent("<myelem>Hello @(\"there\")</myelem>");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Element(frame, "myelem", 3, 0),
frame => AssertFrame.Text(frame, "Hello ", 1),
frame => AssertFrame.Text(frame, "there", 2));
}
[Fact]
public void SupportsElementsAsStaticBlock()
{
// Arrange/Act
var component = CompileToComponent("<myelem>Hello</myelem>");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Markup(frame, "<myelem>Hello</myelem>", 0));
}
[Fact]
public void CreatesSeparateMarkupFrameForEachTopLevelStaticElement()
{
// The JavaScript-side rendering code does not rely on this behavior. It supports
// inserting markup frames with arbitrary markup (e.g., multiple top-level elements
// or none). This test exists only as an observation of the current behavior rather
// than a promise that we never want to change it.
// Arrange/Act
var component = CompileToComponent(
"<root>@(\"Hi\") <child1>a</child1> <child2><another>b</another></child2> </root>");
// Assert
var frames = GetRenderTree(component);
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "root", 5, 0),
frame => AssertFrame.Text(frame, "Hi", 1),
frame => AssertFrame.Text(frame, " ", 2),
frame => AssertFrame.Markup(frame, "<child1>a</child1> ", 3),
frame => AssertFrame.Markup(frame, "<child2><another>b</another></child2> ", 4));
}
[Fact]
public void RendersMarkupStringAsMarkupFrame()
{
// Arrange/Act
var component = CompileToComponent(
"@{ var someMarkup = new MarkupString(\"<div>Hello</div>\"); }"
+ "<p>@someMarkup</p>");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Element(frame, "p", 2, 0),
frame => AssertFrame.Markup(frame, "<div>Hello</div>", 1));
}
[Fact]
public void SupportsSelfClosingElementsWithDynamicContent()
{
// Arrange/Act
var component = CompileToComponent("Some text so elem isn't at position 0 <myelem myattr=@(\"val\") />");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Text(frame, "Some text so elem isn't at position 0 ", 0),
frame => AssertFrame.Element(frame, "myelem", 2, 1),
frame => AssertFrame.Attribute(frame, "myattr", "val", 2));
}
[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.Markup(frame, "Some text so elem isn't at position 0 <input attr=\"123\">", 0));
}
[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.Markup(frame, "Some text so elem isn't at position 0 <img>", 0));
}
[Fact]
public void SupportsComments()
{
// Arrange/Act
var component = CompileToComponent("Start<!-- My comment -->End");
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Markup(frame, "StartEnd", 0));
}
[Fact]
public void SupportsAttributesWithLiteralValues()
{
// Arrange/Act
var component = CompileToComponent("<elem attrib-one=\"Value 1\" a2='v2'>@(\"Hello\")</elem>");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Element(frame, "elem", 4, 0),
frame => AssertFrame.Attribute(frame, "attrib-one", "Value 1", 1),
frame => AssertFrame.Attribute(frame, "a2", "v2", 2),
frame => AssertFrame.Text(frame, "Hello", 3));
}
[Fact]
public void SupportsAttributesWithStringExpressionValues()
{
// Arrange/Act
var component = CompileToComponent(
"@{ var myValue = \"My string\"; }"
+ "<elem attr=@myValue />");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Element(frame, "elem", 2, 0),
frame => AssertFrame.Attribute(frame, "attr", "My string", 1));
}
[Fact]
public void SupportsAttributesWithNonStringExpressionValues()
{
// Arrange/Act
var component = CompileToComponent(
"@{ var myValue = 123; }"
+ "<elem attr=@myValue />");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Element(frame, "elem", 2, 0),
frame => AssertFrame.Attribute(frame, "attr", "123", 1));
}
[Fact]
public void SupportsAttributesWithInterpolatedStringExpressionValues()
{
// Arrange/Act
var component = CompileToComponent(
"@{ var myValue = \"world\"; var myNum=123; }"
+ "<elem attr=\"Hello, @myValue.ToUpperInvariant() with number @(myNum*2)!\" />");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Element(frame, "elem", 2, 0),
frame => AssertFrame.Attribute(frame, "attr", "Hello, WORLD with number 246!", 1));
}
[Fact]
public void SupportsAttributesWithInterpolatedTernaryExpressionValues()
{
// Arrange/Act
var component = CompileToComponent(
"@{ var myValue = \"world\"; }"
+ "<elem attr=\"Hello, @(true ? myValue : \"nothing\")!\" />");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Element(frame, "elem", 2, 0),
frame => AssertFrame.Attribute(frame, "attr", "Hello, world!", 1));
}
[Fact]
public void SupportsHyphenedAttributesWithCSharpExpressionValues()
{
// Arrange/Act
var component = CompileToComponent(
"@{ var myValue = \"My string\"; }"
+ "<elem abc-def=@myValue />");
// Assert
Assert.Collection(GetRenderTree(component),
frame => AssertFrame.Element(frame, "elem", 2, 0),
frame => AssertFrame.Attribute(frame, "abc-def", "My string", 1));
}
[Fact]
public void SupportsDataDashAttributes()
{
// Arrange/Act
var component = CompileToComponent(@"
@{
var myValue = ""Expression value"";
}
<elem data-abc=""Literal value"" data-def=""@myValue"" />");
// Assert
Assert.Collection(
GetRenderTree(component),
frame => AssertFrame.Element(frame, "elem", 3, 0),
frame => AssertFrame.Attribute(frame, "data-abc", "Literal value", 1),
frame => AssertFrame.Attribute(frame, "data-def", "Expression value", 2));
}
[Fact]
public void SupportsUsingStatements()
{
// Arrange/Act
var component = CompileToComponent(
@"@using System.Collections.Generic
@(typeof(List<string>).FullName)");
var frames = GetRenderTree(component);
// Assert
Assert.Collection(frames,
frame => AssertFrame.Text(frame, typeof(List<string>).FullName, 0));
}
[Fact]
public async Task SupportsTwoWayBindingForTextboxes()
{
// Arrange/Act
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<input @bind=""MyValue"" />
@code {
public string MyValue { get; set; } = ""Initial value"";
}");
var myValueProperty = component.GetType().GetProperty("MyValue");
var renderer = new TestRenderer();
// Assert
EventCallback setter = default;
var frames = GetRenderTree(renderer, component);
Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "value", "Initial value", 1),
frame =>
{
AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<EventCallback>(frame.AttributeValue);
});
// Trigger the change event to show it updates the property
//
// This should always complete synchronously.
var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = "Modified value", }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal("Modified value", myValueProperty.GetValue(component));
}
[Fact]
public async Task SupportsTwoWayBindingForTextareas()
{
// Arrange/Act
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<textarea @bind=""MyValue"" ></textarea>
@code {
public string MyValue { get; set; } = ""Initial value"";
}");
var myValueProperty = component.GetType().GetProperty("MyValue");
var renderer = new TestRenderer();
// Assert
EventCallback setter = default;
var frames = GetRenderTree(renderer, component);
Assert.Collection(frames,
frame => AssertFrame.Element(frame, "textarea", 3, 0),
frame => AssertFrame.Attribute(frame, "value", "Initial value", 1),
frame =>
{
AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<EventCallback>(frame.AttributeValue);
});
// Trigger the change event to show it updates the property
//
// This should always complete synchronously.
var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = "Modified value", }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal("Modified value", myValueProperty.GetValue(component));
}
[Fact]
public async Task SupportsTwoWayBindingForDateValues()
{
// Arrange/Act
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<input @bind=""MyDate"" />
@code {
public DateTime MyDate { get; set; } = new DateTime(2018, 3, 4, 1, 2, 3);
}");
var myDateProperty = component.GetType().GetProperty("MyDate");
var renderer = new TestRenderer();
// Assert
EventCallback setter = default;
var frames = GetRenderTree(renderer, component);
Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 3, 4, 1, 2, 3).ToString(), 1),
frame =>
{
AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<EventCallback>(frame.AttributeValue);
});
// Trigger the change event to show it updates the property
// Trigger the change event to show it updates the property
//
// This should always complete synchronously.
var newDateValue = new DateTime(2018, 3, 5, 4, 5, 6);
var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = newDateValue.ToString(), }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal(newDateValue, myDateProperty.GetValue(component));
}
[Fact]
public async Task SupportsTwoWayBindingForDateValuesWithFormatString()
{
// Arrange/Act
var testDateFormat = "ddd yyyy-MM-dd";
var component = CompileToComponent($@"
@using Microsoft.AspNetCore.Components.Web
<input @bind=""@MyDate"" @bind:format=""{testDateFormat}"" />
@code {{
public DateTime MyDate {{ get; set; }} = new DateTime(2018, 3, 4);
}}");
var myDateProperty = component.GetType().GetProperty("MyDate");
var renderer = new TestRenderer();
// Assert
EventCallback setter = default;
var frames = GetRenderTree(renderer, component);
Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 3, 4).ToString(testDateFormat), 1),
frame =>
{
AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<EventCallback>(frame.AttributeValue);
});
// Trigger the change event to show it updates the property
//
// This should always complete synchronously.
var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = new DateTime(2018, 3, 5).ToString(testDateFormat), }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal(new DateTime(2018, 3, 5), myDateProperty.GetValue(component));
}
[Fact] // In this case, onclick is just a normal HTML attribute
public void SupportsEventHandlerWithString()
{
// Arrange
var component = CompileToComponent(@"
<button onclick=""function(){console.log('hello');};"" />");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(frames,
frame => AssertFrame.Markup(frame, "<button onclick=\"function(){console.log('hello');};\"></button>", 0));
}
[Fact]
public void SupportsEventHandlerWithLambda()
{
// Arrange
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<button @onclick=""x => Clicked = true"" />
@code {
public bool Clicked { get; set; }
}");
var clicked = component.GetType().GetProperty("Clicked");
var renderer = new TestRenderer();
// Act
var frames = GetRenderTree(renderer, component);
// Assert
Assert.Collection(frames,
frame => AssertFrame.Element(frame, "button", 2, 0),
frame =>
{
AssertFrame.Attribute(frame, "onclick", 1);
var func = Assert.IsType<Action<MouseEventArgs>>(frame.AttributeValue);
Assert.False((bool)clicked.GetValue(component));
func(new MouseEventArgs());
Assert.True((bool)clicked.GetValue(component));
});
}
[Fact]
public void SupportsEventHandlerWithMethodGroup()
{
// Arrange
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<button @onclick=""OnClick"" />
@code {
public void OnClick(MouseEventArgs e) { Clicked = true; }
public bool Clicked { get; set; }
}");
var clicked = component.GetType().GetProperty("Clicked");
var renderer = new TestRenderer();
// Act
var frames = GetRenderTree(renderer, component);
// Assert
Action<MouseEventArgs> func = default; // Since this is a method group, we don't need to create an EventCallback
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "button", 2, 0),
frame =>
{
AssertFrame.Attribute(frame, "onclick", 1);
func = Assert.IsType<Action<MouseEventArgs>>(frame.AttributeValue);
Assert.False((bool)clicked.GetValue(component));
});
func.Invoke(new MouseEventArgs());
Assert.True((bool)clicked.GetValue(component));
}
[Fact]
public async Task SupportsTwoWayBindingForBoolValues()
{
// Arrange/Act
var component = CompileToComponent(@"
@using Microsoft.AspNetCore.Components.Web
<input @bind=""MyValue"" />
@code {
public bool MyValue { get; set; } = true;
}");
var myValueProperty = component.GetType().GetProperty("MyValue");
var renderer = new TestRenderer();
// Assert
EventCallback setter = default;
var frames = GetRenderTree(renderer, component);
Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "value", true, 1),
frame =>
{
AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<EventCallback>(frame.AttributeValue);
});
// Trigger the change event to show it updates the property
//
// This should always complete synchronously.
var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs() { Value = false, }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.False((bool)myValueProperty.GetValue(component));
}
[Fact]
public async Task SupportsTwoWayBindingForEnumValues()
{
// Arrange/Act
var myEnumType = FullTypeName<MyEnum>();
var component = CompileToComponent($@"
@using Microsoft.AspNetCore.Components.Web
<input @bind=""MyValue"" />
@code {{
public {myEnumType} MyValue {{ get; set; }} = {myEnumType}.{nameof(MyEnum.FirstValue)};
}}");
var myValueProperty = component.GetType().GetProperty("MyValue");
var renderer = new TestRenderer();
// Assert
EventCallback setter = default;
var frames = GetRenderTree(renderer, component);
Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "value", MyEnum.FirstValue.ToString(), 1),
frame =>
{
AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<EventCallback>(frame.AttributeValue);
});
// Trigger the change event to show it updates the property
//
// This should always complete synchronously.
var task = renderer.Dispatcher.InvokeAsync(() => setter.InvokeAsync(new ChangeEventArgs { Value = MyEnum.SecondValue.ToString(), }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal(MyEnum.SecondValue, (MyEnum)myValueProperty.GetValue(component));
}
public enum MyEnum { FirstValue, SecondValue }
[Fact]
public void RazorTemplate_NonGeneric_CanBeUsedFromRazorCode()
{
// Arrange
var component = CompileToComponent(@"
@{ RenderFragment template = @<div>@(""Hello, World!"".ToLower())</div>; }
@for (var i = 0; i < 3; i++)
{
@template;
}
");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1));
}
[Fact]
public void RazorTemplate_Generic_CanBeUsedFromRazorCode()
{
// Arrange
var component = CompileToComponent(@"
@{ RenderFragment<string> template = (context) => @<div>@context.ToLower()</div>; }
@for (var i = 0; i < 3; i++)
{
@template(""Hello, World!"");
}
");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1),
frame => AssertFrame.Element(frame, "div", 2, 0),
frame => AssertFrame.Text(frame, "hello, world!", 1));
}
[Fact]
public void RazorTemplate_NonGeneric_CanBeUsedFromMethod()
{
// Arrange
var component = CompileToComponent(@"
@(Repeat(@<div>@(""Hello, World!"".ToLower())</div>, 3))
@code {
RenderFragment Repeat(RenderFragment template, int count)
{
return (b) =>
{
for (var i = 0; i < count; i++)
{
b.AddContent(i, template);
}
};
}
}");
// Act
var frames = GetRenderTree(component);
// Assert
//
// The sequence numbers start at 1 here because there is an AddContent(0, Repeat(....) call
// that precedes the definition of the lambda. Sequence numbers for the lambda are allocated
// from the same logical sequence as the surrounding code.
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "div", 2, 1),
frame => AssertFrame.Text(frame, "hello, world!", 2),
frame => AssertFrame.Element(frame, "div", 2, 1),
frame => AssertFrame.Text(frame, "hello, world!", 2),
frame => AssertFrame.Element(frame, "div", 2, 1),
frame => AssertFrame.Text(frame, "hello, world!", 2));
}
[Fact]
public void RazorTemplate_Generic_CanBeUsedFromMethod()
{
// Arrange
var component = CompileToComponent(@"
@(Repeat((context) => @<div>@context.ToLower()</div>, ""Hello, World!"", 3))
@code {
RenderFragment Repeat<T>(RenderFragment<T> template, T value, int count)
{
return (b) =>
{
for (var i = 0; i < count; i++)
{
b.AddContent(i, template, value);
}
};
}
}");
// Act
var frames = GetRenderTree(component);
// Assert
//
// The sequence numbers start at 1 here because there is an AddContent(0, Repeat(....) call
// that precedes the definition of the lambda. Sequence numbers for the lambda are allocated
// from the same logical sequence as the surrounding code.
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "div", 2, 1),
frame => AssertFrame.Text(frame, "hello, world!", 2),
frame => AssertFrame.Element(frame, "div", 2, 1),
frame => AssertFrame.Text(frame, "hello, world!", 2),
frame => AssertFrame.Element(frame, "div", 2, 1),
frame => AssertFrame.Text(frame, "hello, world!", 2));
}
}
}

View File

@ -1,3 +0,0 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View File

@ -37,7 +37,7 @@
Private="false" />
</ItemGroup>
<Import Project="Blazor\Build\src\ReferenceFromSource.props" Condition="'$(ReferenceBlazorBuildLocally)' == 'true'" />
<Import Project="WebAssembly\Build\src\ReferenceFromSource.props" Condition="'$(ReferenceBlazorBuildLocally)' == 'true'" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.targets))\Directory.Build.targets" />
</Project>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,7 +18,7 @@ async function boot(options?: any): Promise<void> {
}
started = true;
setEventDispatcher((eventDescriptor, eventArgs) => DotNet.invokeMethodAsync('Microsoft.AspNetCore.Blazor', 'DispatchEvent', eventDescriptor, JSON.stringify(eventArgs)));
setEventDispatcher((eventDescriptor, eventArgs) => DotNet.invokeMethodAsync('Microsoft.AspNetCore.Components.WebAssembly', 'DispatchEvent', eventDescriptor, JSON.stringify(eventArgs)));
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
const platform = Environment.setPlatform(monoPlatform);
@ -30,7 +30,7 @@ async function boot(options?: any): Promise<void> {
// Configure navigation via JS Interop
window['Blazor']._internal.navigationManager.listenForNavigationEvents(async (uri: string, intercepted: boolean): Promise<void> => {
await DotNet.invokeMethodAsync(
'Microsoft.AspNetCore.Blazor',
'Microsoft.AspNetCore.Components.WebAssembly',
'NotifyLocationChanged',
uri,
intercepted

View File

@ -36,7 +36,7 @@ export const monoPlatform: Platform = {
// In the future, we might want Blazor.start to return a Promise<Promise<value>>, where the
// outer promise reflects the startup process, and the inner one reflects the possibly-async
// .NET entrypoint method.
const invokeEntrypoint = bindStaticMethod('Microsoft.AspNetCore.Blazor', 'Microsoft.AspNetCore.Blazor.Hosting.EntrypointInvoker', 'InvokeEntrypoint');
const invokeEntrypoint = bindStaticMethod('Microsoft.AspNetCore.Components.WebAssembly', 'Microsoft.AspNetCore.Components.WebAssembly.Hosting.EntrypointInvoker', 'InvokeEntrypoint');
// Note we're passing in null because passing arrays is problematic until https://github.com/mono/mono/issues/18245 is resolved.
invokeEntrypoint(assemblyName, null);
},

View File

@ -2,9 +2,9 @@
<PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net46</TargetFrameworks>
<TargetName>Microsoft.AspNetCore.Blazor.Build.Tasks</TargetName>
<AssemblyName>Microsoft.AspNetCore.Blazor.Build</AssemblyName>
<Description>Build mechanism for ASP.NET Core Blazor applications.</Description>
<TargetName>Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks</TargetName>
<AssemblyName>Microsoft.AspNetCore.Components.WebAssembly.Build</AssemblyName>
<Description>Build mechanism for ASP.NET Core Blazor WebAssembly applications.</Description>
<IsShippingPackage>true</IsShippingPackage>
<HasReferenceAssembly>false</HasReferenceAssembly>
<GenerateDependencyFile>false</GenerateDependencyFile>
@ -15,7 +15,7 @@
<!-- Producing this package requires building with NodeJS enabled. -->
<IsPackable Condition="'$(BuildNodeJS)' == 'false'">false</IsPackable>
<NoPackageAnalysis>true</NoPackageAnalysis>
<NuspecFile>Microsoft.AspNetCore.Blazor.Build.nuspec</NuspecFile>
<NuspecFile>Microsoft.AspNetCore.Components.WebAssembly.Build.nuspec</NuspecFile>
</PropertyGroup>
<ItemGroup>
@ -26,6 +26,10 @@
<NuspecProperty Include="blazormonoversion=$(MicrosoftAspNetCoreBlazorMonoPackageVersion)" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.WebAssembly.Build.Tests" />
</ItemGroup>
<ItemGroup>
<!-- Add a project dependency without reference output assemblies to enforce build order -->
<!-- Applying workaround for https://github.com/microsoft/msbuild/issues/2661 and https://github.com/dotnet/sdk/issues/952 -->

View File

@ -25,7 +25,7 @@
The Blazor.Build project cross-compiles and we need the output of all TFMs to be available in the build output.
We can't represent this in any good way using ProjectReference elements, but we can try and build it instead.
-->
<MSBuild Projects="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Blazor.Build.csproj" />
<MSBuild Projects="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Components.WebAssembly.Build.csproj" />
</Target>
<!-- This is used as a P2P when building the repo. Normal Blazor projects will get this as a reference through the Blazor.Build package -->
@ -33,12 +33,12 @@
<!-- Ensures these projects are built before the consuming project, but without
adding a runtime dependency on the .dll (to be equivalent to a <PackageDependency>
given that the packed version of this project wouldn't add a .dll reference) -->
<ProjectReference Include="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Blazor.Build.csproj">
<ProjectReference Include="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Components.WebAssembly.Build.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
<Properties>TargetFramework=$(DefaultNetCoreTargetFramework)</Properties>
</ProjectReference>
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj">
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\DevServer\src\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<!-- Optimization. Do not require framework compatibility between these projects. -->
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>

View File

@ -9,7 +9,7 @@ using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
// Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/CreateRootDescriptorFile.cs
public class BlazorCreateRootDescriptorFile : Task

View File

@ -8,7 +8,7 @@ using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Blazor.Build.Tasks
namespace Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks
{
// Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/LinkTask.cs
public class BlazorILLink : ToolTask

View File

@ -11,7 +11,7 @@ using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary<string, string>;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class GenerateBlazorBootJson : Task
{

View File

@ -6,7 +6,7 @@ using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Blazor.Build.Tasks
namespace Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks
{
public class GenerateTypeGranularityLinkingConfig : Task
{

View File

@ -12,7 +12,7 @@ using System.Reflection.PortableExecutable;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class ResolveBlazorRuntimeDependencies : Task
{

View File

@ -9,7 +9,7 @@
<BlazorToolsDir Condition="'$(BlazorToolsDir)' == ''">$(MSBuildThisFileDirectory)..\tools\</BlazorToolsDir>
<_BlazorTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">netcoreapp</_BlazorTasksTFM>
<_BlazorTasksTFM Condition=" '$(_BlazorTasksTFM)' == ''">netfx</_BlazorTasksTFM>
<BlazorTasksPath>$(BlazorToolsDir)$(_BlazorTasksTFM)\Microsoft.AspNetCore.Blazor.Build.Tasks.dll</BlazorTasksPath>
<BlazorTasksPath>$(BlazorToolsDir)$(_BlazorTasksTFM)\Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks.dll</BlazorTasksPath>
<!-- The Blazor build code can only find your referenced assemblies if they are in the output directory -->
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -5,7 +5,7 @@ using System.IO;
using System.Xml.Linq;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class BlazorCreateRootDescriptorFileTest
{

View File

@ -12,7 +12,7 @@ using System.Reflection.PortableExecutable;
using System.Text;
using System.Text.RegularExpressions;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
internal class Assert : Xunit.Assert
{

View File

@ -4,7 +4,7 @@
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class BuildIncrementalismTest
{

View File

@ -5,7 +5,7 @@ using System.IO;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class BuildIntegrationTest
{

View File

@ -7,7 +7,7 @@ using System.IO;
using System.Linq;
using System.Security.Cryptography;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
internal class FileThumbPrint : IEquatable<FileThumbPrint>
{

View File

@ -12,7 +12,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
internal static class MSBuildProcessManager
{

View File

@ -1,7 +1,7 @@
// 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.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
internal class MSBuildResult
{

View File

@ -8,7 +8,7 @@ using System.Linq;
using System.Reflection;
using System.Threading;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
internal class ProjectDirectory : IDisposable
{
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Blazor.Build
throw new InvalidOperationException("RepoRoot was not specified.");
}
var testAppsRoot = Path.Combine(RepoRoot, "src", "Components", "Blazor", "Build", "testassets");
var testAppsRoot = Path.Combine(RepoRoot, "src", "Components", "WebAssembly", "Build", "testassets");
foreach (var project in new string[] { projectName, }.Concat(additionalProjects ?? Array.Empty<string>()))
{
var projectRoot = Path.Combine(testAppsRoot, project);

View File

@ -3,7 +3,7 @@
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class ProjectDirectoryTest
{

View File

@ -5,7 +5,7 @@ using System.IO;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class PublishIntegrationTest
{

View File

@ -6,10 +6,10 @@ using System.Runtime.Serialization.Json;
using Microsoft.Build.Framework;
using Moq;
using Xunit;
using BootJsonData = Microsoft.AspNetCore.Blazor.Build.GenerateBlazorBootJson.BootJsonData;
using ResourceType = Microsoft.AspNetCore.Blazor.Build.GenerateBlazorBootJson.ResourceType;
using BootJsonData = Microsoft.AspNetCore.Components.WebAssembly.Build.GenerateBlazorBootJson.BootJsonData;
using ResourceType = Microsoft.AspNetCore.Components.WebAssembly.Build.GenerateBlazorBootJson.ResourceType;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class GenerateBlazorBootJsonTest
{
@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Blazor.Build
CreateResourceTaskItem(
ResourceType.assembly,
itemSpec: "Ignored",
itemSpec: "Ignored",
relativeOutputPath: Path.Combine("dir", "My.Assembly2.ext2"), // Can specify relative path
fileHash: "012345678901234567890123456789"),

View File

@ -22,20 +22,16 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Blazor.Build" />
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" />
<Reference Include="Microsoft.AspNetCore.Blazor.Mono" />
<Reference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" />
<Reference Include="Microsoft.AspNetCore.Razor.Language" />
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Utilities.Core" />
<Reference Include="Microsoft.CodeAnalysis.Razor" />
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\testassets\StandaloneApp\StandaloneApp.csproj" />
<Compile Include="$(SharedSourceRoot)test\SkipOnHelixAttribute.cs" />
<Compile Include="$(ComponentsSharedSourceRoot)test\**\*.cs" LinkBase="Helpers" />
</ItemGroup>
<ItemGroup>

View File

@ -9,7 +9,7 @@ using System.Text;
using Microsoft.AspNetCore.Testing;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
{
public class RuntimeDependenciesResolverTest
{

View File

@ -4,7 +4,7 @@
<PropertyGroup>
<RepoRoot Condition="'$(RepoRoot)' ==''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), global.json))\</RepoRoot>
<ComponentsRoot>$(RepoRoot)src\Components\</ComponentsRoot>
<BlazorBuildRoot>$(ComponentsRoot)Blazor\Build\src\</BlazorBuildRoot>
<BlazorBuildRoot>$(ComponentsRoot)WebAssembly\Build\src\</BlazorBuildRoot>
<ReferenceBlazorBuildFromSourceProps>$(BlazorBuildRoot)ReferenceBlazorBuildFromSource.props</ReferenceBlazorBuildFromSourceProps>
<!-- Workaround for https://github.com/aspnet/AspNetCore/issues/17308 -->

View File

@ -4,18 +4,19 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Hosting;
using DevServerProgram = Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server.Program;
namespace Microsoft.AspNetCore.Blazor.DevServer.Commands
namespace Microsoft.AspNetCore.Components.Web.DevServer.Commands
{
internal class ServeCommand : CommandLineApplication
{
public ServeCommand(CommandLineApplication parent)
// We pass arbitrary arguments through to the ASP.NET Core configuration
: base(throwOnUnexpectedArg: false)
: base(throwOnUnexpectedArg: false)
{
Parent = parent;
Name = "serve";
Description = "Serve requests to a Blazor application";
@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Blazor.DevServer.Commands
private int Execute()
{
Server.Program.BuildWebHost(RemainingArguments.ToArray()).Run();
DevServerProgram.BuildWebHost(RemainingArguments.ToArray()).Run();
return 0;
}
}

View File

@ -4,10 +4,10 @@
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>
<AssemblyName>blazor-devserver</AssemblyName>
<PackageId>Microsoft.AspNetCore.Blazor.DevServer</PackageId>
<PackageId>Microsoft.AspNetCore.Components.WebAssembly.DevServer</PackageId>
<IsShippingPackage>true</IsShippingPackage>
<HasReferenceAssembly>false</HasReferenceAssembly>
<StartupObject>Microsoft.AspNetCore.Blazor.DevServer.Program</StartupObject>
<StartupObject>Microsoft.AspNetCore.Components.WebAssembly.DevServer.Program</StartupObject>
<Description>Development server for use when building Blazor applications.</Description>
<!-- Set this to false because assemblies should not reference this assembly directly, (except for tests, of course). -->
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
@ -18,7 +18,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Blazor.Server" />
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
</ItemGroup>
@ -26,7 +26,7 @@
<PropertyGroup>
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);publish</GenerateNuspecDependsOn>
<NoPackageAnalysis>true</NoPackageAnalysis>
<NuspecFile>Microsoft.AspNetCore.Blazor.DevServer.nuspec</NuspecFile>
<NuspecFile>Microsoft.AspNetCore.Components.WebAssembly.DevServer.nuspec</NuspecFile>
</PropertyGroup>
<ItemGroup>

View File

@ -1,10 +1,10 @@
// 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.Blazor.DevServer.Commands;
using Microsoft.AspNetCore.Components.Web.DevServer.Commands;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Blazor.DevServer
namespace Microsoft.AspNetCore.Components.WebAssembly.DevServer
{
internal class Program
{

View File

@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace Microsoft.AspNetCore.Blazor.DevServer.Server
namespace Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server
{
// This project is a CLI tool, so we don't expect anyone to reference it
// as a runtime library. As such we consider it reasonable to mark the

View File

@ -13,7 +13,7 @@ using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Blazor.DevServer.Server
namespace Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server
{
internal class Startup
{

View File

@ -5,7 +5,7 @@ using System;
using System.IO;
using System.Linq;
namespace Microsoft.AspNetCore.Blazor.Server
namespace Microsoft.AspNetCore.Components.WebAssembly.Server
{
internal class BlazorConfig
{

View File

@ -4,22 +4,22 @@
using System;
using System.Collections.Generic;
using System.Net.Mime;
using Microsoft.AspNetCore.Blazor.Server;
using Microsoft.AspNetCore.Components.WebAssembly.Server;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Provides extension methods for hosting client-side Blazor applications in ASP.NET Core.
/// Provides extension methods for hosting Blazor WebAssembly applications in ASP.NET Core.
/// </summary>
public static class BlazorHostingApplicationBuilderExtensions
public static class ComponentsWebAssemblyHostingApplicationBuilderExtensions
{
/// <summary>
/// Adds a <see cref="StaticFileMiddleware"/> that will serve static files from the client-side Blazor application
/// Adds a <see cref="StaticFileMiddleware"/> that will serve static files from the Blazor WebAssembly application
/// specified by <typeparamref name="TClientApp"/>.
/// </summary>
/// <typeparam name="TClientApp">A type in the client-side application.</typeparam>
/// <typeparam name="TClientApp">A type in the Blazor WebAssembly application.</typeparam>
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseClientSideBlazorFiles<TClientApp>(this IApplicationBuilder app)
@ -34,10 +34,10 @@ namespace Microsoft.AspNetCore.Builder
}
/// <summary>
/// Adds a <see cref="StaticFileMiddleware"/> that will serve static files from the client-side Blazor application
/// Adds a <see cref="StaticFileMiddleware"/> that will serve static files from the Blazor WebAssembly application
/// specified by <paramref name="clientAssemblyFilePath"/>.
/// </summary>
/// <param name="clientAssemblyFilePath">The file path of the client-side Blazor application assembly.</param>
/// <param name="clientAssemblyFilePath">The file path of the Blazor WebAssembly application assembly.</param>
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseClientSideBlazorFiles(this IApplicationBuilder app, string clientAssemblyFilePath)

View File

@ -3,7 +3,7 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Blazor.Server;
using Microsoft.AspNetCore.Components.WebAssembly.Server;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.StaticFiles;
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Builder
/// <summary>
/// Provides extension methods for hosting client-side Blazor applications in ASP.NET Core.
/// </summary>
public static class BlazorHostingEndpointRouteBuilderExtensions
public static class ComponentsWebAssemblyHostingEndpointRouteBuilderExtensions
{
/// <summary>
/// Adds a low-priority endpoint that will serve the the file specified by <paramref name="filePath"/> from the client-side

View File

@ -18,9 +18,9 @@ using WebAssembly.Net.Debugging;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Provides infrastructure for debugging Blazor applications.
/// Provides infrastructure for debugging Blazor WebAssembly applications.
/// </summary>
public static class BlazorMonoDebugProxyAppBuilderExtensions
public static class WebAssemblyNetDebugProxyAppBuilderExtensions
{
private static JsonSerializerOptions JsonOptions = new JsonSerializerOptions
{
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Builder
private static string DefaultDebuggerHost = "http://localhost:9222";
/// <summary>
/// Adds middleware for needed for debugging Blazor applications
/// Adds middleware for needed for debugging Blazor WebAssembly applications
/// inside Chromium dev tools.
/// </summary>
public static void UseBlazorDebugging(this IApplicationBuilder app)

View File

@ -12,7 +12,7 @@
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests" />
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.DataAnnotations.Validation.Tests" />
</ItemGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More