Add @model specific tests to validate output.

#568
This commit is contained in:
N. Taylor Mullen 2014-06-24 12:09:29 -07:00 committed by Pranav K
parent 54d6b0b113
commit 2ad175b687
5 changed files with 219 additions and 3 deletions

View File

@ -19,16 +19,20 @@ namespace Microsoft.AspNet.Mvc.Razor
protected override CSharpCodeWritingScope BuildClassDeclaration(CSharpCodeWriter writer)
{
var chunks = Context.CodeTreeBuilder.CodeTree.Chunks;
var modelChunks = Context.CodeTreeBuilder.CodeTree.Chunks.OfType<ModelChunk>();
// If there were any model chunks then we need to modify the class declaration signature.
if (chunks.OfType<ModelChunk>().Any())
if (modelChunks.Any())
{
writer.Write(string.Format(CultureInfo.CurrentCulture, "public class {0} : ", Context.ClassName));
// Grab the last model chunk so it gets intellisense.
// NOTE: If there's more than 1 model chunk there will be a Razor error BUT we want intellisense to show up
// on the current model chunk that the user is typing.
var lastModelChunk = modelChunks.Last();
var modelVisitor = new ModelChunkVisitor(writer, Context);
// This generates the base class signature
modelVisitor.Accept(chunks);
modelVisitor.Accept(lastModelChunk);
writer.WriteLine();

View File

@ -24,9 +24,11 @@
</PropertyGroup>
<ItemGroup>
<Content Include="Project.json" />
<Content Include="TestFiles\Input\Model.cshtml" />
<Content Include="TestFiles\Input\Inject.cshtml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ModelChunkVisitorTest.cs" />
<Compile Include="InjectChunkVisitorTest.cs" />
<Compile Include="MvcCSharpRazorCodeParserTest.cs" />
<Compile Include="SpanFactory\RawTextSymbol.cs" />
@ -35,6 +37,7 @@
<Compile Include="SpanFactory\SpanFactoryExtensions.cs" />
<Compile Include="SpanFactory\UnclassifiedSpanConstructor.cs" />
<Compile Include="StringTextBuffer.cs" />
<Compile Include="TestFiles\Output\Model.cs" />
<Compile Include="TestFiles\Output\Inject.cs" />
</ItemGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />

View File

@ -0,0 +1,176 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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 Microsoft.AspNet.Razor;
using Microsoft.AspNet.Razor.Generator;
using Microsoft.AspNet.Razor.Generator.Compiler;
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.Text;
using Xunit;
namespace Microsoft.AspNet.Mvc.Razor
{
public class ModelChunkVisitorTest
{
[Fact]
public void Visit_IgnoresNonModelChunks()
{
// Arrange
var writer = new CSharpCodeWriter();
var context = CreateContext();
var visitor = new ModelChunkVisitor(writer, context);
// Act
visitor.Accept(new Chunk[]
{
new LiteralChunk(),
new CodeAttributeChunk()
});
var code = writer.GenerateCode();
// Assert
Assert.Empty(code);
}
[Fact]
public void Visit_GeneratesBaseClass_ForModelChunks()
{
// Arrange
var expected =
"MyBase<" + Environment.NewLine +
"#line 1 \"\"" + Environment.NewLine +
"My_Generic.After.Periods" + Environment.NewLine +
Environment.NewLine +
"#line default" + Environment.NewLine +
"#line hidden" + Environment.NewLine +
">";
var writer = new CSharpCodeWriter();
var context = CreateContext();
var visitor = new ModelChunkVisitor(writer, context);
var factory = SpanFactory.CreateCsHtml();
var node = (Span)factory.Code("Some code")
.As(new ModelCodeGenerator("MyBase", "MyGeneric"));
// Act
visitor.Accept(new Chunk[]
{
new LiteralChunk(),
new ModelChunk("MyBase", "My_Generic.After.Periods") { Association = node }
});
var code = writer.GenerateCode();
// Assert
Assert.Equal(expected, code);
}
[Fact]
public void Visit_WithDesignTimeHost_GeneratesBaseClass_ForModelChunks()
{
// Arrange
var expected =
"MyBase<" + Environment.NewLine +
"#line 1 \"\"" + Environment.NewLine +
"My_Generic.After.Periods" + Environment.NewLine +
Environment.NewLine +
"#line default" + Environment.NewLine +
"#line hidden" + Environment.NewLine +
">";
var writer = new CSharpCodeWriter();
var context = CreateContext();
context.Host.DesignTimeMode = true;
var visitor = new ModelChunkVisitor(writer, context);
var factory = SpanFactory.CreateCsHtml();
var node = (Span)factory.Code("Some code")
.As(new ModelCodeGenerator("MyType", "MyPropertyName"));
// Act
visitor.Accept(new Chunk[]
{
new LiteralChunk(),
new ModelChunk("MyBase", "My_Generic.After.Periods") { Association = node }
});
var code = writer.GenerateCode();
// Assert
Assert.Equal(expected, code);
}
[Fact]
public void ModelVisitor_GeneratesCorrectLineMappings()
{
// Arrange
var host = new MvcRazorHost("RazorView")
{
DesignTimeMode = true
};
host.NamespaceImports.Clear();
var engine = new RazorTemplateEngine(host);
var source = ReadResource("Model.cshtml");
var expectedCode = ReadResource("Model.cs");
var expectedLineMappings = new List<LineMapping>
{
BuildLineMapping(7, 0, 7, 126, 6, 7, 30),
};
// Act
GeneratorResults results;
using (var buffer = new StringTextBuffer(source))
{
results = engine.GenerateCode(buffer);
}
// Assert
Assert.True(results.Success);
Assert.Equal(expectedCode, results.GeneratedCode);
Assert.Empty(results.ParserErrors);
Assert.Equal(expectedLineMappings, results.DesignTimeLineMappings);
}
private string ReadResource(string resourceName)
{
var assembly = typeof(ModelChunkVisitorTest).Assembly;
using (var stream = assembly.GetManifestResourceStream(resourceName))
using (var streamReader = new StreamReader(stream))
{
return streamReader.ReadToEnd();
}
}
private static CodeGeneratorContext CreateContext()
{
return CodeGeneratorContext.Create(new MvcRazorHost("RazorView"),
"MyClass",
"MyNamespace",
string.Empty,
shouldGenerateLinePragmas: true);
}
private static LineMapping BuildLineMapping(int documentAbsoluteIndex,
int documentLineIndex,
int documentCharacterIndex,
int generatedAbsoluteIndex,
int generatedLineIndex,
int generatedCharacterIndex,
int contentLength)
{
var documentLocation = new SourceLocation(documentAbsoluteIndex,
documentLineIndex,
documentCharacterIndex);
var generatedLocation = new SourceLocation(generatedAbsoluteIndex,
generatedLineIndex,
generatedCharacterIndex);
return new LineMapping(
documentLocation: new MappingLocation(documentLocation, contentLength),
generatedLocation: new MappingLocation(generatedLocation, contentLength));
}
}
}

View File

@ -0,0 +1 @@
@model System.Collections.IEnumerable

View File

@ -0,0 +1,32 @@
namespace Razor
{
using System.Threading.Tasks;
public class __CompiledTemplate : RazorView<
#line 1 ""
System.Collections.IEnumerable
#line default
#line hidden
>
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
#pragma warning restore 219
}
#line hidden
#line hidden
public __CompiledTemplate()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
}
#pragma warning restore 1998
}
}