Working with unit tests and making a few corrections around ContentTypes.

This commit is contained in:
Morten Christensen
2012-11-30 09:34:09 -01:00
parent 2f83e5ba31
commit 152c8e810d
25 changed files with 362 additions and 157 deletions

View File

@@ -13,112 +13,112 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public abstract class ContentTypeCompositionBase : ContentTypeBase, IContentTypeComposition
{
private List<IContentTypeComposition> _contentTypeComposition;
private List<IContentTypeComposition> _contentTypeComposition = new List<IContentTypeComposition>();
protected ContentTypeCompositionBase(int parentId) : base(parentId)
{
_contentTypeComposition = new List<IContentTypeComposition>();
}
private static readonly PropertyInfo ContentTypeCompositionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeCompositionBase, List<IContentTypeComposition>>(x => x.ContentTypeComposition);
private static readonly PropertyInfo ContentTypeCompositionSelector =
ExpressionHelper.GetPropertyInfo<ContentTypeCompositionBase, IEnumerable<IContentTypeComposition>>(
x => x.ContentTypeComposition);
/// <summary>
/// List of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType
/// </summary>
[DataMember]
public List<IContentTypeComposition> ContentTypeComposition
{
get { return _contentTypeComposition; }
set
{
_contentTypeComposition = value;
OnPropertyChanged(ContentTypeCompositionSelector);
}
}
/// <summary>
/// List of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType
/// </summary>
[DataMember]
public IEnumerable<IContentTypeComposition> ContentTypeComposition
{
get { return _contentTypeComposition; }
}
/// <summary>
/// Returns a list of <see cref="PropertyGroup"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyGroup> CompositionPropertyGroups
{
get
{
var groups = PropertyGroups.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyGroups));
return groups;
}
}
/// <summary>
/// Returns a list of <see cref="PropertyGroup"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyGroup> CompositionPropertyGroups
{
get
{
var groups = PropertyGroups.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyGroups));
return groups;
}
}
/// <summary>
/// Returns a list of <see cref="PropertyType"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> CompositionPropertyTypes
{
get
{
var propertyTypes = PropertyTypes.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyTypes));
return propertyTypes;
}
}
/// <summary>
/// Returns a list of <see cref="PropertyType"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> CompositionPropertyTypes
{
get
{
var propertyTypes =
PropertyTypes.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyTypes));
return propertyTypes;
}
}
/// <summary>
/// Adds a new ContentType to the list of composite ContentTypes
/// </summary>
/// <param name="contentType"><see cref="ContentType"/> to add</param>
/// <returns>True if ContentType was added, otherwise returns False</returns>
public bool AddContentType(IContentTypeComposition contentType)
{
if (contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists)))
return false;
/// <summary>
/// Adds a new ContentType to the list of composite ContentTypes
/// </summary>
/// <param name="contentType"><see cref="ContentType"/> to add</param>
/// <returns>True if ContentType was added, otherwise returns False</returns>
public bool AddContentType(IContentTypeComposition contentType)
{
if (contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists)))
return false;
if (!ContentTypeCompositionExists(contentType.Alias))
{
ContentTypeComposition.Add(contentType);
return true;
}
return false;
}
if (!ContentTypeCompositionExists(contentType.Alias))
{
_contentTypeComposition.Add(contentType);
OnPropertyChanged(ContentTypeCompositionSelector);
return true;
}
return false;
}
/// <summary>
/// Removes a ContentType with the supplied alias from the the list of composite ContentTypes
/// </summary>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType was removed, otherwise returns False</returns>
public bool RemoveContentType(string alias)
{
if (!ContentTypeCompositionExists(alias))
{
var contentTypeComposition = ContentTypeComposition.First(x => x.Alias == alias);
return ContentTypeComposition.Remove(contentTypeComposition);
}
return false;
}
/// <summary>
/// Removes a ContentType with the supplied alias from the the list of composite ContentTypes
/// </summary>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType was removed, otherwise returns False</returns>
public bool RemoveContentType(string alias)
{
if (!ContentTypeCompositionExists(alias))
{
var contentTypeComposition = ContentTypeComposition.First(x => x.Alias == alias);
return _contentTypeComposition.Remove(contentTypeComposition);
}
return false;
}
/// <summary>
/// Checks if a ContentType with the supplied alias exists in the list of composite ContentTypes
/// </summary>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType with alias exists, otherwise returns False</returns>
public bool ContentTypeCompositionExists(string alias)
{
if (ContentTypeComposition.Any(x => x.Alias.Equals(alias)))
return true;
/// <summary>
/// Checks if a ContentType with the supplied alias exists in the list of composite ContentTypes
/// </summary>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType with alias exists, otherwise returns False</returns>
public bool ContentTypeCompositionExists(string alias)
{
if (ContentTypeComposition.Any(x => x.Alias.Equals(alias)))
return true;
if (ContentTypeComposition.Any(x => x.ContentTypeCompositionExists(alias)))
return true;
if (ContentTypeComposition.Any(x => x.ContentTypeCompositionExists(alias)))
return true;
return false;
}
return false;
}
/// <summary>
/// Gets a list of ContentType aliases from the current composition
/// </summary>
/// <returns></returns>
/// <remarks>Does not contain the alias of the Current ContentType</remarks>
public IEnumerable<string> CompositionAliases()
{
return ContentTypeComposition.Select(x => x.Alias).Union(ContentTypeComposition.SelectMany(x => x.CompositionAliases()));
}
/// <summary>
/// Gets a list of ContentType aliases from the current composition
/// </summary>
/// <returns></returns>
/// <remarks>Does not contain the alias of the Current ContentType</remarks>
public IEnumerable<string> CompositionAliases()
{
return ContentTypeComposition
.Select(x => x.Alias)
.Union(ContentTypeComposition.SelectMany(x => x.CompositionAliases()));
}
}
}

