// 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.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Web.WebPages.TestUtils;
using Microsoft.AspNetCore.Razor.Chunks.Generators;
using Microsoft.AspNetCore.Razor.CodeGenerators;
using Microsoft.AspNetCore.Razor.Parser;
using Microsoft.AspNetCore.Razor.Parser.Internal;
using Microsoft.AspNetCore.Razor.Text;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Razor
{
public class RazorTemplateEngineTest
{
[Fact]
public void InvalidRazorEngineHostReturnsParseErrorsAtDesignTime()
{
// Arrange
var host = new InvalidRazorEngineHost(new CSharpRazorCodeLanguage())
{
DesignTimeMode = true
};
var razorEngine = new RazorTemplateEngine(host);
var input = new StringTextBuffer("
Hello @(\"World\")
");
var exception = new InvalidOperationException("Hello World");
var expectedError = RazorResources.FormatFatalException("test", Environment.NewLine, exception.Message);
// Act
var result = razorEngine.GenerateCode(input, className: null, rootNamespace: null, sourceFileName: "test");
// Assert
Assert.Empty(result.Document.Children);
Assert.Empty(result.ChunkTree.Children);
Assert.Empty(result.DesignTimeLineMappings);
Assert.Empty(result.GeneratedCode);
var error = Assert.Single(result.ParserErrors);
Assert.Equal(expectedError, error.Message, StringComparer.Ordinal);
Assert.Equal(SourceLocation.Undefined, error.Location);
Assert.Equal(-1, error.Length);
}
[Fact]
public void InvalidRazorEngineHostThrowsAtRuntime()
{
// Arrange
var host = new InvalidRazorEngineHost(new CSharpRazorCodeLanguage())
{
DesignTimeMode = false
};
var razorEngine = new RazorTemplateEngine(host);
var input = new StringTextBuffer("
Hello @(\"World\")
");
// Act
var thrownException = Assert.Throws(() =>
razorEngine.GenerateCode(input, className: null, rootNamespace: null, sourceFileName: "test"));
// Assert
Assert.Equal("Hello World", thrownException.Message, StringComparer.Ordinal);
}
[Fact]
public void ConstructorInitializesHost()
{
// Arrange
var host = new RazorEngineHost(new CSharpRazorCodeLanguage());
// Act
var engine = new RazorTemplateEngine(host);
// Assert
Assert.Same(host, engine.Host);
}
[Fact]
public void CreateParserMethodIsConstructedFromHost()
{
// Arrange
var host = CreateHost();
var engine = new RazorTemplateEngine(host);
// Act
var parser = engine.CreateParser("some-file");
// Assert
Assert.IsType(parser.CodeParser);
Assert.IsType(parser.MarkupParser);
}
[Fact]
public void CreateParserMethodSetsParserContextToDesignTimeModeIfHostSetToDesignTimeMode()
{
// Arrange
var host = CreateHost();
var engine = new RazorTemplateEngine(host);
host.DesignTimeMode = true;
// Act
var parser = engine.CreateParser("some-file");
// Assert
Assert.True(parser.DesignTimeMode);
}
[Fact]
public void CreateParserMethodPassesParsersThroughDecoratorMethodsOnHost()
{
// Arrange
var expectedCode = new Mock().Object;
var expectedMarkup = new Mock().Object;
var mockHost = new Mock(new CSharpRazorCodeLanguage()) { CallBase = true };
mockHost.Setup(h => h.DecorateCodeParser(It.IsAny()))
.Returns(expectedCode);
mockHost.Setup(h => h.DecorateMarkupParser(It.IsAny()))
.Returns(expectedMarkup);
var engine = new RazorTemplateEngine(mockHost.Object);
// Act
var actual = engine.CreateParser("some-file");
// Assert
Assert.Equal(expectedCode, actual.CodeParser);
Assert.Equal(expectedMarkup, actual.MarkupParser);
}
[Fact]
public void CreateChunkGeneratorMethodPassesChunkGeneratorThroughDecorateMethodOnHost()
{
// Arrange
var mockHost = new Mock(new CSharpRazorCodeLanguage()) { CallBase = true };
var expected = new Mock("Foo", "Bar", "Baz", mockHost.Object).Object;
mockHost.Setup(h => h.DecorateChunkGenerator(It.IsAny()))
.Returns(expected);
var engine = new RazorTemplateEngine(mockHost.Object);
// Act
var actual = engine.CreateChunkGenerator("Foo", "Bar", "Baz");
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void CreateCodeGenerator_PassesChunkGeneratorThroughDecorateMethodOnHost()
{
// Arrange
var mockHost = new Mock(new CSharpRazorCodeLanguage()) { CallBase = true };
var codeGeneratorContext = new CodeGeneratorContext(
mockHost.Object,
"different-class",
"different-ns",
string.Empty,
shouldGenerateLinePragmas: true,
errorSink: new ErrorSink());
var expected = new CSharpCodeGenerator(codeGeneratorContext);
mockHost
.Setup(h => h.DecorateCodeGenerator(It.IsAny(), codeGeneratorContext))
.Returns(expected);
var engine = new RazorTemplateEngine(mockHost.Object);
// Act
var actual = engine.CreateCodeGenerator(codeGeneratorContext);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ParseTemplateCopiesTextReaderContentToSeekableTextReaderAndPassesToParseTemplateCore()
{
// Arrange
var mockEngine = new Mock(CreateHost());
var reader = new StringReader("foo");
var source = new CancellationTokenSource();
// Act
mockEngine.Object.ParseTemplate(reader, cancelToken: source.Token);
// Assert
mockEngine.Verify(e => e.ParseTemplateCore(
It.Is(l => l.ReadToEnd() == "foo"),
null,
source.Token));
}
[Fact]
public void GenerateCodeCopiesTextReaderContentToSeekableTextReaderAndPassesToGenerateCodeCore()
{
// Arrange
var mockEngine = new Mock(CreateHost());
var reader = new StringReader("foo");
var source = new CancellationTokenSource();
var className = "Foo";
var ns = "Bar";
var src = "Baz";
// Act
mockEngine.Object.GenerateCode(
reader,
className: className,
rootNamespace: ns,
sourceFileName: src,
cancelToken: source.Token);
// Assert
mockEngine.Verify(e => e.GenerateCodeCore(
It.Is(l => l.ReadToEnd() == "foo"),
className,
ns,
src,
null,
source.Token));
}
[Fact]
public void ParseTemplateOutputsResultsOfParsingProvidedTemplateSource()
{
// Arrange
var engine = new RazorTemplateEngine(CreateHost());
// Act
var results = engine.ParseTemplate(new StringTextBuffer("foo @bar("));
// Assert
Assert.False(results.Success);
Assert.Single(results.ParserErrors);
Assert.NotNull(results.Document);
}
[Fact]
public void GenerateOutputsResultsOfParsingAndGeneration()
{
// Arrange
var engine = new RazorTemplateEngine(CreateHost());
// Act
var results = engine.GenerateCode(new StringTextBuffer("foo @bar("));
// Assert
Assert.False(results.Success);
Assert.Single(results.ParserErrors);
Assert.NotNull(results.Document);
Assert.NotNull(results.GeneratedCode);
}
[Fact]
public void GenerateOutputsDesignTimeMappingsIfDesignTimeSetOnHost()
{
// Arrange
var engine = new RazorTemplateEngine(CreateHost(designTime: true));
// Act
var results = engine.GenerateCode(
new StringTextBuffer("foo @bar()"),
className: null,
rootNamespace: null,
sourceFileName: "foo.cshtml");
// Assert
Assert.True(results.Success);
Assert.Empty(results.ParserErrors);
Assert.NotNull(results.Document);
Assert.NotNull(results.GeneratedCode);
Assert.NotNull(results.DesignTimeLineMappings);
}
public static IEnumerable