// 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.Globalization; using System.IO; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Routing; using Microsoft.Framework.DependencyInjection; using Moq; using Xunit; namespace Microsoft.AspNet.Mvc.Razor { public class RazorPageActivatorTest { [Fact] public void Activate_ActivatesAndContextualizesPropertiesOnViews() { // Arrange var activator = new RazorPageActivator(Mock.Of()); var instance = new TestRazorPage(); var myService = new MyService(); var helper = Mock.Of>(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(MyService))) .Returns(myService); serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper))) .Returns(helper); var httpContext = new Mock(); httpContext.SetupGet(c => c.RequestServices) .Returns(serviceProvider.Object); var routeContext = new RouteContext(httpContext.Object); var actionContext = new ActionContext(routeContext, new ActionDescriptor()); var viewContext = new ViewContext(actionContext, Mock.Of(), new ViewDataDictionary(Mock.Of()), TextWriter.Null); // Act activator.Activate(instance, viewContext); // Assert Assert.Same(helper, instance.Html); Assert.Same(myService, instance.MyService); Assert.Same(viewContext, myService.ViewContext); Assert.Null(instance.MyService2); } [Fact] public void Activate_ThrowsIfTheViewDoesNotDeriveFromRazorViewOfT() { // Arrange var activator = new RazorPageActivator(Mock.Of()); var instance = new DoesNotDeriveFromRazorPageOfT(); var myService = new MyService(); var helper = Mock.Of>(); var serviceProvider = new Mock(); var httpContext = new Mock(); httpContext.SetupGet(c => c.RequestServices) .Returns(serviceProvider.Object); var routeContext = new RouteContext(httpContext.Object); var actionContext = new ActionContext(routeContext, new ActionDescriptor()); var viewContext = new ViewContext(actionContext, Mock.Of(), new ViewDataDictionary(Mock.Of()), TextWriter.Null); // Act and Assert var ex = Assert.Throws(() => activator.Activate(instance, viewContext)); var message = string.Format(CultureInfo.InvariantCulture, "View of type '{0}' cannot be activated by '{1}'.", instance.GetType().FullName, typeof(RazorPageActivator).FullName); Assert.Equal(message, ex.Message); } [Fact] public void Activate_InstantiatesNewViewDataDictionaryType_IfTheTypeDoesNotMatch() { // Arrange var typeActivator = new TypeActivator(); var activator = new RazorPageActivator(typeActivator); var instance = new TestRazorPage(); var myService = new MyService(); var helper = Mock.Of>(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(MyService))) .Returns(myService); serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper))) .Returns(helper); var httpContext = new Mock(); httpContext.SetupGet(c => c.RequestServices) .Returns(serviceProvider.Object); var routeContext = new RouteContext(httpContext.Object); var actionContext = new ActionContext(routeContext, new ActionDescriptor()); var viewData = new ViewDataDictionary(Mock.Of()) { Model = new MyModel() }; var viewContext = new ViewContext(actionContext, Mock.Of(), viewData, TextWriter.Null); // Act activator.Activate(instance, viewContext); // Assert Assert.IsType>(viewContext.ViewData); } [Fact] public void Activate_UsesPassedInViewDataDictionaryInstance_IfPassedInTypeMatches() { // Arrange var typeActivator = new TypeActivator(); var activator = new RazorPageActivator(typeActivator); var instance = new TestRazorPage(); var myService = new MyService(); var helper = Mock.Of>(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(MyService))) .Returns(myService); serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper))) .Returns(helper); var httpContext = new Mock(); httpContext.SetupGet(c => c.RequestServices) .Returns(serviceProvider.Object); var routeContext = new RouteContext(httpContext.Object); var actionContext = new ActionContext(routeContext, new ActionDescriptor()); var viewData = new ViewDataDictionary(Mock.Of()) { Model = new MyModel() }; var viewContext = new ViewContext(actionContext, Mock.Of(), viewData, TextWriter.Null); // Act activator.Activate(instance, viewContext); // Assert Assert.Same(viewData, viewContext.ViewData); } [Fact] public void Activate_DeterminesModelTypeFromProperty() { // Arrange var typeActivator = new TypeActivator(); var activator = new RazorPageActivator(typeActivator); var instance = new DoesNotDeriveFromRazorPageOfTButHasModelProperty(); var myService = new MyService(); var helper = Mock.Of>(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(MyService))) .Returns(myService); serviceProvider.Setup(p => p.GetService(typeof(IHtmlHelper))) .Returns(helper); var httpContext = new Mock(); httpContext.SetupGet(c => c.RequestServices) .Returns(serviceProvider.Object); var routeContext = new RouteContext(httpContext.Object); var actionContext = new ActionContext(routeContext, new ActionDescriptor()); var viewData = new ViewDataDictionary(Mock.Of()); var viewContext = new ViewContext(actionContext, Mock.Of(), viewData, TextWriter.Null); // Act activator.Activate(instance, viewContext); // Assert Assert.IsType>(viewContext.ViewData); } private abstract class TestPageBase : RazorPage { [Activate] public MyService MyService { get; set; } public MyService MyService2 { get; set; } } private class TestRazorPage : TestPageBase { [Activate] internal IHtmlHelper Html { get; private set; } public override Task ExecuteAsync() { throw new NotImplementedException(); } } private abstract class DoesNotDeriveFromRazorPageOfTBase : RazorPage { } private class DoesNotDeriveFromRazorPageOfT : DoesNotDeriveFromRazorPageOfTBase { public override Task ExecuteAsync() { throw new NotImplementedException(); } } private class DoesNotDeriveFromRazorPageOfTButHasModelProperty : DoesNotDeriveFromRazorPageOfTBase { public string Model { get; set; } public override Task ExecuteAsync() { throw new NotImplementedException(); } } private class MyService : ICanHasViewContext { public ViewContext ViewContext { get; private set; } public void Contextualize(ViewContext viewContext) { ViewContext = viewContext; } } private class MyModel { } } }