View File

@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets a list of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType
/// </summary>
List<IContentTypeComposition> ContentTypeComposition { get; }
IEnumerable<IContentTypeComposition> ContentTypeComposition { get; }
/// <summary>
/// Gets a list of <see cref="PropertyGroup"/> objects from the composition

View File

@@ -9,9 +9,11 @@ namespace Umbraco.Core.Models.Rdbms
{
[Column("parentContentTypeId")]
[PrimaryKeyColumn(AutoIncrement = false, Clustered = true, Name = "PK_cmsContentType2ContentType", OnColumns = "parentContentTypeId, childContentTypeId")]
[ForeignKey(typeof(NodeDto), Name = "FK_cmsContentType2ContentType_umbracoNode_parent")]
public int ParentId { get; set; }
[Column("childContentTypeId")]
[ForeignKey(typeof(NodeDto), Name = "FK_cmsContentType2ContentType_umbracoNode_child")]
public int ChildId { get; set; }
}
}

View File

@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models.Rdbms
public int Id { get; set; }
[Column("datatypeNodeId")]
[ForeignKey(typeof(DataTypeDto))]
[ForeignKey(typeof(DataTypeDto), Column = "nodeId")]
public int DataTypeNodeId { get; set; }
[Column("value")]

View File

@@ -84,7 +84,19 @@ namespace Umbraco.Core.Persistence.Repositories
{
if (composition.Id == entity.Id) continue;//Just to ensure that we aren't creating a reference to ourself.
Database.Insert(new ContentType2ContentTypeDto { ParentId = composition.Id, ChildId = entity.Id });
if (composition.HasIdentity)
{
Database.Insert(new ContentType2ContentTypeDto { ParentId = composition.Id, ChildId = entity.Id });
}
else
{
//Fallback for ContentTypes with no identity
var contentTypeDto = Database.FirstOrDefault<ContentTypeDto>("WHERE alias = @Alias", new {Alias = composition.Alias});
if (contentTypeDto != null)
{
Database.Insert(new ContentType2ContentTypeDto { ParentId = contentTypeDto.NodeId, ChildId = entity.Id });
}
}
}
//Insert collection of allowed content types

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
@@ -126,6 +127,8 @@ namespace Umbraco.Core.Services
content.Value.CreatorId = 0;
repository.AddOrUpdate(content.Value);
_unitOfWork.Commit();
LogHelper.Info<ContentTypeService>(string.Format("Saved ContentType with Alias '{0}' and Id '{1}'", content.Value.Alias, content.Value.Id));
}
}

View File

