Last active
October 30, 2019 20:03
-
-
Save lars-erik/d6716f516153511b6461fc06abd53371 to your computer and use it in GitHub Desktop.
Umbracosupport 7.15
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using Umbraco.Core; | |
using Umbraco.Core.Models; | |
using Umbraco.Core.Models.PublishedContent; | |
using Umbraco.Web; | |
namespace Umbraco.UnitTesting.Adapter.Support | |
{ | |
public class FakeModelFactoryResolver : PublishedContentModelFactoryResolver | |
{ | |
public FakeModelFactoryResolver(IPublishedContentModelFactory factory) : base(factory) | |
{ | |
} | |
} | |
public class FakeContentModelFactory : IPublishedContentModelFactory | |
{ | |
protected Dictionary<string, Func<IPublishedContent, IPublishedContent>> Factories { get; } = new Dictionary<string, Func<IPublishedContent, IPublishedContent>>(); | |
protected Dictionary<Guid, IPublishedContent> items = new Dictionary<Guid, IPublishedContent>(); | |
public void Register(string alias, Func<IPublishedContent, IPublishedContent> factory) | |
{ | |
if (Factories.ContainsKey(alias)) | |
Factories[alias] = factory; | |
else | |
Factories.Add(alias, factory); | |
} | |
public IPublishedContent CreateModel(IPublishedContent content) | |
{ | |
if (items.ContainsKey(content.GetKey())) | |
return items[content.GetKey()]; | |
if (Factories.ContainsKey(content.DocumentTypeAlias)) | |
content = Factories[content.DocumentTypeAlias](content); | |
items.Add(content.GetKey(), content); | |
return content; | |
} | |
} | |
public static class ContentTypeHandler | |
{ | |
public static Func<string, PublishedContentType> CreateDelegate = alias => new PublishedContentType(ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias)); | |
public static PublishedContentType Create(string alias) | |
{ | |
return CreateDelegate(alias); | |
} | |
public static void Init() | |
{ | |
PublishedContentType.GetPublishedContentTypeCallback = Create; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Globalization; | |
using System.Linq; | |
using System.Reflection; | |
using System.Web; | |
using System.Web.Mvc; | |
using System.Web.Routing; | |
using Moq; | |
using NUnit.Framework; | |
using umbraco.BusinessLogic; | |
using Umbraco.Core; | |
using Umbraco.Core.Configuration.UmbracoSettings; | |
using Umbraco.Core.Logging; | |
using Umbraco.Core.Models; | |
using Umbraco.Core.Models.PublishedContent; | |
using Umbraco.Core.ObjectResolution; | |
using Umbraco.Core.Persistence; | |
using Umbraco.Core.PropertyEditors; | |
using Umbraco.Core.Services; | |
using Umbraco.Tests.TestHelpers; | |
using Umbraco.Web; | |
using Umbraco.Web.Mvc; | |
using Umbraco.Web.Routing; | |
namespace Umbraco.UnitTesting.Adapter.Support | |
{ | |
public class UmbracoSupport : UmbracoSupport<IPublishedContent> | |
{ | |
public UmbracoSupport() | |
: base(c => c) | |
{ | |
} | |
} | |
public class UmbracoSupport<T> : BaseRoutingTest | |
where T : class, IPublishedContent | |
{ | |
bool initialized = false; | |
private Func<IPublishedContent, T> contentFactory; | |
public UmbracoContext UmbracoContext => umbracoContext; | |
public new ServiceContext ServiceContext => serviceContext; | |
public T CurrentPage => currentPage; | |
public RouteData RouteData => routeData; | |
public UmbracoHelper UmbracoHelper => umbracoHelper; | |
public HttpContextBase HttpContext => umbracoContext.HttpContext; | |
public string ContentCacheXml { get; set; } | |
public string Url { get; private set; } | |
public PublishedContentRequest PublishedContentRequest => umbracoContext.PublishedContentRequest; | |
public IUmbracoSettingsSection Settings => settings; | |
public RoutingContext RoutingContext => routingContext; | |
public FakeContentModelFactory ModelFactory => fakeContentModelFactory; | |
public List<Type> ConverterTypes => converterTypes; | |
private List<Action> onInitialized = new List<Action>(); | |
private IList<IContentType> contentTypes = new List<IContentType>(); | |
public UmbracoSupport(Func<IPublishedContent, T> contentFactory) | |
{ | |
this.contentFactory = contentFactory; | |
} | |
public void RegisterOnInitialized(Action action) | |
{ | |
onInitialized.Add(action); | |
} | |
/// <summary> | |
/// Initializes a stubbed Umbraco request context. Generally called from [SetUp] methods. | |
/// Remember to call UmbracoSupport.DisposeUmbraco from your [TearDown]. | |
/// </summary> | |
public void SetupUmbraco(string url = "http://localhost") | |
{ | |
if (initialized) | |
throw new Exception("UmbracoSupport has already been initialized."); | |
var watch = new Stopwatch(); | |
watch.Start(); | |
Url = url; | |
InitializeFixture(); | |
InitializeResolvers(); | |
TryBaseInitialize(); | |
InitializeSettings(); | |
CreateRouteData(); | |
CreateContexts(); | |
onInitialized.ForEach(x => x()); | |
CreateCurrentPage(); | |
CreateHelper(); | |
SetupContentTypeService(); | |
InitializePublishedContentRequest(); | |
watch.Stop(); | |
Console.WriteLine("Umbraco init: " + watch.Elapsed); | |
InitializeHttpContext(); | |
initialized = true; | |
} | |
protected override void FreezeResolution() | |
{ | |
base.FreezeResolution(); | |
var field = typeof(ResolverBase<LoggerResolver>).GetField("_resolver", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Static); | |
field.SetValue(null, new LoggerResolver(Logger)); | |
} | |
/// <summary> | |
/// Cleans up the stubbed Umbraco request context. Generally called from [TearDown] methods. | |
/// Must be called before another UmbracoSupport.SetupUmbraco. | |
/// </summary> | |
public void DisposeUmbraco() | |
{ | |
if (!initialized) | |
throw new Exception("Cannot teardown non-initialized UmbracoSupport"); | |
var field = typeof(ResolverBase<LoggerResolver>).GetField("_resolver", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Static); | |
field.SetValue(null, null); | |
initialized = false; | |
typeof(StateHelper).GetField("_customHttpContext", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, null); | |
global::System.Web.HttpContext.Current = null; | |
TearDown(); | |
} | |
public void SetContentFactory(Func<IPublishedContent, T> factory) | |
{ | |
if (initialized) | |
throw new Exception("Can't set content factory after initialization"); | |
this.contentFactory = factory; | |
} | |
private void InitializeHttpContext() | |
{ | |
Assert.That(umbracoContext.HttpContext.Request.Cookies.Count, Is.EqualTo(1)); | |
Assert.That(umbracoContext.HttpContext.Request.Cookies.AllKeys[0], Is.EqualTo("UMB_UCONTEXT")); | |
var responseCookies = new HttpCookieCollection(); | |
var responseMock = Mock.Get(umbracoContext.HttpContext.Response); | |
Assert.That(umbracoContext.HttpContext.Response.Cookies, Is.Null); | |
responseMock.Setup(r => r.Cookies).Returns(() => responseCookies); | |
} | |
/// <summary> | |
/// Attaches the stubbed UmbracoContext et. al. to the Controller. | |
/// </summary> | |
/// <param name="controller"></param> | |
public void PrepareController(Controller controller) | |
{ | |
var controllerContext = new ControllerContext(HttpContext, RouteData, controller); | |
controller.ControllerContext = controllerContext; | |
if (routeData.Values.ContainsKey("controller")) | |
{ | |
return; | |
} | |
routeData.Values.Add("controller", controller.GetType().Name.Replace("Controller", "")); | |
routeData.Values.Add("action", "Dummy"); | |
} | |
protected override string GetXmlContent(int templateId) | |
{ | |
if (ContentCacheXml != null) | |
return ContentCacheXml; | |
return base.GetXmlContent(templateId); | |
} | |
private UmbracoContext umbracoContext; | |
private ServiceContext serviceContext; | |
private IUmbracoSettingsSection settings; | |
private RoutingContext routingContext; | |
private T currentPage; | |
private RouteData routeData; | |
private UmbracoHelper umbracoHelper; | |
private PublishedContentRequest publishedContentRequest; | |
private FakeContentModelFactory fakeContentModelFactory; | |
private readonly List<Type> converterTypes = new List<Type>(); | |
protected override ApplicationContext CreateApplicationContext() | |
{ | |
// Overrides the base CreateApplicationContext to inject a completely stubbed servicecontext | |
serviceContext = GetMockedServiceContext(); | |
var appContext = new ApplicationContext( | |
new DatabaseContext(Mock.Of<IDatabaseFactory>(), Logger, SqlSyntax, GetDbProviderName()), | |
serviceContext, | |
CacheHelper, | |
ProfilingLogger); | |
return appContext; | |
} | |
public static ServiceContext GetMockedServiceContext() | |
{ | |
return new ServiceContext( | |
new Mock<IContentService>().Object, | |
new Mock<IMediaService>().Object, | |
new Mock<IContentTypeService>().Object, | |
new Mock<IDataTypeService>().Object, | |
new Mock<IFileService>().Object, | |
new Mock<ILocalizationService>().Object, | |
new Mock<IPackagingService>().Object, | |
new Mock<IEntityService>().Object, | |
new Mock<IRelationService>().Object, | |
new Mock<IMemberGroupService>().Object, | |
new Mock<IMemberTypeService>().Object, | |
new Mock<IMemberService>().Object, | |
new Mock<IUserService>().Object, | |
new Mock<ISectionService>().Object, | |
new Mock<IApplicationTreeService>().Object, | |
new Mock<ITagService>().Object, | |
new Mock<INotificationService>().Object, | |
new Mock<ILocalizedTextService>().Object, | |
new Mock<IAuditService>().Object, | |
new Mock<IDomainService>().Object, | |
new Mock<ITaskService>().Object, | |
new Mock<IMacroService>().Object, | |
new Mock<IPublicAccessService>().Object, | |
new Mock<IExternalLoginService>().Object, | |
new Mock<IMigrationEntryService>().Object, | |
new Mock<IRedirectUrlService>().Object, | |
new Mock<IConsentService>().Object | |
); | |
} | |
private void InitializeResolvers() | |
{ | |
UrlProviderResolver.Current = new UrlProviderResolver( | |
new ActivatorServiceProvider(), | |
Logger, | |
new[] | |
{ | |
typeof(DefaultUrlProvider) | |
} | |
); | |
SiteDomainHelperResolver.Current = new SiteDomainHelperResolver(new SiteDomainHelper()); | |
fakeContentModelFactory = new FakeContentModelFactory(); | |
PublishedContentModelFactoryResolver.Current = new FakeModelFactoryResolver(fakeContentModelFactory); | |
PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver( | |
new ActivatorServiceProvider(), | |
Logger, | |
converterTypes | |
); | |
} | |
private void TryBaseInitialize() | |
{ | |
// Delegates to Umbraco.Tests initialization. Gives a nice hint about disposing the support class for each test. | |
try | |
{ | |
Initialize(); | |
} | |
catch (InvalidOperationException ex) | |
{ | |
if (ex.Message.StartsWith("Resolution is frozen")) | |
throw new Exception("Resolution is frozen. This is probably because UmbracoSupport.DisposeUmbraco wasn't called before another UmbracoSupport.SetupUmbraco call."); | |
} | |
} | |
private void InitializeSettings() | |
{ | |
// Stub up all the settings in Umbraco so we don't need a big app.config file. | |
settings = SettingsForTests.GenerateMockSettings(); | |
SettingsForTests.ConfigureSettings(settings); | |
SettingsForTests.UseDirectoryUrls = true; | |
SettingsForTests.HideTopLevelNodeFromPath = true; | |
Mock.Get(Settings.RequestHandler).Setup(s => s.AddTrailingSlash).Returns(false); | |
} | |
private void CreateCurrentPage() | |
{ | |
// Stubs up the content used as current page in all contexts | |
var publishedContent = Mock.Of<IPublishedContent>(); | |
currentPage = (T)contentFactory?.Invoke(publishedContent) ?? (T)publishedContent; | |
} | |
private void CreateRouteData() | |
{ | |
// Route data is used in many of the contexts, and might need more data throughout your tests. | |
routeData = new RouteData(); | |
} | |
private void CreateContexts() | |
{ | |
// Surface- and RenderMvcControllers need a routing context to fint the current content. | |
// Umbraco.Tests creates one and whips up the UmbracoContext in the process. | |
routingContext = GetRoutingContext(Url, -1, routeData, true, settings); | |
umbracoContext = routingContext.UmbracoContext; | |
} | |
protected new RoutingContext GetRoutingContext(string url, int templateId, RouteData routeData = null, bool setUmbracoContextCurrent = false, IUmbracoSettingsSection umbracoSettings = null) | |
{ | |
var umbracoContext = this.GetUmbracoContext(url, templateId, routeData, false); | |
UrlProvider urlProvider = new UrlProvider(umbracoContext, umbracoSettings.WebRouting, new[] | |
{ | |
new DefaultUrlProvider(umbracoSettings.RequestHandler) as IUrlProvider | |
}) | |
{ | |
Mode = UrlProviderMode.Absolute | |
}; | |
var routingContext = new RoutingContext(umbracoContext, Enumerable.Empty<IContentFinder>(), Mock.Of<IContentFinder>(), urlProvider); | |
umbracoContext.RoutingContext = routingContext; | |
if (setUmbracoContextCurrent) | |
UmbracoContext.Current = umbracoContext; | |
return routingContext; | |
} | |
private void CreateHelper() | |
{ | |
umbracoHelper = new UmbracoHelper(umbracoContext, currentPage); | |
} | |
private void InitializePublishedContentRequest() | |
{ | |
// Some deep core methods fetch the published content request from routedata | |
// others access it through the context | |
// in any case, this is the one telling everyone which content is the current content. | |
publishedContentRequest = new PublishedContentRequest(new Uri(Url), routingContext, settings.WebRouting, s => new string[0]) | |
{ | |
PublishedContent = currentPage, | |
Culture = CultureInfo.CurrentCulture | |
}; | |
umbracoContext.PublishedContentRequest = publishedContentRequest; | |
var routeDefinition = new RouteDefinition | |
{ | |
PublishedContentRequest = publishedContentRequest | |
}; | |
routeData.DataTokens.Add("umbraco-route-def", routeDefinition); | |
routeData.DataTokens.Add("umbraco-doc-request", publishedContentRequest); | |
} | |
private void SetupContentTypeService() | |
{ | |
Mock.Get(ServiceContext.ContentTypeService).Setup(x => x.GetAllContentTypes(It.IsAny<int[]>())) | |
.Returns(contentTypes); | |
Mock.Get(ServiceContext.ContentTypeService).Setup(x => x.GetAllContentTypes(It.IsAny<IEnumerable<Guid>>())) | |
.Returns(contentTypes); | |
} | |
private int contentTypeId = 0; | |
public void SetupContentType(string alias, PropertyType[] propertyTypes, int id = 0) | |
{ | |
PublishedContentType.GetPublishedContentTypeCallback = null; | |
var contentType = Mock.Of<IContentType>(); | |
Mock.Get(this.ServiceContext.ContentTypeService).Setup(s => s.GetContentType(alias)) | |
.Returns(contentType); | |
Mock.Get(this.ServiceContext.ContentTypeService).Setup(s => s.GetContentType(id)) | |
.Returns(contentType); | |
var mock = Mock.Get(contentType); | |
mock.Setup(t => t.CompositionPropertyTypes).Returns(propertyTypes); | |
mock.Setup(t => t.Alias).Returns(alias); | |
mock.Setup(t => t.Icon).Returns("icon-for-" + alias); | |
mock.Setup(t => t.Id).Returns(id == 0 ? ++contentTypeId : id); | |
contentTypes.Add(contentType); | |
} | |
public void SetPublishedContentRequestDomain(IDomain domain) | |
{ | |
publishedContentRequest.UmbracoDomain = domain; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment