public async Task Publish_SatelliteAssemblies_AreCopiedToBuildOutput()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary", "classlibrarywithsatelliteassemblies" });
            project.AddProjectFileContent(
                @"
<PropertyGroup>
    <DefineConstants>$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies</DefineConstants>
</PropertyGroup>
<ItemGroup>
    <ProjectReference Include=""..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj"" />
</ItemGroup>");

            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args : "/restore");

            Assert.BuildPassed(result);

            var publishDirectory       = project.PublishOutputDirectory;
            var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");

            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "Microsoft.CodeAnalysis.CSharp.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "fr", "Microsoft.CodeAnalysis.CSharp.resources.dll"); // Verify satellite assemblies are present in the build output.

            var bootJsonPath = Path.Combine(blazorPublishDirectory, "_framework", "blazor.boot.json");

            Assert.FileContains(result, bootJsonPath, "\"Microsoft.CodeAnalysis.CSharp.dll\"");
            Assert.FileContains(result, bootJsonPath, "\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");

            VerifyBootManifestHashes(result, blazorPublishDirectory);
            VerifyServiceWorkerFiles(result, blazorPublishDirectory,
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the production service worker",
                                     assetsManifestPath: "custom-service-worker-assets.js");
        }
        // Regression test for https://github.com/dotnet/aspnetcore/issues/18752
        public async Task Publish_HostedApp_WithLinkOnBuildFalse_Works()
        {
            // Arrange
            using var project       = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", });
            project.TargetFramework = TestFacts.DefaultNetCoreTargetFramework;

            AddSiblingProjectFileContent(project, @"
<PropertyGroup>
    <BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
</PropertyGroup>");

            // 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 result = await MSBuildProcessManager.DotnetMSBuild(project, "Build");

            Assert.BuildPassed(result);

            // Publish
            result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:BuildDependencies=false");

            var publishDirectory = project.PublishOutputDirectory;

            // Make sure the main project exists
            Assert.FileExists(result, publishDirectory, "blazorhosted.dll");

            // Verification for https://github.com/dotnet/aspnetcore/issues/19926. Verify binaries for projects
            // referenced by the Hosted project appear in the publish directory
            Assert.FileExists(result, publishDirectory, "RazorClassLibrary.dll");
            Assert.FileExists(result, publishDirectory, "standalone.dll");

            var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");

            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.boot.json");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.webassembly.js");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "standalone.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "RazorClassLibrary.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.

            // Verify static assets are in the publish directory
            Assert.FileExists(result, blazorPublishDirectory, "index.html");

            // Verify static web assets from referenced projects are copied.
            Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
            Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css");

            // Verify static assets are in the publish directory
            Assert.FileExists(result, blazorPublishDirectory, "index.html");

            // Verify web.config
            Assert.FileExists(result, publishDirectory, "web.config");

            VerifyBootManifestHashes(result, blazorPublishDirectory);
            VerifyServiceWorkerFiles(result, blazorPublishDirectory,
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the production service worker",
                                     assetsManifestPath: "custom-service-worker-assets.js");
        }
        public async Task Publish_HostedApp_WithLinkOnBuildTrue_Works()
        {
            // Arrange
            using var project       = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", });
            project.TargetFramework = TestFacts.DefaultNetCoreTargetFramework;
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            AddSiblingProjectFileContent(project, @"
<PropertyGroup>
    <BlazorWebAssemblyEnableLinking>true</BlazorWebAssemblyEnableLinking>
</PropertyGroup>");

            Assert.BuildPassed(result);

            var publishDirectory = project.PublishOutputDirectory;

            // Make sure the main project exists
            Assert.FileExists(result, publishDirectory, "blazorhosted.dll");
            Assert.FileExists(result, publishDirectory, "RazorClassLibrary.dll");

            var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");

            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.boot.json");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.webassembly.js");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "standalone.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
            // Verify project references appear as static web assets
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "RazorClassLibrary.dll");
            // Also verify project references to the server project appear in the publish output
            Assert.FileExists(result, publishDirectory, "RazorClassLibrary.dll");

            // Verify static assets are in the publish directory
            Assert.FileExists(result, blazorPublishDirectory, "index.html");

            // Verify static web assets from referenced projects are copied.
            Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
            Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css");

            // Verify web.config
            Assert.FileExists(result, publishDirectory, "web.config");

            VerifyBootManifestHashes(result, blazorPublishDirectory);
            VerifyServiceWorkerFiles(result, blazorPublishDirectory,
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the production service worker",
                                     assetsManifestPath: "custom-service-worker-assets.js");
        }
        public async Task Build_SatelliteAssembliesFileIsPreserved()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            File.Move(Path.Combine(project.DirectoryPath, "Resources.ja.resx.txt"), Path.Combine(project.DirectoryPath, "Resource.ja.resx"));
            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var satelliteAssemblyCacheFile = Path.Combine(project.IntermediateOutputDirectory, "blazor", "blazor.satelliteasm.props");
            var satelliteAssemblyFile      = Path.Combine(project.BuildOutputDirectory, "wwwroot", "_framework", "_bin", "ja", "standalone.resources.dll");
            var bootJson = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");

            // Assert
            for (var i = 0; i < 3; i++)
            {
                result = await MSBuildProcessManager.DotnetMSBuild(project);

                Assert.BuildPassed(result);

                Verify();
            }

            // Assert - incremental builds with BuildingProject=false
            for (var i = 0; i < 3; i++)
            {
                result = await MSBuildProcessManager.DotnetMSBuild(project, args : "/p:BuildingProject=false");

                Assert.BuildPassed(result);

                Verify();
            }

            void Verify()
            {
                Assert.FileExists(result, satelliteAssemblyCacheFile);
                Assert.FileExists(result, satelliteAssemblyFile);

                var bootJsonFile = JsonSerializer.Deserialize <GenerateBlazorBootJson.BootJsonData>(File.ReadAllText(bootJson), new JsonSerializerOptions {
                    PropertyNameCaseInsensitive = true
                });
                var satelliteResources = bootJsonFile.resources.satelliteResources;
                var kvp = Assert.Single(satelliteResources);

                Assert.Equal("ja", kvp.Key);
                Assert.Equal("ja/standalone.resources.dll", Assert.Single(kvp.Value).Key);
            }
        }
        public async Task Publish_WithDefaultSettings_Works()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("standalone", additionalProjects: new [] { "razorclasslibrary", "LinkBaseToWebRoot" });
            project.Configuration = "Debug";
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            Assert.BuildPassed(result);

            var publishDirectory = project.PublishOutputDirectory;

            var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");

            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.boot.json");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.webassembly.js");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "standalone.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.

            // Verify referenced static web assets
            Assert.FileExists(result, blazorPublishDirectory, "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
            Assert.FileExists(result, blazorPublishDirectory, "_content", "RazorClassLibrary", "styles.css");

            // Verify static assets are in the publish directory
            Assert.FileExists(result, blazorPublishDirectory, "index.html");

            // Verify link item assets are in the publish directory
            Assert.FileExists(result, blazorPublishDirectory, "js", "LinkedScript.js");
            var cssFile = Assert.FileExists(result, blazorPublishDirectory, "css", "app.css");

            Assert.FileContains(result, cssFile, ".publish");
            Assert.FileDoesNotExist(result, "dist", "Fake-License.txt");

            // Verify web.config
            Assert.FileExists(result, publishDirectory, "web.config");
            Assert.FileCountEquals(result, 1, publishDirectory, "*", SearchOption.TopDirectoryOnly);

            VerifyBootManifestHashes(result, blazorPublishDirectory);
            VerifyServiceWorkerFiles(result, blazorPublishDirectory,
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the production service worker",
                                     assetsManifestPath: "custom-service-worker-assets.js");

            // When publishing without linker, we expect to have collation information present in mscorlib.dll
            Assert.AssemblyContainsResource(result, Path.Combine(blazorPublishDirectory, "_framework", "_bin", "mscorlib.dll"), "collation.cjkCHS.bin");
        }
        public async Task Publish_WithNoBuild_Works()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Build");

            Assert.BuildPassed(result);

            result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:NoBuild=true");

            Assert.BuildPassed(result);

            var publishDirectory       = project.PublishOutputDirectory;
            var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");

            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.boot.json");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.webassembly.js");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "standalone.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.

            // Verify static assets are in the publish directory
            Assert.FileExists(result, blazorPublishDirectory, "index.html");

            // Verify static web assets from referenced projects are copied.
            Assert.FileExists(result, blazorPublishDirectory, "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
            Assert.FileExists(result, blazorPublishDirectory, "_content", "RazorClassLibrary", "styles.css");

            // Verify static assets are in the publish directory
            Assert.FileExists(result, blazorPublishDirectory, "index.html");

            // Verify web.config
            Assert.FileExists(result, publishDirectory, "web.config");

            VerifyBootManifestHashes(result, blazorPublishDirectory);
            VerifyServiceWorkerFiles(result, blazorPublishDirectory,
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the production service worker",
                                     assetsManifestPath: "custom-service-worker-assets.js");

            VerifyCompression(result, blazorPublishDirectory);
        }
        public async Task Publish_HostedApp_VisualStudio()
        {
            // Simulates publishing the same way VS does by setting BuildProjectReferences=false.
            // Arrange
            using var project       = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", });
            project.TargetFramework = TestFacts.DefaultNetCoreTargetFramework;
            project.Configuration   = "Release";
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Build", "/p:BuildInsideVisualStudio=true");

            Assert.BuildPassed(result);

            result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:BuildProjectReferences=false /p:BuildInsideVisualStudio=true");

            var publishDirectory = project.PublishOutputDirectory;

            // Make sure the main project exists
            Assert.FileExists(result, publishDirectory, "blazorhosted.dll");

            var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");

            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.boot.json");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.webassembly.js");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "standalone.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.

            // Verify static assets are in the publish directory
            Assert.FileExists(result, blazorPublishDirectory, "index.html");

            // Verify static web assets from referenced projects are copied.
            Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
            Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css");

            // Verify web.config
            Assert.FileExists(result, publishDirectory, "web.config");

            VerifyBootManifestHashes(result, blazorPublishDirectory);
            VerifyServiceWorkerFiles(result, blazorPublishDirectory,
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the production service worker",
                                     assetsManifestPath: "custom-service-worker-assets.js");
        }
        public async Task Build_SatelliteAssembliesFileIsDeleted_IfAllSatelliteFilesAreRemoved()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            File.Move(Path.Combine(project.DirectoryPath, "Resources.ja.resx.txt"), Path.Combine(project.DirectoryPath, "Resource.ja.resx"));

            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var satelliteAssemblyCacheFile = Path.Combine(project.IntermediateOutputDirectory, "blazor", "blazor.satelliteasm.props");
            var satelliteAssemblyFile      = Path.Combine(project.BuildOutputDirectory, "wwwroot", "_framework", "_bin", "ja", "standalone.resources.dll");
            var bootJson = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");

            result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            Assert.FileExists(result, satelliteAssemblyCacheFile);
            Assert.FileExists(result, satelliteAssemblyFile);
            var bootJsonFile = JsonSerializer.Deserialize <GenerateBlazorBootJson.BootJsonData>(File.ReadAllText(bootJson), new JsonSerializerOptions {
                PropertyNameCaseInsensitive = true
            });
            var satelliteResources = bootJsonFile.resources.satelliteResources;
            var kvp = Assert.Single(satelliteResources);

            Assert.Equal("ja", kvp.Key);
            Assert.Equal("ja/standalone.resources.dll", Assert.Single(kvp.Value).Key);


            File.Delete(Path.Combine(project.DirectoryPath, "Resource.ja.resx"));
            result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            Assert.FileDoesNotExist(result, satelliteAssemblyCacheFile);
            bootJsonFile = JsonSerializer.Deserialize <GenerateBlazorBootJson.BootJsonData>(File.ReadAllText(bootJson), new JsonSerializerOptions {
                PropertyNameCaseInsensitive = true
            });
            satelliteResources = bootJsonFile.resources.satelliteResources;
            Assert.Null(satelliteResources);
        }
