Testing your Content Types for the missing AllowedTypes attribute

When defining new content types, we usually decorate all page types with the AvailableContentTypes attribute and all ContentAreas with the AllowedTypes attribute.

We don't want our editors to get "creative" and create pages that are not "by design."

Sometimes, we have the information architecture ready before we start writing the code. This makes the whole process of defining content types, and decorating them with the AllowedTypes and AvailableContentTypes attributes, much easier. However, sometimes we don’t, and as a result, we have to be more agile.

Here's how you can test your content types for the missing AllowedTypes and AvailableContentTypes attributes:

public class ContetTypeTests
{
    private readonly List<Type> _allContentTypes;

    public ContetTypeTests()
    {
        _allContentTypes = GetContentTypes();
    }

    [Test]
    public void All_PageTypes_Are_Decorated_With_AllowedContentTypesAttribute()
    {
        var failed = (from contentType in _allContentTypes
                      where !Attribute.IsDefined(contentType, typeof(AvailableContentTypesAttribute))
                      select contentType.Name).ToList();

        if (failed.Any())
        {
            Assert.Fail(string.Join(", ", failed));
        }
    }

    [Test]
    public void All_ContentAreas_Are_Decorated_With_AllowedTypes()
    {
        var failed = new List<string>();

        foreach (var contentType in _allContentTypes)
        {
            var nonInheritedProperties = contentType.GetProperties(
                BindingFlags.DeclaredOnly |
                BindingFlags.Instance |
                BindingFlags.Public);

            failed.AddRange(from property in nonInheritedProperties
                            where property.PropertyType == typeof(ContentArea)
                            let allowedTypesAttributes =
                                (AllowedTypesAttribute[])property.GetCustomAttributes(
                                    typeof(AllowedTypesAttribute), true)
                            where allowedTypesAttributes.Length == 0
                            select contentType.Name + " - " + property.Name);
        }

        if (failed.Any())
        {
            Assert.Fail(string.Join(", ", failed));
        }
    }

    private List<Type> GetContentTypes()
    {
        var _assembly = typeof(EPiServerApplication).Assembly;
        var classes = _assembly.GetTypes()
                               .Where(t => t.IsClass &&
                                           t.GetCustomAttributes(typeof(ContentTypeAttribute), true).Any())
                               .ToList();
        return classes;
    }
}

Namespaces to include:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using EPiServer.Core;
using EPiServer.DataAnnotations;
using NUnit.Framework;

And here's how it looks in action:

Testing Episerver Content Areas

Testing Episerver Page Types

comments powered by Disqus