// 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.Reflection; using System.Threading.Tasks; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Testing; using Microsoft.Framework.DependencyInjection; using Microsoft.Net.Http.Headers; using RazorWebSite; using Xunit; namespace Microsoft.AspNet.Mvc.FunctionalTests { public class ViewEngineTests { private const string SiteName = nameof(RazorWebSite); private static readonly Assembly _assembly = typeof(ViewEngineTests).GetTypeInfo().Assembly; private readonly Action _app = new Startup().Configure; private readonly Action _configureServices = new Startup().ConfigureServices; public static IEnumerable RazorView_ExecutesPageAndLayoutData { get { yield return new[] { "ViewWithoutLayout", @"ViewWithoutLayout-Content" }; yield return new[] { "ViewWithLayout", @" ViewWithLayout-Content " }; yield return new[] { "ViewWithFullPath", @" ViewWithFullPath-content " }; yield return new[] { "ViewWithNestedLayout", @" /ViewEngine/ViewWithNestedLayout ViewWithNestedLayout-Content " }; yield return new[] { "ViewWithDataFromController", "

hello from controller

" }; } } [Theory] [MemberData(nameof(RazorView_ExecutesPageAndLayoutData))] public async Task RazorView_ExecutesPageAndLayout(string actionName, string expected) { var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/ViewEngine/" + actionName); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } [Fact] public async Task RazorView_ExecutesPartialPagesWithCorrectContext() { var expected = @"98052 98052 test-value"; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/ViewEngine/ViewWithPartial"); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } [Fact] public async Task RazorView_DoesNotThrow_PartialViewWithEnumerableModel() { // Arrange var expected = "HelloWorld"; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync( "http://localhost/ViewEngine/ViewWithPartialTakingModelFromIEnumerable"); // Assert Assert.Equal(expected, body.Trim()); } [Fact] public async Task RazorView_PassesViewContextBetweenViewAndLayout() { var expected = @"Page title partial-content component-content"; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/ViewEngine/ViewPassesViewDataToLayout"); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } public static IEnumerable RazorViewEngine_UsesAllExpandedPathsToLookForViewsData { get { var expected1 = @"expander-index gb-partial"; yield return new[] { "en-GB", expected1 }; var expected2 = @"fr-index fr-partial"; yield return new[] { "fr", expected2 }; if (!TestPlatformHelper.IsMono) { // https://github.com/aspnet/Mvc/issues/2759 var expected3 = @"expander-index expander-partial"; yield return new[] { "!-invalid-!", expected3 }; } } } [Theory] [MemberData(nameof(RazorViewEngine_UsesAllExpandedPathsToLookForViewsData))] public async Task RazorViewEngine_UsesViewExpandersForViewsAndPartials(string value, string expected) { // Arrange var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); var cultureCookie = "c=" + value + "|uic=" + value; client.DefaultRequestHeaders.Add( "Cookie", new CookieHeaderValue("ASPNET_CULTURE", cultureCookie).ToString()); // Act var body = await client.GetStringAsync("http://localhost/TemplateExpander"); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } public static TheoryData ViewLocationExpanders_PassesInIsPartialToViewLocationExpanderContextData { get { return new TheoryData { { "Index", "/Shared-Views/ExpanderViews/_ExpanderPartial.cshtml" }, { "Partial", "/Shared-Views/ExpanderViews/_ExpanderPartial.cshtml" } }; } } [Theory] [MemberData(nameof(ViewLocationExpanders_PassesInIsPartialToViewLocationExpanderContextData))] public async Task ViewLocationExpanders_PassesInIsPartialToViewLocationExpanderContext(string action, string expected) { // Arrange var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync($"http://localhost/ExpanderViews/{action}"); // Assert Assert.Equal(expected, body.Trim()); } public static IEnumerable RazorViewEngine_RendersPartialViewsData { get { yield return new[] { "ViewWithoutLayout", "ViewWithoutLayout-Content" }; yield return new[] { "PartialViewWithNamePassedIn", @" ViewWithLayout-Content " }; yield return new[] { "ViewWithFullPath", @" ViewWithFullPath-content " }; yield return new[] { "ViewWithNestedLayout", @" /PartialViewEngine/ViewWithNestedLayout ViewWithNestedLayout-Content " }; yield return new[] { "PartialWithDataFromController", "

hello from controller

" }; yield return new[] { "PartialWithModel", @"my name is judge 98052 " }; } } [Theory] [MemberData(nameof(RazorViewEngine_RendersPartialViewsData))] public async Task RazorViewEngine_RendersPartialViews(string actionName, string expected) { // Arrange var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/PartialViewEngine/" + actionName); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } [Fact] public async Task LayoutValueIsPassedBetweenNestedViewStarts() { // Arrange var expected = @"viewstart-value ~/Views/NestedViewStarts/NestedViewStarts/Layout.cshtml index-content"; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/NestedViewStarts"); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } public static IEnumerable RazorViewEngine_UsesExpandersForLayoutsData { get { var expected1 = @" View With Layout "; yield return new[] { "en-GB", expected1 }; if (!TestPlatformHelper.IsMono) { // https://github.com/aspnet/Mvc/issues/2759 yield return new[] { "!-invalid-!", expected1 }; } var expected2 = @" View With Layout "; yield return new[] { "fr", expected2 }; } } [Theory] [MemberData(nameof(RazorViewEngine_UsesExpandersForLayoutsData))] public async Task RazorViewEngine_UsesExpandersForLayouts(string value, string expected) { // Arrange var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); var cultureCookie = "c=" + value + "|uic=" + value; client.DefaultRequestHeaders.Add( "Cookie", new CookieHeaderValue("ASPNET_CULTURE", cultureCookie).ToString()); // Act var body = await client.GetStringAsync("http://localhost/TemplateExpander/ViewWithLayout"); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } [Fact] public async Task ViewStartsCanUseDirectivesInjectedFromParentGlobals() { // Arrange var expected = @"Hello Controller-Person Hello Controller-Person"; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); var target = "http://localhost/NestedViewImports"; // Act var body = await client.GetStringAsync(target); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } [Fact] public async Task ViewComponentsExecuteLayout() { // Arrange var expected = @"View With Component With Layout Page Content ViewComponent With Title Component With Layout"; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/ViewEngine/ViewWithComponentThatHasLayout"); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } [Fact] public async Task ViewComponentsDoNotExecuteViewStarts() { // Arrange var expected = @"ViewComponent With ViewStart"; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/ViewEngine/ViewWithComponentThatHasViewStart"); // Assert Assert.Equal(expected, body.Trim()); } [Fact] public async Task PartialDoNotExecuteViewStarts() { // Arrange var expected = "Partial that does not specify Layout"; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/PartialsWithLayout/PartialDoesNotExecuteViewStarts"); // Assert Assert.Equal(expected, body.Trim()); } [Fact] public async Task PartialsRenderedViaRenderPartialAsync_CanRenderLayouts() { // Arrange var expected = @" Partial that specifies Layout Partial that does not specify Layout "; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/PartialsWithLayout/PartialsRenderedViaRenderPartial"); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } [Fact] public async Task PartialsRenderedViaPartialAsync_CanRenderLayouts() { // Arrange var expected = @" Partial that specifies Layout Partial that does not specify Layout "; var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); // Act var body = await client.GetStringAsync("http://localhost/PartialsWithLayout/PartialsRenderedViaPartialAsync"); // Assert Assert.Equal(expected, body.Trim(), ignoreLineEndingDifferences: true); } [Fact] public async Task RazorView_SetsViewPathAndExecutingPagePath() { // Arrange var server = TestHelper.CreateServer(_app, SiteName, _configureServices); var client = server.CreateClient(); var outputFile = "compiler/resources/ViewEngineController.ViewWithPaths.txt"; var expectedContent = await ResourceFile.ReadResourceAsync(_assembly, outputFile, sourceFile: false); // Act var responseContent = await client.GetStringAsync("http://localhost/ViewWithPaths"); // Assert responseContent = responseContent.Trim(); #if GENERATE_BASELINES ResourceFile.UpdateFile(_assembly, outputFile, expectedContent, responseContent); #else Assert.Equal( PlatformNormalizer.NormalizePath(expectedContent), responseContent, ignoreLineEndingDifferences: true); #endif } } }