File: Compilation\DefaultViewCompilerTest.cs
Web Access
Project: src\src\Mvc\Mvc.Razor\test\Microsoft.AspNetCore.Mvc.Razor.Test.csproj (Microsoft.AspNetCore.Mvc.Razor.Test)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.Logging.Abstractions;
 
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation;
 
public class DefaultViewCompilerTest
{
    [Fact]
    public async Task CompileAsync_ReturnsResultWithNullAttribute_IfFileIsNotFoundInFileSystem()
    {
        // Arrange
        var path = "/file/does-not-exist";
        var viewCompiler = GetViewCompiler();
 
        // Act
        var result1 = await viewCompiler.CompileAsync(path);
        var result2 = await viewCompiler.CompileAsync(path);
 
        // Assert
        Assert.Empty(result1.ExpirationTokens);
    }
 
    [Fact]
    public async Task CompileAsync_ReturnsCompiledViews()
    {
        // Arrange
        var path = "/Views/Home/Index.cshtml";
        var compiledView = new CompiledViewDescriptor
        {
            RelativePath = path,
        };
        var viewCompiler = GetViewCompiler(compiledViews: new[] { compiledView });
 
        // Act
        var result = await viewCompiler.CompileAsync(path);
 
        // Assert
        Assert.Same(compiledView, result);
 
        // This view doesn't have checksums so it can't be recompiled.
        Assert.Null(compiledView.ExpirationTokens);
    }
 
    [Theory]
    [InlineData("/views/home/index.cshtml")]
    [InlineData("/VIEWS/HOME/INDEX.CSHTML")]
    [InlineData("/viEws/HoME/inDex.cshtml")]
    public async Task CompileAsync_PerformsCaseInsensitiveLookupsForCompiledViews(string lookupPath)
    {
        // Arrange
        var path = "/Views/Home/Index.cshtml";
        var precompiledView = new CompiledViewDescriptor
        {
            RelativePath = path,
        };
        var viewCompiler = GetViewCompiler(compiledViews: new[] { precompiledView });
 
        // Act
        var result = await viewCompiler.CompileAsync(lookupPath);
 
        // Assert
        Assert.Same(precompiledView, result);
    }
 
    [Fact]
    public async Task CompileAsync_PerformsCaseInsensitiveLookupsForCompiledViews_WithNonNormalizedPaths()
    {
        // Arrange
        var path = "/Views/Home/Index.cshtml";
        var compiledView = new CompiledViewDescriptor
        {
            RelativePath = path,
        };
        var viewCompiler = GetViewCompiler(compiledViews: new[] { compiledView });
 
        // Act
        var result = await viewCompiler.CompileAsync("Views\\Home\\Index.cshtml");
 
        // Assert
        Assert.Same(compiledView, result);
    }
 
    [Fact]
    public async Task CompileAsync_DiscoversHotReloadedTypes()
    {
        // Arrange
        var path = "/Views/Home/Index.cshtml";
        var compiledView = new CompiledViewDescriptor
        {
            RelativePath = path,
        };
        var compiledViews = new List<CompiledViewDescriptor>
            {
                compiledView,
            };
        var viewCompiler = GetViewCompiler(compiledViews);
 
        // Act - 1
        var result = await viewCompiler.CompileAsync(path);
 
        // Assert - 1
        Assert.Same(compiledView, result);
 
        // Act - 2
        var hotReloaded = new CompiledViewDescriptor { RelativePath = path };
        compiledViews[0] = hotReloaded;
        viewCompiler.ClearCache();
 
        result = await viewCompiler.CompileAsync(path);
 
        // Assert - 2
        Assert.Same(hotReloaded, result);
    }
 
    private static TestRazorViewCompiler GetViewCompiler(IList<CompiledViewDescriptor> compiledViews = null)
    {
        compiledViews = compiledViews ?? Array.Empty<CompiledViewDescriptor>();
 
        var viewCompiler = new TestRazorViewCompiler(compiledViews);
        return viewCompiler;
    }
 
    private class TestRazorViewCompiler : DefaultViewCompiler
    {
        public TestRazorViewCompiler(IList<CompiledViewDescriptor> compiledViews) :
            base(GetApplicationPartManager(new TestViewsFeatureProvider { CompiledViews = compiledViews }), NullLogger<DefaultViewCompiler>.Instance)
        {
        }
 
        public TestRazorViewCompiler(TestViewsFeatureProvider featureProvider) :
           base(GetApplicationPartManager(featureProvider), NullLogger<DefaultViewCompiler>.Instance)
        {
        }
 
        private static ApplicationPartManager GetApplicationPartManager(TestViewsFeatureProvider featureProvider)
        {
            var manager = new ApplicationPartManager();
            manager.FeatureProviders.Add(featureProvider);
 
            return manager;
        }
    }
 
    private class TestViewsFeatureProvider : IApplicationFeatureProvider<ViewsFeature>
    {
        public IList<CompiledViewDescriptor> CompiledViews { get; init; }
 
        public void PopulateFeature(IEnumerable<ApplicationPart> parts, ViewsFeature feature)
        {
            foreach (var item in CompiledViews)
            {
                feature.ViewDescriptors.Add(item);
            }
        }
    }
}