Просмотр исходного кода

Merge remote-tracking branch 'origin/blazor-wasm' into prkrishn/merge-remaining-blazor-wasm

Pranav K 6 лет назад
Родитель
Сommit
ca16c7fd59
51 измененных файлов с 235 добавлено и 161 удалено
  1. 1 1
      eng/Build.props
  2. 0 15
      src/Components/Blazor/Templates/src/Directory.Build.props
  3. 0 17
      src/Components/Blazor/Templates/src/Directory.Build.targets
  4. 0 64
      src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj
  5. 0 16
      src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec
  6. 1 16
      src/Components/Components.sln
  7. 3 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/.gitignore
  8. 4 4
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in
  9. 2 3
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in
  10. 0 1
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Shared.csproj.in
  11. 41 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj
  12. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json
  13. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/icon.png
  14. 4 16
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json
  15. 1 1
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json
  16. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/BlazorWasm-CSharp.sln
  17. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor
  18. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/Counter.razor
  19. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor
  20. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/Index.razor
  21. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs
  22. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor
  23. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/NavMenu.razor
  24. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor
  25. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs
  26. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor
  27. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css
  28. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css.map
  29. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/FONT-LICENSE
  30. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/ICON-LICENSE
  31. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/README.md
  32. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css
  33. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot
  34. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf
  35. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.svg
  36. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf
  37. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff
  38. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/site.css
  39. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/index.html
  40. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/sample-data/weather.json
  41. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs
  42. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Program.cs
  43. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs
  44. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/WeatherForecast.cs
  45. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/Directory.Build.props
  46. 0 0
      src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/Directory.Build.targets
  47. 14 0
      src/ProjectTemplates/ProjectTemplates.sln
  48. 155 0
      src/ProjectTemplates/test/BlazorWasmTemplateTest.cs
  49. 5 5
      src/ProjectTemplates/test/Helpers/Project.cs
  50. 3 2
      src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs
  51. 1 0
      src/ProjectTemplates/test/ProjectTemplates.Tests.csproj

+ 1 - 1
eng/Build.props

@@ -35,7 +35,7 @@
                       $(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
                       $(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
                       $(RepoRoot)src\Components\Blazor\Build\testassets\**\*.*proj;
-                      $(RepoRoot)src\Components\Blazor\Templates\src\content\**\*.*proj;
+                      $(RepoRoot)src\ProjectTemplates\BlazorWasm.ProjectTemplates\content\**\*.csproj;
                       $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj;
                       $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj;
                       $(RepoRoot)src\ProjectTemplates\Web.Spa.ProjectTemplates\content\**\*.csproj;

+ 0 - 15
src/Components/Blazor/Templates/src/Directory.Build.props

@@ -1,15 +0,0 @@
-<Project>
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
-
-  <PropertyGroup>
-    <GenerateDocumentationFile>false</GenerateDocumentationFile>
-    <IncludeSymbols>false</IncludeSymbols>
-  </PropertyGroup>
-
-  <PropertyGroup Label="Package Versions">
-    <!-- Used only in development when running the template contents directly from source -->
-    <TemplateBlazorPackageVersion>0.8.0-preview-19064-0339</TemplateBlazorPackageVersion>
-    <TemplateComponentsPackageVersion>3.0.0-preview-19064-0339</TemplateComponentsPackageVersion>
-  </PropertyGroup>
-
-</Project>

+ 0 - 17
src/Components/Blazor/Templates/src/Directory.Build.targets

@@ -1,17 +0,0 @@
-<Project>
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.targets))\Directory.Build.targets" />
-
-  <Target Name="SetTemplateJsonSymbolReplacements">
-    <PropertyGroup>
-      <!--
-        Properties here will be injected into the template config *.json files
-        during the build, replacing tokens of the form ${PropertyName}
-      -->
-      <GeneratedContentProperties>
-        TemplateBlazorVersion=$(PackageVersion);
-        TemplateComponentsVersion=$(ComponentsPackageVersion);
-        RepositoryCommit=$(SourceRevisionId);
-      </GeneratedContentProperties>
-    </PropertyGroup>
-  </Target>
-</Project>

+ 0 - 64
src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.csproj

