public async Task Publish_WithLinkerAndCompression_IsIncremental()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "blazorwasm", "razorclasslibrary" });
            var result = await MSBuildProcessManager.DotnetMSBuild(project, target : "publish");

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

            // Act
            var compressedFilesFolder = Path.Combine("..", "blazorwasm", project.IntermediateOutputDirectory, "brotli");
            var thumbPrint            = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);

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

                Assert.BuildPassed(result);

                var newThumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
                Assert.Equal(thumbPrint.Count, newThumbPrint.Count);
                for (var j = 0; j < thumbPrint.Count; j++)
                {
                    Assert.Equal(thumbPrint[j], newThumbPrint[j]);
                }
            }
        }
        public async Task Publish_WithoutLinkerAndCompression_UpdatesFilesWhenSourcesChange()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "blazorwasm", "razorclasslibrary" });
            var result = await MSBuildProcessManager.DotnetMSBuild(project, target : "publish", args : "/p:BlazorWebAssemblyEnableLinking=false");

            Assert.BuildPassed(result);

            // Act
            var mainAppDll           = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework", "blazorwasm.dll");
            var mainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);

            var mainAppCompressedDll           = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework", "blazorwasm.dll.br");
            var mainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);

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

            File.WriteAllText(programFile, programFileContents.Replace("args", "arguments"));

            // Assert
            result = await MSBuildProcessManager.DotnetMSBuild(project, target : "publish", args : "/p:BlazorWebAssemblyEnableLinking=false");

            Assert.BuildPassed(result);
            var newMainAppDllThumbPrint           = FileThumbPrint.Create(mainAppDll);
            var newMainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);

            Assert.NotEqual(mainAppDllThumbPrint, newMainAppDllThumbPrint);
            Assert.NotEqual(mainAppCompressedDllThumbPrint, newMainAppCompressedDllThumbPrint);
        }
Example #3
0
        public async Task Build_InRelease_Works()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" });
            project.Configuration = "Release";
            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", "dotnet.wasm");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", DotNetJsFileName);
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "System.Text.Json.dll"); // Verify dependencies are part of the output.
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.pdb");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "RazorClassLibrary.pdb");

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

            Assert.FileContains(result, staticWebAssets, Path.Combine(project.TargetFramework, "wwwroot"));
            Assert.FileContains(result, staticWebAssets, Path.GetFullPath(Path.Combine(project.SolutionPath, "razorclasslibrary", "wwwroot")));
        }
Example #4
0
        public async Task Build_SatelliteAssembliesAreCopiedToBuildOutput()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary", "classlibrarywithsatelliteassemblies" });
            project.AddProjectFileContent(
                @"
<PropertyGroup>
    <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", "blazorwasm.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "classlibrarywithsatelliteassemblies.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "Microsoft.CodeAnalysis.CSharp.dll");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "fr", "Microsoft.CodeAnalysis.CSharp.resources.dll"); // Verify satellite assemblies are present in the build output.

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

            Assert.FileContains(result, bootJsonPath, "\"Microsoft.CodeAnalysis.CSharp.dll\"");
            Assert.FileContains(result, bootJsonPath, "\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");
        }
Example #5
0
        public async Task Build_WithBlazorEnableTimeZoneSupportDisabled_DoesNotCopyTimeZoneInfo()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" });
            project.Configuration = "Release";
            project.AddProjectFileContent(
                @"
<PropertyGroup>
    <BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
</PropertyGroup>");

            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

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

            var runtime = bootJsonData.resources.runtime.Keys;

            Assert.Contains("dotnet.wasm", runtime);
            Assert.DoesNotContain("dotnet.timezones.dat", runtime);

            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.wasm");
            Assert.FileDoesNotExist(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.timezones.dat");
        }
Example #6
0
        public async Task Build_InRelease_ProducesBootJsonDataWithExpectedContent()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" });
            project.Configuration = "Release";
            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

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

            var runtime = bootJsonData.resources.runtime.Keys;

            Assert.Contains(DotNetJsFileName, runtime);
            Assert.Contains("dotnet.wasm", runtime);

            var assemblies = bootJsonData.resources.assembly.Keys;

            Assert.Contains("blazorwasm.dll", assemblies);
            Assert.Contains("RazorClassLibrary.dll", assemblies);
            Assert.Contains("System.Text.Json.dll", assemblies);

            var pdb = bootJsonData.resources.pdb.Keys;

            Assert.Contains("blazorwasm.pdb", pdb);
            Assert.Contains("RazorClassLibrary.pdb", pdb);
            Assert.Null(bootJsonData.resources.satelliteResources);
        }
Example #7
0
        public async Task Build_WithAspNetCoreFrameworkReference_Fails()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm-fxref");

            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildError(result, "BLAZORSDK1001");
        }