Beispiel #9
0
        public async Task Build_WithBlazorWebAssemblyEnableLinkingFalse_SatelliteAssembliesAreCopiedToBuildOutput()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary", "classlibrarywithsatelliteassemblies" });
            project.AddProjectFileContent(
                @"
<PropertyGroup>
    <BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
    <DefineConstants>$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies</DefineConstants>
</PropertyGroup>
<ItemGroup>
    <ProjectReference Include=""..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj"" />
</ItemGroup>");

            var resxfileInProject = Path.Combine(project.DirectoryPath, "Resources.ja.resx.txt");

            File.Move(resxfileInProject, Path.Combine(project.DirectoryPath, "Resource.ja.resx"));

            var result = await MSBuildProcessManager.DotnetMSBuild(project, args : "/restore");

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "classlibrarywithsatelliteassemblies.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.CodeAnalysis.CSharp.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "fr", "Microsoft.CodeAnalysis.CSharp.resources.dll"); // Verify satellite assemblies are present in the build output.

            var bootJson = ReadBootJsonData(result, Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json"));

            var satelliteResources = bootJson.resources.satelliteResources;

            Assert.NotNull(satelliteResources);

            Assert.Contains("es-ES", satelliteResources.Keys);
            Assert.Contains("es-ES/classlibrarywithsatelliteassemblies.resources.dll", satelliteResources["es-ES"].Keys);
            Assert.Contains("fr", satelliteResources.Keys);
            Assert.Contains("fr/Microsoft.CodeAnalysis.CSharp.resources.dll", satelliteResources["fr"].Keys);
            Assert.Contains("ja", satelliteResources.Keys);
            Assert.Contains("ja/standalone.resources.dll", satelliteResources["ja"].Keys);
        }
        public async Task Publish_LinkerEnabledAndBlazorWebAssemblyPreserveCollationDataSet_CollationInformationIsPreserved()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            project.Configuration = "Release";
            project.AddProjectFileContent(
                @"<PropertyGroup>
    <BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData>
</PropertyGroup>");
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            Assert.BuildPassed(result);

            var publishDirectory = project.PublishOutputDirectory;

            var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");

            // When publishing with BlazorWebAssemblyPreserveCollationData=false, collation information should be stripped out.
            Assert.AssemblyDoesNotContainResource(result, Path.Combine(blazorPublishDirectory, "_framework", "_bin", "mscorlib.dll"), "collation.cjkCHS.bin");
        }
        public async Task Publish_WithExistingWebConfig_Works()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary", "LinkBaseToWebRoot" });
            project.Configuration = "Release";

            var webConfigContents = "test webconfig contents";

            AddFileToProject(project, "web.config", webConfigContents);

            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            Assert.BuildPassed(result);

            var publishDirectory = project.PublishOutputDirectory;

            // Verify web.config
            Assert.FileExists(result, publishDirectory, "web.config");
            Assert.FileContains(result, Path.Combine(publishDirectory, "web.config"), webConfigContents);
        }
