diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/App.razor b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/App.razor
new file mode 100644
index 000000000000..28a0c6092098
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/App.razor
@@ -0,0 +1 @@
+
@typeof(BlazorMultipleApps.FirstClient.Program)
\ No newline at end of file
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/BlazorMultipleApps.FirstClient.csproj b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/BlazorMultipleApps.FirstClient.csproj
new file mode 100644
index 000000000000..e3d84a7d4ac3
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/BlazorMultipleApps.FirstClient.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net5.0
+ FirstApp
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_BlazorBrotliCompressionLevel>NoCompression
+
+
+
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/Program.cs b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/Program.cs
new file mode 100644
index 000000000000..11cc7c57ce6d
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/Program.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.Text;
+
+namespace BlazorMultipleApps.FirstClient
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ GC.KeepAlive(typeof(Newtonsoft.Json.JsonConvert));
+ }
+ }
+}
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/wwwroot/css/app.css b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/wwwroot/css/app.css
new file mode 100644
index 000000000000..4855bd609d2d
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/wwwroot/css/app.css
@@ -0,0 +1 @@
+/* First app.css */
\ No newline at end of file
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/wwwroot/index.html b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/wwwroot/index.html
new file mode 100644
index 000000000000..1f450f51fb8a
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.FirstClient/wwwroot/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ BlazorMultipleApps
+
+
+
+
+
+
+
+
+
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/App.razor b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/App.razor
new file mode 100644
index 000000000000..28e849ebde1f
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/App.razor
@@ -0,0 +1 @@
+@typeof(BlazorMultipleApps.SecondClient.Program)
\ No newline at end of file
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/BlazorMultipleApps.SecondClient.csproj b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/BlazorMultipleApps.SecondClient.csproj
new file mode 100644
index 000000000000..30356758d74d
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/BlazorMultipleApps.SecondClient.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net5.0
+ SecondApp
+
+
+
+
+
+
+
+
+
+
+
+
+ <_BlazorBrotliCompressionLevel>NoCompression
+
+
+
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/Program.cs b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/Program.cs
new file mode 100644
index 000000000000..c910511317b0
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/Program.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+
+namespace BlazorMultipleApps.SecondClient
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ }
+ }
+}
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/wwwroot/css/app.css b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/wwwroot/css/app.css
new file mode 100644
index 000000000000..d7cff8ab9dee
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/wwwroot/css/app.css
@@ -0,0 +1 @@
+/* Second app.css */
\ No newline at end of file
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/wwwroot/index.html b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/wwwroot/index.html
new file mode 100644
index 000000000000..bd7f2bbf7754
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.SecondClient/wwwroot/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ SecondBlazorApp
+
+
+
+
+
+
+
+
+
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj
new file mode 100644
index 000000000000..2f62b1cad702
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net5.0
+
+
+
+
+
+
+
+
+
+
+ <_BlazorBrotliCompressionLevel>NoCompression
+
+
+
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Server/Program.cs b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Server/Program.cs
new file mode 100644
index 000000000000..c571651ff9d6
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Server/Program.cs
@@ -0,0 +1,10 @@
+namespace BlazorMultipleApps.Server
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+
+ }
+ }
+}
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Shared/BlazorMultipleApps.Shared.csproj b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Shared/BlazorMultipleApps.Shared.csproj
new file mode 100644
index 000000000000..d4c395e8cb78
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Shared/BlazorMultipleApps.Shared.csproj
@@ -0,0 +1,7 @@
+
+
+
+ netstandard2.1
+
+
+
diff --git a/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Shared/WeatherForecast.cs b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Shared/WeatherForecast.cs
new file mode 100644
index 000000000000..7c92131eaea7
--- /dev/null
+++ b/src/Assets/TestProjects/BlazorMultiApp/BlazorMultipleApps.Shared/WeatherForecast.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BlazorMultipleApps.Shared
+{
+ public class WeatherForecast
+ {
+ public DateTime Date { get; set; }
+
+ public int TemperatureC { get; set; }
+
+ public string Summary { get; set; }
+
+ public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+ }
+}
diff --git a/src/BlazorWasmSdk/Sdk/Sdk.targets b/src/BlazorWasmSdk/Sdk/Sdk.targets
index 616c56fb8a0b..4dbd28518446 100644
--- a/src/BlazorWasmSdk/Sdk/Sdk.targets
+++ b/src/BlazorWasmSdk/Sdk/Sdk.targets
@@ -15,6 +15,10 @@ Copyright (c) .NET Foundation. All rights reserved.
<_BlazorWebAssemblyTargetsFile Condition="'$(_BlazorWebAssemblyTargetsFile)' == ''">$(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets
+
+
+
+
diff --git a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets
index 61cdadedf909..632d6a5b86ed 100644
--- a/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets
+++ b/src/BlazorWasmSdk/Targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets
@@ -515,7 +515,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<_BlazorPublishBootResource
Include="@(ResolvedFileToPublish)"
- Condition="$([System.String]::Copy('%(RelativePath)').Replace('\','/').StartsWith('wwwroot/_framework')) AND '%(Extension)' != '.a'" />
+ Condition="$([System.String]::Copy('%(RelativePath)').Replace('\','/').StartsWith($(_BlazorFrameworkPublishPath.Replace('\', '/')))) AND '%(Extension)' != '.a'" />
diff --git a/src/RazorSdk/Sdk/Sdk.targets b/src/RazorSdk/Sdk/Sdk.targets
index 13a27ba07073..70a55ee2b33a 100644
--- a/src/RazorSdk/Sdk/Sdk.targets
+++ b/src/RazorSdk/Sdk/Sdk.targets
@@ -14,7 +14,7 @@ Copyright (c) .NET Foundation. All rights reserved.
- $(MSBuildThisFileDirectory)..\build\netstandard2.0\Sdk.Razor.CurrentVersion.targets
+ $(MSBuildThisFileDirectory)..\build\netstandard2.0\Sdk.Razor.CurrentVersion.targets
diff --git a/src/RazorSdk/Tasks/Microsoft.NET.Sdk.Razor.Tasks.csproj b/src/RazorSdk/Tasks/Microsoft.NET.Sdk.Razor.Tasks.csproj
index c719e3ff6199..3b2e5e81da50 100644
--- a/src/RazorSdk/Tasks/Microsoft.NET.Sdk.Razor.Tasks.csproj
+++ b/src/RazorSdk/Tasks/Microsoft.NET.Sdk.Razor.Tasks.csproj
@@ -71,6 +71,9 @@
+
+ Shared\CommandLine\%(FileName)
+
Shared\ServerProtocol\%(FileName)
diff --git a/src/RazorSdk/Tool/Application.cs b/src/RazorSdk/Tool/Application.cs
index f370d824edce..a3c02226f1e2 100644
--- a/src/RazorSdk/Tool/Application.cs
+++ b/src/RazorSdk/Tool/Application.cs
@@ -88,7 +88,7 @@ public Application(
private string GetInformationalVersion()
{
- var assembly = typeof(Application).GetTypeInfo().Assembly;
+ var assembly = typeof(Application).Assembly;
var attribute = assembly.GetCustomAttribute();
return attribute.InformationalVersion;
}
diff --git a/src/RazorSdk/Tool/ArgumentEscaper.cs b/src/RazorSdk/Tool/CommandLine/ArgumentEscaper.cs
similarity index 98%
rename from src/RazorSdk/Tool/ArgumentEscaper.cs
rename to src/RazorSdk/Tool/CommandLine/ArgumentEscaper.cs
index aa61e6a16298..22f817752934 100644
--- a/src/RazorSdk/Tool/ArgumentEscaper.cs
+++ b/src/RazorSdk/Tool/CommandLine/ArgumentEscaper.cs
@@ -5,7 +5,7 @@
using System.Linq;
using System.Text;
-namespace Microsoft.NET.Sdk.Razor.Tool
+namespace Microsoft.NET.Sdk.Razor.Tool.CommandLineUtils
{
///
/// A utility for escaping arguments for new processes.
diff --git a/src/RazorSdk/Tool/ServerProtocol/ServerConnection.cs b/src/RazorSdk/Tool/ServerProtocol/ServerConnection.cs
index 51754942118e..a4fbc2f617d4 100644
--- a/src/RazorSdk/Tool/ServerProtocol/ServerConnection.cs
+++ b/src/RazorSdk/Tool/ServerProtocol/ServerConnection.cs
@@ -9,6 +9,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.NET.Sdk.Razor.Tool.CommandLineUtils;
namespace Microsoft.NET.Sdk.Razor.Tool
{
@@ -296,8 +297,7 @@ internal static bool TryCreateServerCore(string clientDir, string pipeName, out
"-p",
pipeName
};
- // var processArguments = ArgumentEscaper.EscapeAndConcatenate(argumentList);
- var processArguments = argumentList.ToString();
+ var processArguments = ArgumentEscaper.EscapeAndConcatenate(argumentList);
if (!File.Exists(expectedCompilerPath))
{
diff --git a/src/Tests/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/WasmPublishTest.cs b/src/Tests/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/WasmPublishTest.cs
index 744dda365f8b..154c5cd1d74b 100644
--- a/src/Tests/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/WasmPublishTest.cs
+++ b/src/Tests/Microsoft.NET.Sdk.BlazorWebAssembly.Tests/WasmPublishTest.cs
@@ -26,6 +26,38 @@ public class WasmPublishIntegrationTest : SdkTest
{
public WasmPublishIntegrationTest(ITestOutputHelper log) : base(log) { }
+ [Fact]
+ public void Publish_MinimalApp_Works()
+ {
+ // Arrange
+ var testAppName = "BlazorWasmMinimal";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
+
+ var publishCommand = new PublishCommand(Log, testInstance.TestRoot);
+ publishCommand.Execute().Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory("net5.0");
+
+ var expectedFiles = new[]
+ {
+ "wwwroot/_framework/blazor.boot.json",
+ "wwwroot/_framework/blazor.webassembly.js",
+ "wwwroot/_framework/dotnet.wasm",
+ "wwwroot/_framework/blazorwasm-minimal.dll",
+ "wwwroot/index.html",
+ "web.config"
+ };
+
+ publishDirectory.Should().HaveFiles(expectedFiles);
+
+ // Verify web.config
+ var content = File.ReadAllText(Path.Combine(publishDirectory.ToString(), "web.config"));
+ content.Should().Contain("");
+
+ VerifyBootManifestHashes(testInstance, Path.Combine(publishDirectory.ToString(), "wwwroot"));
+ }
+
[Fact]
public void Publish_WithDefaultSettings_Works()
{
@@ -54,10 +86,6 @@ public void Publish_WithDefaultSettings_Works()
"web.config"
};
- // Verify web.config
- var content = File.ReadAllText(Path.Combine(publishDirectory.ToString(), "web.config"));
- content.Should().Contain("");
-
publishDirectory.Should().HaveFiles(expectedFiles);
var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
@@ -76,6 +104,86 @@ public void Publish_WithDefaultSettings_Works()
VerifyTypeGranularTrimming(blazorPublishDirectory);
}
+ [Fact]
+ public void Publish_WithScopedCss_Works()
+ {
+ // Arrange
+ var testAppName = "BlazorWasmWithLibrary";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
+ File.WriteAllText(Path.Combine(testInstance.TestRoot, "blazorwasm", "App.razor.css"), "h1 { font-size: 16px; }");
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorwasm"));
+ publishCommand.Execute().Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory("net5.0");
+
+ var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
+
+ var expectedFiles = new[]
+ {
+ "wwwroot/_framework/blazor.boot.json",
+ "wwwroot/_framework/blazor.webassembly.js",
+ "wwwroot/_framework/dotnet.wasm",
+ "wwwroot/_framework/blazorwasm.dll",
+ "wwwroot/_framework/System.Text.Json.dll",
+ "wwwroot/_content/RazorClassLibrary/wwwroot/exampleJsInterop.js",
+ "wwwroot/_content/RazorClassLibrary/styles.css",
+ "wwwroot/index.html",
+ "wwwroot/js/LinkedScript.js",
+ "wwwroot/blazorwasm.styles.css",
+ "wwwroot/css/app.css",
+ "web.config"
+ };
+
+ publishDirectory.Should().HaveFiles(expectedFiles);
+
+ new FileInfo(Path.Combine(blazorPublishDirectory, "css", "app.css")).Should().Contain(".publish");
+
+ VerifyBootManifestHashes(testInstance, blazorPublishDirectory);
+ VerifyServiceWorkerFiles(testInstance, blazorPublishDirectory,
+ serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
+ serviceWorkerContent: "// This is the production service worker",
+ assetsManifestPath: "custom-service-worker-assets.js");
+ }
+
+ [Fact]
+ public void Publish_InRelease_Works()
+ {
+ // Arrange
+ var testAppName = "BlazorWasmWithLibrary";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
+ File.WriteAllText(Path.Combine(testInstance.TestRoot, "blazorwasm", "App.razor.css"), "h1 { font-size: 16px; }");
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorwasm"));
+ publishCommand.Execute("/p:Configuration=Release").Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory("net5.0", "Release");
+
+ var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
+
+ var expectedFiles = new[]
+ {
+ "wwwroot/_framework/blazor.boot.json",
+ "wwwroot/_framework/blazor.webassembly.js",
+ "wwwroot/_framework/dotnet.wasm",
+ "wwwroot/_framework/blazorwasm.dll",
+ "wwwroot/_framework/System.Text.Json.dll",
+ "wwwroot/_content/RazorClassLibrary/wwwroot/exampleJsInterop.js",
+ "wwwroot/_content/RazorClassLibrary/styles.css",
+ "wwwroot/index.html",
+ "wwwroot/js/LinkedScript.js",
+ "wwwroot/blazorwasm.styles.css",
+ "wwwroot/css/app.css",
+ "web.config"
+ };
+
+ publishDirectory.Should().HaveFiles(expectedFiles);
+
+ new FileInfo(Path.Combine(blazorPublishDirectory, "css", "app.css")).Should().Contain(".publish");
+ }
+
[Fact]
public void Publish_WithExistingWebConfig_Works()
{
@@ -142,8 +250,8 @@ public void Publish_WithNoBuild_Works()
}
[Theory]
- [InlineData("different-path/")]
- [InlineData("/different-path/")]
+ [InlineData("different-path")]
+ [InlineData("/different-path")]
public void Publish_WithStaticWebBasePathWorks(string basePath)
{
// Arrange
@@ -160,6 +268,7 @@ public void Publish_WithStaticWebBasePathWorks(string basePath)
itemGroup.Add(new XElement("StaticWebAssetBasePath", basePath));
project.Root.Add(itemGroup);
}
+
});
var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorwasm"));
@@ -204,13 +313,13 @@ public void Publish_WithStaticWebBasePathWorks(string basePath)
}
[Theory]
- [InlineData("different-path")]
- [InlineData("/different-path")]
+ [InlineData("different-path/")]
+ [InlineData("/different-path/")]
public void Publish_Hosted_WithStaticWebBasePathWorks(string basePath)
{
var testAppName = "BlazorHosted";
var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
- .WithSource();
+ .WithSource();;
testInstance.WithProjectChanges((path, project) =>
{
@@ -221,6 +330,7 @@ public void Publish_Hosted_WithStaticWebBasePathWorks(string basePath)
itemGroup.Add(new XElement("StaticWebAssetBasePath", basePath));
project.Root.Add(itemGroup);
}
+
});
var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorhosted"));
@@ -271,24 +381,23 @@ private static void VerifyCompression(TestAsset testAsset, string blazorPublishD
}
[Fact]
- public void Publish_SatelliteAssemblies_AreCopiedToBuildOutput()
+ public void Publish_WithTrimmingdDisabled_Works()
{
// Arrange
var testAppName = "BlazorWasmWithLibrary";
- var testInstance = _testAssetsManager.CopyTestAsset(testAppName).WithSource();
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
testInstance.WithProjectChanges((path, project) =>
{
if (path.Contains("blazorwasm"))
{
var ns = project.Root.Name.Namespace;
- var propertyGroup = new XElement(ns + "PropertyGroup");
- propertyGroup.Add(new XElement("DefineConstants", @"$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies"));
- var itemGroup = new XElement(ns + "ItemGroup");
- itemGroup.Add(new XElement("ProjectReference", new XAttribute("Include", @"..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj")));
- project.Root.Add(propertyGroup);
+ var itemGroup = new XElement(ns + "PropertyGroup");
+ itemGroup.Add(new XElement("PublishTrimmed", false));
project.Root.Add(itemGroup);
}
+
});
var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorwasm"));
@@ -299,61 +408,115 @@ public void Publish_SatelliteAssemblies_AreCopiedToBuildOutput()
publishDirectory.Should().HaveFiles(new[]
{
- "wwwroot/_framework/Microsoft.CodeAnalysis.CSharp.dll",
- "wwwroot/_framework/fr/Microsoft.CodeAnalysis.CSharp.resources.dll"
+ "wwwroot/_framework/blazor.boot.json",
+ "wwwroot/_framework/blazor.webassembly.js",
+ "wwwroot/_framework/dotnet.wasm",
+ "wwwroot/_framework/blazorwasm.dll",
+ "wwwroot/_framework/System.Text.Json.dll"
});
- var bootJsonData = new FileInfo(Path.Combine(blazorPublishDirectory, "_framework", "blazor.boot.json"));
- bootJsonData.Should().Contain("\"Microsoft.CodeAnalysis.CSharp.dll\"");
- bootJsonData.Should().Contain("\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");
+ // Verify compression works
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/_framework/dotnet.wasm.br",
+ "wwwroot/_framework/System.Text.Json.dll.br"
+ });
+
+ // Verify static assets are in the publish directory
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/index.html"
+ });
+
+ // Verify referenced static web assets
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/_content/RazorClassLibrary/wwwroot/exampleJsInterop.js",
+ "wwwroot/_content/RazorClassLibrary/styles.css",
+ });
+
+ // Verify web.config
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "web.config"
+ });
VerifyBootManifestHashes(testInstance, blazorPublishDirectory);
+ VerifyServiceWorkerFiles(testInstance, blazorPublishDirectory,
+ serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
+ serviceWorkerContent: "// This is the production service worker",
+ assetsManifestPath: "custom-service-worker-assets.js");
+
+ // Verify assemblies are not trimmed
+ var loggingAssemblyPath = Path.Combine(blazorPublishDirectory, "_framework", "Microsoft.Extensions.Logging.Abstractions.dll");
+ VerifyAssemblyHasTypes(loggingAssemblyPath, new[] { "Microsoft.Extensions.Logging.Abstractions.NullLogger" });
}
[Fact]
- public void Publish_HostedApp_WithSatelliteAssemblies()
+ public void Publish_SatelliteAssemblies_AreCopiedToBuildOutput()
{
// Arrange
- var testAppName = "BlazorHosted";
- var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
- .WithSource();
+ var testAppName = "BlazorWasmWithLibrary";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName).WithSource();
testInstance.WithProjectChanges((path, project) =>
{
if (path.Contains("blazorwasm"))
{
var ns = project.Root.Name.Namespace;
- // Workaround for https://github.com/mono/linker/issues/1390
var propertyGroup = new XElement(ns + "PropertyGroup");
-
- propertyGroup.Add(new XElement("PublishTrimmed", false));
propertyGroup.Add(new XElement("DefineConstants", @"$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies"));
var itemGroup = new XElement(ns + "ItemGroup");
itemGroup.Add(new XElement("ProjectReference", new XAttribute("Include", @"..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj")));
project.Root.Add(propertyGroup);
project.Root.Add(itemGroup);
}
+ });
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorwasm"));
+ publishCommand.Execute().Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory("net5.0");
+ var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/_framework/Microsoft.CodeAnalysis.CSharp.dll",
+ "wwwroot/_framework/fr/Microsoft.CodeAnalysis.CSharp.resources.dll"
});
- var resxfileInProject = Path.Combine(testInstance.TestRoot, "blazorwasm", "Resources.ja.resx.txt");
- File.Move(resxfileInProject, Path.Combine(testInstance.TestRoot, "blazorwasm", "Resource.ja.resx"));
+ var bootJsonData = new FileInfo(Path.Combine(blazorPublishDirectory, "_framework", "blazor.boot.json"));
+ bootJsonData.Should().Contain("\"Microsoft.CodeAnalysis.CSharp.dll\"");
+ bootJsonData.Should().Contain("\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");
+
+ VerifyBootManifestHashes(testInstance, blazorPublishDirectory);
+ }
+
+ [Fact]
+ public void Publish_HostedApp_DefaultSettings_Works()
+ {
+ // Arrange
+ var testAppName = "BlazorHosted";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorhosted"));
publishCommand.Execute().Should().Pass();
- var publishOutputDirectory = publishCommand.GetOutputDirectory("net5.0");
+ var publishDirectory = publishCommand.GetOutputDirectory("net5.0");
+ // Make sure the main project exists
+ new FileInfo(Path.Combine(publishDirectory.ToString(), "blazorhosted.dll")).Should().Exist();
// Verification for https://github.com/dotnet/aspnetcore/issues/19926. Verify binaries for projects
// referenced by the Hosted project appear in the publish directory
- publishOutputDirectory.Should().HaveFiles(new[]
+ publishDirectory.Should().HaveFiles(new[]
{
"RazorClassLibrary.dll",
"blazorwasm.dll"
});
- var blazorPublishDirectory = Path.Combine(publishOutputDirectory.ToString(), "wwwroot");
- publishOutputDirectory.Should().HaveFiles(new[]
+ var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
+ publishDirectory.Should().HaveFiles(new[]
{
"wwwroot/_framework/blazor.boot.json",
"wwwroot/_framework/blazor.webassembly.js",
@@ -363,27 +526,27 @@ public void Publish_HostedApp_WithSatelliteAssemblies()
});
// Verify project references appear as static web assets
- publishOutputDirectory.Should().HaveFiles(new[]
+ publishDirectory.Should().HaveFiles(new[]
{
"wwwroot/_framework/RazorClassLibrary.dll",
"RazorClassLibrary.dll"
});
// Verify static assets are in the publish directory
- publishOutputDirectory.Should().HaveFiles(new[]
+ publishDirectory.Should().HaveFiles(new[]
{
"wwwroot/index.html"
});
// Verify static web assets from referenced projects are copied.
- publishOutputDirectory.Should().HaveFiles(new[]
+ publishDirectory.Should().HaveFiles(new[]
{
"wwwroot/_content/RazorClassLibrary/wwwroot/exampleJsInterop.js",
"wwwroot/_content/RazorClassLibrary/styles.css",
});
// Verify web.config
- publishOutputDirectory.Should().HaveFiles(new[]
+ publishDirectory.Should().HaveFiles(new[]
{
"web.config"
});
@@ -391,7 +554,7 @@ public void Publish_HostedApp_WithSatelliteAssemblies()
VerifyBootManifestHashes(testInstance, blazorPublishDirectory);
// Verify compression works
- publishOutputDirectory.Should().HaveFiles(new[]
+ publishDirectory.Should().HaveFiles(new[]
{
"wwwroot/_framework/dotnet.wasm.br",
"wwwroot/_framework/blazorwasm.dll.br",
@@ -399,7 +562,7 @@ public void Publish_HostedApp_WithSatelliteAssemblies()
"wwwroot/_framework/System.Text.Json.dll.br"
});
- publishOutputDirectory.Should().HaveFiles(new[]
+ publishDirectory.Should().HaveFiles(new[]
{
"wwwroot/_framework/dotnet.wasm.gz",
"wwwroot/_framework/blazorwasm.dll.gz",
@@ -407,8 +570,32 @@ public void Publish_HostedApp_WithSatelliteAssemblies()
"wwwroot/_framework/System.Text.Json.dll.gz"
});
- // Verify that Blazor bootJSON contains the right contents
- var bootJsonPath = Path.Combine(blazorPublishDirectory, "_framework", "blazor.boot.json");
+ VerifyServiceWorkerFiles(testInstance, blazorPublishDirectory,
+ serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
+ serviceWorkerContent: "// This is the production service worker",
+ assetsManifestPath: "custom-service-worker-assets.js");
+
+ VerifyTypeGranularTrimming(blazorPublishDirectory);
+ }
+
+ [Fact]
+ public void Publish_HostedApp_ProducesBootJsonDataWithExpectedContent()
+ {
+ // Arrange
+ var testAppName = "BlazorHosted";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
+
+ var wwwroot = Path.Combine(testInstance.TestRoot, "blazorwasm", "wwwroot");
+ File.WriteAllText(Path.Combine(wwwroot, "appsettings.json"), "Default settings");
+ File.WriteAllText(Path.Combine(wwwroot, "appsettings.development.json"), "Development settings");
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorhosted"));
+ publishCommand.Execute().Should().Pass();
+
+ var buildOutputDirectory = publishCommand.GetOutputDirectory("net5.0").ToString();
+
+ var bootJsonPath = Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
var bootJsonData = ReadBootJsonData(bootJsonPath);
var runtime = bootJsonData.resources.runtime;
@@ -419,12 +606,47 @@ public void Publish_HostedApp_WithSatelliteAssemblies()
assemblies.Should().ContainKey("RazorClassLibrary.dll");
assemblies.Should().ContainKey("System.Text.Json.dll");
- VerifyServiceWorkerFiles(testInstance, blazorPublishDirectory,
- serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
- serviceWorkerContent: "// This is the production service worker",
- assetsManifestPath: "custom-service-worker-assets.js");
+ bootJsonData.resources.satelliteResources.Should().BeNull();
- VerifyTypeGranularTrimming(blazorPublishDirectory);
+ bootJsonData.config.Should().Contain("appsettings.json");
+ bootJsonData.config.Should().Contain("appsettings.development.json");
+ }
+
+ [Fact]
+ public void Publish_HostedApp_WithSatelliteAssemblies()
+ {
+ // Arrange
+ var testAppName = "BlazorHosted";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
+
+ testInstance.WithProjectChanges((path, project) =>
+ {
+ if (path.Contains("blazorwasm"))
+ {
+ var ns = project.Root.Name.Namespace;
+ // Workaround for https://github.com/mono/linker/issues/1390
+ var propertyGroup = new XElement(ns + "PropertyGroup");
+
+ propertyGroup.Add(new XElement("PublishTrimmed", false));
+ propertyGroup.Add(new XElement("DefineConstants", @"$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies"));
+ var itemGroup = new XElement(ns + "ItemGroup");
+ itemGroup.Add(new XElement("ProjectReference", new XAttribute("Include", @"..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj")));
+ project.Root.Add(propertyGroup);
+ project.Root.Add(itemGroup);
+ }
+
+ });
+
+ var resxfileInProject = Path.Combine(testInstance.TestRoot, "blazorwasm", "Resources.ja.resx.txt");
+ File.Move(resxfileInProject, Path.Combine(testInstance.TestRoot, "blazorwasm", "Resource.ja.resx"));
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorhosted"));
+ publishCommand.Execute().Should().Pass();
+
+ var publishOutputDirectory = publishCommand.GetOutputDirectory("net5.0");
+
+ var bootJsonData = new FileInfo(Path.Combine(publishOutputDirectory.ToString(), "wwwroot", "_framework", "blazor.boot.json"));
publishOutputDirectory.Should().HaveFiles(new[]
{
@@ -434,9 +656,8 @@ public void Publish_HostedApp_WithSatelliteAssemblies()
"wwwroot/_framework/fr/Microsoft.CodeAnalysis.CSharp.resources.dll",
});
- var bootJsonFile = new FileInfo(Path.Combine(blazorPublishDirectory, "_framework", "blazor.boot.json"));
- bootJsonFile.Should().Contain("\"Microsoft.CodeAnalysis.CSharp.dll\"");
- bootJsonFile.Should().Contain("\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");
+ bootJsonData.Should().Contain("\"Microsoft.CodeAnalysis.CSharp.dll\"");
+ bootJsonData.Should().Contain("\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");
}
[Fact]
@@ -466,7 +687,7 @@ public void Publish_HostedApp_WithoutTrimming_Works()
// Publish
var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorhosted"));
- publishCommand.Execute("/p:BuildDependencies=false").Should().Pass();
+ publishCommand.Execute("/p:BuildDependencies=false /bl").Should().Pass();
var publishDirectory = publishCommand.GetOutputDirectory("net5.0");
// Make sure the main project exists
@@ -595,30 +816,97 @@ public void Publish_HostedApp_WithNoBuild_Works()
}
[Fact]
- public void Publish_HostedAppWithScopedCssAndSatelliteAssemblies_VisualStudio()
+ public void Publish_HostedApp_VisualStudio()
{
// Simulates publishing the same way VS does by setting BuildProjectReferences=false.
+ // Arrange
var testAppName = "BlazorHosted";
var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
.WithSource();
- testInstance.WithProjectChanges((path, project) =>
+ // VS builds projects individually and then a publish with BuildDependencies=false, but building the main project is a close enough approximation for this test.
+ var buildCommand = new BuildCommand(testInstance, "blazorwasm");
+ buildCommand.Execute("/p:BuildInsideVisualStudio=true").Should().Pass();
+
+ // Publish
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorhosted"));
+ publishCommand.Execute("/p:BuildProjectReferences=false /p:BuildInsideVisualStudio=true").Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory("net5.0");
+ // Make sure the main project exists
+ new FileInfo(Path.Combine(publishDirectory.ToString(), "blazorhosted.dll")).Should().Exist();
+
+ // Verification for https://github.com/dotnet/aspnetcore/issues/19926. Verify binaries for projects
+ // referenced by the Hosted project appear in the publish directory
+ publishDirectory.Should().HaveFiles(new[]
{
- if (path.Contains("blazorwasm"))
- {
- var ns = project.Root.Name.Namespace;
- var propertyGroup = new XElement(ns + "PropertyGroup");
- propertyGroup.Add(new XElement("DefineConstants", @"$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies"));
- var itemGroup = new XElement(ns + "ItemGroup");
- itemGroup.Add(new XElement("ProjectReference", new XAttribute("Include", @"..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj")));
- project.Root.Add(propertyGroup);
- project.Root.Add(itemGroup);
- }
+ "RazorClassLibrary.dll",
+ "blazorwasm.dll"
});
- var resxfileInProject = Path.Combine(testInstance.TestRoot, "blazorwasm", "Resources.ja.resx.txt");
- File.Move(resxfileInProject, Path.Combine(testInstance.TestRoot, "blazorwasm", "Resource.ja.resx"));
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/_framework/blazor.boot.json",
+ "wwwroot/_framework/blazor.webassembly.js",
+ "wwwroot/_framework/dotnet.wasm",
+ "wwwroot/_framework/blazorwasm.dll",
+ "wwwroot/_framework/System.Text.Json.dll"
+ });
+
+ // Verify project references appear as static web assets
+ // Also verify project references to the server project appear in the publish output
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/_framework/RazorClassLibrary.dll",
+ "RazorClassLibrary.dll"
+ });
+
+ // Verify static assets are in the publish directory
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/index.html"
+ });
+
+ // Verify static web assets from referenced projects are copied.
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/_content/RazorClassLibrary/wwwroot/exampleJsInterop.js",
+ "wwwroot/_content/RazorClassLibrary/styles.css",
+ });
+
+ // Verify web.config
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "web.config"
+ });
+ VerifyBootManifestHashes(testInstance, Path.Combine(publishDirectory.ToString(), "wwwroot"));
+
+ // Verify compression works
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/_framework/dotnet.wasm.br",
+ "wwwroot/_framework/blazorwasm.dll.br",
+ "wwwroot/_framework/RazorClassLibrary.dll.br",
+ "wwwroot/_framework/System.Text.Json.dll.br"
+ });
+
+ var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
+
+ VerifyBootManifestHashes(testInstance, blazorPublishDirectory);
+ VerifyServiceWorkerFiles(testInstance, blazorPublishDirectory,
+ serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
+ serviceWorkerContent: "// This is the production service worker",
+ assetsManifestPath: "custom-service-worker-assets.js");
+ }
+
+ [Fact]
+ public void Publish_HostedAppWithScopedCss_VisualStudio()
+ {
+ // Simulates publishing the same way VS does by setting BuildProjectReferences=false.
+ var testAppName = "BlazorHosted";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
File.WriteAllText(Path.Combine(testInstance.TestRoot, "blazorwasm", "App.razor.css"), "h1 { font-size: 16px; }");
// VS builds projects individually and then a publish with BuildDependencies=false, but building the main project is a close enough approximation for this test.
@@ -630,24 +918,9 @@ public void Publish_HostedAppWithScopedCssAndSatelliteAssemblies_VisualStudio()
publishCommand.Execute("/p:BuildProjectReferences=false /p:BuildInsideVisualStudio=true").Should().Pass();
var publishDirectory = publishCommand.GetOutputDirectory("net5.0");
- var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
-
// Make sure the main project exists
new FileInfo(Path.Combine(publishDirectory.ToString(), "blazorhosted.dll")).Should().Exist();
- // Verification for satelitte assemblies
- publishDirectory.Should().HaveFiles(new[]
- {
- "wwwroot/_framework/blazor.boot.json",
- "wwwroot/_framework/ja/blazorwasm.resources.dll",
- "wwwroot/_framework/fr/Microsoft.CodeAnalysis.CSharp.resources.dll"
- });
-
- var bootJsonData = new FileInfo(Path.Combine(blazorPublishDirectory, "_framework", "blazor.boot.json"));
- bootJsonData.Should().Contain("\"es-ES\\/classlibrarywithsatelliteassemblies.resources.dll\"");
- bootJsonData.Should().Contain("\"ja\\/blazorwasm.resources.dll\"");
- bootJsonData.Should().Contain("\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");
-
// Verification for https://github.com/dotnet/aspnetcore/issues/19926. Verify binaries for projects
// referenced by the Hosted project appear in the publish directory
publishDirectory.Should().HaveFiles(new[]
@@ -709,6 +982,8 @@ public void Publish_HostedAppWithScopedCssAndSatelliteAssemblies_VisualStudio()
"wwwroot/_framework/System.Text.Json.dll.br"
});
+ var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
+
VerifyBootManifestHashes(testInstance, blazorPublishDirectory);
VerifyServiceWorkerFiles(testInstance, blazorPublishDirectory,
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
@@ -716,6 +991,55 @@ public void Publish_HostedAppWithScopedCssAndSatelliteAssemblies_VisualStudio()
assetsManifestPath: "custom-service-worker-assets.js");
}
+ // Regression test to verify satellite assemblies from the blazor app are copied to the published app's wwwroot output directory as
+ // part of publishing in VS
+ [Fact]
+ public void Publish_HostedApp_VisualStudio_WithSatelliteAssemblies()
+ {
+ var testAppName = "BlazorWasmWithLibrary";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName).WithSource();
+
+ testInstance.WithProjectChanges((path, project) =>
+ {
+ if (path.Contains("blazorwasm"))
+ {
+ var ns = project.Root.Name.Namespace;
+ var propertyGroup = new XElement(ns + "PropertyGroup");
+ propertyGroup.Add(new XElement("DefineConstants", @"$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies"));
+ var itemGroup = new XElement(ns + "ItemGroup");
+ itemGroup.Add(new XElement("ProjectReference", new XAttribute("Include", @"..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj")));
+ project.Root.Add(propertyGroup);
+ project.Root.Add(itemGroup);
+ }
+ });
+
+ var resxfileInProject = Path.Combine(testInstance.TestRoot, "blazorwasm", "Resources.ja.resx.txt");
+ File.Move(resxfileInProject, Path.Combine(testInstance.TestRoot, "blazorwasm", "Resource.ja.resx"));
+
+ var buildCommand = new BuildCommand(testInstance, "blazorwasm");
+ buildCommand.Execute().Should().Pass();
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorwasm"));
+ publishCommand.Execute("/p:BuildProjectReferences=false").Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory("net5.0");
+ var blazorPublishDirectory = Path.Combine(publishDirectory.ToString(), "wwwroot");
+
+ publishDirectory.Should().HaveFiles(new[]
+ {
+ "wwwroot/_framework/blazor.boot.json",
+ "wwwroot/_framework/ja/blazorwasm.resources.dll",
+ "wwwroot/_framework/fr/Microsoft.CodeAnalysis.CSharp.resources.dll"
+ });
+
+ var bootJsonData = new FileInfo(Path.Combine(blazorPublishDirectory, "_framework", "blazor.boot.json"));
+ bootJsonData.Should().Contain("\"es-ES\\/classlibrarywithsatelliteassemblies.resources.dll\"");
+ bootJsonData.Should().Contain("\"ja\\/blazorwasm.resources.dll\"");
+ bootJsonData.Should().Contain("\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");
+
+ VerifyBootManifestHashes(testInstance, blazorPublishDirectory);
+ }
+
[Fact]
public void Publish_HostedApp_WithRidSpecifiedInCLI_Works()
{
@@ -730,6 +1054,19 @@ public void Publish_HostedApp_WithRidSpecifiedInCLI_Works()
AssertRIDPublishOuput(publishCommand, testInstance);
}
+ [Fact]
+ public void Publish_HostedApp_WithRid_Works()
+ {
+ // Arrange
+ var testAppName = "BlazorHostedRID";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName).WithSource();
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "blazorhosted"));
+ publishCommand.Execute().Should().Pass();
+
+ AssertRIDPublishOuput(publishCommand, testInstance);
+ }
+
private static void AssertRIDPublishOuput(PublishCommand command, TestAsset testInstance)
{
var publishDirectory = command.GetOutputDirectory("net5.0", "Debug", "linux-x64");
@@ -837,6 +1174,7 @@ public void Publish_WithInvariantGlobalizationEnabled_DoesNotCopyGlobalizationDa
runtime.Should().NotContainKey("icudt.dat");
runtime.Should().NotContainKey("icudt_EFIGS.dat");
+
new FileInfo(Path.Combine(publishOutputDirectory, "wwwroot", "_framework", "dotnet.wasm")).Should().Exist();
new FileInfo(Path.Combine(publishOutputDirectory, "wwwroot", "_framework", "icudt.dat")).Should().NotExist();
new FileInfo(Path.Combine(publishOutputDirectory, "wwwroot", "_framework", "icudt_CJK.dat")).Should().NotExist();
@@ -844,6 +1182,64 @@ public void Publish_WithInvariantGlobalizationEnabled_DoesNotCopyGlobalizationDa
new FileInfo(Path.Combine(publishOutputDirectory, "wwwroot", "_framework", "icudt_no_CJK.dat")).Should().NotExist();
}
+ [Fact]
+ public void Publish_HostingMultipleBlazorWebApps_Works()
+ {
+ // Regression test for https://github.com/dotnet/aspnetcore/issues/29264
+ // Arrange
+ var testAppName = "BlazorMultiApp";
+ var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
+ .WithSource();
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testInstance.TestRoot, "BlazorMultipleApps.Server"));
+ publishCommand.Execute().Should().Pass();
+
+ var publishOutputDirectory = publishCommand.GetOutputDirectory("net5.0").ToString();
+
+ new FileInfo(Path.Combine(publishOutputDirectory, "BlazorMultipleApps.Server.dll")).Should().Exist();
+ new FileInfo(Path.Combine(publishOutputDirectory, "BlazorMultipleApps.FirstClient.dll")).Should().Exist();
+ new FileInfo(Path.Combine(publishOutputDirectory, "BlazorMultipleApps.SecondClient.dll")).Should().Exist();
+
+ var firstAppPublishDirectory = Path.Combine(publishOutputDirectory, "wwwroot", "FirstApp");
+
+ var firstCss = Path.Combine(firstAppPublishDirectory, "css", "app.css");
+ new FileInfo(firstCss).Should().Exist();
+ new FileInfo(firstCss).Should().Exist("/* First app.css */");
+
+ var firstBootJsonPath = Path.Combine(firstAppPublishDirectory, "_framework", "blazor.boot.json");
+ var firstBootJson = ReadBootJsonData(firstBootJsonPath);
+
+ // Do a sanity check that the boot json has files.
+ firstBootJson.resources.assembly.Keys.Should().Contain("System.Text.Json.dll");
+
+ VerifyBootManifestHashes(testInstance, firstAppPublishDirectory);
+
+ // Verify compression works
+ new FileInfo(Path.Combine(firstAppPublishDirectory, "_framework", "dotnet.wasm.br")).Should().Exist();
+ new FileInfo(Path.Combine(firstAppPublishDirectory, "_framework", "BlazorMultipleApps.FirstClient.dll.br")).Should().Exist();
+ new FileInfo(Path.Combine(firstAppPublishDirectory, "_framework", "Newtonsoft.Json.dll.br")).Should().Exist();
+
+ var secondAppPublishDirectory = Path.Combine(publishOutputDirectory, "wwwroot", "SecondApp");
+
+ var secondCss = Path.Combine(secondAppPublishDirectory, "css", "app.css");
+ new FileInfo(secondCss).Should().Exist();
+ new FileInfo(secondCss).Should().Exist("/* Second app.css */");
+
+ var secondBootJsonPath = Path.Combine(secondAppPublishDirectory, "_framework", "blazor.boot.json");
+ var secondBootJson = ReadBootJsonData(secondBootJsonPath);
+
+ // Do a sanity check that the boot json has files.
+ secondBootJson.resources.assembly.Keys.Should().Contain("System.Private.CoreLib.dll");
+
+ VerifyBootManifestHashes(testInstance, secondAppPublishDirectory);
+
+ // Verify compression works
+ new FileInfo(Path.Combine(secondAppPublishDirectory, "_framework", "dotnet.wasm.br")).Should().Exist();
+ new FileInfo(Path.Combine(secondAppPublishDirectory, "_framework", "BlazorMultipleApps.SecondClient.dll.br")).Should().Exist();
+ new FileInfo(Path.Combine(secondAppPublishDirectory, "_framework", "System.Private.CoreLib.dll.br")).Should().Exist();
+ new FileInfo(Path.Combine(secondAppPublishDirectory, "_framework", "Newtonsoft.Json.dll.br")).Should().NotExist();
+ }
+
private static void VerifyBootManifestHashes(TestAsset testAsset, string blazorPublishDirectory)
{
var bootManifestResolvedPath = Path.Combine(blazorPublishDirectory, "_framework", "blazor.boot.json");