Example #8
0
        public async Task Publish_HostedApp_WithRid_Works()
        {
            // Arrange
            using var project         = ProjectDirectory.Create("blazorhosted-rid", additionalProjects: new[] { "blazorwasm", "razorclasslibrary", });
            project.RuntimeIdentifier = "linux-x64";
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            AssertRIDPublishOuput(project, result);
        }
Example #9
0
        public async Task Publish_HostedApp_DefaultSettings_Works()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "blazorwasm", "razorclasslibrary", });
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            Assert.BuildPassed(result);

            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, "blazorwasm.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", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll"); // Verify dependencies are part of the output.

            // Verify project references appear as static web assets
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "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);

            // Verify compression works
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br");

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

            VerifyTypeGranularTrimming(result, blazorPublishDirectory);
        }
        public async Task Publish_HostedApp_WithRid_Works()
        {
            // Arrange
            using var project         = ProjectDirectory.Create("blazorhosted-rid", additionalProjects: new[] { "blazorwasm", "razorclasslibrary", });
            project.RuntimeIdentifier = "linux-x64";
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            Assert.BuildPassed(result);

            var publishDirectory = project.PublishOutputDirectory;

            // Make sure the main project exists
            Assert.FileExists(result, publishDirectory, "blazorhosted-rid.dll");
            Assert.FileExists(result, publishDirectory, "libhostfxr.so"); // Verify that we're doing a self-contained deployment

            Assert.FileExists(result, publishDirectory, "RazorClassLibrary.dll");
            Assert.FileExists(result, publishDirectory, "blazorwasm.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", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll"); // Verify dependencies are part of the output.

            // Verify project references appear as static web assets
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "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);

            // Verify compression works
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br");

            VerifyServiceWorkerFiles(result, blazorPublishDirectory,
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the production service worker",
                                     assetsManifestPath: "custom-service-worker-assets.js");
        }
Example #11
0
        public async Task ManualServerShutdown_NoPipeName_ShutsDownServer()
        {
            // We are trying to test whether the correct pipe name is generated (from the location of rzc tool)
            // when we don't explicitly specify a pipe name.

            // Publish rzc tool to a temporary path. This is the location based on which the pipe name is generated.
            var repositoryRoot        = ProjectDirectory.SearchUp(AppContext.BaseDirectory, "global.json");
            var solutionRoot          = Path.Combine(repositoryRoot, "src", "Razor");
            var toolAssemblyDirectory = Path.Combine(solutionRoot, "src", "Microsoft.AspNetCore.Razor.Tools");
            var toolAssemblyPath      = Path.Combine(toolAssemblyDirectory, "Microsoft.AspNetCore.Razor.Tools.csproj");
            var projectDirectory      = new TestProjectDirectory(solutionRoot, toolAssemblyDirectory, toolAssemblyPath);
            var publishDir            = Path.Combine(Path.GetTempPath(), "Razor", Path.GetRandomFileName(), "RzcPublish");
            var publishResult         = await MSBuildProcessManager.RunProcessAsync(projectDirectory, $"/t:Publish /p:PublishDir=\"{publishDir}\"");

            try
            {
                // Make sure publish succeeded.
                Assert.BuildPassed(publishResult);

                // Run the build using the published tool
                var toolAssembly = Path.Combine(publishDir, "rzc.dll");
                var result       = await DotnetMSBuild(
                    "Build",
                    $"/p:_RazorForceBuildServer=true /p:_RazorToolAssembly={toolAssembly}",
                    suppressBuildServer : true); // We don't want to specify a pipe name

                Assert.BuildPassed(result);

                // Manually shutdown the server
                var processStartInfo = new ProcessStartInfo()
                {
                    WorkingDirectory       = publishDir,
                    UseShellExecute        = false,
                    RedirectStandardError  = true,
                    RedirectStandardOutput = true,
                    FileName  = "dotnet",
                    Arguments = $"{toolAssembly} shutdown -w"
                };

                var logFilePath = Path.Combine(publishDir, "out.log");
                processStartInfo.Environment.Add("RAZORBUILDSERVER_LOG", logFilePath);
                var shutdownResult = await MSBuildProcessManager.RunProcessCoreAsync(processStartInfo);

                Assert.Equal(0, shutdownResult.ExitCode);
                var output = await File.ReadAllTextAsync(logFilePath);

                Assert.Contains("shut down completed", output);
            }
            finally
            {
                // Finally delete the temporary publish directory
                ProjectDirectory.CleanupDirectory(publishDir);
            }
        }
        internal Task <MSBuildResult> DotnetMSBuild(
            string target,
            string args                           = null,
            bool suppressTimeout                  = false,
            bool suppressBuildServer              = false,
            string buildServerPipeName            = null,
            MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet)
        {
            var timeout = suppressTimeout ? (TimeSpan?)Timeout.InfiniteTimeSpan : 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",

                // Let the test app know it is running as part of a test.
                "/p:RunningAsTest=true",

                $"/p:MicrosoftNETCoreAppRuntimeVersion={BuildVariables.MicrosoftNETCoreAppRuntimeVersion}",
                $"/p:MicrosoftNetCompilersToolsetPackageVersion={BuildVariables.MicrosoftNetCompilersToolsetPackageVersion}",
                $"/p:RazorSdkDirectoryRoot={BuildVariables.RazorSdkDirectoryRoot}",
                $"/p:RepoRoot={BuildVariables.RepoRoot}",
            };

            if (!suppressBuildServer)
            {
                buildArgumentList.Add($@"/p:_RazorBuildServerPipeName=""{buildServerPipeName ?? BuildServer.PipeName}""");
            }

            if (!string.IsNullOrEmpty(target))
            {
                buildArgumentList.Add($"/t:{target}");
            }
            else
            {
                buildArgumentList.Add($"/t:Build");
            }

            buildArgumentList.Add($"/p:Configuration={Configuration} {args}");
            var buildArguments = string.Join(" ", buildArgumentList);

            return(MSBuildProcessManager.RunProcessAsync(
                       Project,
                       buildArguments,
                       timeout,
                       msBuildProcessKind));
        }
        internal async Task PackAsync(ITestOutputHelper output)
        {
            if (_packed)
            {
                return;
            }

            var projectsToPack = GetProjectsToPack();

            foreach (var project in projectsToPack)
            {
                output.WriteLine(project);
            }

            foreach (var project in projectsToPack)
            {
                var psi = new ProcessStartInfo
                {
                    FileName = DotNetMuxer.MuxerPathOrDefault(),
#if DEBUG
                    Arguments = "msbuild /t:Restore;Pack /p:Configuration=Debug",
#else
                    Arguments = "msbuild /t:Restore;Pack /p:Configuration=Release",
#endif
                    WorkingDirectory       = project,
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true
                };

                for (int i = 0; i < MaxPackRetries; i++)
                {
                    try
                    {
                        var result = await MSBuildProcessManager.RunProcessCoreAsync(
                            psi,
                            TimeSpan.FromMinutes(MaxPackTimeoutInMinutes));

                        output.WriteLine(result.Output);
                        Assert.Equal(0, result.ExitCode);
                        break;
                    }
                    catch
                    {
                        await Task.Delay(1000);
                    }
                }
            }

            _packed = true;
        }
Example #14
0
        public async Task Build_WithCustomOutputPath_Works()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm", 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);
        }
        public async Task Build_SatelliteAssembliesFileIsPreserved()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm", 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.satelliteasm.props");
            var satelliteAssemblyFile      = Path.Combine(project.BuildOutputDirectory, "wwwroot", "_framework", "ja", "blazorwasm.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 <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/blazorwasm.resources.dll", Assert.Single(kvp.Value).Key);
            }
        }
Example #16
0
        public async Task Publish_WithTrimmingdDisabled_Works()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" });
            project.AddProjectFileContent(
                @"<PropertyGroup>
    <PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>");

            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", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll"); // Verify dependencies are part of the output.

            // Verify compression works
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br"); //

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

            // Verify referenced static web assets
            Assert.FileExists(result, blazorPublishDirectory, "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
            Assert.FileExists(result, blazorPublishDirectory, "_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");

            // Verify assemblies are not trimmed
            var loggingAssemblyPath = Path.Combine(blazorPublishDirectory, "_framework", "Microsoft.Extensions.Logging.Abstractions.dll");

            Assert.AssemblyContainsType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.Abstractions.NullLogger");
        }
Example #17
0
        internal Task <MSBuildResult> DotnetMSBuild(
            string target,
            string args          = null,
            bool suppressRestore = false,
            bool suppressTimeout = false,
            MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet)
        {
            var timeout         = suppressTimeout ? (TimeSpan?)Timeout.InfiniteTimeSpan : null;
            var restoreArgument = suppressRestore ? "" : "/restore";

            return(MSBuildProcessManager.RunProcessAsync(
                       Project,
                       $"{restoreArgument} /t:{target} /p:Configuration={Configuration} {args}",
                       timeout,
                       msBuildProcessKind));
        }
Example #18
0
        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[] { "blazorwasm", "razorclasslibrary", });
            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", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.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 compression works
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "dotnet.wasm.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "RazorClassLibrary.dll.br");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.dll.br");

            // 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");
        }
Example #19
0
        public async Task Publish_WithDefaultSettings_Works()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("blazorwasm", 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", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.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");

            VerifyTypeGranularTrimming(result, blazorPublishDirectory);
        }
Example #20
0
        public async Task Build_Hosted_Works()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "blazorwasm", "razorclasslibrary", });
            var result = await MSBuildProcessManager.DotnetMSBuild(project);

            Assert.BuildPassed(result);

            var buildOutputDirectory = project.BuildOutputDirectory;

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

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

            Assert.FileContains(result, staticWebAssets, Path.Combine("net6.0", "wwwroot"));
            Assert.FileContains(result, staticWebAssets, Path.Combine("razorclasslibrary", "wwwroot"));
            Assert.FileContains(result, staticWebAssets, Path.Combine("blazorwasm", "wwwroot"));
        }
Example #21
0
        public async Task Publish_LazyLoadExplicitAssembly_InvalidAssembly()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" });
            project.Configuration = "Release";

            project.AddProjectFileContent(
                @"
<ItemGroup>
    <BlazorWebAssemblyLazyLoad Include='RazorClassLibraryInvalid.dll' />
</ItemGroup>
");
            // Act
            var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");

            // Assert
            Assert.BuildError(result, "BLAZORSDK1001");
            Assert.BuildFailed(result);
        }
Example #22
0
        public async Task Publish_WithNoBuild_Works()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm", 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", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.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 Build_SatelliteAssembliesFileIsDeleted_IfAllSatelliteFilesAreRemoved()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm", 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.satelliteasm.props");
            var satelliteAssemblyFile      = Path.Combine(project.BuildOutputDirectory, "wwwroot", "_framework", "ja", "blazorwasm.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 <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/blazorwasm.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 <BootJsonData>(File.ReadAllText(bootJson), new JsonSerializerOptions {
                PropertyNameCaseInsensitive = true
            });
            satelliteResources = bootJsonFile.resources.satelliteResources;
            Assert.Null(satelliteResources);
        }
Example #24
0
        public async Task Publish_WithExistingWebConfig_Works()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("blazorwasm", 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);
        }
Example #25
0
        public async Task Build_ServiceWorkerAssetsManifest_Works()
        {
            // Arrange
            var expectedExtensions = new[] { ".dll", ".pdb", ".js", ".wasm" };

            using var project = ProjectDirectory.Create("blazorwasm", 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", "dotnet.wasm");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", DotNetJsFileName);
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm.dll");

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

            Assert.FileContains(result, staticWebAssets, Path.Combine(project.TargetFramework, "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)));

            VerifyServiceWorkerFiles(result,
                                     Path.Combine(buildOutputDirectory, "wwwroot"),
                                     serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
                                     serviceWorkerContent: "// This is the development service worker",
                                     assetsManifestPath: "service-worker-assets.js");
        }
Example #26
0
        public async Task Publish_UpdatesServiceWorkerVersionHash_WhenSourcesChange()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm", 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
            result = 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);
        }
Example #27
0
        public async Task Publish_InRelease_Works()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary", "LinkBaseToWebRoot" });
            project.Configuration = "Release";
            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", "dotnet.wasm");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", DotNetJsFileName);
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazorwasm.dll");
            Assert.FileExists(result, blazorPublishDirectory, "_framework", "System.Text.Json.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);
        }
        public async Task BuildMinimal_Works()
        {
            // Arrange
            // Minimal has no project references, service worker etc. This is pretty close to the project template.
            using var project = ProjectDirectory.Create("blazorwasm-minimal");
            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", "dotnet.wasm");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "dotnet.wasm.gz");
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", DotNetJsFileName);
            Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazorwasm-minimal.dll");

            var staticWebAssets = Assert.FileExists(result, buildOutputDirectory, "blazorwasm-minimal.StaticWebAssets.xml");

            Assert.FileContains(result, staticWebAssets, Path.Combine(project.TargetFramework, "wwwroot"));
        }
        public async Task Publish_CompressesAllFrameworkFiles()
        {
            // Arrange
            using var project = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" });
            var result = await MSBuildProcessManager.DotnetMSBuild(project, target : "publish");

            Assert.BuildPassed(result);

            var extensions = new[] { ".dll", ".js", ".pdb", ".wasm", ".map", ".json", ".dat" };

            // Act
            var frameworkFilesPath = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework");

            foreach (var file in Directory.EnumerateFiles(frameworkFilesPath, "*", new EnumerationOptions {
                RecurseSubdirectories = true,
            }))
            {
                var extension = Path.GetExtension(file);
                if (extension != ".br" && extension != ".gz")
                {
                    Assert.FileExists(result, file + ".br");
                }
            }
        }
Example #30
0
        public async Task Publish_LazyLoadExplicitAssembly_Debug_Works()
        {
            // Arrange
            using var project     = ProjectDirectory.Create("blazorwasm", 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", "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 lazyAssemblies = bootJson.resources.lazyAssembly;
            var assemblies     = bootJson.resources.assembly;

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

            // App assembly should not be lazy loaded
            Assert.DoesNotContain("blazorwasm.dll", lazyAssemblies.Keys);
            Assert.Contains("blazorwasm.dll", assemblies.Keys);
        }