@@ -1,64 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-  <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
-    <NuspecFile>Microsoft.AspNetCore.Blazor.Templates.nuspec</NuspecFile>
-    <IsShippingPackage>true</IsShippingPackage>
-    <EnableDefaultItems>False</EnableDefaultItems>
-    <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
-    <IncludeBuildOutput>False</IncludeBuildOutput>
-    <CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory>
-    <DebugType>none</DebugType>
-    <GenerateDocumentationFile>false</GenerateDocumentationFile>
-    <NoWarn>$(NoWarn);2008</NoWarn>
-    <Description>Templates for ASP.NET Core Blazor projects.</Description>
-    <PackageTags>aspnet;templates;blazor;spa</PackageTags>
-    <IsProjectReferenceProvider>false</IsProjectReferenceProvider>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <UpToDateCheckInput Include="content\**\.template.config.src\**\*.*" />
-  </ItemGroup>
-
-  <Target Name="PrepareFileLists" AfterTargets="PrepareForBuild">
-    <ItemGroup>
-      <_TemplateConfigMainFile Include="content\**\.template.config.src\template.json" />
-      <_TemplateConfigDir Include="@(_TemplateConfigMainFile->'$([System.IO.Path]::GetDirectoryName('%(_TemplateConfigMainFile.FullPath)'))')" />
-      <_TemplateConfigFileToCopy Include="%(_TemplateConfigDir.Identity)\**\*.*">
-        <DestDir>$([System.IO.Path]::GetDirectoryName('%(_TemplateConfigDir.Identity)'))\.template.config\</DestDir>
-      </_TemplateConfigFileToCopy>
-    </ItemGroup>
-  </Target>
-
-  <Target
-    Name="TransformTemplateConfigs"
-    BeforeTargets="CoreBuild"
-    DependsOnTargets="SetTemplateJsonSymbolReplacements"
-    Inputs="@(_TemplateConfigFileToCopy)"
-    Outputs="@(_TemplateConfigFileToCopy->'%(DestDir)%(FileName)%(Extension)')">
-
-    <!--
-      For each template, copy its '.template.config.src' directory to '.template.config',
-      removing any earlier output at that location
-    -->
-    <RemoveDir Directories="%(_TemplateConfigFileToCopy.DestDir)" />
-    <Copy SourceFiles="%(_TemplateConfigFileToCopy.Identity)" DestinationFolder="%(_TemplateConfigFileToCopy.DestDir)" />
-
-    <!--
-      Modify the .json files in the .template.config dirs to stamp MSBuild properties into them
-    -->
-    <ItemGroup>
-      <GeneratedContent Include="@(_TemplateConfigFileToCopy->WithMetadataValue('Extension','.json'))">
-        <OutputPath>%(DestDir)%(RecursiveDir)%(Filename)%(Extension)</OutputPath>
-        <Properties>$(GeneratedContentProperties)</Properties>
-      </GeneratedContent>
-    </ItemGroup>
-    <GenerateFileFromTemplate
-      TemplateFile="%(GeneratedContent.Identity)"
-      Properties="%(GeneratedContent.Properties)"
-      OutputPath="%(GeneratedContent.OutputPath)">
-
-      <Output TaskParameter="OutputPath" ItemName="FileWrites" />
-      <Output TaskParameter="OutputPath" ItemName="Content" />
-    </GenerateFileFromTemplate>
-  </Target>
-</Project>

+ 0 - 16
src/Components/Blazor/Templates/src/Microsoft.AspNetCore.Blazor.Templates.nuspec

@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
-  <metadata>
-    $CommonMetadataElements$
-    <packageTypes>
-      <packageType name="Template" />
-    </packageTypes>
-  </metadata>
-  <files>
-    $CommonFileElements$
-    <file
-      src="content/**"
-      exclude="**/bin/**;**/obj/**;**/.template.config.src/**;content/Directory.Build.props;content/Directory.Build.targets;"
-      target="Content" />
-  </files>
-</package>

+ 1 - 16
src/Components/Components.sln

@@ -25,8 +25,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Server", "Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj", "{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}"
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Templates", "Blazor\Templates\src\Microsoft.AspNetCore.Blazor.Templates.csproj", "{66036B70-6C93-4E45-A1A1-819F15CA757A}"
-EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{A7ABAC29-F73F-456D-AE54-46842CFC2E10}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "Blazor\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{FD37F740-A654-4117-BFB6-9112CE4C1D3B}"
@@ -248,7 +246,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -368,18 +366,6 @@ Global
 		{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x64.Build.0 = Release|Any CPU
 		{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x86.ActiveCfg = Release|Any CPU
 		{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}.Release|x86.Build.0 = Release|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|x64.Build.0 = Debug|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Debug|x86.Build.0 = Debug|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|Any CPU.Build.0 = Release|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|x64.ActiveCfg = Release|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|x64.Build.0 = Release|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|x86.ActiveCfg = Release|Any CPU
-		{66036B70-6C93-4E45-A1A1-819F15CA757A}.Release|x86.Build.0 = Release|Any CPU
 		{FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{FD37F740-A654-4117-BFB6-9112CE4C1D3B}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -1546,7 +1532,6 @@ Global
 		{A6C8050D-7C18-4585-ADCF-833AC1765847} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
 		{08773DD6-6FED-4BF2-BD9F-C19D2CF919BB} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
 		{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
-		{66036B70-6C93-4E45-A1A1-819F15CA757A} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
 		{A7ABAC29-F73F-456D-AE54-46842CFC2E10} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
 		{FD37F740-A654-4117-BFB6-9112CE4C1D3B} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
 		{C1E2C117-BE47-4E29-94B3-753262D97A5C} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}

+ 3 - 0
src/ProjectTemplates/BlazorWasm.ProjectTemplates/.gitignore

@@ -0,0 +1,3 @@
+# This file is generated by the build
+content/*/*.*proj
+content/*/*/*.*proj

+ 4 - 4
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj → src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Client.csproj.in

@@ -6,10 +6,10 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.Blazor" Version="$(TemplateBlazorPackageVersion)" />
-    <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="$(TemplateBlazorPackageVersion)" PrivateAssets="all" />
-    <PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="$(TemplateBlazorPackageVersion)" />
-    <PackageReference Include="Microsoft.AspNetCore.Blazor.DevServer" Version="$(TemplateBlazorPackageVersion)" PrivateAssets="all" />
+    <PackageReference Include="Microsoft.AspNetCore.Blazor" Version="${MicrosoftAspNetCoreBlazorPackageVersion}" />
+    <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="${MicrosoftAspNetCoreBlazorBuildPackageVersion}" PrivateAssets="all" />
+    <PackageReference Include="Microsoft.AspNetCore.Blazor.DevServer" Version="${MicrosoftAspNetCoreBlazorDevServerPackageVersion}" PrivateAssets="all" />
+    <PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="${MicrosoftAspNetCoreBlazorHttpClientPackageVersion}" />
   </ItemGroup>
   <!--#if Hosted -->
   <ItemGroup>

+ 2 - 3
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/BlazorWasm-CSharp.Server.csproj → src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Server.csproj.in

@@ -1,12 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
   <PropertyGroup>
-    <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
-    <LangVersion>7.3</LangVersion>
+    <TargetFramework>${DefaultNetCoreTargetFramework}</TargetFramework>
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.Blazor.Server" Version="$(TemplateBlazorPackageVersion)" />
+    <PackageReference Include="Microsoft.AspNetCore.Blazor.Server" Version="${MicrosoftAspNetCoreBlazorServerPackageVersion}" />
   </ItemGroup>
 
   <ItemGroup>

+ 0 - 1
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj → src/ProjectTemplates/BlazorWasm.ProjectTemplates/BlazorWasm-CSharp.Shared.csproj.in

@@ -2,7 +2,6 @@
 
   <PropertyGroup>
     <TargetFramework>netstandard2.1</TargetFramework>
-    <LangVersion>7.3</LangVersion>
   </PropertyGroup>
 
 </Project>

+ 41 - 0
src/ProjectTemplates/BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj

@@ -0,0 +1,41 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
+    <IsShippingPackage>true</IsShippingPackage>
+    <Description>Templates for ASP.NET Core Blazor projects.</Description>
+    <PackageTags>$(PackageTags);blazor;spa</PackageTags>
+  </PropertyGroup>
+
+  <PropertyGroup>
+    <!-- Lists the versions of dependencies not built in this repo. Packages produced from this repo should be listed as a PackageVersionVariableReference.  -->
+    <GeneratedContentProperties>
+      DefaultNetCoreTargetFramework=$(DefaultNetCoreTargetFramework);
+      MicrosoftAspNetCoreBlazorPackageVersion=$(MicrosoftAspNetCoreBlazorPackageVersion);
+      MicrosoftAspNetCoreBlazorBuildPackageVersion=$(MicrosoftAspNetCoreBlazorBuildPackageVersion);
+      MicrosoftAspNetCoreBlazorDevServerPackageVersion=$(MicrosoftAspNetCoreBlazorDevServerPackageVersion);
+      MicrosoftAspNetCoreBlazorHttpClientPackageVersion=$(MicrosoftAspNetCoreBlazorHttpClientPackageVersion);
+      MonoWebAssemblyInteropPackageVersion=$(MonoWebAssemblyInteropPackageVersion);
+      MicrosoftEntityFrameworkCoreSqlServerPackageVersion=$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion);
+      MicrosoftAspNetCoreBlazorServerPackageVersion=$(MicrosoftAspNetCoreBlazorServerPackageVersion);
+    </GeneratedContentProperties>
+
+    <BlazorProjectsRoot>$(RepoRoot)src\Components\Blazor\</BlazorProjectsRoot>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <!-- These projects product packages that the templates depend on. See GenerateContent.targets -->
+    <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Blazor\src\Microsoft.AspNetCore.Blazor.csproj" />
+    <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Build\src\Microsoft.AspNetCore.Blazor.Build.csproj" />
+    <PackageVersionVariableReference Include="$(BlazorProjectsRoot)DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj" />
+    <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj" />
+    <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj" />
+    <PackageVersionVariableReference Include="$(BlazorProjectsRoot)Server\src\Microsoft.AspNetCore.Blazor.Server.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <GeneratedContent Include="BlazorWasm-CSharp.Client.csproj.in" OutputPath="content/BlazorWasm-CSharp/Client/BlazorWasm-CSharp.Client.csproj" />
+    <GeneratedContent Include="BlazorWasm-CSharp.Shared.csproj.in" OutputPath="content/BlazorWasm-CSharp/Shared/BlazorWasm-CSharp.Shared.csproj" />
+    <GeneratedContent Include="BlazorWasm-CSharp.Server.csproj.in" OutputPath="content/BlazorWasm-CSharp/Server/BlazorWasm-CSharp.Server.csproj" />
+  </ItemGroup>
+
+</Project>

+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/dotnetcli.host.json → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/dotnetcli.host.json


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/icon.png → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/icon.png


+ 4 - 16
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/template.json → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/template.json

@@ -1,13 +1,16 @@
 {
+  "$schema": "http://json.schemastore.org/template",
   "author": "Microsoft",
   "classifications": [
     "Web",
     "Blazor",
     "WebAssembly"
   ],
+  "name": "Blazor WebAssembly App",
   "defaultName": "WebApplication",
   "description": "A project template for creating a Blazor app that runs on WebAssembly and is optionally hosted by an ASP.NET Core app. This template can be used for web apps with rich dynamic user interfaces (UIs).",
   "groupIdentity": "Microsoft.Web.Blazor.Wasm",
+  "precedence": "6001",
   "guids": [
     "4C26868E-5E7C-458D-82E3-040509D0C71F",
     "5990939C-7E7B-4CFA-86FF-44CA5756498A",
@@ -15,7 +18,6 @@
     "0AFFA7FD-4E37-4636-AB91-3753E746DB98"
   ],
   "identity": "Microsoft.Web.Blazor.Wasm.CSharp",
-  "name": "Blazor WebAssembly App",
   "preferNameDirectory": true,
   "primaryOutputs": [
     {
@@ -94,20 +96,6 @@
       "type": "bind",
       "binding": "HostIdentifier"
     },
-    "TemplateBlazorVersionSymbol": {
-      "type": "parameter",
-      "datatype": "string",
-      "description": "Specifies which version of Blazor packages to use.",
-      "replaces": "$(TemplateBlazorPackageVersion)",
-      "defaultValue": "${TemplateBlazorVersion}"
-    },
-    "TemplateComponentsVersionSymbol": {
-      "type": "parameter",
-      "datatype": "string",
-      "description": "Specifies which version of Components packages to use.",
-      "replaces": "$(TemplateComponentsPackageVersion)",
-      "defaultValue": "${TemplateComponentsVersion}"
-    },
     "skipRestore": {
       "type": "parameter",
       "datatype": "bool",
@@ -146,7 +134,7 @@
         }
       ],
       "args": {
-        "files": [ "BlazorWasm-CSharp.Client.csproj" ]
+        "files": ["BlazorWasm-CSharp.Client.csproj"]
       },
       "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025",
       "continueOnError": true

+ 1 - 1
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/.template.config.src/vs-2017.3.host.json → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/.template.config/vs-2017.3.host.json

@@ -11,7 +11,7 @@
   },
   "order": 610,
   "icon": "icon.png",
-  "learnMoreLink": "https://github.com/aspnet/blazor",
+  "learnMoreLink": "https://github.com/aspnet/AspNetCore",
   "uiFilters": [
     "oneaspnet"
   ],

+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/BlazorWasm-CSharp.sln → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/BlazorWasm-CSharp.sln


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/App.razor


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/Counter.razor → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/Counter.razor


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/FetchData.razor


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/Index.razor → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Pages/Index.razor


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Program.cs → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Program.cs


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/MainLayout.razor


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/NavMenu.razor → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/NavMenu.razor


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Startup.cs → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/Startup.cs


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/_Imports.razor → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/_Imports.razor


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css.map → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/bootstrap/bootstrap.min.css.map


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/FONT-LICENSE → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/FONT-LICENSE


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/ICON-LICENSE → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/ICON-LICENSE


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/README.md → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/README.md


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.svg → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.svg


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/css/site.css → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/css/site.css


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/index.html → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/index.html


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/wwwroot/sample-data/weather.json → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/sample-data/weather.json


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Controllers/WeatherForecastController.cs


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Program.cs → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Program.cs


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Server/Startup.cs → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Server/Startup.cs


+ 0 - 0
src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Shared/WeatherForecast.cs → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Shared/WeatherForecast.cs


+ 0 - 0
src/Components/Blazor/Templates/src/content/Directory.Build.props → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/Directory.Build.props


+ 0 - 0
src/Components/Blazor/Templates/src/content/Directory.Build.targets → src/ProjectTemplates/BlazorWasm.ProjectTemplates/content/Directory.Build.targets


+ 14 - 0
src/ProjectTemplates/ProjectTemplates.sln

@@ -177,6 +177,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ApiAut
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SpaServices.Extensions", "..\Middleware\SpaServices.Extensions\src\Microsoft.AspNetCore.SpaServices.Extensions.csproj", "{06D0D7B2-EDA3-45A2-A060-AB791ED1DB80}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Blazor.Templates", "BlazorWasm.ProjectTemplates\Microsoft.AspNetCore.Blazor.Templates.csproj", "{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -1231,6 +1233,18 @@ Global
 		{06D0D7B2-EDA3-45A2-A060-AB791ED1DB80}.Release|x64.Build.0 = Release|Any CPU
 		{06D0D7B2-EDA3-45A2-A060-AB791ED1DB80}.Release|x86.ActiveCfg = Release|Any CPU
 		{06D0D7B2-EDA3-45A2-A060-AB791ED1DB80}.Release|x86.Build.0 = Release|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|x64.Build.0 = Debug|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Debug|x86.Build.0 = Debug|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|x64.ActiveCfg = Release|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|x64.Build.0 = Release|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|x86.ActiveCfg = Release|Any CPU
+		{C6D371A8-D8EA-4CF4-844E-8C6DFDF61642}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 155 - 0
src/ProjectTemplates/test/BlazorWasmTemplateTest.cs

@@ -0,0 +1,155 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.IO;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.E2ETesting;
+using Microsoft.AspNetCore.Testing;
+using OpenQA.Selenium;
+using Templates.Test.Helpers;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Templates.Test
+{
+    public class BlazorWasmTemplateTest : BrowserTestBase
+    {
+        public BlazorWasmTemplateTest(ProjectFactoryFixture projectFactory, BrowserFixture browserFixture, ITestOutputHelper output)
+            : base(browserFixture, output)
+        {
+            ProjectFactory = projectFactory;
+        }
+
+        public ProjectFactoryFixture ProjectFactory { get; set; }
+
+        [Fact]
+        public async Task BlazorWasmStandaloneTemplate_Works()
+        {
+            var project = await ProjectFactory.GetOrCreateProject("blazorstandalone", Output);
+
+            var createResult = await project.RunDotNetNewAsync("blazorwasm");
+            Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
+
+            // We can't run a published standalone app, but let's just make sure it publishes fine
+            var publishResult = await project.RunDotNetPublishAsync();
+            Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", project, publishResult));
+
+            var buildResult = await project.RunDotNetBuildAsync();
+            Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", project, buildResult));
+
+            await BuildAndRunTest(project.ProjectName, project);
+        }
+
+        [Fact]
+        public async Task BlazorWasmHostedTemplate_Works()
+        {
+            var project = await ProjectFactory.GetOrCreateProject("blazorhosted", Output);
+
+            var createResult = await project.RunDotNetNewAsync("blazorwasm", args: new[] { "--hosted" });
+            Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
+
+            var serverProject = GetSubProject(project, "Server", $"{project.ProjectName}.Server");
+
+            var publishResult = await serverProject.RunDotNetPublishAsync();
+            Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", serverProject, publishResult));
+
+            var buildResult = await serverProject.RunDotNetBuildAsync();
+            Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", serverProject, buildResult));
+
+            await BuildAndRunTest(project.ProjectName, serverProject);
+
+            using var aspNetProcess = serverProject.StartPublishedProjectAsync();
+
+            Assert.False(
+                aspNetProcess.Process.HasExited,
+                ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", serverProject, aspNetProcess.Process));
+
+            await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html");
+            if (BrowserFixture.IsHostAutomationSupported())
+            {
+                aspNetProcess.VisitInBrowser(Browser);
+                TestBasicNavigation(project.ProjectName, serverProject);
+            }
+            else
+            {
+                BrowserFixture.EnforceSupportedConfigurations();
+            }
+        }
+
+        protected async Task BuildAndRunTest(string appName, Project project)
+        {
+            using var aspNetProcess = project.StartBuiltProjectAsync();
+
+            Assert.False(
+                aspNetProcess.Process.HasExited,
+                ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
+
+            await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html");
+            if (BrowserFixture.IsHostAutomationSupported())
+            {
+                aspNetProcess.VisitInBrowser(Browser);
+                TestBasicNavigation(appName, project);
+            }
+            else
+            {
+                BrowserFixture.EnforceSupportedConfigurations();
+            }
+        }
+
+        private void TestBasicNavigation(string appName, Project project)
+        {
+            // Give components.server enough time to load so that it can replace
+            // the prerendered content before we start making assertions.
+            Thread.Sleep(5000);
+            Browser.Exists(By.TagName("ul"));
+
+            // <title> element gets project ID injected into it during template execution
+            Browser.Equal(appName.Trim(), () => Browser.Title.Trim());
+
+            // Initially displays the home page
+            Browser.Equal("Hello, world!", () => Browser.FindElement(By.TagName("h1")).Text);
+
+            // Can navigate to the counter page
+            Browser.FindElement(By.PartialLinkText("Counter")).Click();
+            Browser.Contains("counter", () => Browser.Url);
+            Browser.Equal("Counter", () => Browser.FindElement(By.TagName("h1")).Text);
+
+            // Clicking the counter button works
+            Browser.Equal("Current count: 0", () => Browser.FindElement(By.CssSelector("h1 + p")).Text);
+            Browser.FindElement(By.CssSelector("p+button")).Click();
+            Browser.Equal("Current count: 1", () => Browser.FindElement(By.CssSelector("h1 + p")).Text);
+
+            // Can navigate to the 'fetch data' page
+            Browser.FindElement(By.PartialLinkText("Fetch data")).Click();
+            Browser.Contains("fetchdata", () => Browser.Url);
+            Browser.Equal("Weather forecast", () => Browser.FindElement(By.TagName("h1")).Text);
+
+            // Asynchronously loads and displays the table of weather forecasts
+            Browser.Exists(By.CssSelector("table>tbody>tr"));
+            Browser.Equal(5, () => Browser.FindElements(By.CssSelector("p+table>tbody>tr")).Count);
+        }
+
+        private Project GetSubProject(Project project, string projectDirectory, string projectName)
+        {
+            var subProjectDirectory = Path.Combine(project.TemplateOutputDir, projectDirectory);
+            if (!Directory.Exists(subProjectDirectory))
+            {
+                throw new DirectoryNotFoundException($"Directory {subProjectDirectory} was not found.");
+            }
+
+            var subProject = new Project
+            {
+                DotNetNewLock = project.DotNetNewLock,
+                NodeLock = project.NodeLock,
+                Output = project.Output,
+                DiagnosticsMessageSink = project.DiagnosticsMessageSink,
+                ProjectName = projectName,
+                TemplateOutputDir = subProjectDirectory,
+            };
+
+            return subProject;
+        }
+    }
+}

+ 5 - 5
src/ProjectTemplates/test/Helpers/Project.cs

@@ -110,7 +110,7 @@ namespace Templates.Test.Helpers
             }
         }
 
-        internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null)
+        internal async Task<ProcessEx> RunDotNetPublishAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null, string additionalArgs = null)
         {
             Output.WriteLine("Publishing ASP.NET application...");
 
@@ -121,7 +121,7 @@ namespace Templates.Test.Helpers
             await effectiveLock.WaitAsync();
             try
             {
-                var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"publish -c Release /bl", packageOptions);
+                var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"publish -c Release /bl /nr:false {additionalArgs}", packageOptions);
                 await result.Exited;
                 CaptureBinLogOnFailure(result);
                 return result;
@@ -132,7 +132,7 @@ namespace Templates.Test.Helpers
             }
         }
 
-        internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null)
+        internal async Task<ProcessEx> RunDotNetBuildAsync(bool takeNodeLock = false, IDictionary<string,string> packageOptions = null, string additionalArgs = null)
         {
             Output.WriteLine("Building ASP.NET application...");
 
@@ -143,7 +143,7 @@ namespace Templates.Test.Helpers
             await effectiveLock.WaitAsync();
             try
             {
-                var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), "build -c Debug /bl", packageOptions);
+                var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"build -c Debug /bl /nr:false {additionalArgs}", packageOptions);
                 await result.Exited;
                 CaptureBinLogOnFailure(result);
                 return result;
@@ -211,7 +211,7 @@ namespace Templates.Test.Helpers
             };
 
             var projectDll = Path.Combine(TemplateBuildDir, $"{ProjectName}.dll");
-            return new AspNetProcess(Output, TemplateOutputDir, projectDll, environment, hasListeningUri: hasListeningUri);
+            return new AspNetProcess(Output, TemplateOutputDir, projectDll, environment, published: false, hasListeningUri: hasListeningUri);
         }
 
         internal AspNetProcess StartPublishedProjectAsync(bool hasListeningUri = true)

+ 3 - 2
src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs

@@ -38,7 +38,8 @@ namespace Templates.Test.Helpers
             "Microsoft.DotNet.Web.Spa.ProjectTemplates.3.0",
             "Microsoft.DotNet.Web.Spa.ProjectTemplates.3.1",
             "Microsoft.DotNet.Web.Spa.ProjectTemplates.5.0",
-            "Microsoft.DotNet.Web.Spa.ProjectTemplates"
+            "Microsoft.DotNet.Web.Spa.ProjectTemplates",
+            "Microsoft.AspNetCore.Blazor.Templates",
         };
 
         public static string CustomHivePath { get; } = typeof(TemplatePackageInstaller)
@@ -88,7 +89,7 @@ namespace Templates.Test.Helpers
                 .Where(p => _templatePackages.Any(t => Path.GetFileName(p).StartsWith(t, StringComparison.OrdinalIgnoreCase)))
                 .ToArray();
 
-            Assert.Equal(4, builtPackages.Length);
+            Assert.Equal(5, builtPackages.Length);
 
             /*
              * The templates are indexed by path, for example:

+ 1 - 0
src/ProjectTemplates/test/ProjectTemplates.Tests.csproj

@@ -46,6 +46,7 @@
     <ProjectReference Include="../Web.ItemTemplates/Microsoft.DotNet.Web.ItemTemplates.csproj" ReferenceOutputAssembly="false" />
     <ProjectReference Include="../Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj" ReferenceOutputAssembly="false" />
     <ProjectReference Include="../Web.Spa.ProjectTemplates/Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj" ReferenceOutputAssembly="false" />
+    <ProjectReference Include="../BlazorWasm.ProjectTemplates/Microsoft.AspNetCore.Blazor.Templates.csproj" ReferenceOutputAssembly="false" />
   </ItemGroup>
 
   <ItemGroup>