Beispiel #12
0
        public async Task Build_Hosted_Works()
        {
            // Arrange
            using var project       = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", });
            project.TargetFramework = TestFacts.DefaultNetCoreTargetFramework;
            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

            var path = Path.GetFullPath(Path.Combine(project.SolutionPath, "standalone", "bin", project.Configuration, "netstandard2.1", "standalone.dll"));

            Assert.FileDoesNotExist(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");

            var staticWebAssets = Assert.FileExists(result, buildOutputDirectory, "blazorhosted.StaticWebAssets.xml");

            Assert.FileContains(result, staticWebAssets, Path.Combine("netstandard2.1", "wwwroot"));
            Assert.FileContains(result, staticWebAssets, Path.Combine("razorclasslibrary", "wwwroot"));
            Assert.FileContains(result, staticWebAssets, Path.Combine("standalone", "wwwroot"));
        }
Beispiel #13
0
        public async Task Publish_UpdatesServiceWorkerVersionHash_WhenSourcesChange()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args : "/bl:initial.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");

            Assert.BuildPassed(result);

            var publishOutputDirectory = project.PublishOutputDirectory;

            var serviceWorkerFile = Assert.FileExists(result, publishOutputDirectory, "wwwroot", "serviceworkers", "my-service-worker.js");
            var version           = File.ReadAllLines(serviceWorkerFile).Last();
            var match             = Regex.Match(version, "\\/\\* Manifest version: (.{8}) \\*\\/");

            Assert.True(match.Success);
            Assert.Equal(2, match.Groups.Count);
            Assert.NotNull(match.Groups[1].Value);
            var capture = match.Groups[1].Value;

            // Act
            var cssFile = Path.Combine(project.DirectoryPath, "LinkToWebRoot", "css", "app.css");

            File.WriteAllText(cssFile, ".updated { }");

            // Assert
            var updatedResult = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args : "/bl:updated.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");

            Assert.BuildPassed(result);

            var updatedVersion = File.ReadAllLines(serviceWorkerFile).Last();
            var updatedMatch   = Regex.Match(updatedVersion, "\\/\\* Manifest version: (.{8}) \\*\\/");

            Assert.True(updatedMatch.Success);
            Assert.Equal(2, updatedMatch.Groups.Count);
            Assert.NotNull(updatedMatch.Groups[1].Value);
            var updatedCapture = updatedMatch.Groups[1].Value;

            Assert.NotEqual(capture, updatedCapture);
        }
