Try our conversational search powered by Generative AI!

Stefan Forsberg
May 7, 2010
(1 votes)

How do you setup different states that depends on EpiServer page structure?

Let’s say you have a page that acts as a container for news. The page simply lists all it’s children in a PageList. Now our GUI developer want us to have at least 21 pages to that they can check that the html they wrote for the paging functionality behaves ok. Soon after you need to verify that if the container doesn’t contain any children at all a message is displayed to inform the user that no news were found.

While these examples might seem somewhat silly the thing I’m getting at is that sometimes you (or your team) need your page structure to be in a certain state for you to verify and or test something.



So, what options do we have today to accomplish this?


1. The manual approach

This is basically just going into edit mode and create whatever structure(s) you need to verify your testing.


2. Creating lists programmatically

In the above examples we don’t really care what data is in the news items them self so we can create lists specifically for the test scenarios . Since we’re using a PageList we do have to make sure that we’re using a PageDataCollection and that the pages are correctly setup to not be filtered by FilterForVisitor.


3. Hooking up to DataFactory.LoadedChildren

This event enables us to change the resulting PageDataCollection. This results in much the same approach as number 2 above but keep in mind that this will also affect the way that the Episerver tree itself is generated too.


4. Using a custom page type builder.

This enables us to create a whole structure that behaves exactly like ordinary pages without them actually existing.


So how do these techniques measure up?

My problem with 1-3 is that modifying your “production” code and setup the state for your tests there almost always leads to a mess. You get those if debug statements (or even worse, code you have to remember to uncomment before deploying) and all in all it just feels fragile. Alternative 1 also can be tricky to do in a unit testing scenario since it can require manual fixing, which probably means that those test won’t run / pass very often.

Alternative 4 can be a good solution but it has some drawbacks. Depending on how much and what you want to test it might be slightly overkill to implement. A custom page provider also requires a enterprise license, which probably isn’t a problem in your local development but if you for some reason would like to use your faked structure on the live server (yes I know this is highly unlikely) you might not be able to do so. The final drawback is somewhat of a nitpick for me, but to use this in your unit tests you have to setup the whole configuration for episerver in your tests. Sure, it doesn’t take a trip to the database, but still.


Using DI and PTB 1.2

One of the new features in PageTypeBuilder 1.2 is the ability to inject dependencies into your TypedPageData classes. Joel has written a post about this here. I’ve done some simple proof on concepting about using this to setup structure, so please take the code for what it is.

To be able to controll the fetching of child pages we inject a dependency to IPageSource. Using the example above out news container could look like this

   1: [PageType("345D0610AE114BC5B5AAE8450D364757", Name = "News Container", Filename = "~/UI/Pages/NewsContainer.aspx")]
   2: public class NewsContainer : TypedPageData
   3: {
   4:     private readonly IPageSource pageSource;
   6:     public NewsContainer(IPageSource pageSource)
   7:     {
   8:         this.pageSource = pageSource;
   9:     }
  11:     public List<NewsItem> GetNews()
  12:     {
  13:         return pageSource
  14:             .GetChildren(PageLink)
  15:             .OfType<NewsItem>()
  16:             .ToList();
  17:     }
  18: }


We can now create “fake” classes to use for when we actually have the need to see the pages (for instance the scenario with paging described in the beginning of the post).

   1: public class FakeData : IPageSource
   2: {
   3:     public PageDataCollection GetChildren(PageReference pageLink)
   4:     {
   5:         var pageTypeID = PageTypeResolver.Instance.GetPageTypeID(typeof (NewsItem)).Value;
   6:         var pageType = PageType.Load(pageTypeID);
   8:         InitializeBaseData initializer = new InitializeBaseData();
  10:         PageDataCollection pageDataCollection = new PageDataCollection();
  11:         for (int i = 0; i < 50; i++)
  12:         {
  13:             var newsItem = new NewsItem { MainBody = "Hello" };
  14:             initializer.InitializePageData(newsItem, "SomePageName" + i, pageType, Guid.NewGuid(), new PageReference(5000 + i), pageLink, new List<string>(), string.Empty);
  15:             pageDataCollection.Add(newsItem);
  16:         }
  18:         return pageDataCollection;
  19:     }
  21:     public PageData GetPage(PageReference pageLink)
  22:     {
  23:         throw new NotImplementedException();
  24:     }
  27:     public PageData CurrentPage
  28:     {
  29:         get { throw new NotImplementedException(); }
  30:     }
  31: }


The class InitializeBaseData is more a less a copy of the reflected code from the method InitializePageData in PageProviderBase (minus the UrlSegment part since it’s method GetUrlFriendlySegment for some reason is internal). The reason for doing this is to make sure the PageData part of the TypedPageData has values to be able to use it with the PageList controll.



In our unit tests we can simply mock the IPageSource interface to test whatever scenario we want to test.

   1: [TestMethod]
   2: public void Some_pretty_redundant_test_that_doesnt_really_test_anything()
   3: {
   5:     var pageSourceMock = new Moq.Mock<IPageSource>();
   6:     pageSourceMock.Setup(x => x.GetChildren(It.IsAny<PageReference>())).Returns(new PageDataCollection());
   7:     NewsContainer container = new NewsContainer(pageSourceMock.Object);
   9:     Assert.IsTrue(container.GetNews().Count == 0);
  10: }


Hopefully I’ll have time to come back to this subject in a later post.


May 07, 2010


Joel Abrahamsson
Joel Abrahamsson Sep 21, 2010 10:33 AM

Great post Stefan!

I would love to see a follow up where you combine this with StructureMap profiles creating a lifecycle aware site.

Please login to comment.
Latest blogs
Headless forms reloaded (beta)

Forms is used on the vast majority of CMS installations. But using Forms in a headless setup is a bit of pain since the rendering pipeline is based...

MartinOttosen | Mar 1, 2024

Uploading blobs to Optimizely DXP via PowerShell

We had a client moving from an On-Prem v11 Optimizely instance to DXP v12 and we had a lot of blobs (over 40 GB) needing uploading to DXP as a part...

Nick Hamlin | Mar 1, 2024 | Syndicated blog

DbLocalizationProvider v8.0 Released

I’m pleased to announce that Localization Provider v8.0 is finally out.

valdis | Feb 28, 2024 | Syndicated blog

Epinova DXP deployment extension – With Octopus deploy

Example how you can use Epinova DXP deployment extension in Octopus deployment.

Ove Lartelius | Feb 28, 2024 | Syndicated blog

Identify Azure web app instance id's for an Optimizely CMS site

When running Optimizely CMS in Azure, you will be using an instance bound cloud license. What instances are counted, and how can you check them? Le...

Tomas Hensrud Gulla | Feb 27, 2024 | Syndicated blog

Introducing Image Transformer - AI Assistant for Optimizely

We've got something super cool to share with you, and it's all about giving your images a fresh spin. Image Transformer, the latest feature from ou...

Luc Gosso (MVP) | Feb 26, 2024 | Syndicated blog