@@ -0,0 +1,18 @@
using System;
namespace Umbraco.Tests.CodeFirst.Attributes
{
[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class MixinAttribute : Attribute
{
public MixinAttribute(Type type)
{
Type = type;
}
/// <summary>
/// Gets or sets the Type of the implementing class
/// </summary>
public Type Type { get; private set; }
}
}

View File

@@ -30,8 +30,8 @@ namespace Umbraco.Tests.CodeFirst.Attributes
if(string.IsNullOrEmpty(PreValue) == false)
{
Conventions.CreatePrevalueForDataTypeDefinition(definition.DataTypeDefinition.Id, PreValue, 0,
string.Empty);
//TODO - test inserting a prevalue when a DataTypeDefinition has been created, as its currently throwing a foreignkey constraint error.
Conventions.CreatePrevalueForDataTypeDefinition(definition.DataTypeDefinition.Id, PreValue, 0, string.Empty);
}
return definition;

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NUnit.Framework;
@@ -10,6 +9,7 @@ using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Serialization;
using Umbraco.Tests.CodeFirst.Definitions;
using Umbraco.Tests.CodeFirst.TestModels;
using Umbraco.Tests.CodeFirst.TestModels.Composition;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
using umbraco.editorControls.tinyMCE3;
@@ -32,7 +32,8 @@ namespace Umbraco.Tests.CodeFirst
PluginManager.Current.AssembliesToScan = new[]
{
typeof(IDataType).Assembly,
typeof(tinyMCE3dataType).Assembly
typeof(tinyMCE3dataType).Assembly,
typeof (ContentTypeBase).Assembly
};
DataTypesResolver.Current = new DataTypesResolver(
@@ -187,37 +188,43 @@ namespace Umbraco.Tests.CodeFirst
}
private SerializationService SerializationService { get; set; }
private static int[] GetTopologicalSortOrder(IList<DependencyField> fields)
[Test]
public void Can_Resolve_ContentType_Composition_And_Save_To_Database()
{
var g = new TopologicalSorter(fields.Count());
var _indexes = new Dictionary<string, int>();
ContentTypeDefinitionFactory.ClearContentTypeCache();
//add vertices
for (int i = 0; i < fields.Count(); i++)
{
_indexes[fields[i].Alias.ToLower()] = g.AddVertex(i);
}
var metaSeoModel = typeof(MetaSeo);
var seoContentType = ContentTypeDefinitionFactory.GetContentTypeDefinition(metaSeoModel);
var metaModel = typeof(Meta);
var metaContentType = ContentTypeDefinitionFactory.GetContentTypeDefinition(metaModel);
var baseModel = typeof(Base);
var baseContentType = ContentTypeDefinitionFactory.GetContentTypeDefinition(baseModel);
var newsModel = typeof(News);
var newsContentType = ContentTypeDefinitionFactory.GetContentTypeDefinition(newsModel);
//add edges
for (int i = 0; i < fields.Count; i++)
{
if (fields[i].DependsOn != null)
{
for (int j = 0; j < fields[i].DependsOn.Length; j++)
{
g.AddEdge(i,
_indexes[fields[i].DependsOn[j].ToLower()]);
}
}
}
int[] result = g.Sort();
return result;
var mappedContentTypes = ContentTypeDefinitionFactory.RetrieveMappedContentTypes().ToList();
ServiceContext.ContentTypeService.Save(mappedContentTypes);
Assert.That(mappedContentTypes.Count(), Is.EqualTo(4));
}
[Test]
public void Can_Resolve_Full_List_Of_Models_Implementing_ContentTypeBase()
{
ContentTypeDefinitionFactory.ClearContentTypeCache();
var foundTypes = PluginManager.Current.ResolveContentTypeBaseTypes();
var contentTypeList = foundTypes.Select(ContentTypeDefinitionFactory.GetContentTypeDefinition).ToList();
var mappedContentTypes = ContentTypeDefinitionFactory.RetrieveMappedContentTypes();
Assert.That(contentTypeList.Count(), Is.EqualTo(mappedContentTypes.Count()));
ServiceContext.ContentTypeService.Save(mappedContentTypes);//Save to db
}
private SerializationService SerializationService { get; set; }
[TearDown]
public override void TearDown()
{

View File

@@ -37,6 +37,9 @@ namespace Umbraco.Tests.CodeFirst.Definitions
? PlainPocoConvention(modelType, existing)
: ContentTypeConvention(contentTypeAttribute, modelType, existing);
//Check for interfaces that'll be used for ContentTypeComposition
var mixins = GetAliasesFromTypeInterfaces(modelType);
var definitions = new List<PropertyDefinition>();
int order = 0;
var objProperties = modelType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly).ToList();
@@ -126,17 +129,48 @@ namespace Umbraco.Tests.CodeFirst.Definitions
//Add the resolved ContentType to the internal cache
var field = new DependencyField {ContentType = contentType, Alias = contentType.Value.Alias};
var dependencies = new List<string>();
//If current type has a parent (inherited model) we add the alias of that type as a dependency
if(hasParent)
{
dependencies.Add(parent.Value.Alias);
}
//Check ContentType for existing 'Allowed ContentTypes'
if(contentType.Value.AllowedContentTypes.Any())
{
dependencies.AddRange(contentType.Value.AllowedContentTypes.Select(allowed => allowed.Alias));
}
//Check for interfaces with AliasAttribute and add those as dependencies
//NOTE: might also be an idea to check if ContentType has already been created/added to cache that implements the interface.
if(mixins.Any())
{
foreach (var mixin in mixins)
{
if(dependencies.Contains(mixin.Item1)) continue;
dependencies.Add(mixin.Item1);
var isMixinResolved = _contentTypeCache.ContainsKey(mixin.Item2);
Lazy<IContentType> compositionType = null;
if (isMixinResolved)
{
compositionType = _contentTypeCache[mixin.Item2].ContentType;
}
else
{
GetContentTypeDefinition(mixin.Item3);
compositionType = _contentTypeCache[mixin.Item2].ContentType;
}
contentType.Value.AddContentType(compositionType.Value);
}
}
field.DependsOn = dependencies.ToArray();
_contentTypeCache.AddOrUpdate(modelType.FullName, field, (x, y) => field);
return contentType;
}
private static int[] GetTopologicalSortOrder(IList<DependencyField> fields)
{
var g = new TopologicalSorter(fields.Count());
@@ -191,6 +225,37 @@ namespace Umbraco.Tests.CodeFirst.Definitions
_contentTypeCache.Clear();
}
/// <summary>
/// Retrieves a list of aliases that correspond to the interfaces on the passed in type,
/// which are attributed with the AliasAttribute.
/// </summary>
/// <remarks>
/// The modelType is also used to ensure that the implementing class doesn't reference
/// itself via its interface.
/// </remarks>
/// <param name="modelType">Type of the model to retrieve interface aliases from</param>
/// <returns>An enumerable list of strings with aliases</returns>
private static IEnumerable<Tuple<string, string, Type>> GetAliasesFromTypeInterfaces(Type modelType)
{
var interfaces = modelType.GetInterfaces().ToList().Distinct();
var list = new List<Tuple<string, string, Type>>();
foreach (var interfaceType in interfaces)
{
var mixinAttribute = interfaceType.FirstAttribute<MixinAttribute>();
if (mixinAttribute != null)
{
if(mixinAttribute.Type == modelType) continue;
var contentTypeAttribute = mixinAttribute.Type.FirstAttribute<ContentTypeAttribute>();
var contentTypeAlias = contentTypeAttribute == null ? mixinAttribute.Type.Name.ToUmbracoAlias() : contentTypeAttribute.Alias;
var tuple = new Tuple<string, string, Type>(contentTypeAlias, mixinAttribute.Type.FullName, mixinAttribute.Type);
list.Add(tuple);
}
}
return list;
}
/// <summary>
/// Convention that converts a class decorated with the ContentTypeAttribute to an initial ContentType
/// </summary>

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using Umbraco.Core;
namespace Umbraco.Tests.CodeFirst
{
/// <summary>
/// Used for PluginTypeResolverTests
/// </summary>
internal static class PluginManagerExtensions
{
public static IEnumerable<Type> ResolveContentTypeBaseTypes(this PluginManager resolver)
{
return resolver.ResolveTypes<ContentTypeBase>();
}
}
}

