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\Installers\**\*.*proj;
|
||||||
$(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
|
$(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
|
||||||
$(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
|
$(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
|
||||||
$(RepoRoot)src\Components\Blazor\Build\testassets\**\*.*proj;
|
$(RepoRoot)src\Components\WebAssembly\Build\testassets\**\*.*proj;
|
||||||
$(RepoRoot)src\ProjectTemplates\BlazorWasm.ProjectTemplates\content\**\*.csproj;
|
$(RepoRoot)src\ProjectTemplates\ComponentsWebAssembly.ProjectTemplates\content\**\*.csproj;
|
||||||
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj;
|
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj;
|
||||||
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj;
|
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj;
|
||||||
$(RepoRoot)src\ProjectTemplates\Web.Spa.ProjectTemplates\content\**\*.csproj;
|
$(RepoRoot)src\ProjectTemplates\Web.Spa.ProjectTemplates\content\**\*.csproj;
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,12 @@
|
||||||
-->
|
-->
|
||||||
<Project>
|
<Project>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.Build" ProjectPath="$(RepoRoot)src\Components\Blazor\Build\src\Microsoft.AspNetCore.Blazor.Build.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\Blazor\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.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\Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj" />
|
<ProjectReferenceProvider Include="Mono.WebAssembly.Interop" ProjectPath="$(RepoRoot)src\Components\WebAssembly\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.Components.WebAssembly.Server" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.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.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\Blazor\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
|
||||||
<ProjectReferenceProvider Include="BlazorServerApp" ProjectPath="$(RepoRoot)src\Components\Samples\BlazorServerApp\BlazorServerApp.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" />
|
||||||
<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" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -11,65 +11,65 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.Driver", "
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.TestApp", "benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj", "{10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.TestApp", "benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj", "{10E5AD2E-25A9-4B8B-BD33-207B12D5BAE4}"
|
||||||
EndProject
|
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
|
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
|
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
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A82B9830-447D-4E26-BEB7-C724A3956C0D}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A82B9830-447D-4E26-BEB7-C724A3956C0D}"
|
||||||
EndProject
|
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
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{B4ACD900-27B6-482B-B434-2C1E86E9D8BC}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{B4ACD900-27B6-482B-B434-2C1E86E9D8BC}"
|
||||||
EndProject
|
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
|
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
|
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
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevServer", "DevServer", "{A44FB7D1-78AB-41C4-B1C7-94399396EA6C}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevServer", "DevServer", "{A44FB7D1-78AB-41C4-B1C7-94399396EA6C}"
|
||||||
EndProject
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Http", "Http", "{F4995C96-8D4E-4B26-8FB8-614B020156C2}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Http", "Http", "{F4995C96-8D4E-4B26-8FB8-614B020156C2}"
|
||||||
EndProject
|
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
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{37FA056D-A7B3-4F72-A8B9-8D3C175E831E}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{37FA056D-A7B3-4F72-A8B9-8D3C175E831E}"
|
||||||
EndProject
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{7920B09F-8016-49CF-A229-E72D0CECDD17}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{7920B09F-8016-49CF-A229-E72D0CECDD17}"
|
||||||
EndProject
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{CBD2BB24-3EC3-4950-ABE4-8C521D258DCD}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{CBD2BB24-3EC3-4950-ABE4-8C521D258DCD}"
|
||||||
EndProject
|
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
|
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
|
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
|
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
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Validation", "Validation", "{09758C93-6707-46E3-9211-470449280C2C}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Validation", "Validation", "{09758C93-6707-46E3-9211-470449280C2C}"
|
||||||
EndProject
|
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
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{194596E0-E6F5-4728-8A7A-A82EA0893111}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{194596E0-E6F5-4728-8A7A-A82EA0893111}"
|
||||||
EndProject
|
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" />
|
Private="false" />
|
||||||
</ItemGroup>
|
</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" />
|
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.targets))\Directory.Build.targets" />
|
||||||
</Project>
|
</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;
|
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
|
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
|
||||||
const platform = Environment.setPlatform(monoPlatform);
|
const platform = Environment.setPlatform(monoPlatform);
|
||||||
|
|
@ -30,7 +30,7 @@ async function boot(options?: any): Promise<void> {
|
||||||
// Configure navigation via JS Interop
|
// Configure navigation via JS Interop
|
||||||
window['Blazor']._internal.navigationManager.listenForNavigationEvents(async (uri: string, intercepted: boolean): Promise<void> => {
|
window['Blazor']._internal.navigationManager.listenForNavigationEvents(async (uri: string, intercepted: boolean): Promise<void> => {
|
||||||
await DotNet.invokeMethodAsync(
|
await DotNet.invokeMethodAsync(
|
||||||
'Microsoft.AspNetCore.Blazor',
|
'Microsoft.AspNetCore.Components.WebAssembly',
|
||||||
'NotifyLocationChanged',
|
'NotifyLocationChanged',
|
||||||
uri,
|
uri,
|
||||||
intercepted
|
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
|
// 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
|
// outer promise reflects the startup process, and the inner one reflects the possibly-async
|
||||||
// .NET entrypoint method.
|
// .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.
|
// Note we're passing in null because passing arrays is problematic until https://github.com/mono/mono/issues/18245 is resolved.
|
||||||
invokeEntrypoint(assemblyName, null);
|
invokeEntrypoint(assemblyName, null);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net46</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net46</TargetFrameworks>
|
||||||
<TargetName>Microsoft.AspNetCore.Blazor.Build.Tasks</TargetName>
|
<TargetName>Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks</TargetName>
|
||||||
<AssemblyName>Microsoft.AspNetCore.Blazor.Build</AssemblyName>
|
<AssemblyName>Microsoft.AspNetCore.Components.WebAssembly.Build</AssemblyName>
|
||||||
<Description>Build mechanism for ASP.NET Core Blazor applications.</Description>
|
<Description>Build mechanism for ASP.NET Core Blazor WebAssembly applications.</Description>
|
||||||
<IsShippingPackage>true</IsShippingPackage>
|
<IsShippingPackage>true</IsShippingPackage>
|
||||||
<HasReferenceAssembly>false</HasReferenceAssembly>
|
<HasReferenceAssembly>false</HasReferenceAssembly>
|
||||||
<GenerateDependencyFile>false</GenerateDependencyFile>
|
<GenerateDependencyFile>false</GenerateDependencyFile>
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
<!-- Producing this package requires building with NodeJS enabled. -->
|
<!-- Producing this package requires building with NodeJS enabled. -->
|
||||||
<IsPackable Condition="'$(BuildNodeJS)' == 'false'">false</IsPackable>
|
<IsPackable Condition="'$(BuildNodeJS)' == 'false'">false</IsPackable>
|
||||||
<NoPackageAnalysis>true</NoPackageAnalysis>
|
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||||
<NuspecFile>Microsoft.AspNetCore.Blazor.Build.nuspec</NuspecFile>
|
<NuspecFile>Microsoft.AspNetCore.Components.WebAssembly.Build.nuspec</NuspecFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -26,6 +26,10 @@
|
||||||
<NuspecProperty Include="blazormonoversion=$(MicrosoftAspNetCoreBlazorMonoPackageVersion)" />
|
<NuspecProperty Include="blazormonoversion=$(MicrosoftAspNetCoreBlazorMonoPackageVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.WebAssembly.Build.Tests" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- Add a project dependency without reference output assemblies to enforce build order -->
|
<!-- 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 -->
|
<!-- 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.
|
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.
|
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>
|
</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 -->
|
<!-- 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
|
<!-- Ensures these projects are built before the consuming project, but without
|
||||||
adding a runtime dependency on the .dll (to be equivalent to a <PackageDependency>
|
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) -->
|
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>
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||||
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
|
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
|
||||||
<Properties>TargetFramework=$(DefaultNetCoreTargetFramework)</Properties>
|
<Properties>TargetFramework=$(DefaultNetCoreTargetFramework)</Properties>
|
||||||
</ProjectReference>
|
</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>
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||||
<!-- Optimization. Do not require framework compatibility between these projects. -->
|
<!-- Optimization. Do not require framework compatibility between these projects. -->
|
||||||
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
|
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
|
||||||
|
|
@ -9,7 +9,7 @@ using System.Xml.Linq;
|
||||||
using Microsoft.Build.Framework;
|
using Microsoft.Build.Framework;
|
||||||
using Microsoft.Build.Utilities;
|
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
|
// Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/CreateRootDescriptorFile.cs
|
||||||
public class BlazorCreateRootDescriptorFile : Task
|
public class BlazorCreateRootDescriptorFile : Task
|
||||||
|
|
@ -8,7 +8,7 @@ using System.Text;
|
||||||
using Microsoft.Build.Framework;
|
using Microsoft.Build.Framework;
|
||||||
using Microsoft.Build.Utilities;
|
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
|
// Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/LinkTask.cs
|
||||||
public class BlazorILLink : ToolTask
|
public class BlazorILLink : ToolTask
|
||||||
|
|
@ -11,7 +11,7 @@ using Microsoft.Build.Framework;
|
||||||
using Microsoft.Build.Utilities;
|
using Microsoft.Build.Utilities;
|
||||||
using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary<string, string>;
|
using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary<string, string>;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class GenerateBlazorBootJson : Task
|
public class GenerateBlazorBootJson : Task
|
||||||
{
|
{
|
||||||
|
|
@ -6,7 +6,7 @@ using System.Xml.Linq;
|
||||||
using Microsoft.Build.Framework;
|
using Microsoft.Build.Framework;
|
||||||
using Microsoft.Build.Utilities;
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build.Tasks
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks
|
||||||
{
|
{
|
||||||
public class GenerateTypeGranularityLinkingConfig : Task
|
public class GenerateTypeGranularityLinkingConfig : Task
|
||||||
{
|
{
|
||||||
|
|
@ -12,7 +12,7 @@ using System.Reflection.PortableExecutable;
|
||||||
using Microsoft.Build.Framework;
|
using Microsoft.Build.Framework;
|
||||||
using Microsoft.Build.Utilities;
|
using Microsoft.Build.Utilities;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class ResolveBlazorRuntimeDependencies : Task
|
public class ResolveBlazorRuntimeDependencies : Task
|
||||||
{
|
{
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<BlazorToolsDir Condition="'$(BlazorToolsDir)' == ''">$(MSBuildThisFileDirectory)..\tools\</BlazorToolsDir>
|
<BlazorToolsDir Condition="'$(BlazorToolsDir)' == ''">$(MSBuildThisFileDirectory)..\tools\</BlazorToolsDir>
|
||||||
<_BlazorTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">netcoreapp</_BlazorTasksTFM>
|
<_BlazorTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">netcoreapp</_BlazorTasksTFM>
|
||||||
<_BlazorTasksTFM Condition=" '$(_BlazorTasksTFM)' == ''">netfx</_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 -->
|
<!-- The Blazor build code can only find your referenced assemblies if they are in the output directory -->
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
|
@ -5,7 +5,7 @@ using System.IO;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class BlazorCreateRootDescriptorFileTest
|
public class BlazorCreateRootDescriptorFileTest
|
||||||
{
|
{
|
||||||
|
|
@ -12,7 +12,7 @@ using System.Reflection.PortableExecutable;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
internal class Assert : Xunit.Assert
|
internal class Assert : Xunit.Assert
|
||||||
{
|
{
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class BuildIncrementalismTest
|
public class BuildIncrementalismTest
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class BuildIntegrationTest
|
public class BuildIntegrationTest
|
||||||
{
|
{
|
||||||
|
|
@ -7,7 +7,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
internal class FileThumbPrint : IEquatable<FileThumbPrint>
|
internal class FileThumbPrint : IEquatable<FileThumbPrint>
|
||||||
{
|
{
|
||||||
|
|
@ -12,7 +12,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.CommandLineUtils;
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
internal static class MSBuildProcessManager
|
internal static class MSBuildProcessManager
|
||||||
{
|
{
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// 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
|
internal class MSBuildResult
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +8,7 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
internal class ProjectDirectory : IDisposable
|
internal class ProjectDirectory : IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Blazor.Build
|
||||||
throw new InvalidOperationException("RepoRoot was not specified.");
|
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>()))
|
foreach (var project in new string[] { projectName, }.Concat(additionalProjects ?? Array.Empty<string>()))
|
||||||
{
|
{
|
||||||
var projectRoot = Path.Combine(testAppsRoot, project);
|
var projectRoot = Path.Combine(testAppsRoot, project);
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class ProjectDirectoryTest
|
public class ProjectDirectoryTest
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class PublishIntegrationTest
|
public class PublishIntegrationTest
|
||||||
{
|
{
|
||||||
|
|
@ -6,10 +6,10 @@ using System.Runtime.Serialization.Json;
|
||||||
using Microsoft.Build.Framework;
|
using Microsoft.Build.Framework;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using BootJsonData = Microsoft.AspNetCore.Blazor.Build.GenerateBlazorBootJson.BootJsonData;
|
using BootJsonData = Microsoft.AspNetCore.Components.WebAssembly.Build.GenerateBlazorBootJson.BootJsonData;
|
||||||
using ResourceType = Microsoft.AspNetCore.Blazor.Build.GenerateBlazorBootJson.ResourceType;
|
using ResourceType = Microsoft.AspNetCore.Components.WebAssembly.Build.GenerateBlazorBootJson.ResourceType;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class GenerateBlazorBootJsonTest
|
public class GenerateBlazorBootJsonTest
|
||||||
{
|
{
|
||||||
|
|
@ -22,20 +22,16 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.AspNetCore.Blazor.Build" />
|
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Blazor.Mono" />
|
<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.Framework" />
|
||||||
<Reference Include="Microsoft.Build.Utilities.Core" />
|
<Reference Include="Microsoft.Build.Utilities.Core" />
|
||||||
<Reference Include="Microsoft.CodeAnalysis.Razor" />
|
|
||||||
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
|
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\testassets\StandaloneApp\StandaloneApp.csproj" />
|
<ProjectReference Include="..\..\testassets\StandaloneApp\StandaloneApp.csproj" />
|
||||||
<Compile Include="$(SharedSourceRoot)test\SkipOnHelixAttribute.cs" />
|
<Compile Include="$(SharedSourceRoot)test\SkipOnHelixAttribute.cs" />
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)test\**\*.cs" LinkBase="Helpers" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -9,7 +9,7 @@ using System.Text;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Build
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||||
{
|
{
|
||||||
public class RuntimeDependenciesResolverTest
|
public class RuntimeDependenciesResolverTest
|
||||||
{
|
{
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RepoRoot Condition="'$(RepoRoot)' ==''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), global.json))\</RepoRoot>
|
<RepoRoot Condition="'$(RepoRoot)' ==''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), global.json))\</RepoRoot>
|
||||||
<ComponentsRoot>$(RepoRoot)src\Components\</ComponentsRoot>
|
<ComponentsRoot>$(RepoRoot)src\Components\</ComponentsRoot>
|
||||||
<BlazorBuildRoot>$(ComponentsRoot)Blazor\Build\src\</BlazorBuildRoot>
|
<BlazorBuildRoot>$(ComponentsRoot)WebAssembly\Build\src\</BlazorBuildRoot>
|
||||||
<ReferenceBlazorBuildFromSourceProps>$(BlazorBuildRoot)ReferenceBlazorBuildFromSource.props</ReferenceBlazorBuildFromSourceProps>
|
<ReferenceBlazorBuildFromSourceProps>$(BlazorBuildRoot)ReferenceBlazorBuildFromSource.props</ReferenceBlazorBuildFromSourceProps>
|
||||||
|
|
||||||
<!-- Workaround for https://github.com/aspnet/AspNetCore/issues/17308 -->
|
<!-- Workaround for https://github.com/aspnet/AspNetCore/issues/17308 -->
|
||||||
|
|
@ -4,8 +4,9 @@
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.CommandLineUtils;
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
using Microsoft.Extensions.Hosting;
|
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
|
internal class ServeCommand : CommandLineApplication
|
||||||
{
|
{
|
||||||
|
|
@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Blazor.DevServer.Commands
|
||||||
|
|
||||||
private int Execute()
|
private int Execute()
|
||||||
{
|
{
|
||||||
Server.Program.BuildWebHost(RemainingArguments.ToArray()).Run();
|
DevServerProgram.BuildWebHost(RemainingArguments.ToArray()).Run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,10 +4,10 @@
|
||||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<AssemblyName>blazor-devserver</AssemblyName>
|
<AssemblyName>blazor-devserver</AssemblyName>
|
||||||
<PackageId>Microsoft.AspNetCore.Blazor.DevServer</PackageId>
|
<PackageId>Microsoft.AspNetCore.Components.WebAssembly.DevServer</PackageId>
|
||||||
<IsShippingPackage>true</IsShippingPackage>
|
<IsShippingPackage>true</IsShippingPackage>
|
||||||
<HasReferenceAssembly>false</HasReferenceAssembly>
|
<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>
|
<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). -->
|
<!-- Set this to false because assemblies should not reference this assembly directly, (except for tests, of course). -->
|
||||||
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
|
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.AspNetCore.Blazor.Server" />
|
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
|
||||||
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
|
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);publish</GenerateNuspecDependsOn>
|
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);publish</GenerateNuspecDependsOn>
|
||||||
<NoPackageAnalysis>true</NoPackageAnalysis>
|
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||||
<NuspecFile>Microsoft.AspNetCore.Blazor.DevServer.nuspec</NuspecFile>
|
<NuspecFile>Microsoft.AspNetCore.Components.WebAssembly.DevServer.nuspec</NuspecFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// 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;
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.DevServer
|
namespace Microsoft.AspNetCore.Components.WebAssembly.DevServer
|
||||||
{
|
{
|
||||||
internal class Program
|
internal class Program
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Hosting;
|
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
|
// 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
|
// 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.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.DevServer.Server
|
namespace Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server
|
||||||
{
|
{
|
||||||
internal class Startup
|
internal class Startup
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Blazor.Server
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Server
|
||||||
{
|
{
|
||||||
internal class BlazorConfig
|
internal class BlazorConfig
|
||||||
{
|
{
|
||||||
|
|
@ -4,22 +4,22 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using Microsoft.AspNetCore.Blazor.Server;
|
using Microsoft.AspNetCore.Components.WebAssembly.Server;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Builder
|
namespace Microsoft.AspNetCore.Builder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public static class BlazorHostingApplicationBuilderExtensions
|
public static class ComponentsWebAssemblyHostingApplicationBuilderExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <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"/>.
|
/// specified by <typeparamref name="TClientApp"/>.
|
||||||
/// </summary>
|
/// </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>
|
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
||||||
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
||||||
public static IApplicationBuilder UseClientSideBlazorFiles<TClientApp>(this IApplicationBuilder app)
|
public static IApplicationBuilder UseClientSideBlazorFiles<TClientApp>(this IApplicationBuilder app)
|
||||||
|
|
@ -34,10 +34,10 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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"/>.
|
/// specified by <paramref name="clientAssemblyFilePath"/>.
|
||||||
/// </summary>
|
/// </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>
|
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
||||||
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
/// <returns>The <see cref="IApplicationBuilder"/>.</returns>
|
||||||
public static IApplicationBuilder UseClientSideBlazorFiles(this IApplicationBuilder app, string clientAssemblyFilePath)
|
public static IApplicationBuilder UseClientSideBlazorFiles(this IApplicationBuilder app, string clientAssemblyFilePath)
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Blazor.Server;
|
using Microsoft.AspNetCore.Components.WebAssembly.Server;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides extension methods for hosting client-side Blazor applications in ASP.NET Core.
|
/// Provides extension methods for hosting client-side Blazor applications in ASP.NET Core.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class BlazorHostingEndpointRouteBuilderExtensions
|
public static class ComponentsWebAssemblyHostingEndpointRouteBuilderExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a low-priority endpoint that will serve the the file specified by <paramref name="filePath"/> from the client-side
|
/// 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
|
namespace Microsoft.AspNetCore.Builder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides infrastructure for debugging Blazor applications.
|
/// Provides infrastructure for debugging Blazor WebAssembly applications.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class BlazorMonoDebugProxyAppBuilderExtensions
|
public static class WebAssemblyNetDebugProxyAppBuilderExtensions
|
||||||
{
|
{
|
||||||
private static JsonSerializerOptions JsonOptions = new JsonSerializerOptions
|
private static JsonSerializerOptions JsonOptions = new JsonSerializerOptions
|
||||||
{
|
{
|
||||||
|
|
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
private static string DefaultDebuggerHost = "http://localhost:9222";
|
private static string DefaultDebuggerHost = "http://localhost:9222";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds middleware for needed for debugging Blazor applications
|
/// Adds middleware for needed for debugging Blazor WebAssembly applications
|
||||||
/// inside Chromium dev tools.
|
/// inside Chromium dev tools.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void UseBlazorDebugging(this IApplicationBuilder app)
|
public static void UseBlazorDebugging(this IApplicationBuilder app)
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<InternalsVisibleTo Include="Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests" />
|
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.DataAnnotations.Validation.Tests" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue