diff --git a/.appveyor.yml b/.appveyor.yml index 73071d19bd..7f621f2e90 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,13 +16,13 @@ test: 'off' deploy: 'off' os: Visual Studio 2017 Preview build_script: - - build.cmd /p:SkipTests=true + - build.cmd /p:SkipTests=true /p:BlazorOutputStatistics=true before_test: - choco install googlechrome --ignore-checksum - npm install -g selenium-standalone - selenium-standalone install - ps: $SeleniumProcess = Start-Process "selenium-standalone" -ArgumentList "start" -PassThru test_script: - - build.cmd /t:Test /p:BlazorAllTests=true + - build.cmd /t:Test /p:BlazorAllTests=true /p:BlazorOutputStatistics=true after_test: - ps: Stop-Process -Id $SeleniumProcess.Id diff --git a/.gitignore b/.gitignore index 23cf891bc7..9b152674da 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ obj/ launchSettings.json artifacts/ msbuild.binlog +.vscode/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index c116645850..69592e6a5a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,6 @@ install: - curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel Current --version latest --install-dir "$DOTNET_INSTALL_DIR" - export PATH="$DOTNET_INSTALL_DIR:$PATH" script: - - ./build.sh /p:SkipTests=true + - ./build.sh /p:SkipTests=true /p:BlazorOutputStatistics=true - selenium-standalone start & - ./build.sh /t:Test /p:BlazorAllTests=true diff --git a/Blazor.sln b/Blazor.sln index 25459a67fa..c1c5691370 100644 --- a/Blazor.sln +++ b/Blazor.sln @@ -12,16 +12,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mono", "mono", "{7B5CAAB1-A src\mono\mono.targets = src\mono\mono.targets EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Mono", "src\Microsoft.AspNetCore.Blazor.Mono\Microsoft.AspNetCore.Blazor.Mono.csproj", "{39FEC72D-AF52-47A3-B63D-7BF0E4335248}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanity", "samples\MonoSanity\MonoSanity.csproj", "{7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Server", "src\Microsoft.AspNetCore.Blazor.Server\Microsoft.AspNetCore.Blazor.Server.csproj", "{5A694793-3257-4D37-BB74-4A41B3894685}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{ADA3AE29-F6DE-49F6-8C7C-B321508CAE8E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Mono.Test", "test\Microsoft.AspNetCore.Blazor.Mono.Test\Microsoft.AspNetCore.Blazor.Mono.Test.csproj", "{118484D3-3993-45CE-97C1-6F28A517529B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.E2ETest", "test\Microsoft.AspNetCore.Blazor.E2ETest\Microsoft.AspNetCore.Blazor.E2ETest.csproj", "{5BC2A10D-B6CA-43AE-B73C-2A41AE1039F9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanityClient", "samples\MonoSanityClient\MonoSanityClient.csproj", "{06AAAE9E-96DE-4574-97DA-9C4C7D9FE990}" @@ -40,10 +36,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneApp", "samples\St EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MonoSanity", "MonoSanity", "{2A076721-6081-4517-8329-B9E5110D6DAC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Common", "src\Microsoft.AspNetCore.Blazor.Common\Microsoft.AspNetCore.Blazor.Common.csproj", "{21EF76A4-63CC-455D-907C-F86C9E442CEC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Common.Test", "test\Microsoft.AspNetCore.Blazor.Common.Test\Microsoft.AspNetCore.Blazor.Common.Test.csproj", "{7F0BF3EA-6985-49F6-8070-0BBA41448BB0}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Build.Test", "test\Microsoft.AspNetCore.Blazor.Build.Test\Microsoft.AspNetCore.Blazor.Build.Test.csproj", "{709C7EBE-EB93-4F6D-9491-D714B0D2E898}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.Build", "src\Microsoft.AspNetCore.Blazor.Build\Microsoft.AspNetCore.Blazor.Build.csproj", "{8B3D0F1C-0E38-4E6D-BFF1-C4FDA0CD9815}" @@ -103,14 +95,6 @@ Global ReleaseNoVSIX|Any CPU = ReleaseNoVSIX|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {39FEC72D-AF52-47A3-B63D-7BF0E4335248}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {39FEC72D-AF52-47A3-B63D-7BF0E4335248}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39FEC72D-AF52-47A3-B63D-7BF0E4335248}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {39FEC72D-AF52-47A3-B63D-7BF0E4335248}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {39FEC72D-AF52-47A3-B63D-7BF0E4335248}.Release|Any CPU.ActiveCfg = Release|Any CPU - {39FEC72D-AF52-47A3-B63D-7BF0E4335248}.Release|Any CPU.Build.0 = Release|Any CPU - {39FEC72D-AF52-47A3-B63D-7BF0E4335248}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {39FEC72D-AF52-47A3-B63D-7BF0E4335248}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU @@ -127,14 +111,6 @@ Global {5A694793-3257-4D37-BB74-4A41B3894685}.Release|Any CPU.Build.0 = Release|Any CPU {5A694793-3257-4D37-BB74-4A41B3894685}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU {5A694793-3257-4D37-BB74-4A41B3894685}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {118484D3-3993-45CE-97C1-6F28A517529B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {118484D3-3993-45CE-97C1-6F28A517529B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {118484D3-3993-45CE-97C1-6F28A517529B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {118484D3-3993-45CE-97C1-6F28A517529B}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {118484D3-3993-45CE-97C1-6F28A517529B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {118484D3-3993-45CE-97C1-6F28A517529B}.Release|Any CPU.Build.0 = Release|Any CPU - {118484D3-3993-45CE-97C1-6F28A517529B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {118484D3-3993-45CE-97C1-6F28A517529B}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {5BC2A10D-B6CA-43AE-B73C-2A41AE1039F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5BC2A10D-B6CA-43AE-B73C-2A41AE1039F9}.Debug|Any CPU.Build.0 = Debug|Any CPU {5BC2A10D-B6CA-43AE-B73C-2A41AE1039F9}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU @@ -191,22 +167,6 @@ Global {B241434A-1642-44CC-AE9A-2012B5C5BD02}.Release|Any CPU.Build.0 = Release|Any CPU {B241434A-1642-44CC-AE9A-2012B5C5BD02}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU {B241434A-1642-44CC-AE9A-2012B5C5BD02}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {21EF76A4-63CC-455D-907C-F86C9E442CEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {21EF76A4-63CC-455D-907C-F86C9E442CEC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21EF76A4-63CC-455D-907C-F86C9E442CEC}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {21EF76A4-63CC-455D-907C-F86C9E442CEC}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {21EF76A4-63CC-455D-907C-F86C9E442CEC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {21EF76A4-63CC-455D-907C-F86C9E442CEC}.Release|Any CPU.Build.0 = Release|Any CPU - {21EF76A4-63CC-455D-907C-F86C9E442CEC}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {21EF76A4-63CC-455D-907C-F86C9E442CEC}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0}.Release|Any CPU.Build.0 = Release|Any CPU - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {709C7EBE-EB93-4F6D-9491-D714B0D2E898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {709C7EBE-EB93-4F6D-9491-D714B0D2E898}.Debug|Any CPU.Build.0 = Debug|Any CPU {709C7EBE-EB93-4F6D-9491-D714B0D2E898}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU @@ -347,10 +307,8 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {7B5CAAB1-A3EB-44F7-87E3-A13ED89FC17D} = {B867E038-B3CE-43E3-9292-61568C46CDEB} - {39FEC72D-AF52-47A3-B63D-7BF0E4335248} = {B867E038-B3CE-43E3-9292-61568C46CDEB} {7C53BB6B-5906-4753-B507-C9FCC2F7E5B7} = {2A076721-6081-4517-8329-B9E5110D6DAC} {5A694793-3257-4D37-BB74-4A41B3894685} = {B867E038-B3CE-43E3-9292-61568C46CDEB} - {118484D3-3993-45CE-97C1-6F28A517529B} = {ADA3AE29-F6DE-49F6-8C7C-B321508CAE8E} {5BC2A10D-B6CA-43AE-B73C-2A41AE1039F9} = {ADA3AE29-F6DE-49F6-8C7C-B321508CAE8E} {06AAAE9E-96DE-4574-97DA-9C4C7D9FE990} = {2A076721-6081-4517-8329-B9E5110D6DAC} {BB34336F-E68E-4411-9805-CAAA919F5EA1} = {B867E038-B3CE-43E3-9292-61568C46CDEB} @@ -360,8 +318,6 @@ Global {7FD8C650-74B3-4153-AEA1-00F4F6AF393D} = {B867E038-B3CE-43E3-9292-61568C46CDEB} {B241434A-1642-44CC-AE9A-2012B5C5BD02} = {F5FDD4E5-6A52-4A86-BE5E-5E42CB1DC8DA} {2A076721-6081-4517-8329-B9E5110D6DAC} = {F5FDD4E5-6A52-4A86-BE5E-5E42CB1DC8DA} - {21EF76A4-63CC-455D-907C-F86C9E442CEC} = {B867E038-B3CE-43E3-9292-61568C46CDEB} - {7F0BF3EA-6985-49F6-8070-0BBA41448BB0} = {ADA3AE29-F6DE-49F6-8C7C-B321508CAE8E} {709C7EBE-EB93-4F6D-9491-D714B0D2E898} = {ADA3AE29-F6DE-49F6-8C7C-B321508CAE8E} {8B3D0F1C-0E38-4E6D-BFF1-C4FDA0CD9815} = {B867E038-B3CE-43E3-9292-61568C46CDEB} {8A19B1CE-9B62-4440-93B3-152DDBB39D0A} = {B867E038-B3CE-43E3-9292-61568C46CDEB} diff --git a/samples/HostedInAspNet.Client/HostedInAspNet.Client.csproj b/samples/HostedInAspNet.Client/HostedInAspNet.Client.csproj index 6e1a1b5904..736c817a6f 100644 --- a/samples/HostedInAspNet.Client/HostedInAspNet.Client.csproj +++ b/samples/HostedInAspNet.Client/HostedInAspNet.Client.csproj @@ -3,6 +3,7 @@ netstandard2.0 Exe + true diff --git a/samples/MonoSanityClient/MonoSanityClient.csproj b/samples/MonoSanityClient/MonoSanityClient.csproj index dce14f8fe8..e111ca166b 100644 --- a/samples/MonoSanityClient/MonoSanityClient.csproj +++ b/samples/MonoSanityClient/MonoSanityClient.csproj @@ -1,8 +1,9 @@ - + netstandard2.0 false + false diff --git a/samples/StandaloneApp/StandaloneApp.csproj b/samples/StandaloneApp/StandaloneApp.csproj index 253651db56..8e6c89d340 100644 --- a/samples/StandaloneApp/StandaloneApp.csproj +++ b/samples/StandaloneApp/StandaloneApp.csproj @@ -2,7 +2,7 @@ netstandard2.0 - + true dotnet run --project ../../src/Microsoft.AspNetCore.Blazor.Cli serve diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/BlazorBrowserFileProvider.cs b/src/Microsoft.AspNetCore.Blazor.Browser.JS/BlazorBrowserFileProvider.cs deleted file mode 100644 index b14d18d5c9..0000000000 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/BlazorBrowserFileProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Blazor.Internal.Common.FileProviders; -using Microsoft.Extensions.FileProviders; - -namespace Microsoft.AspNetCore.Blazor.Browser.JS -{ - public static class BlazorBrowserFileProvider - { - public static IFileProvider Instance = new EmbeddedResourceFileProvider( - typeof(BlazorBrowserFileProvider).Assembly, - "blazor."); - } -} diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/Microsoft.AspNetCore.Blazor.Browser.JS.csproj b/src/Microsoft.AspNetCore.Blazor.Browser.JS/Microsoft.AspNetCore.Blazor.Browser.JS.csproj index b475b5b7d7..eeef6cbf15 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/Microsoft.AspNetCore.Blazor.Browser.JS.csproj +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/Microsoft.AspNetCore.Blazor.Browser.JS.csproj @@ -15,10 +15,6 @@ - - - - diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/package-lock.json b/src/Microsoft.AspNetCore.Blazor.Browser.JS/package-lock.json index cf7f6a5473..b74213bea2 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/package-lock.json +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/package-lock.json @@ -1830,15 +1830,6 @@ "xtend": "4.0.1" } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -1872,6 +1863,15 @@ } } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", diff --git a/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/BuildCommand.cs b/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/BuildCommand.cs deleted file mode 100644 index 771611e332..0000000000 --- a/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/BuildCommand.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Blazor.Build.Core; -using Microsoft.Extensions.CommandLineUtils; -using System; - -namespace Microsoft.AspNetCore.Blazor.Build.Cli.Commands -{ - internal class BuildCommand - { - public static void Command(CommandLineApplication command) - { - var clientAssemblyPath = command.Argument("assembly", - "Specifies the assembly for the Blazor application."); - var webRootPath = command.Option("--webroot", - "Specifies the path to the directory containing static files to be served", - CommandOptionType.SingleValue); - - command.OnExecute(() => - { - if (string.IsNullOrEmpty(clientAssemblyPath.Value)) - { - Console.WriteLine($"ERROR: No value specified for required argument '{clientAssemblyPath.Name}'."); - return 1; - } - - try - { - Console.WriteLine($"Building Blazor app from {clientAssemblyPath.Value}..."); - AppBuilder.Execute(clientAssemblyPath.Value, webRootPath.HasValue() ? webRootPath.Value() : null); - return 0; - } - catch (Exception ex) - { - Console.WriteLine($"ERROR: {ex.Message}"); - Console.WriteLine(ex.StackTrace); - return 1; - } - }); - } - } -} diff --git a/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/BuildIndexHtmlCommand.cs b/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/BuildIndexHtmlCommand.cs new file mode 100644 index 0000000000..02e188c1cb --- /dev/null +++ b/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/BuildIndexHtmlCommand.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.CommandLineUtils; + +namespace Microsoft.AspNetCore.Blazor.Build.Cli.Commands +{ + internal class BuildIndexHtmlCommand + { + public static void Command(CommandLineApplication command) + { + var clientPage = command.Option("--html-page", + "Path to the HTML Page containing the Blazor bootstrap script tag.", + CommandOptionType.SingleValue); + + var references = command.Option("--reference", + "The path from the _bin folder to a given referenced dll file (Typically just the dll name)", + CommandOptionType.MultipleValue); + + var outputPath = command.Option("--output", + "Path to the output file", + CommandOptionType.SingleValue); + + var mainAssemblyPath = command.Argument("assembly", + "Path to the assembly containing the entry point of the application."); + + command.OnExecute(() => + { + if (string.IsNullOrEmpty(mainAssemblyPath.Value) || + !clientPage.HasValue() || !references.HasValue() || !outputPath.HasValue()) + { + command.ShowHelp(command.Name); + return 1; + } + + try + { + IndexHtmlWriter.UpdateIndex(clientPage.Value(), mainAssemblyPath.Value, references.Values.ToArray(), outputPath.Value()); + return 0; + } + catch (Exception ex) + { + Console.WriteLine($"ERROR: {ex.Message}"); + Console.WriteLine(ex.StackTrace); + return 1; + } + }); + } + } +} diff --git a/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/ResolveRuntimeDependenciesCommand.cs b/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/ResolveRuntimeDependenciesCommand.cs new file mode 100644 index 0000000000..4a892f2872 --- /dev/null +++ b/src/Microsoft.AspNetCore.Blazor.Build/Cli/Commands/ResolveRuntimeDependenciesCommand.cs @@ -0,0 +1,56 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.CommandLineUtils; + +namespace Microsoft.AspNetCore.Blazor.Build.Cli.Commands +{ + class ResolveRuntimeDependenciesCommand + { + public static void Command(CommandLineApplication command) + { + var references = command.Option("--reference", + "Full path to a referenced assembly file", + CommandOptionType.MultipleValue); + + var baseClassLibrary = command.Option("--base-class-library", + "Full path to a directory in which BCL assemblies can be found", + CommandOptionType.MultipleValue); + + var outputPath = command.Option("--output", + "Path to the output file that will contain the list with the full paths of the resolved assemblies", + CommandOptionType.SingleValue); + + var mainAssemblyPath = command.Argument("assembly", + "Path to the assembly containing the entry point of the application."); + + command.OnExecute(() => + { + if (string.IsNullOrEmpty(mainAssemblyPath.Value) || + !baseClassLibrary.HasValue() || !outputPath.HasValue()) + { + command.ShowHelp(command.Name); + return 1; + } + + try + { + RuntimeDependenciesResolver.ResolveRuntimeDependencies( + mainAssemblyPath.Value, + references.Values.ToArray(), + baseClassLibrary.Values.ToArray(), + outputPath.Value()); + + return 0; + } + catch (Exception ex) + { + Console.WriteLine($"ERROR: {ex.Message}"); + Console.WriteLine(ex.StackTrace); + return 1; + } + }); + } + } +} diff --git a/src/Microsoft.AspNetCore.Blazor.Build/Cli/Program.cs b/src/Microsoft.AspNetCore.Blazor.Build/Cli/Program.cs index d8022c7ce7..db72e2ba8f 100644 --- a/src/Microsoft.AspNetCore.Blazor.Build/Cli/Program.cs +++ b/src/Microsoft.AspNetCore.Blazor.Build/Cli/Program.cs @@ -16,7 +16,8 @@ namespace Microsoft.AspNetCore.Blazor.Build }; app.HelpOption("-?|-h|--help"); - app.Command("build", BuildCommand.Command); + app.Command("build", BuildIndexHtmlCommand.Command); + app.Command("resolve-dependencies", ResolveRuntimeDependenciesCommand.Command); if (args.Length > 0) { diff --git a/src/Microsoft.AspNetCore.Blazor.Build/Core/AppBuilder.cs b/src/Microsoft.AspNetCore.Blazor.Build/Core/AppBuilder.cs deleted file mode 100644 index 041e2648d0..0000000000 --- a/src/Microsoft.AspNetCore.Blazor.Build/Core/AppBuilder.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Blazor.Build.Core.FileSystem; -using System.IO; - -namespace Microsoft.AspNetCore.Blazor.Build.Core -{ - internal static class AppBuilder - { - internal static void Execute(string assemblyPath, string webRootPath) - { - var clientFileSystem = new ClientFileProvider(assemblyPath, webRootPath); - var distDirPath = Path.Combine(Path.GetDirectoryName(assemblyPath), "dist"); - FileUtil.WriteFileProviderToDisk(clientFileSystem, distDirPath, clean: true); - } - } -} diff --git a/src/Microsoft.AspNetCore.Blazor.Build/Core/FileSystem/ClientFileProvider.cs b/src/Microsoft.AspNetCore.Blazor.Build/Core/FileSystem/ClientFileProvider.cs deleted file mode 100644 index 8ff6e301e7..0000000000 --- a/src/Microsoft.AspNetCore.Blazor.Build/Core/FileSystem/ClientFileProvider.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Blazor.Internal.Common.FileProviders; -using Microsoft.Extensions.FileProviders; -using Mono.Cecil; -using System; -using System.Collections.Generic; -using System.IO; - -namespace Microsoft.AspNetCore.Blazor.Build.Core.FileSystem -{ - internal class ClientFileProvider : CompositeMountedFileProvider - { - public ClientFileProvider(string clientAssemblyPath, string webRootPath) - : base(GetContents(clientAssemblyPath, webRootPath)) - { - } - - private static (string, IFileProvider)[] GetContents(string clientAssemblyPath, string webRootPath) - { - var fileProviders = new List<(string, IFileProvider)>(); - - // There must always be a client assembly, and we always supply a /_framework - // directory containing everything needed to execute it - if (!File.Exists(clientAssemblyPath)) - { - throw new FileNotFoundException($"Could not find client assembly file at '{clientAssemblyPath}'.", clientAssemblyPath); - } - var frameworkFileProvider = new FrameworkFileProvider(clientAssemblyPath); - fileProviders.Add(("/_framework", frameworkFileProvider)); - - // The web root directory is optional. If it exists and contains /index.html, then - // we will inject the relevant "; - var htmlTemplateSuffix = @" - - "; - var htmlTemplate = - $@"{htmlTemplatePrefix} - - {htmlTemplateSuffix}"; - var dependencies = new IFileInfo[] - { - new TestFileInfo("System.Abc.dll"), - new TestFileInfo("MyApp.ClassLib.dll"), - }; - var instance = new IndexHtmlFileProvider( - htmlTemplate, "MyApp.Entrypoint", "MyNamespace.MyType::MyMethod", dependencies); - - // Act - var file = instance.GetFileInfo("/index.html"); - var fileContents = ReadString(file); - - // Assert: Start and end is not modified (including formatting) - Assert.StartsWith(htmlTemplatePrefix, fileContents); - Assert.EndsWith(htmlTemplateSuffix, fileContents); - - // Assert: Boot tag is correct - var scriptTagText = fileContents.Substring(htmlTemplatePrefix.Length, fileContents.Length - htmlTemplatePrefix.Length - htmlTemplateSuffix.Length); - var parsedHtml = new HtmlParser().Parse("" + scriptTagText + ""); - var scriptElem = parsedHtml.Body.QuerySelector("script"); - Assert.False(scriptElem.HasChildNodes); - Assert.Equal("_framework/blazor.js", scriptElem.GetAttribute("src")); - Assert.Equal("MyApp.Entrypoint.dll", scriptElem.GetAttribute("main")); - Assert.Equal("MyNamespace.MyType::MyMethod", scriptElem.GetAttribute("entrypoint")); - Assert.Equal("System.Abc.dll,MyApp.ClassLib.dll", scriptElem.GetAttribute("references")); - Assert.False(scriptElem.HasAttribute("type")); - Assert.Equal(string.Empty, scriptElem.Attributes["custom1"].Value); - Assert.Equal("value", scriptElem.Attributes["custom2"].Value); - } - - [Fact] - public void SuppliesHtmlTemplateUnchangedIfNoBootScriptPresent() - { - // Arrange - var htmlTemplate = "

Hello

Some text"; - var dependencies = new IFileInfo[] - { - new TestFileInfo("System.Abc.dll"), - new TestFileInfo("MyApp.ClassLib.dll"), - }; - var instance = new IndexHtmlFileProvider( - htmlTemplate, "MyApp.Entrypoint", "MyNamespace.MyType::MyMethod", dependencies); - - // Act - var file = instance.GetFileInfo("/index.html"); - - // Assert - Assert.Equal(htmlTemplate, ReadString(file)); - } - - private static string ReadString(IFileInfo file) - { - using (var stream = file.CreateReadStream()) - using (var sr = new StreamReader(stream)) - { - return sr.ReadToEnd(); - } - } - - class TestFileInfo : IFileInfo - { - public TestFileInfo(string physicalPath) - { - PhysicalPath = physicalPath; - } - - public bool Exists => true; - - public long Length => throw new NotImplementedException(); - - public string PhysicalPath { get; } - - public string Name => Path.GetFileName(PhysicalPath); - - public DateTimeOffset LastModified => throw new NotImplementedException(); - - public bool IsDirectory => false; - - public Stream CreateReadStream() => throw new NotImplementedException(); - } - } -} diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/IndexHtmlWriterTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/IndexHtmlWriterTest.cs new file mode 100644 index 0000000000..a37c7117d2 --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/IndexHtmlWriterTest.cs @@ -0,0 +1,74 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using AngleSharp.Parser.Html; +using Xunit; + +namespace Microsoft.AspNetCore.Blazor.Build.Test +{ + public class IndexHtmlWriterTest + { + [Fact] + public void InjectsScriptTagReferencingAssemblyAndDependencies() + { + // Arrange + var htmlTemplatePrefix = @" + + +

Hello

+ Some text + "; + var htmlTemplateSuffix = @" + + "; + var htmlTemplate = + $@"{htmlTemplatePrefix} + + {htmlTemplateSuffix}"; + var dependencies = new string[] + { + "System.Abc.dll", + "MyApp.ClassLib.dll", + }; + var instance = IndexHtmlWriter.GetIndexHtmlContents( + htmlTemplate, + "MyApp.Entrypoint", + "MyNamespace.MyType::MyMethod", dependencies); + + // Act & Assert: Start and end is not modified (including formatting) + Assert.StartsWith(htmlTemplatePrefix, instance); + Assert.EndsWith(htmlTemplateSuffix, instance); + + // Assert: Boot tag is correct + var scriptTagText = instance.Substring(htmlTemplatePrefix.Length, instance.Length - htmlTemplatePrefix.Length - htmlTemplateSuffix.Length); + var parsedHtml = new HtmlParser().Parse("" + scriptTagText + ""); + var scriptElem = parsedHtml.Body.QuerySelector("script"); + Assert.False(scriptElem.HasChildNodes); + Assert.Equal("_framework/blazor.js", scriptElem.GetAttribute("src")); + Assert.Equal("MyApp.Entrypoint.dll", scriptElem.GetAttribute("main")); + Assert.Equal("MyNamespace.MyType::MyMethod", scriptElem.GetAttribute("entrypoint")); + Assert.Equal("System.Abc.dll,MyApp.ClassLib.dll", scriptElem.GetAttribute("references")); + Assert.False(scriptElem.HasAttribute("type")); + Assert.Equal(string.Empty, scriptElem.Attributes["custom1"].Value); + Assert.Equal("value", scriptElem.Attributes["custom2"].Value); + } + + [Fact] + public void SuppliesHtmlTemplateUnchangedIfNoBootScriptPresent() + { + // Arrange + var htmlTemplate = "

Hello

Some text"; + var dependencies = new string[] + { + "System.Abc.dll", + "MyApp.ClassLib.dll", + }; + + var content = IndexHtmlWriter.GetIndexHtmlContents( + htmlTemplate, "MyApp.Entrypoint", "MyNamespace.MyType::MyMethod", dependencies); + + // Assert + Assert.Equal(htmlTemplate, content); + } + } +} diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/Microsoft.AspNetCore.Blazor.Build.Test.csproj b/test/Microsoft.AspNetCore.Blazor.Build.Test/Microsoft.AspNetCore.Blazor.Build.Test.csproj index 390a062ea2..6e2c4fc345 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/Microsoft.AspNetCore.Blazor.Build.Test.csproj +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/Microsoft.AspNetCore.Blazor.Build.Test.csproj @@ -22,8 +22,13 @@ + + + + + - + diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/ReferencedAssemblyFileProviderTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/ReferencedAssemblyFileProviderTest.cs deleted file mode 100644 index 30e153b7e0..0000000000 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/ReferencedAssemblyFileProviderTest.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Blazor.Build.Core.FileSystem; -using Microsoft.AspNetCore.Blazor.Mono; -using Mono.Cecil; -using System; -using System.IO; -using System.Linq; -using Xunit; - -namespace Microsoft.AspNetCore.Blazor.Server.Test -{ - public class ReferencedAssemblyFileProviderTest - { - [Fact] - public void RootDirContainsOnlyDlls() - { - var provider = new ReferencedAssemblyFileProvider( - "mscorlib", - new ReferencedAssemblyResolver(MonoStaticFileProvider.BclFiles, string.Empty)); - foreach (var item in provider.GetDirectoryContents("/")) - { - Assert.False(item.IsDirectory); - Assert.EndsWith(".dll", item.Name); - } - } - - [Fact] - public void FindsReferencedAssemblyGraphSimple() - { - var provider = new ReferencedAssemblyFileProvider( - "System.Linq.Expressions", - new ReferencedAssemblyResolver(MonoStaticFileProvider.BclFiles, string.Empty)); - var contents = provider.GetDirectoryContents("").OrderBy(i => i.Name).ToList(); - Assert.Collection(contents, - item => { Assert.Equal("/Mono.Security.dll", item.PhysicalPath); }, - item => { Assert.Equal("/mscorlib.dll", item.PhysicalPath); }, - item => { Assert.Equal("/System.Core.dll", item.PhysicalPath); }, - item => { Assert.Equal("/System.dll", item.PhysicalPath); }, - item => { Assert.Equal("/System.Linq.Expressions.dll", item.PhysicalPath); }, - item => { Assert.Equal("/System.Xml.dll", item.PhysicalPath); }); - } - - [Fact] - public void FindsReferencedAssemblyGraphRealistic() - { - // Arrange - var standaloneAppAssembly = typeof(StandaloneApp.Program).Assembly; - var provider = new ReferencedAssemblyFileProvider( - standaloneAppAssembly.GetName().Name, - new ReferencedAssemblyResolver( - MonoStaticFileProvider.BclFiles, - Path.GetDirectoryName(standaloneAppAssembly.Location))); - var expectedContents = new[] - { - /* - The current Mono WASM BCL forwards from netstandard.dll to various facade assemblies - in which small bits of implementation live, such as System.Xml.XPath.XDocument. So - if you reference netstandard, then you also reference System.Xml.XPath.XDocument.dll, - even though you're very unlikely to be calling it at runtime. That's why the following - list (for a very basic Blazor app) is longer than you'd expect. - - These redundant references could be stripped out during publishing, but it's still - unfortunate that in development mode you'd see all these unexpected assemblies get - fetched from the server. We should try to get the Mono WASM BCL reorganized so that - all the implementation goes into mscorlib.dll, with the facade assemblies existing only - in case someone (or some 3rd party assembly) references them directly, but with their - implementations 100% forwarding to mscorlib.dll. Then in development you'd fetch far - fewer assemblies from the server, and during publishing, illink would remove all the - uncalled implementation code from mscorlib.dll anyway. - */ - "/Microsoft.AspNetCore.Blazor.Browser.dll", - "/Microsoft.AspNetCore.Blazor.dll", - "/Mono.Security.dll", - "/mscorlib.dll", - "/netstandard.dll", - "/StandaloneApp.dll", - "/System.ComponentModel.Composition.dll", - "/System.Core.dll", - "/System.Data.dll", - "/System.Diagnostics.StackTrace.dll", - "/System.dll", - "/System.Drawing.dll", - "/System.Globalization.Extensions.dll", - "/System.IO.Compression.dll", - "/System.IO.Compression.FileSystem.dll", - "/System.Net.Http.dll", - "/System.Numerics.dll", - "/System.Runtime.Serialization.dll", - "/System.Runtime.Serialization.Primitives.dll", - "/System.Runtime.Serialization.Xml.dll", - "/System.Security.Cryptography.Algorithms.dll", - "/System.Security.SecureString.dll", - "/System.ServiceModel.Internals.dll", - "/System.Transactions.dll", - "/System.Web.Services.dll", - "/System.Xml.dll", - "/System.Xml.Linq.dll", - "/System.Xml.XPath.XDocument.dll", - }; - - // Act - var contents = provider.GetDirectoryContents("") - .OrderBy(i => i.Name, StringComparer.InvariantCulture).ToList(); - - // Assert - Assert.Equal(expectedContents.Length, contents.Count); - for (var i = 0; i < expectedContents.Length; i++) - { - Assert.Equal(expectedContents[i], contents[i].PhysicalPath); - } - } - - private static (AssemblyDefinition, byte[]) GetBclAssemblyForTest(string name) - { - var possibleFilenames = new[] { $"/bcl/{name}.dll", $"/bcl/Facades/{name}.dll" }; - var fileInfo = possibleFilenames - .Select(MonoStaticFileProvider.BclFiles.GetFileInfo) - .First(item => item.Exists); - using (var data = new MemoryStream()) - { - fileInfo.CreateReadStream().CopyTo(data); - return (AssemblyDefinition.ReadAssembly(fileInfo.CreateReadStream()), data.ToArray()); - } - } - } -} diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeDependenciesResolverTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeDependenciesResolverTest.cs new file mode 100644 index 0000000000..b4d1fe4ae0 --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeDependenciesResolverTest.cs @@ -0,0 +1,108 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using Xunit; + +namespace Microsoft.AspNetCore.Blazor.Build.Test +{ + public class RuntimeDependenciesResolverTest + { + [Fact] + public void FindsReferenceAssemblyGraph_ForStandaloneApp() + { + // Arrange + var standaloneAppAssembly = typeof(StandaloneApp.Program).Assembly; + var mainAssemblyLocation = standaloneAppAssembly.Location; + // This list of hints is populated by MSBuild so it will be on the output + // folder. + var hintPaths = File.ReadAllLines(Path.Combine( + Path.GetDirectoryName(mainAssemblyLocation), + "referenceHints.txt")); + var references = new[] + { + "Microsoft.AspNetCore.Blazor.Browser.dll", + "Microsoft.AspNetCore.Blazor.dll", + "Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "Microsoft.Extensions.DependencyInjection.dll" + }.Select(a => hintPaths.Single(p => Path.GetFileName(p) == a)) + .ToArray(); + + var basePath = Path.GetDirectoryName(typeof(RuntimeDependenciesResolverTest).Assembly.Location); + var bclLocations = new [] + { + Path.Combine(basePath, "../../../../../src/mono/dist/optimized/bcl/"), + Path.Combine(basePath, "../../../../../src/mono/dist/optimized/bcl/Facades/"), + }; + + var expectedContents = new[] + { + /* + The current Mono WASM BCL forwards from netstandard.dll to various facade assemblies + in which small bits of implementation live, such as System.Xml.XPath.XDocument. So + if you reference netstandard, then you also reference System.Xml.XPath.XDocument.dll, + even though you're very unlikely to be calling it at runtime. That's why the following + list (for a very basic Blazor app) is longer than you'd expect. + + These redundant references could be stripped out during publishing, but it's still + unfortunate that in development mode you'd see all these unexpected assemblies get + fetched from the server. We should try to get the Mono WASM BCL reorganized so that + all the implementation goes into mscorlib.dll, with the facade assemblies existing only + in case someone (or some 3rd party assembly) references them directly, but with their + implementations 100% forwarding to mscorlib.dll. Then in development you'd fetch far + fewer assemblies from the server, and during publishing, illink would remove all the + uncalled implementation code from mscorlib.dll anyway. + */ + "Microsoft.AspNetCore.Blazor.Browser.dll", + "Microsoft.AspNetCore.Blazor.dll", + "Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "Microsoft.Extensions.DependencyInjection.dll", + "Mono.Security.dll", + "mscorlib.dll", + "netstandard.dll", + "StandaloneApp.dll", + "System.ComponentModel.Composition.dll", + "System.Core.dll", + "System.Data.dll", + "System.Diagnostics.StackTrace.dll", + "System.dll", + "System.Drawing.dll", + "System.Globalization.Extensions.dll", + "System.IO.Compression.dll", + "System.IO.Compression.FileSystem.dll", + "System.Net.Http.dll", + "System.Numerics.dll", + "System.Runtime.Serialization.dll", + "System.Runtime.Serialization.Primitives.dll", + "System.Runtime.Serialization.Xml.dll", + "System.Security.Cryptography.Algorithms.dll", + "System.Security.SecureString.dll", + "System.ServiceModel.Internals.dll", + "System.Transactions.dll", + "System.Web.Services.dll", + "System.Xml.dll", + "System.Xml.Linq.dll", + "System.Xml.XPath.XDocument.dll", + }.OrderBy(i => i, StringComparer.Ordinal) + .ToArray(); + + // Act + + var paths = RuntimeDependenciesResolver + .ResolveRuntimeDependenciesCore( + mainAssemblyLocation, + references, + bclLocations); + + var contents = paths + .Select(p => Path.GetFileName(p)) + .OrderBy(i => i, StringComparer.Ordinal) + .ToArray(); + + // Assert + Assert.Equal(expectedContents, contents); + } + } +} diff --git a/test/Microsoft.AspNetCore.Blazor.Common.Test/CompositeMountedFileProviderTest.cs b/test/Microsoft.AspNetCore.Blazor.Common.Test/CompositeMountedFileProviderTest.cs deleted file mode 100644 index 83a18773a0..0000000000 --- a/test/Microsoft.AspNetCore.Blazor.Common.Test/CompositeMountedFileProviderTest.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Blazor.Internal.Common.FileProviders; -using Microsoft.Extensions.FileProviders; -using System; -using System.IO; -using System.Linq; -using System.Text; -using Xunit; - -namespace Microsoft.AspNetCore.Blazor.Common.Test -{ - public class CompositeMountedFileProviderTest - { - private (string, byte[]) TestItem(string name) => (name, Array.Empty()); - private (string, byte[]) TestItem(string name, string data) => (name, Encoding.UTF8.GetBytes(data)); - private IFileProvider TestFileProvider(params string[] paths) => new InMemoryFileProvider(paths.Select(TestItem)); - - [Fact] - public void MountPointsMustStartWithSlash() - { - Assert.Throws(() => - { - new CompositeMountedFileProvider( - ("test", TestFileProvider("/something.txt"))); - }); - } - - [Fact] - public void NonRootMountPointsMustNotEndWithSlash() - { - Assert.Throws(() => - { - new CompositeMountedFileProvider( - ("/test/", TestFileProvider("/something.txt"))); - }); - } - - [Fact] - public void MountedFilePathsMustStartWithSlash() - { - Assert.Throws(() => - { - new CompositeMountedFileProvider( - ("/test", TestFileProvider("something.txt"))); - }); - } - - [Fact] - public void CanMountFileProviderAtRoot() - { - // Arrange - IFileProvider childProvider = new InMemoryFileProvider(new[] - { - TestItem("/rootitem.txt", "Root item contents"), - TestItem("/subdir/another", "Another test item"), - }); - var instance = new CompositeMountedFileProvider(("/", childProvider)); - - // Act - var rootContents = instance.GetDirectoryContents(string.Empty); - var subdirContents = instance.GetDirectoryContents("/subdir"); - - // Assert - Assert.Collection(rootContents, - item => - { - Assert.Equal("/rootitem.txt", item.PhysicalPath); - Assert.False(item.IsDirectory); - Assert.Equal("Root item contents", new StreamReader(item.CreateReadStream()).ReadToEnd()); - }, - item => - { - Assert.Equal("/subdir", item.PhysicalPath); - Assert.True(item.IsDirectory); - }); - - Assert.Collection(subdirContents, - item => - { - Assert.Equal("/subdir/another", item.PhysicalPath); - Assert.False(item.IsDirectory); - Assert.Equal("Another test item", new StreamReader(item.CreateReadStream()).ReadToEnd()); - }); - } - - [Fact] - public void CanMountFileProvidersAtSubPaths() - { - // Arrange - var instance = new CompositeMountedFileProvider( - ("/dir", TestFileProvider("/first", "/A/second", "/A/third")), - ("/dir/sub", TestFileProvider("/X", "/B/Y", "/B/Z")), - ("/other", TestFileProvider("/final"))); - - // Act - var rootContents = instance.GetDirectoryContents("/"); - var rootDirContents = instance.GetDirectoryContents("/dir"); - var rootDirAContents = instance.GetDirectoryContents("/dir/A"); - var rootDirSubContents = instance.GetDirectoryContents("/dir/sub"); - var rootDirSubBContents = instance.GetDirectoryContents("/dir/sub/B"); - var otherContents = instance.GetDirectoryContents("/other"); - - // Assert - Assert.Collection(rootContents, - item => Assert.Equal("/dir", item.PhysicalPath), - item => Assert.Equal("/other", item.PhysicalPath)); - Assert.Collection(rootDirContents, - item => Assert.Equal("/dir/first", item.PhysicalPath), - item => Assert.Equal("/dir/A", item.PhysicalPath), - item => Assert.Equal("/dir/sub", item.PhysicalPath)); - Assert.Collection(rootDirAContents, - item => Assert.Equal("/dir/A/second", item.PhysicalPath), - item => Assert.Equal("/dir/A/third", item.PhysicalPath)); - Assert.Collection(rootDirSubContents, - item => Assert.Equal("/dir/sub/X", item.PhysicalPath), - item => Assert.Equal("/dir/sub/B", item.PhysicalPath)); - Assert.Collection(rootDirSubBContents, - item => Assert.Equal("/dir/sub/B/Y", item.PhysicalPath), - item => Assert.Equal("/dir/sub/B/Z", item.PhysicalPath)); - Assert.Collection(otherContents, - item => Assert.Equal("/other/final", item.PhysicalPath)); - } - - [Fact] - public void CanMountMultipleFileProvidersAtSameLocation() - { - // Arrange - var instance = new CompositeMountedFileProvider( - ("/dir", TestFileProvider("/first")), - ("/dir", TestFileProvider("/second"))); - - // Act - var contents = instance.GetDirectoryContents("/dir"); - - // Assert - Assert.Collection(contents, - item => Assert.Equal("/dir/first", item.PhysicalPath), - item => Assert.Equal("/dir/second", item.PhysicalPath)); - } - - [Fact] - public void DisallowsOverlappingFiles() - { - Assert.Throws(() => - { - new CompositeMountedFileProvider( - ("/dir", TestFileProvider("/file")), - ("/", TestFileProvider("/dir/file"))); - }); - } - } -} diff --git a/test/Microsoft.AspNetCore.Blazor.Common.Test/InMemoryFileProviderTest.cs b/test/Microsoft.AspNetCore.Blazor.Common.Test/InMemoryFileProviderTest.cs deleted file mode 100644 index a29766733e..0000000000 --- a/test/Microsoft.AspNetCore.Blazor.Common.Test/InMemoryFileProviderTest.cs +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Blazor.Internal.Common.FileProviders; -using System; -using System.IO; -using System.Text; -using Xunit; - -namespace Microsoft.AspNetCore.Blazor.Common.Test -{ - public class InMemoryFileProviderTest - { - private (string, byte[]) TestItem(string name) => (name, Array.Empty()); - - [Fact] - public void RequiresPathsToStartWithSlash() - { - Assert.Throws(() => - { - new InMemoryFileProvider(new[] { TestItem("item") }); - }); - } - - [Fact] - public void RequiresPathsNotToEndWithSlash() - { - Assert.Throws(() => - { - new InMemoryFileProvider(new[] { TestItem("/item/") }); - }); - } - - [Fact] - public void ReturnsFileInfosForExistingFiles() - { - // Arrange - var instance = new InMemoryFileProvider(new[] - { - ("/dirA/item", Encoding.UTF8.GetBytes("Contents of /dirA/item")), - ("/dirB/item", Encoding.UTF8.GetBytes("Contents of /dirB/item")) - }); - - // Act - var dirAItem = instance.GetFileInfo("/dirA/item"); - var dirBItem = instance.GetFileInfo("/dirB/item"); - - // Assert - Assert.Equal( - "Contents of /dirA/item", - new StreamReader(dirAItem.CreateReadStream()).ReadToEnd()); - Assert.Equal( - "Contents of /dirB/item", - new StreamReader(dirBItem.CreateReadStream()).ReadToEnd()); - Assert.True(dirAItem.Exists); - Assert.False(dirAItem.IsDirectory); - Assert.True((DateTime.Now - dirAItem.LastModified).TotalDays < 1); // Exact behaviour doesn't need to be defined (at least not yet) but it should be a valid date - Assert.Equal(22, dirAItem.Length); - Assert.Equal("item", dirAItem.Name); - Assert.Equal("/dirA/item", dirAItem.PhysicalPath); - } - - [Fact] - public void ReturnsFileInfosForNonExistingFiles() - { - // Arrange - var instance = new InMemoryFileProvider(new[] { TestItem("/dirA/item") }); - - // Act - var mismatchedCaseItem = instance.GetFileInfo("/dira/item"); - var dirBItem = instance.GetFileInfo("/dirB/item"); - - // Assert - Assert.False(mismatchedCaseItem.Exists); - Assert.False(dirBItem.Exists); - Assert.False(dirBItem.IsDirectory); - Assert.Equal("item", dirBItem.Name); - Assert.Equal("/dirB/item", dirBItem.PhysicalPath); - } - - [Fact] - public void ReturnsDirectoryContentsForExistingDirectory() - { - // Arrange - var instance = new InMemoryFileProvider(new[] - { - TestItem("/dir/subdir/item1"), - TestItem("/dir/subdir/item2"), - TestItem("/dir/otherdir/item3") - }); - - // Act - var contents = instance.GetDirectoryContents("/dir/subdir"); - - // Assert - Assert.True(contents.Exists); - Assert.Collection(contents, - item => Assert.Equal("/dir/subdir/item1", item.PhysicalPath), - item => Assert.Equal("/dir/subdir/item2", item.PhysicalPath)); - } - - [Fact] - public void EmptyStringAndSlashAreBothInterpretedAsRootDir() - { - // Technically this test duplicates checking the behavior asserted - // previously (i.e., trailing slashes are ignored), but it's worth - // checking that nothing bad happens when the path is an empty string - - // Arrange - var instance = new InMemoryFileProvider(new[] { TestItem("/item") }); - - // Act/Assert - Assert.Collection(instance.GetDirectoryContents(string.Empty), - item => Assert.Equal("/item", item.PhysicalPath)); - Assert.Collection(instance.GetDirectoryContents("/"), - item => Assert.Equal("/item", item.PhysicalPath)); - } - - [Fact] - public void ReturnsDirectoryContentsIfGivenPathEndsWithSlash() - { - // Arrange - var instance = new InMemoryFileProvider(new[] { TestItem("/dir/subdir/item1") }); - - // Act - var contents = instance.GetDirectoryContents("/dir/subdir/"); - - // Assert - Assert.True(contents.Exists); - Assert.Collection(contents, - item => Assert.Equal("/dir/subdir/item1", item.PhysicalPath)); - } - - [Fact] - public void ReturnsDirectoryContentsForNonExistingDirectory() - { - // Arrange - var instance = new InMemoryFileProvider(new[] { TestItem("/dir/subdir/item1") }); - - // Act - var contents = instance.GetDirectoryContents("/dir/otherdir"); - - // Assert - Assert.False(contents.Exists); - Assert.Throws(() => contents.GetEnumerator()); - } - - [Fact] - public void IncludesSubdirectoriesInDirectoryContents() - { - // Arrange - var instance = new InMemoryFileProvider(new[] { - TestItem("/dir/sub/item1"), - TestItem("/dir/sub/item2"), - TestItem("/dir/sub2/item"), - TestItem("/unrelated/item") - }); - - // Act - var contents = instance.GetDirectoryContents("/dir"); - - // Assert - Assert.True(contents.Exists); - Assert.Collection(contents, - item => - { - // For this example, verify all properties. Don't need to do this for all examples. - Assert.True(item.Exists); - Assert.True(item.IsDirectory); - Assert.Equal(default(DateTimeOffset), item.LastModified); - Assert.Throws(() => item.Length); - Assert.Throws(() => item.CreateReadStream()); - Assert.Equal("sub", item.Name); - Assert.Equal("/dir/sub", item.PhysicalPath); - }, - item => - { - Assert.Equal("/dir/sub2", item.PhysicalPath); - Assert.True(item.IsDirectory); - }); - } - - [Fact] - public void HasAllAncestorDirectoriesForDirectory() - { - // Arrange - var instance = new InMemoryFileProvider(new[] { TestItem("/a/b/c") }); - - // Act/Assert - Assert.Collection(instance.GetDirectoryContents("/"), - item => - { - Assert.Equal("/a", item.PhysicalPath); - Assert.True(item.IsDirectory); - }); - Assert.Collection(instance.GetDirectoryContents("/a"), - item => - { - Assert.Equal("/a/b", item.PhysicalPath); - Assert.True(item.IsDirectory); - }); - Assert.Collection(instance.GetDirectoryContents("/a/b"), - item => - { - Assert.Equal("/a/b/c", item.PhysicalPath); - Assert.False(item.IsDirectory); - }); - } - } -} diff --git a/test/Microsoft.AspNetCore.Blazor.Common.Test/Microsoft.AspNetCore.Blazor.Common.Test.csproj b/test/Microsoft.AspNetCore.Blazor.Common.Test/Microsoft.AspNetCore.Blazor.Common.Test.csproj deleted file mode 100644 index 15f57d1e87..0000000000 --- a/test/Microsoft.AspNetCore.Blazor.Common.Test/Microsoft.AspNetCore.Blazor.Common.Test.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netcoreapp2.0 - - false - - - - - - - - - - - - - diff --git a/test/Microsoft.AspNetCore.Blazor.Mono.Test/Microsoft.AspNetCore.Blazor.Mono.Test.csproj b/test/Microsoft.AspNetCore.Blazor.Mono.Test/Microsoft.AspNetCore.Blazor.Mono.Test.csproj deleted file mode 100644 index 289374638f..0000000000 --- a/test/Microsoft.AspNetCore.Blazor.Mono.Test/Microsoft.AspNetCore.Blazor.Mono.Test.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - netcoreapp2.0 - - false - - - - - - - - - - - - - - diff --git a/test/Microsoft.AspNetCore.Blazor.Mono.Test/MonoStaticFileProviderTest.cs b/test/Microsoft.AspNetCore.Blazor.Mono.Test/MonoStaticFileProviderTest.cs deleted file mode 100644 index 22001b9f71..0000000000 --- a/test/Microsoft.AspNetCore.Blazor.Mono.Test/MonoStaticFileProviderTest.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using Xunit; - -namespace Microsoft.AspNetCore.Blazor.Mono.Test -{ - public class MonoStaticFileProviderTest - { - [Fact] - public void SuppliesJsFiles() - { - // The collection is small enough that we can assert the exact full list - - Assert.Collection(MonoStaticFileProvider.JsFiles.GetDirectoryContents("/").OrderBy(i => i.Name), - item => Assert.Equal("/asmjs", item.PhysicalPath), - item => Assert.Equal("/wasm", item.PhysicalPath)); - - Assert.Collection(MonoStaticFileProvider.JsFiles.GetDirectoryContents("/asmjs").OrderBy(i => i.Name), - item => Assert.Equal("/asmjs/mono.asm.js", item.PhysicalPath), - item => Assert.Equal("/asmjs/mono.js", item.PhysicalPath), - item => Assert.Equal("/asmjs/mono.js.mem", item.PhysicalPath)); - - Assert.Collection(MonoStaticFileProvider.JsFiles.GetDirectoryContents("/wasm").OrderBy(i => i.Name), - item => Assert.Equal("/wasm/mono.js", item.PhysicalPath), - item => Assert.Equal("/wasm/mono.wasm", item.PhysicalPath)); - } - - [Fact] - public void SuppliesBclFiles() - { - Assert.Collection(MonoStaticFileProvider.BclFiles.GetDirectoryContents("/"), - item => Assert.Equal("/bcl", item.PhysicalPath)); - - // Not an exhaustive list. The full list is long. - var actualBclRootFiles = MonoStaticFileProvider.BclFiles.GetDirectoryContents("/bcl"); - Assert.Contains(actualBclRootFiles, item => item.PhysicalPath == "/bcl/mscorlib.dll"); - Assert.Contains(actualBclRootFiles, item => item.PhysicalPath == "/bcl/System.Core.dll"); - Assert.Contains(actualBclRootFiles, item => item.PhysicalPath == "/bcl/System.dll"); - - // Not an exhaustive list. The full list is long. - var actualFacades = MonoStaticFileProvider.BclFiles.GetDirectoryContents("/bcl/Facades"); - Assert.Contains(actualFacades, item => item.PhysicalPath == "/bcl/Facades/netstandard.dll"); - Assert.Contains(actualFacades, item => item.PhysicalPath == "/bcl/Facades/System.Console.dll"); - } - } -} diff --git a/test/testapps/BasicTestApp/BasicTestApp.csproj b/test/testapps/BasicTestApp/BasicTestApp.csproj index 18e39f8f4c..5cb5aa8933 100644 --- a/test/testapps/BasicTestApp/BasicTestApp.csproj +++ b/test/testapps/BasicTestApp/BasicTestApp.csproj @@ -2,6 +2,7 @@ netstandard2.0 + true dotnet