using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Web; using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; using System.Web.Security; using Moq; using Semver; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Dictionary; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Web.WebApi; using LightInject; using System.Globalization; namespace Umbraco.Tests.TestHelpers.ControllerTesting { /// /// Used to mock all of the services required for re-mocking and testing controllers /// /// /// A more complete version of this is found in the Umbraco REST API project but this has the basics covered /// public abstract class TestControllerActivatorBase : DefaultHttpControllerActivator, IHttpControllerActivator { IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { // default if (!typeof (UmbracoApiControllerBase).IsAssignableFrom(controllerType)) return base.Create(request, controllerDescriptor, controllerType); var owinContext = request.TryGetOwinContext().Result; var mockedUserService = Mock.Of(); var mockedContentService = Mock.Of(); var mockedMediaService = Mock.Of(); var mockedEntityService = Mock.Of(); var mockedMemberService = Mock.Of(); var mockedMemberTypeService = Mock.Of(); var mockedDataTypeService = Mock.Of(); var mockedContentTypeService = Mock.Of(); var serviceContext = new ServiceContext( userService: mockedUserService, contentService: mockedContentService, mediaService: mockedMediaService, entityService: mockedEntityService, memberService: mockedMemberService, memberTypeService: mockedMemberTypeService, dataTypeService: mockedDataTypeService, contentTypeService: mockedContentTypeService, localizedTextService:Mock.Of(), sectionService:Mock.Of()); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); // fixme v8? ////new app context //var dbCtx = new Mock(Mock.Of(), Mock.Of(), Mock.Of(), "test"); ////ensure these are set so that the appctx is 'Configured' //dbCtx.Setup(x => x.CanConnect).Returns(true); //dbCtx.Setup(x => x.IsDatabaseConfigured).Returns(true); //var appCtx = ApplicationContext.EnsureContext( // dbCtx.Object, // //pass in mocked services // serviceContext, // CacheHelper.CreateDisabledCacheHelper(), // new ProfilingLogger(Mock.Of(), Mock.Of()), // true); var httpContextItems = new Dictionary { //add the special owin environment to the httpcontext items, this is how the GetOwinContext works ["owin.Environment"] = new Dictionary() }; //httpcontext with an auth'd user var httpContext = Mock.Of( http => http.User == owinContext.Authentication.User //ensure the request exists with a cookies collection && http.Request == Mock.Of(r => r.Cookies == new HttpCookieCollection()) //ensure the request exists with an items collection && http.Items == httpContextItems); //chuck it into the props since this is what MS does when hosted and it's needed there request.Properties["MS_HttpContext"] = httpContext; var backofficeIdentity = (UmbracoBackOfficeIdentity) owinContext.Authentication.User.Identity; var webSecurity = new Mock(null, null, globalSettings); //mock CurrentUser var groups = new List(); for (var index = 0; index < backofficeIdentity.Roles.Length; index++) { var role = backofficeIdentity.Roles[index]; groups.Add(new ReadOnlyUserGroup(index + 1, role, "icon-user", null, null, role, new string[0], new string[0])); } webSecurity.Setup(x => x.CurrentUser) .Returns(Mock.Of(u => u.IsApproved == true && u.IsLockedOut == false && u.AllowedSections == backofficeIdentity.AllowedApplications && u.Groups == groups && u.Email == "admin@admin.com" && u.Id == (int) backofficeIdentity.Id && u.Language == "en" && u.Name == backofficeIdentity.RealName && u.StartContentIds == backofficeIdentity.StartContentNodes && u.StartMediaIds == backofficeIdentity.StartMediaNodes && u.Username == backofficeIdentity.Username)); //mock Validate webSecurity.Setup(x => x.ValidateCurrentUser()) .Returns(() => true); webSecurity.Setup(x => x.UserHasSectionAccess(It.IsAny(), It.IsAny())) .Returns(() => true); var publishedSnapshot = new Mock(); publishedSnapshot.Setup(x => x.Members).Returns(Mock.Of()); var publishedSnapshotService = new Mock(); publishedSnapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny())).Returns(publishedSnapshot.Object); //var umbracoContextAccessor = new TestUmbracoContextAccessor(); //Umbraco.Web.Composing.Current.UmbracoContextAccessor = umbracoContextAccessor; var umbracoContextAccessor = Umbraco.Web.Composing.Current.UmbracoContextAccessor; Current.Container.Register(factory => umbracoContextAccessor.UmbracoContext); // but really, should we inject this?! var umbCtx = UmbracoContext.EnsureContext( umbracoContextAccessor, httpContext, publishedSnapshotService.Object, webSecurity.Object, Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == UrlProviderMode.Auto.ToString())), Enumerable.Empty(), globalSettings, mockedEntityService, true); //replace it var urlHelper = new Mock(); urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns("/hello/world/1234"); var membershipHelper = new MembershipHelper(umbCtx, Mock.Of(), Mock.Of()); var mockedTypedContent = Mock.Of(); var umbHelper = new UmbracoHelper(umbCtx, Mock.Of(), mockedTypedContent, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), membershipHelper, serviceContext, CacheHelper.NoCache); return CreateController(controllerType, request, umbHelper); } protected abstract ApiController CreateController(Type controllerType, HttpRequestMessage msg, UmbracoHelper helper); } }