View File

@@ -1,10 +1,14 @@
namespace Umbraco.Tests.CodeFirst.TestModels.Composition
using Umbraco.Tests.CodeFirst.Attributes;
namespace Umbraco.Tests.CodeFirst.TestModels.Composition
{
public class Base : IBase
public class Base : ContentTypeBase, IBase
{
[Richtext(PropertyGroup = "Content")]
public string BodyContent { get; set; }
}
[Mixin(typeof(Base))]
public interface IBase
{

View File

@@ -1,13 +1,19 @@
using Umbraco.Tests.CodeFirst.Attributes;
using umbraco.editorControls.textfield;
using umbraco.editorControls.textfieldmultiple;
namespace Umbraco.Tests.CodeFirst.TestModels.Composition
{
public class Meta : IMeta
public class Meta : ContentTypeBase, IMeta
{
[PropertyType(typeof(TextFieldDataType), PropertyGroup = "Content")]
public string MetaKeywords { get; set; }
[PropertyType(typeof(textfieldMultipleDataType))]
public string MetaDescription { get; set; }
}
[Alias("meta", Name = "Meta")]
[Mixin(typeof(Meta))]
public interface IMeta
{}
}

View File

@@ -0,0 +1,15 @@
using Umbraco.Tests.CodeFirst.Attributes;
using umbraco.editorControls.textfieldmultiple;
namespace Umbraco.Tests.CodeFirst.TestModels.Composition
{
public class MetaSeo : ContentTypeBase, IMetaSeo
{
[PropertyType(typeof(textfieldMultipleDataType))]
public string FriendlySeoStuff { get; set; }
}
[Mixin(typeof(MetaSeo))]
public interface IMetaSeo
{}
}

View File

@@ -1,10 +1,14 @@
namespace Umbraco.Tests.CodeFirst.TestModels.Composition
using Umbraco.Tests.CodeFirst.Attributes;
using umbraco.editorControls.textfield;
namespace Umbraco.Tests.CodeFirst.TestModels.Composition
{
/// <summary>
/// Deriving class is parent, interfaces are compositions
/// </summary>
public class News : Base, IMeta, ISeo
public class News : Base, IMetaSeo, IMeta
{
[PropertyType(typeof(TextFieldDataType), PropertyGroup = "Content")]
public string Author { get; set; }
}
}

View File

@@ -1,13 +0,0 @@
using Umbraco.Tests.CodeFirst.Attributes;
namespace Umbraco.Tests.CodeFirst.TestModels.Composition
{
public class Seo : ISeo
{
}
[Alias("seo", Name = "Seo")]
public interface ISeo : IBase
{}
}

View File

@@ -7,7 +7,7 @@ namespace Umbraco.Tests.CodeFirst.TestModels
[ContentType("modelPage",
AllowedChildContentTypes = new[] { typeof(ContentPage) },
AllowedTemplates = new[]{"umbMaster"})]
public class DecoratedModelPage
public class DecoratedModelPage : ContentTypeBase
{
[PropertyType(typeof(TextFieldDataType), PropertyGroup = "Content")]
public string Author { get; set; }

View File

@@ -5,7 +5,7 @@ using umbraco.editorControls.textfieldmultiple;
namespace Umbraco.Tests.CodeFirst.TestModels
{
[ContentType("home", AllowedChildContentTypes = new[] { typeof(ContentPage) })]
public class Home
public class Home : ContentTypeBase
{
[PropertyType(typeof(TextFieldDataType))]
public string SiteName { get; set; }

View File

@@ -4,7 +4,7 @@ using umbraco.editorControls.tinymce;
namespace Umbraco.Tests.CodeFirst.TestModels
{
public class ModelWithNewDataType
public class ModelWithNewDataType : ContentTypeBase
{
[PropertyType(typeof(TextFieldDataType), PropertyGroup = "Content")]
public string Title { get; set; }

View File

@@ -2,7 +2,7 @@
namespace Umbraco.Tests.CodeFirst.TestModels
{
public class NumericModel
public class NumericModel : ContentTypeBase
{
[Numeric("Number DataType", PreValue = "5", PropertyGroup = "Content")]
public int Number { get; set; }

View File

@@ -2,17 +2,22 @@
namespace Umbraco.Tests.CodeFirst.TestModels
{
//Plain Poco Type - plainPocoType
public class PlainPocoType
//Name: Plain Poco Type - Alias: plainPocoType
public class PlainPocoType : ContentTypeBase
{
//Name: Title, Alias: title, DataType: Text Field
public string Title { get; set; }
//Name: Author, Alias: author, DataType: Text Field
public string Author { get; set; }
//Name: Is Finished, Alias: isFinished, DataType: Yes/No
public bool IsFinished { get; set; }
//Name: Weight, Alias: weight, DataType: Number
public int Weight { get; set; }
//Name: Publish Date, Alias: publishDate, DataType: Datepicker
public DateTime PublishDate { get; set; }
}
}

View File

@@ -3,7 +3,7 @@ using umbraco.editorControls.textfield;
namespace Umbraco.Tests.CodeFirst.TestModels
{
public class SimpleContentPage
public class SimpleContentPage : ContentTypeBase
{
[PropertyType(typeof(TextFieldDataType), PropertyGroup = "Content")]
public string Title { get; set; }

View File

@@ -3,7 +3,7 @@ using umbraco.editorControls.textfield;
namespace Umbraco.Tests.CodeFirst.TestModels
{
public class TextPage
public class TextPage : ContentTypeBase
{
[PropertyType(typeof(TextFieldDataType), PropertyGroup = "Content")]
public string Author { get; set; }

View File

@@ -1,24 +1,82 @@
using System.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Tests.CodeFirst.Attributes;
using Umbraco.Tests.CodeFirst.Definitions;
using Umbraco.Tests.CodeFirst.TestModels.Composition;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.CodeFirst
{
[TestFixture]
public class TypeInheritanceTest
{
[SetUp]
public void Initialize()
{
TestHelper.SetupLog4NetForTests();
//this ensures its reset
PluginManager.Current = new PluginManager(false);
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
PluginManager.Current.AssembliesToScan = new[]
{
typeof (ContentTypeBase).Assembly
};
}
[Test]
public void Can_Get_Interfaces_From_Type()
{
var type = typeof (News);
var interfaces = type.GetInterfaces().ToList();
bool hasSeo = interfaces.Any(x => x.Name == typeof(ISeo).Name);
bool hasSeo = interfaces.Any(x => x.Name == typeof(IMetaSeo).Name);
bool hasMeta = interfaces.Any(x => x.Name == typeof(IMeta).Name);
Assert.That(hasSeo, Is.True);
Assert.That(hasMeta, Is.True);
Assert.That(interfaces.Count, Is.EqualTo(3));
}
[Test]
public void Can_Get_MixinAttribute_From_Types()
{
var type = typeof(News);
var interfaces = type.GetInterfaces().ToList();
var list = new List<string>();
foreach (var interfaceType in interfaces)
{
var mixinAttribute = interfaceType.FirstAttribute<MixinAttribute>();
if(mixinAttribute != null)
{
var modelType = mixinAttribute.Type;
var contentTypeAttribute = modelType.FirstAttribute<ContentTypeAttribute>();
var contentTypeAlias = contentTypeAttribute == null ? modelType.Name.ToUmbracoAlias() : contentTypeAttribute.Alias;
list.Add(contentTypeAlias);
}
}
Assert.That(list.Count, Is.EqualTo(2));
Assert.That(list.Any(x => x == "meta"), Is.True);
Assert.That(list.Any(x => x == "seo"), Is.True);
}
[Test]
public void Ensure_Only_One_Type_List_Created()
{
var foundTypes = PluginManager.Current.ResolveContentTypeBaseTypes();
Assert.That(foundTypes.Count(), Is.EqualTo(13));
Assert.AreEqual(1,
PluginManager.Current.GetTypeLists()
.Count(x => x.IsTypeList<ContentTypeBase>(PluginManager.TypeResolutionKind.FindAllTypes)));
}
}
}

View File

@@ -101,6 +101,7 @@
<Compile Include="CodeFirst\Attributes\AliasAttribute.cs" />
<Compile Include="CodeFirst\Attributes\ContentTypeAttribute.cs" />
<Compile Include="CodeFirst\Attributes\DescriptionAttribute.cs" />
<Compile Include="CodeFirst\Attributes\MixinAttribute.cs" />
<Compile Include="CodeFirst\Attributes\Numeric.cs" />
<Compile Include="CodeFirst\Attributes\PropertyTypeAttribute.cs" />
<Compile Include="CodeFirst\Attributes\PropertyTypeConventionAttribute.cs" />
@@ -113,11 +114,12 @@
<Compile Include="CodeFirst\Definitions\DependencyField.cs" />
<Compile Include="CodeFirst\Definitions\PropertyDefinition.cs" />
<Compile Include="CodeFirst\Mvc\UmbracoTemplatePage`T.cs" />
<Compile Include="CodeFirst\PluginManagerExtensions.cs" />
<Compile Include="CodeFirst\TestModels\AdvancedContentPage.cs" />
<Compile Include="CodeFirst\TestModels\Composition\Base.cs" />
<Compile Include="CodeFirst\TestModels\Composition\Meta.cs" />
<Compile Include="CodeFirst\TestModels\Composition\News.cs" />
<Compile Include="CodeFirst\TestModels\Composition\Seo.cs" />
<Compile Include="CodeFirst\TestModels\Composition\MetaSeo.cs" />
<Compile Include="CodeFirst\TestModels\ContentPage.cs" />
<Compile Include="CodeFirst\TestModels\DecoratedModelPage.cs" />
<Compile Include="CodeFirst\TestModels\Home.cs" />