Beispiel #14
0
        public async Task Build_WithI8NOption_CopiesI8NAssembliesWithLinkerEnabled()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            project.Configuration = "Debug";
            project.AddProjectFileContent(
                @"
<PropertyGroup>
    <BlazorWebAssemblyEnableLinking>true</BlazorWebAssemblyEnableLinking>
    <BlazorWebAssemblyI18NAssemblies>other</BlazorWebAssemblyI18NAssemblies>
</PropertyGroup>");

            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.Other.dll");
            Assert.FileDoesNotExist(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.West.dll");
        }
Beispiel #15
0
        public async Task Build_WithLinkerAndCompression_UpdatesFilesWhenSourcesChange()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var mainAppDll                     = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
            var mainAppDllThumbPrint           = FileThumbPrint.Create(mainAppDll);
            var mainAppCompressedDll           = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll.gz");
            var mainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);

            var blazorBootJson                     = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
            var blazorBootJsonThumbPrint           = FileThumbPrint.Create(blazorBootJson);
            var blazorBootJsonCompressed           = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json.gz");
            var blazorBootJsonCompressedThumbPrint = FileThumbPrint.Create(blazorBootJsonCompressed);

            // Act
            var programFile         = Path.Combine(project.DirectoryPath, "Program.cs");
            var programFileContents = File.ReadAllText(programFile);

            File.WriteAllText(programFile, programFileContents.Replace("args", "arguments"));
            result = await MSBuildProcessManager.DotnetMSBuild(project);

            // Assert
            Assert.BuildPassed(result);
            var newMainAppDllThumbPrint               = FileThumbPrint.Create(mainAppDll);
            var newMainAppCompressedDllThumbPrint     = FileThumbPrint.Create(mainAppCompressedDll);
            var newBlazorBootJsonThumbPrint           = FileThumbPrint.Create(blazorBootJson);
            var newBlazorBootJsonCompressedThumbPrint = FileThumbPrint.Create(blazorBootJsonCompressed);

            Assert.NotEqual(mainAppDllThumbPrint, newMainAppDllThumbPrint);
            Assert.NotEqual(mainAppCompressedDllThumbPrint, newMainAppCompressedDllThumbPrint);

            Assert.NotEqual(blazorBootJsonThumbPrint, newBlazorBootJsonThumbPrint);
            Assert.NotEqual(blazorBootJsonCompressedThumbPrint, newBlazorBootJsonCompressedThumbPrint);
        }
Beispiel #16
0
        public async Task Build_WithCustomOutputPath_Works()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });

            project.AddDirectoryBuildContent(
                @"<PropertyGroup>
    <BaseOutputPath>$(MSBuildThisFileDirectory)build\bin\</BaseOutputPath>
    <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)build\obj\</BaseIntermediateOutputPath>
</PropertyGroup>");

            var result = await MSBuildProcessManager.DotnetMSBuild(project, args : "/restore");

            Assert.BuildPassed(result);

            var compressedFilesPath = Path.Combine(
                project.DirectoryPath,
                "build",
                project.IntermediateOutputDirectory,
                "compressed");

            Assert.True(Directory.Exists(compressedFilesPath));
        }
Beispiel #17
0
        public async Task Build_CompressesAllFrameworkFiles()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

            var extensions = new[] { ".dll", ".js", ".pdb", ".wasm", ".map", ".json", ".dat" };
            // Act
            var compressedFilesPath = Path.Combine(
                project.DirectoryPath,
                project.IntermediateOutputDirectory,
                "compressed",
                "_framework");
            var compressedFiles = Directory.EnumerateFiles(
                compressedFilesPath,
                "*",
                SearchOption.AllDirectories)
                                  .Where(f => Path.GetExtension(f) == ".gz")
                                  .Select(f => Path.GetRelativePath(compressedFilesPath, f[0..^ 3]))
        public static Task <MSBuildResult> DotnetMSBuild(
            ProjectDirectory project,
            string target = "Build",
            string args   = null)
        {
            var buildArgumentList = new List <string>
            {
                // Disable node-reuse. We don't want msbuild processes to stick around
                // once the test is completed.
                "/nr:false",

                // Always generate a bin log for debugging purposes
                "/bl",
            };

            buildArgumentList.Add($"/t:{target}");
            buildArgumentList.Add($"/p:Configuration={project.Configuration}");
            buildArgumentList.Add($"/p:BlazorBuildConfiguration={ProjectDirectory.TestProjectConfiguration}");
            buildArgumentList.Add(args);

            var buildArguments = string.Join(" ", buildArgumentList);

            return(MSBuildProcessManager.RunProcessAsync(project, buildArguments));
        }
Beispiel #19
0
        public async Task Build_ServiceWorkerAssetsManifest_Works()
        {
            // Arrange
            var expectedExtensions = new[] { ".dll", ".pdb", ".js", ".wasm" };

            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            var result = await MSBuildProcessManager.DotnetMSBuild(project, args : "/p:ServiceWorkerAssetsManifest=service-worker-assets.js");

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.wasm");
            Assert.FileCountEquals(result, 1, Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "wasm"), "dotnet.*.js");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.

            var staticWebAssets = Assert.FileExists(result, buildOutputDirectory, "standalone.StaticWebAssets.xml");

            Assert.FileContains(result, staticWebAssets, Path.Combine("netstandard2.1", "wwwroot"));

            var serviceWorkerAssetsManifest = Assert.FileExists(result, buildOutputDirectory, "wwwroot", "service-worker-assets.js");
            // Trim prefix 'self.assetsManifest = ' and suffix ';'
            var manifestContents = File.ReadAllText(serviceWorkerAssetsManifest).TrimEnd()[22..^ 1];

            var manifestContentsJson = JsonDocument.Parse(manifestContents);

            Assert.True(manifestContentsJson.RootElement.TryGetProperty("assets", out var assets));
            Assert.Equal(JsonValueKind.Array, assets.ValueKind);

            var entries = assets.EnumerateArray().Select(e => e.GetProperty("url").GetString()).OrderBy(e => e).ToArray();

            Assert.All(entries, e => expectedExtensions.Contains(Path.GetExtension(e)));
        }
        public async Task Publish_LazyLoadExplicitAssembly_Debug_Works()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            project.Configuration = "Debug";

            project.AddProjectFileContent(
                @"
<ItemGroup>
    <BlazorWebAssemblyLazyLoad Include='RazorClassLibrary.dll' />
</ItemGroup>
");

            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            var publishDirectory = project.PublishOutputDirectory;

            // Verify that a blazor.boot.json file has been created
            Assert.FileExists(result, publishDirectory, "wwwroot", "_framework", "blazor.boot.json");
            // And that the assembly is in the output
            Assert.FileExists(result, publishDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.dll");

            var bootJson = ReadBootJsonData(result, Path.Combine(publishDirectory, "wwwroot", "_framework", "blazor.boot.json"));

            // And that it has been labelled as a dynamic assembly in the boot.json
            var dynamicAssemblies = bootJson.resources.dynamicAssembly;
            var assemblies        = bootJson.resources.assembly;

            Assert.NotNull(dynamicAssemblies);
            Assert.Contains("RazorClassLibrary.dll", dynamicAssemblies.Keys);
            Assert.DoesNotContain("RazorClassLibrary.dll", assemblies.Keys);

            // App assembly should not be lazy loaded
            Assert.DoesNotContain("standalone.dll", dynamicAssemblies.Keys);
            Assert.Contains("standalone.dll", assemblies.Keys);
        }
Beispiel #21
0
        public async Task Build_WithLinkOnBuildDisabled_Works()
        {
            // Arrange
            using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
            project.AddProjectFileContent(
                @"<PropertyGroup>
    <BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
</PropertyGroup>");

            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.wasm");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", DotNetJsFileName);
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.timezones.dat");

            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
        }
        public async Task Publish_HostedApp_VisualStudio_WithSatelliteAssemblies()
        {
            // Simulates publishing the same way VS does by setting BuildProjectReferences=false.
            // Arrange
            var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", "classlibrarywithsatelliteassemblies" });

            project.TargetFramework = TestFacts.DefaultNetCoreTargetFramework;
            project.Configuration   = "Release";
            var standaloneProjectDirectory = Path.Combine(project.DirectoryPath, "..", "standalone");

            // Setup the standalone app to have it's own satellite assemblies as well as transitively imported satellite assemblies.
            var resxfileInProject = Path.Combine(standaloneProjectDirectory, "Resources.ja.resx.txt");

            File.Move(resxfileInProject, Path.Combine(standaloneProjectDirectory, "Resource.ja.resx"));

            var standaloneProjFile = Path.Combine(standaloneProjectDirectory, "standalone.csproj");
            var existing           = File.ReadAllText(standaloneProjFile);
            var updatedContent     = @"
<PropertyGroup>
    <DefineConstants>$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies</DefineConstants>
</PropertyGroup>
<ItemGroup>
    <ProjectReference Include=""..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj"" />
</ItemGroup>";
            var updated            = existing.Replace("<!-- Test Placeholder -->", updatedContent);

            File.WriteAllText(standaloneProjFile, updated);

            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Build", $"/restore");

            Assert.BuildPassed(result);

            result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:BuildProjectReferences=false");

            var publishDirectory = project.PublishOutputDirectory;

            // Make sure the main project exists
            Assert.FileExists(result, publishDirectory, "blazorhosted.dll");

            var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");

            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.boot.json");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "ja", "standalone.resources.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "fr", "Microsoft.CodeAnalysis.resources.dll");

            var bootJson     = Path.Combine(project.DirectoryPath, blazorPublishDirectory, "_framework", "blazor.boot.json");
            var bootJsonFile = JsonSerializer.Deserialize <GenerateBlazorBootJson.BootJsonData>(File.ReadAllText(bootJson), new JsonSerializerOptions {
                PropertyNameCaseInsensitive = true
            });
            var satelliteResources = bootJsonFile.resources.satelliteResources;

            Assert.Contains("es-ES", satelliteResources.Keys);
            Assert.Contains("es-ES/classlibrarywithsatelliteassemblies.resources.dll", satelliteResources["es-ES"].Keys);
            Assert.Contains("fr", satelliteResources.Keys);
            Assert.Contains("fr/Microsoft.CodeAnalysis.CSharp.resources.dll", satelliteResources["fr"].Keys);
            Assert.Contains("ja", satelliteResources.Keys);
            Assert.Contains("ja/standalone.resources.dll", satelliteResources["ja"].Keys);

            VerifyServiceWorkerFiles(result, blazorPublishDirectory,
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the production service worker",
                                     assetsManifestPath: "custom-service-worker-assets.js");
        }