From 39b64c1bc3961137aae8876d18a60d934b072123 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 13 Dec 2017 12:33:03 +0000 Subject: [PATCH] Add tests for IndexHtmlFileProvider, plus minor cleanups --- .../FrameworkFiles/FrameworkFileProvider.cs | 11 +- .../WebRootFiles/IndexHtmlFileProvider.cs | 20 +-- .../WebRootFiles/WebRootFileProvider.cs | 10 +- .../IndexHtmlFileProviderTest.cs | 124 ++++++++++++++++++ .../Microsoft.Blazor.Server.Test.csproj | 1 + 5 files changed, 148 insertions(+), 18 deletions(-) create mode 100644 test/Microsoft.Blazor.Server.Test/IndexHtmlFileProviderTest.cs diff --git a/src/Microsoft.Blazor.Server/FrameworkFiles/FrameworkFileProvider.cs b/src/Microsoft.Blazor.Server/FrameworkFiles/FrameworkFileProvider.cs index 854ffee3b0..aee39d5741 100644 --- a/src/Microsoft.Blazor.Server/FrameworkFiles/FrameworkFileProvider.cs +++ b/src/Microsoft.Blazor.Server/FrameworkFiles/FrameworkFileProvider.cs @@ -12,12 +12,15 @@ namespace Microsoft.Blazor.Server.FrameworkFiles { public static IFileProvider Instantiate(string clientAssemblyPath) => new CompositeFileProvider( - MonoStaticFileProvider.JsFiles, - BlazorBrowserFileProvider.Instance, - new ReferencedAssemblyFileProvider( + MonoStaticFileProvider.JsFiles, // /_framework/wasm/*, /framework/asmjs/* + BlazorBrowserFileProvider.Instance, // /_framework/blazor.js + BinDirFileProvider(clientAssemblyPath)); // /_framework/_bin/* + + private static IFileProvider BinDirFileProvider(string clientAssemblyPath) + => new ReferencedAssemblyFileProvider( Path.GetFileNameWithoutExtension(clientAssemblyPath), new ReferencedAssemblyResolver( MonoStaticFileProvider.BclFiles, - Path.GetDirectoryName(clientAssemblyPath)))); + Path.GetDirectoryName(clientAssemblyPath))); } } diff --git a/src/Microsoft.Blazor.Server/WebRootFiles/IndexHtmlFileProvider.cs b/src/Microsoft.Blazor.Server/WebRootFiles/IndexHtmlFileProvider.cs index b19dbfb623..7242811ff3 100644 --- a/src/Microsoft.Blazor.Server/WebRootFiles/IndexHtmlFileProvider.cs +++ b/src/Microsoft.Blazor.Server/WebRootFiles/IndexHtmlFileProvider.cs @@ -12,33 +12,27 @@ namespace Microsoft.Blazor.Server.WebRootFiles { internal class IndexHtmlFileProvider : InMemoryFileProvider { - public IndexHtmlFileProvider(string clientWebRoot, string assemblyName, IEnumerable binFiles) - : base(ComputeContents(clientWebRoot, assemblyName, binFiles)) + public IndexHtmlFileProvider(string htmlTemplate, string assemblyName, IEnumerable binFiles) + : base(ComputeContents(htmlTemplate, assemblyName, binFiles)) { } - private static IEnumerable<(string, Stream)> ComputeContents(string clientWebRoot, string assemblyName, IEnumerable binFiles) + private static IEnumerable<(string, Stream)> ComputeContents(string htmlTemplate, string assemblyName, IEnumerable binFiles) { - var html = GetIndexHtmlContents(clientWebRoot, assemblyName, binFiles); - if (html != null) + if (htmlTemplate != null) { + var html = GetIndexHtmlContents(htmlTemplate, assemblyName, binFiles); var htmlBytes = Encoding.UTF8.GetBytes(html); var htmlStream = new MemoryStream(htmlBytes); yield return ("/index.html", htmlStream); } } - private static string GetIndexHtmlContents(string clientWebRoot, string assemblyName, IEnumerable binFiles) + private static string GetIndexHtmlContents(string htmlTemplate, string assemblyName, IEnumerable binFiles) { - var indexHtmlPath = Path.Combine(clientWebRoot, "index.html"); - if (!File.Exists(indexHtmlPath)) - { - return null; - } - // TODO: Consider parsing the HTML properly so for example we don't insert into // the wrong place if there was also '' in a JavaScript string literal - return File.ReadAllText(indexHtmlPath) + return htmlTemplate .Replace("", CreateBootMarkup(assemblyName, binFiles) + "\n"); } diff --git a/src/Microsoft.Blazor.Server/WebRootFiles/WebRootFileProvider.cs b/src/Microsoft.Blazor.Server/WebRootFiles/WebRootFileProvider.cs index ed33eb66f0..4c009609ab 100644 --- a/src/Microsoft.Blazor.Server/WebRootFiles/WebRootFileProvider.cs +++ b/src/Microsoft.Blazor.Server/WebRootFiles/WebRootFileProvider.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.FileProviders; using System.Collections.Generic; +using System.IO; namespace Microsoft.Blazor.Server.WebRootFiles { @@ -11,7 +12,14 @@ namespace Microsoft.Blazor.Server.WebRootFiles public static IFileProvider Instantiate( string clientWebRoot, string assemblyName, IEnumerable binFiles) => new CompositeFileProvider( - new IndexHtmlFileProvider(clientWebRoot, assemblyName, binFiles), + new IndexHtmlFileProvider( + ReadIndexHtmlFile(clientWebRoot), assemblyName, binFiles), new PhysicalFileProvider(clientWebRoot)); + + private static string ReadIndexHtmlFile(string clientWebRoot) + { + var path = Path.Combine(clientWebRoot, "index.html"); + return File.Exists(path) ? File.ReadAllText(path) : null; + } } } diff --git a/test/Microsoft.Blazor.Server.Test/IndexHtmlFileProviderTest.cs b/test/Microsoft.Blazor.Server.Test/IndexHtmlFileProviderTest.cs new file mode 100644 index 0000000000..3015e15e41 --- /dev/null +++ b/test/Microsoft.Blazor.Server.Test/IndexHtmlFileProviderTest.cs @@ -0,0 +1,124 @@ +// 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.Blazor.Server.WebRootFiles; +using Microsoft.Extensions.FileProviders; +using System.IO; +using System.Linq; +using Xunit; +using System; +using AngleSharp.Parser.Html; + +namespace Microsoft.Blazor.Server.Test +{ + public class IndexHtmlFileProviderTest + { + [Fact] + public void SuppliesNoIndexHtmlFileGivenNoTemplate() + { + // Arrange + var instance = new IndexHtmlFileProvider( + null, "fakeassembly", Enumerable.Empty()); + + // Act + var file = instance.GetFileInfo("/index.html"); + + // Assert + Assert.False(file.Exists); + } + + [Fact] + public void SuppliesIndexHtmlFileGivenTemplate() + { + // Arrange + var htmlTemplate = "test"; + var instance = new IndexHtmlFileProvider( + htmlTemplate, "fakeassembly", Enumerable.Empty()); + + // Act + var file = instance.GetFileInfo("/index.html"); + + // Assert + Assert.True(file.Exists); + Assert.False(file.IsDirectory); + Assert.Equal("/index.html", file.PhysicalPath); + Assert.Equal("index.html", file.Name); + Assert.Equal(htmlTemplate, ReadString(file)); + Assert.Equal(htmlTemplate.Length, file.Length); + } + + [Fact] + public void RootDirectoryContainsOnlyIndexHtml() + { + // Arrange + var htmlTemplate = "test"; + var instance = new IndexHtmlFileProvider( + htmlTemplate, "fakeassembly", Enumerable.Empty()); + + // Act + var directory = instance.GetDirectoryContents(string.Empty); + + // Assert + Assert.True(directory.Exists); + Assert.Collection(directory, + item => Assert.Equal("/index.html", item.PhysicalPath)); + } + + [Fact] + public void InsertsScriptTagReferencingAssemblyAndDependencies() + { + // Arrange + var htmlTemplate = "Hello"; + var dependencies = new IFileInfo[] + { + new TestFileInfo("System.Abc.dll"), + new TestFileInfo("MyApp.ClassLib.dll"), + }; + var instance = new IndexHtmlFileProvider( + htmlTemplate, "MyApp.Entrypoint", dependencies); + + // Act + var file = instance.GetFileInfo("/index.html"); + var parsedHtml = new HtmlParser().Parse(ReadString(file)); + var scriptElem = parsedHtml.Body.LastElementChild; + + // Assert + Assert.Equal("script", scriptElem.TagName.ToLowerInvariant()); + Assert.False(scriptElem.HasChildNodes); + Assert.Equal("/_framework/blazor.js", scriptElem.GetAttribute("src")); + Assert.Equal("MyApp.Entrypoint.dll", scriptElem.GetAttribute("main")); + Assert.Equal("System.Abc.dll,MyApp.ClassLib.dll", scriptElem.GetAttribute("references")); + } + + 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.Blazor.Server.Test/Microsoft.Blazor.Server.Test.csproj b/test/Microsoft.Blazor.Server.Test/Microsoft.Blazor.Server.Test.csproj index 143ed632a6..4667c107ff 100644 --- a/test/Microsoft.Blazor.Server.Test/Microsoft.Blazor.Server.Test.csproj +++ b/test/Microsoft.Blazor.Server.Test/Microsoft.Blazor.Server.Test.csproj @@ -7,6 +7,7 @@ +