Blazor WebAssembly package renames (#19026)
Fixes https://github.com/dotnet/aspnetcore/issues/18384
This commit is contained in:
parent
07098b3d97
commit
c935e9aa2d
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Build.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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(@"<span>Hi</span>");
|
||||
|
||||
// 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><span>Hi</span></div>");
|
||||
|
||||
// Act
|
||||
var frames = GetRenderTree(component);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
frames,
|
||||
frame => AssertFrame.Markup(frame, "<div><span>Hi</span></div>"));
|
||||
}
|
||||
|
||||
// Integration test for HTML block rewriting
|
||||
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/6183")]
|
||||
public void Render_HtmlBlock_Integration()
|
||||
{
|
||||
// Arrange
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 { }
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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 -->
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Build
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class BuildIncrementalismTest
|
||||
{
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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>
|
||||
{
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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);
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Build
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class ProjectDirectoryTest
|
||||
{
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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"),
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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 -->
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
Loading…
Reference in New Issue