Port old Razor tests to new Razor
This commit is contained in:
parent
8d5abd433f
commit
c349929cc1
|
|
@ -33,7 +33,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
private const string CS0246 = nameof(CS0246);
|
||||
|
||||
private readonly CSharpCompiler _compiler;
|
||||
private readonly IFileProvider _fileProvider;
|
||||
private readonly ILogger _logger;
|
||||
private readonly Action<RoslynCompilationContext> _compilationCallback;
|
||||
|
||||
|
|
@ -42,16 +41,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
/// </summary>
|
||||
/// <param name="compiler">The <see cref="CSharpCompiler"/>.</param>
|
||||
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
|
||||
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
public DefaultRoslynCompilationService(
|
||||
CSharpCompiler compiler,
|
||||
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
|
||||
IOptions<RazorViewEngineOptions> optionsAccessor,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
_compiler = compiler;
|
||||
_fileProvider = fileProviderAccessor.FileProvider;
|
||||
_compilationCallback = optionsAccessor.Value.CompilationCallback;
|
||||
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,175 +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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor;
|
||||
using Microsoft.AspNetCore.Razor.Chunks;
|
||||
using Microsoft.AspNetCore.Razor.Chunks.Generators;
|
||||
using Microsoft.AspNetCore.Razor.CodeGenerators;
|
||||
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Host
|
||||
{
|
||||
public static class ChunkVisitorTestFactory
|
||||
{
|
||||
private static string _testClass = "TestClass";
|
||||
private static string _testNamespace = "TestNamespace";
|
||||
private static string _testFile = "TestFile";
|
||||
|
||||
public static CodeGeneratorContext CreateCodeGeneratorContext()
|
||||
{
|
||||
var language = new CSharpRazorCodeLanguage();
|
||||
var host = new RazorEngineHost(language);
|
||||
var chunkGeneratorContext = new ChunkGeneratorContext
|
||||
(
|
||||
host,
|
||||
_testClass,
|
||||
_testNamespace,
|
||||
_testFile,
|
||||
shouldGenerateLinePragmas: false
|
||||
);
|
||||
|
||||
var codeGeneratorContext = new CodeGeneratorContext(
|
||||
chunkGeneratorContext,
|
||||
errorSink: new ErrorSink());
|
||||
return codeGeneratorContext;
|
||||
}
|
||||
|
||||
public static IList<Chunk> GetTestChunks(bool visitedTagHelperChunks)
|
||||
{
|
||||
return new List<Chunk>
|
||||
{
|
||||
GetTagHelperChunk("Baz"),
|
||||
GetNestedViewComponentTagHelperChunk("Foo", visitedTagHelperChunks),
|
||||
GetViewComponentTagHelperChunk("Bar", visitedTagHelperChunks),
|
||||
GetIndexerViewComponentTagHelperChunk(
|
||||
"Bee",
|
||||
visitedTagHelperChunks,
|
||||
"System.Collections.Generic.Dictionary<global::System.String, global::System.Collections.Generic.List<global::System.Int32>>"),
|
||||
};
|
||||
}
|
||||
|
||||
private static TagHelperChunk GetTagHelperChunk(string name)
|
||||
{
|
||||
var tagHelperChunk = new TagHelperChunk(
|
||||
name.ToLowerInvariant(),
|
||||
TagMode.SelfClosing,
|
||||
new List<TagHelperAttributeTracker>(),
|
||||
new List<TagHelperDescriptor>
|
||||
{
|
||||
new TagHelperDescriptor
|
||||
{
|
||||
AssemblyName = $"{name}Assembly",
|
||||
TagName = name.ToLowerInvariant(),
|
||||
TypeName = $"{name}Type",
|
||||
}
|
||||
});
|
||||
|
||||
return tagHelperChunk;
|
||||
}
|
||||
|
||||
private static ParentChunk GetNestedViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks)
|
||||
{
|
||||
var parentChunk = GetTagHelperChunk("blah");
|
||||
var tagHelperChunk = GetViewComponentTagHelperChunk(name, visitedTagHelperChunks);
|
||||
parentChunk.Children.Add(tagHelperChunk);
|
||||
return parentChunk;
|
||||
}
|
||||
|
||||
private static TagHelperChunk GetViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks)
|
||||
{
|
||||
var typeName = visitedTagHelperChunks ? $"{_testNamespace}.{_testClass}.{name}Type" : $"{name}Type";
|
||||
|
||||
var attribute = new TagHelperAttributeDescriptor
|
||||
{
|
||||
Name = "attribute",
|
||||
PropertyName = "Attribute",
|
||||
TypeName = typeof(string).FullName
|
||||
};
|
||||
|
||||
var requiredAttribute = new TagHelperRequiredAttributeDescriptor
|
||||
{
|
||||
Name = "Attribute"
|
||||
};
|
||||
|
||||
var tagHelperDescriptor = new TagHelperDescriptor
|
||||
{
|
||||
AssemblyName = $"{name}Assembly",
|
||||
TagName = name.ToLowerInvariant(),
|
||||
TypeName = typeName,
|
||||
Attributes = new[]
|
||||
{
|
||||
attribute
|
||||
},
|
||||
RequiredAttributes = new[]
|
||||
{
|
||||
requiredAttribute
|
||||
}
|
||||
};
|
||||
|
||||
tagHelperDescriptor.PropertyBag.Add(
|
||||
ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey,
|
||||
name);
|
||||
|
||||
var tagHelperChunk = new TagHelperChunk(
|
||||
$"vc:{name.ToLowerInvariant()}",
|
||||
TagMode.SelfClosing,
|
||||
new List<TagHelperAttributeTracker>(),
|
||||
new[]
|
||||
{
|
||||
tagHelperDescriptor
|
||||
});
|
||||
|
||||
return tagHelperChunk;
|
||||
}
|
||||
|
||||
private static TagHelperChunk GetIndexerViewComponentTagHelperChunk(string name, bool visitedTagHelperChunks, string attributeTypeName)
|
||||
{
|
||||
var typeName = visitedTagHelperChunks ? $"{_testNamespace}.{_testClass}.{name}Type" : $"{name}Type";
|
||||
|
||||
var attribute = new TagHelperAttributeDescriptor
|
||||
{
|
||||
Name = "attribute",
|
||||
PropertyName = "Attribute",
|
||||
TypeName = attributeTypeName
|
||||
};
|
||||
|
||||
var indexerAttribute = new TagHelperAttributeDescriptor
|
||||
{
|
||||
Name = attribute.Name + "-",
|
||||
PropertyName = attribute.PropertyName,
|
||||
TypeName = attributeTypeName,
|
||||
IsIndexer = true
|
||||
};
|
||||
|
||||
var tagHelperDescriptor = new TagHelperDescriptor
|
||||
{
|
||||
AssemblyName = $"{name}Assembly",
|
||||
TagName = name.ToLowerInvariant(),
|
||||
TypeName = typeName,
|
||||
Attributes = new[]
|
||||
{
|
||||
attribute,
|
||||
indexerAttribute
|
||||
}
|
||||
};
|
||||
|
||||
tagHelperDescriptor.PropertyBag.Add(
|
||||
ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey,
|
||||
name);
|
||||
|
||||
var tagHelperChunk = new TagHelperChunk(
|
||||
$"vc:{name.ToLowerInvariant()}",
|
||||
TagMode.SelfClosing,
|
||||
new List<TagHelperAttributeTracker>(),
|
||||
new[]
|
||||
{
|
||||
tagHelperDescriptor
|
||||
});
|
||||
|
||||
return tagHelperChunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +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;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Chunks;
|
||||
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Host.Test
|
||||
{
|
||||
public class TagHelperChunkDecoratorTest
|
||||
{
|
||||
#if OLD_RAZOR
|
||||
[Fact]
|
||||
public void Accept_CorrectlyDecoratesViewComponentChunks()
|
||||
{
|
||||
// Arrange
|
||||
var codeGeneratorContext = ChunkVisitorTestFactory.CreateCodeGeneratorContext();
|
||||
var syntaxTreeNode = new Mock<Span>(new SpanBuilder());
|
||||
foreach (var chunk in ChunkVisitorTestFactory.GetTestChunks(visitedTagHelperChunks: false))
|
||||
{
|
||||
codeGeneratorContext.ChunkTreeBuilder.AddChunk(chunk, syntaxTreeNode.Object);
|
||||
}
|
||||
|
||||
var tagHelperChunkDecorator = new TagHelperChunkDecorator(codeGeneratorContext);
|
||||
var expectedChunks = ChunkVisitorTestFactory.GetTestChunks(visitedTagHelperChunks: true);
|
||||
|
||||
// Act
|
||||
var resultChunks = codeGeneratorContext.ChunkTreeBuilder.Root.Children;
|
||||
tagHelperChunkDecorator.Accept(resultChunks);
|
||||
|
||||
// Assert
|
||||
// Test the normal tag helper chunk, Baz.
|
||||
Assert.Equal(expectedChunks.Count, resultChunks.Count);
|
||||
|
||||
var expectedTagHelperChunk = (TagHelperChunk)expectedChunks[0];
|
||||
var resultTagHelperChunk = Assert.IsType<TagHelperChunk>(resultChunks[0]);
|
||||
|
||||
Assert.Equal(
|
||||
expectedTagHelperChunk.Descriptors.First().TypeName,
|
||||
Assert.Single(resultTagHelperChunk.Descriptors).TypeName);
|
||||
|
||||
// Test the parent chunk with view component tag helper inside, Foo.
|
||||
var expectedParentChunk = (ParentChunk)expectedChunks[1];
|
||||
var resultParentChunk = Assert.IsType<TagHelperChunk>(resultChunks[1]);
|
||||
Assert.Single(resultParentChunk.Children);
|
||||
|
||||
expectedTagHelperChunk = (TagHelperChunk)expectedParentChunk.Children.First();
|
||||
resultTagHelperChunk = (TagHelperChunk)resultParentChunk.Children.First();
|
||||
|
||||
Assert.Equal(expectedTagHelperChunk.Descriptors.First().TypeName,
|
||||
resultTagHelperChunk.Descriptors.First().TypeName,
|
||||
StringComparer.Ordinal);
|
||||
|
||||
// Test the view component tag helper, Bar.
|
||||
expectedTagHelperChunk = expectedChunks.ElementAt(2) as TagHelperChunk;
|
||||
resultTagHelperChunk = resultChunks.ElementAt(2) as TagHelperChunk;
|
||||
Assert.NotNull(resultTagHelperChunk);
|
||||
|
||||
Assert.Equal(expectedTagHelperChunk.Descriptors.First().TypeName,
|
||||
resultTagHelperChunk.Descriptors.First().TypeName,
|
||||
StringComparer.Ordinal);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
|
@ -38,7 +36,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
|
|||
TypeName = "System.Int32",
|
||||
Name = "Foo",
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -86,7 +83,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
|
|||
Name = "Foo",
|
||||
PropertyName = "Foo",
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -169,7 +165,6 @@ public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.
|
|||
PropertyName = "Tags",
|
||||
IsIndexer = true,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -221,6 +216,99 @@ public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.
|
|||
", vcthClass.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ViewComponentTagHelperPass_Execute_CreatesViewComponentTagHelper_Nested()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = CreateDocument(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<p foo=""17""><tagcloud foo=""17""></p>");
|
||||
|
||||
var tagHelpers = new[]
|
||||
{
|
||||
new TagHelperDescriptor()
|
||||
{
|
||||
AssemblyName = "TestAssembly",
|
||||
TypeName = "PTestTagHelper",
|
||||
TagName = "p",
|
||||
Attributes = new TagHelperAttributeDescriptor[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor()
|
||||
{
|
||||
TypeName = "System.Int32",
|
||||
Name = "Foo",
|
||||
}
|
||||
}
|
||||
},
|
||||
new TagHelperDescriptor()
|
||||
{
|
||||
AssemblyName = "TestAssembly",
|
||||
TypeName = "TestTagHelper",
|
||||
TagName = "tagcloud",
|
||||
Attributes = new TagHelperAttributeDescriptor[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor()
|
||||
{
|
||||
TypeName = "System.Int32",
|
||||
Name = "Foo",
|
||||
PropertyName = "Foo",
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tagHelpers[1].PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "TagCloud");
|
||||
|
||||
var engine = CreateEngine(tagHelpers);
|
||||
var pass = new ViewComponentTagHelperPass()
|
||||
{
|
||||
Engine = engine,
|
||||
};
|
||||
|
||||
var irDocument = CreateIRDocument(engine, codeDocument);
|
||||
|
||||
var expectedTagHelperName = "PTestTagHelper";
|
||||
var expectedVCTHName = "AspNetCore.Generated_test.__Generated__TagCloudViewComponentTagHelper";
|
||||
|
||||
// Act
|
||||
pass.Execute(codeDocument, irDocument);
|
||||
|
||||
// Assert
|
||||
var outerTagHelper = FindTagHelperNode(irDocument);
|
||||
Assert.Equal(expectedTagHelperName, Assert.IsType<CreateTagHelperIRNode>(outerTagHelper.Children[1]).TagHelperTypeName);
|
||||
Assert.Equal(expectedTagHelperName, Assert.IsType<SetTagHelperPropertyIRNode>(outerTagHelper.Children[2]).TagHelperTypeName);
|
||||
|
||||
var vcth = FindTagHelperNode(outerTagHelper.Children[0]);
|
||||
Assert.Equal(expectedVCTHName, Assert.IsType<CreateTagHelperIRNode>(vcth.Children[1]).TagHelperTypeName);
|
||||
Assert.Equal(expectedVCTHName, Assert.IsType<SetTagHelperPropertyIRNode>(vcth.Children[2]).TagHelperTypeName);
|
||||
|
||||
|
||||
var @class = FindClassNode(irDocument);
|
||||
Assert.Equal(3, @class.Children.Count);
|
||||
|
||||
var vcthClass = Assert.IsType<CSharpStatementIRNode>(@class.Children[2]);
|
||||
Assert.Equal(@"[Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute(""tagcloud"")]
|
||||
public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
|
||||
{
|
||||
private readonly global::Microsoft.AspNetCore.Mvc.IViewComponentHelper _helper = null;
|
||||
public __Generated__TagCloudViewComponentTagHelper(global::Microsoft.AspNetCore.Mvc.IViewComponentHelper helper)
|
||||
{
|
||||
_helper = helper;
|
||||
}
|
||||
[Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute, global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute]
|
||||
public global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; }
|
||||
public System.Int32 Foo { get; set; }
|
||||
public override async global::System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output)
|
||||
{
|
||||
(_helper as global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware)?.Contextualize(ViewContext);
|
||||
var content = await _helper.InvokeAsync(""TagCloud"", new { Foo });
|
||||
output.TagName = null;
|
||||
output.Content.SetHtmlContent(content);
|
||||
}
|
||||
}
|
||||
", vcthClass.Content);
|
||||
}
|
||||
|
||||
private RazorCodeDocument CreateDocument(string content)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
// 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.Reflection;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
|
|
@ -17,7 +19,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
{
|
||||
public class DefaultRoslynCompilationServiceTest
|
||||
{
|
||||
#if OLD_RAZOR
|
||||
[Fact]
|
||||
public void Compile_ReturnsCompilationResult()
|
||||
{
|
||||
|
|
@ -26,12 +27,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
public class MyTestType {}";
|
||||
|
||||
var compilationService = GetRoslynCompilationService();
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
|
||||
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "test.cshtml"));
|
||||
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = content
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
var result = compilationService.Compile(codeDocument, csharpDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("MyTestType", result.CompiledType.Name);
|
||||
|
|
@ -46,20 +51,23 @@ public class MyTestType {}";
|
|||
var content = $@"
|
||||
#line 1 ""{viewPath}""
|
||||
this should fail";
|
||||
var fileProvider = new TestFileProvider();
|
||||
var fileInfo = fileProvider.AddFile(viewPath, fileContent);
|
||||
|
||||
var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path");
|
||||
var compilationService = GetRoslynCompilationService();
|
||||
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(fileContent), viewPath));
|
||||
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = content
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
var result = compilationService.Compile(codeDocument, csharpDocument);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
Assert.Null(result.CompiledType);
|
||||
var compilationFailure = Assert.Single(result.CompilationFailures);
|
||||
Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath);
|
||||
Assert.Equal(viewPath, compilationFailure.SourceFilePath);
|
||||
Assert.Equal(fileContent, compilationFailure.SourceFileContent);
|
||||
}
|
||||
|
||||
|
|
@ -67,16 +75,20 @@ this should fail";
|
|||
public void Compile_ReturnsGeneratedCodePath_IfLinePragmaIsNotAvailable()
|
||||
{
|
||||
// Arrange
|
||||
var viewPath = "some-relative-path";
|
||||
var fileContent = "file content";
|
||||
var content = "this should fail";
|
||||
|
||||
var compilationService = GetRoslynCompilationService();
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { Content = fileContent },
|
||||
"some-relative-path");
|
||||
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(fileContent), viewPath));
|
||||
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = content
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
var result = compilationService.Compile(codeDocument, csharpDocument);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
|
|
@ -87,39 +99,11 @@ this should fail";
|
|||
Assert.Equal(content, compilationFailure.SourceFileContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_DoesNotThrow_IfFileCannotBeRead()
|
||||
{
|
||||
// Arrange
|
||||
var path = "some-relative-path";
|
||||
var content = $@"
|
||||
#line 1 ""{path}""
|
||||
this should fail";
|
||||
|
||||
var mockFileInfo = new Mock<IFileInfo>();
|
||||
mockFileInfo.Setup(f => f.CreateReadStream())
|
||||
.Throws(new Exception());
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(path, mockFileInfo.Object);
|
||||
|
||||
var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
|
||||
var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path);
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<CompilationResult>(result);
|
||||
Assert.Null(result.CompiledType);
|
||||
var compilationFailure = Assert.Single(result.CompilationFailures);
|
||||
Assert.Equal(path, compilationFailure.SourceFilePath);
|
||||
Assert.Null(compilationFailure.SourceFileContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_UsesApplicationsCompilationSettings_ForParsingAndCompilation()
|
||||
{
|
||||
// Arrange
|
||||
var viewPath = "some-relative-path";
|
||||
var content = @"
|
||||
#if MY_CUSTOM_DEFINE
|
||||
public class MyCustomDefinedClass {}
|
||||
|
|
@ -130,12 +114,15 @@ public class MyNonCustomDefinedClass {}
|
|||
var options = GetOptions();
|
||||
options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("MY_CUSTOM_DEFINE");
|
||||
var compilationService = GetRoslynCompilationService(options: options);
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), viewPath));
|
||||
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = content
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
var result = compilationService.Compile(codeDocument, csharpDocument);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result.CompiledType);
|
||||
|
|
@ -148,11 +135,8 @@ public class MyNonCustomDefinedClass {}
|
|||
// Arrange
|
||||
var viewPath = "Views/Home/Index";
|
||||
var generatedCodeFileName = "Generated Code";
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(viewPath, "view-content");
|
||||
var options = new RazorViewEngineOptions();
|
||||
options.FileProviders.Add(fileProvider);
|
||||
var compilationService = GetRoslynCompilationService(options: options, fileProvider: fileProvider);
|
||||
var compilationService = GetRoslynCompilationService();
|
||||
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent("view-content"), viewPath));
|
||||
var assemblyName = "random-assembly-name";
|
||||
|
||||
var diagnostics = new[]
|
||||
|
|
@ -179,7 +163,7 @@ public class MyNonCustomDefinedClass {}
|
|||
|
||||
// Act
|
||||
var compilationResult = compilationService.GetCompilationFailedResult(
|
||||
viewPath,
|
||||
codeDocument,
|
||||
"compilation-content",
|
||||
assemblyName,
|
||||
diagnostics);
|
||||
|
|
@ -235,13 +219,16 @@ public class MyNonCustomDefinedClass {}
|
|||
RoslynCompilationContext usedCompilation = null;
|
||||
var options = GetOptions(c => usedCompilation = c);
|
||||
var compilationService = GetRoslynCompilationService(options: options);
|
||||
|
||||
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path"));
|
||||
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path");
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = content
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
var result = compilationService.Compile(codeDocument, csharpDocument);
|
||||
|
||||
Assert.NotNull(usedCompilation);
|
||||
Assert.Single(usedCompilation.Compilation.SyntaxTrees);
|
||||
|
|
@ -257,12 +244,15 @@ public class MyNonCustomDefinedClass {}
|
|||
});
|
||||
var content = "public class MyTestType {}";
|
||||
var compilationService = GetRoslynCompilationService(options: options);
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path.cshtml");
|
||||
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path.cshtml"));
|
||||
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = content
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
var result = compilationService.Compile(codeDocument, csharpDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Single(result.CompilationFailures);
|
||||
|
|
@ -284,12 +274,15 @@ public class MyNonCustomDefinedClass {}
|
|||
var applicationPartManager = new ApplicationPartManager();
|
||||
var compilationService = GetRoslynCompilationService(applicationPartManager, options);
|
||||
|
||||
var relativeFileInfo = new RelativeFileInfo(
|
||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||
"some-relative-path.cshtml");
|
||||
var codeDocument = RazorCodeDocument.Create(RazorSourceDocument.ReadFrom(CreateStreamContent(), "some-relative-path.cshtml"));
|
||||
|
||||
var csharpDocument = new RazorCSharpDocument()
|
||||
{
|
||||
GeneratedCode = content
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = compilationService.Compile(relativeFileInfo, content);
|
||||
var result = compilationService.Compile(codeDocument, csharpDocument);
|
||||
|
||||
// Assert
|
||||
Assert.Null(result.CompilationFailures);
|
||||
|
|
@ -315,15 +308,6 @@ public class MyNonCustomDefinedClass {}
|
|||
};
|
||||
}
|
||||
|
||||
private static IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
|
||||
{
|
||||
var options = new Mock<IRazorViewEngineFileProviderAccessor>();
|
||||
options.SetupGet(o => o.FileProvider)
|
||||
.Returns(fileProvider ?? new TestFileProvider());
|
||||
|
||||
return options.Object;
|
||||
}
|
||||
|
||||
private static IOptions<RazorViewEngineOptions> GetAccessor(RazorViewEngineOptions options)
|
||||
{
|
||||
var optionsAccessor = new Mock<IOptions<RazorViewEngineOptions>>();
|
||||
|
|
@ -343,8 +327,7 @@ public class MyNonCustomDefinedClass {}
|
|||
|
||||
private static DefaultRoslynCompilationService GetRoslynCompilationService(
|
||||
ApplicationPartManager partManager = null,
|
||||
RazorViewEngineOptions options = null,
|
||||
IFileProvider fileProvider = null)
|
||||
RazorViewEngineOptions options = null)
|
||||
{
|
||||
partManager = partManager ?? GetApplicationPartManager();
|
||||
options = options ?? GetOptions();
|
||||
|
|
@ -354,10 +337,22 @@ public class MyNonCustomDefinedClass {}
|
|||
|
||||
return new DefaultRoslynCompilationService(
|
||||
compiler,
|
||||
GetFileProviderAccessor(fileProvider),
|
||||
optionsAccessor,
|
||||
NullLoggerFactory.Instance);
|
||||
}
|
||||
#endif
|
||||
|
||||
private static MemoryStream CreateStreamContent(string content = "Hello, World!", Encoding encoding = null)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
encoding = encoding ?? Encoding.UTF8;
|
||||
using (var writer = new StreamWriter(stream, encoding, bufferSize: 1024, leaveOpen: true))
|
||||
{
|
||||
writer.Write(content);
|
||||
}
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.AspNetCore.Razor;
|
||||
using Microsoft.AspNetCore.Razor.Chunks;
|
||||
using Microsoft.AspNetCore.Razor.CodeGenerators;
|
||||
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
|
||||
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNetCore.Razor.Evolution;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -19,61 +15,82 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
{
|
||||
public class RazorCompilationServiceTest
|
||||
{
|
||||
#if OLD_RAZOR
|
||||
[Theory]
|
||||
[InlineData(@"src\work\myapp", @"src\work\myapp\Views\index\home.cshtml")]
|
||||
[InlineData(@"src\work\myapp\", @"src\work\myapp\Views\index\home.cshtml")]
|
||||
public void CompileCalculatesRootRelativePath(string appPath, string viewPath)
|
||||
[Fact]
|
||||
public void CompileCalculatesRootRelativePath()
|
||||
{
|
||||
// Arrange
|
||||
var host = new Mock<RazorEngineHost>();
|
||||
host.Setup(h => h.GenerateCode(@"Views\index\home.cshtml", It.IsAny<Stream>()))
|
||||
.Returns(GetGeneratorResult())
|
||||
.Verifiable();
|
||||
var viewPath = @"src\work\myapp\Views\index\home.cshtml";
|
||||
var relativePath = @"Views\index\home.cshtml";
|
||||
|
||||
var fileInfo = new Mock<IFileInfo>();
|
||||
fileInfo.Setup(f => f.PhysicalPath).Returns(viewPath);
|
||||
fileInfo.Setup(f => f.CreateReadStream()).Returns(Stream.Null);
|
||||
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
|
||||
fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 }));
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(relativePath, fileInfo.Object);
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath);
|
||||
|
||||
var compiler = new Mock<ICompilationService>();
|
||||
compiler.Setup(c => c.Compile(relativeFileInfo, It.IsAny<string>()))
|
||||
compiler.Setup(c => c.Compile(It.IsAny<RazorCodeDocument>(), It.IsAny<RazorCSharpDocument>()))
|
||||
.Returns(new CompilationResult(typeof(RazorCompilationServiceTest)));
|
||||
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance);
|
||||
var engine = new Mock<RazorEngine>();
|
||||
engine.Setup(e => e.Process(It.IsAny<RazorCodeDocument>()))
|
||||
.Callback<RazorCodeDocument>(document =>
|
||||
{
|
||||
document.SetCSharpDocument(new RazorCSharpDocument()
|
||||
{
|
||||
Diagnostics = new List<RazorError>()
|
||||
});
|
||||
|
||||
Assert.Equal(viewPath, document.Source.Filename); // Assert if source file name is the root relative path
|
||||
}).Verifiable();
|
||||
|
||||
var razorService = new RazorCompilationService(
|
||||
compiler.Object,
|
||||
engine.Object,
|
||||
new DefaultRazorProject(fileProvider),
|
||||
GetFileProviderAccessor(fileProvider),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
razorService.Compile(relativeFileInfo);
|
||||
|
||||
// Assert
|
||||
host.Verify();
|
||||
engine.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsFailedResultIfParseFails()
|
||||
{
|
||||
// Arrange
|
||||
var errorSink = new ErrorSink();
|
||||
errorSink.OnError(new RazorError("some message", 1, 1, 1, 1));
|
||||
var generatorResult = new GeneratorResults(
|
||||
new Block(new BlockBuilder { Type = BlockType.Comment }),
|
||||
Enumerable.Empty<TagHelperDescriptor>(),
|
||||
errorSink,
|
||||
new CodeGeneratorResult("", new LineMapping[0]),
|
||||
new ChunkTree());
|
||||
var host = new Mock<IMvcRazorHost>();
|
||||
host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>()))
|
||||
.Returns(generatorResult)
|
||||
.Verifiable();
|
||||
|
||||
var relativePath = @"Views\index\home.cshtml";
|
||||
var fileInfo = new Mock<IFileInfo>();
|
||||
fileInfo.Setup(f => f.CreateReadStream())
|
||||
.Returns(Stream.Null);
|
||||
fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 }));
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(relativePath, fileInfo.Object);
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath);
|
||||
|
||||
var compiler = new Mock<ICompilationService>(MockBehavior.Strict);
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance);
|
||||
|
||||
var engine = new Mock<RazorEngine>();
|
||||
engine.Setup(e => e.Process(It.IsAny<RazorCodeDocument>()))
|
||||
.Callback<RazorCodeDocument>(document =>
|
||||
{
|
||||
document.SetCSharpDocument(new RazorCSharpDocument()
|
||||
{
|
||||
Diagnostics = new List<RazorError>()
|
||||
{
|
||||
new RazorError("some message", 1, 1, 1, 1)
|
||||
}
|
||||
});
|
||||
}).Verifiable();
|
||||
|
||||
var razorService = new RazorCompilationService(
|
||||
compiler.Object,
|
||||
engine.Object,
|
||||
new DefaultRazorProject(fileProvider),
|
||||
GetFileProviderAccessor(fileProvider),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var result = razorService.Compile(relativeFileInfo);
|
||||
|
|
@ -86,35 +103,41 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
var message = Assert.Single(failure.Messages);
|
||||
Assert.Equal("some message", message.Message);
|
||||
});
|
||||
host.Verify();
|
||||
engine.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compile_ReturnsResultFromCompilationServiceIfParseSucceeds()
|
||||
{
|
||||
// Arrange
|
||||
var code = "compiled-content";
|
||||
var generatorResult = new GeneratorResults(
|
||||
new Block(new BlockBuilder { Type = BlockType.Comment }),
|
||||
Enumerable.Empty<TagHelperDescriptor>(),
|
||||
new ErrorSink(),
|
||||
new CodeGeneratorResult(code, new LineMapping[0]),
|
||||
new ChunkTree());
|
||||
var host = new Mock<IMvcRazorHost>();
|
||||
host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>()))
|
||||
.Returns(generatorResult);
|
||||
|
||||
var relativePath = @"Views\index\home.cshtml";
|
||||
var fileInfo = new Mock<IFileInfo>();
|
||||
fileInfo.Setup(f => f.CreateReadStream())
|
||||
.Returns(Stream.Null);
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
|
||||
fileInfo.Setup(f => f.CreateReadStream()).Returns(new MemoryStream(new byte[] { 0 }));
|
||||
var fileProvider = new TestFileProvider();
|
||||
fileProvider.AddFile(relativePath, fileInfo.Object);
|
||||
var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, relativePath);
|
||||
|
||||
var compilationResult = new CompilationResult(typeof(object));
|
||||
var compiler = new Mock<ICompilationService>();
|
||||
compiler.Setup(c => c.Compile(relativeFileInfo, code))
|
||||
compiler.Setup(c => c.Compile(It.IsAny<RazorCodeDocument>(), It.IsAny<RazorCSharpDocument>()))
|
||||
.Returns(compilationResult)
|
||||
.Verifiable();
|
||||
var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance);
|
||||
|
||||
var engine = new Mock<RazorEngine>();
|
||||
engine.Setup(e => e.Process(It.IsAny<RazorCodeDocument>()))
|
||||
.Callback<RazorCodeDocument>(document =>
|
||||
{
|
||||
document.SetCSharpDocument(new RazorCSharpDocument()
|
||||
{
|
||||
Diagnostics = new List<RazorError>()
|
||||
});
|
||||
});
|
||||
|
||||
var razorService = new RazorCompilationService(
|
||||
compiler.Object,
|
||||
engine.Object,
|
||||
new DefaultRazorProject(fileProvider),
|
||||
GetFileProviderAccessor(fileProvider),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var result = razorService.Compile(relativeFileInfo);
|
||||
|
|
@ -130,7 +153,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
// Arrange
|
||||
var viewPath = @"views/index.razor";
|
||||
var viewImportsPath = @"views/global.import.cshtml";
|
||||
var host = Mock.Of<IMvcRazorHost>();
|
||||
|
||||
var fileProvider = new TestFileProvider();
|
||||
var file = fileProvider.AddFile(viewPath, "View Content");
|
||||
|
|
@ -138,7 +160,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
var relativeFileInfo = new RelativeFileInfo(file, viewPath);
|
||||
var razorService = new RazorCompilationService(
|
||||
Mock.Of<ICompilationService>(),
|
||||
Mock.Of<IMvcRazorHost>(),
|
||||
Mock.Of<RazorEngine>(),
|
||||
new DefaultRazorProject(fileProvider),
|
||||
GetFileProviderAccessor(fileProvider),
|
||||
NullLoggerFactory.Instance);
|
||||
var errors = new[]
|
||||
|
|
@ -205,16 +228,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
});
|
||||
}
|
||||
|
||||
private static GeneratorResults GetGeneratorResult()
|
||||
{
|
||||
return new GeneratorResults(
|
||||
new Block(new BlockBuilder { Type = BlockType.Comment }),
|
||||
Enumerable.Empty<TagHelperDescriptor>(),
|
||||
new ErrorSink(),
|
||||
new CodeGeneratorResult("", new LineMapping[0]),
|
||||
new ChunkTree());
|
||||
}
|
||||
|
||||
private static IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
|
||||
{
|
||||
var options = new Mock<IRazorViewEngineFileProviderAccessor>();
|
||||
|
|
@ -223,7 +236,5 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
|
||||
return options.Object;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue