Tests for LayoutDisplay component

This commit is contained in:
Steve Sanderson 2018-02-16 17:22:36 +00:00
parent df825de86d
commit 6e7c4ec6c0
3 changed files with 305 additions and 1 deletions

View File

@ -0,0 +1,39 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Blazor.Components;
using Microsoft.AspNetCore.Blazor.RenderTree;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Blazor.Test.Helpers
{
public static class IComponentExtensions
{
public static void SetParameters(
this IComponent component,
Dictionary<string, object> parameters)
{
component.SetParameters(DictionaryToParameterCollection(parameters));
}
private static ParameterCollection DictionaryToParameterCollection(
IDictionary<string, object> parameters)
{
var builder = new RenderTreeBuilder(new TestRenderer());
builder.OpenComponent<AbstractComponent>(0);
foreach (var pair in parameters)
{
builder.AddAttribute(0, pair.Key, pair.Value);
}
builder.CloseElement();
return new ParameterCollection(builder.GetFrames().Array, 0);
}
private abstract class AbstractComponent : IComponent
{
public abstract void Init(RenderHandle renderHandle);
public abstract void SetParameters(ParameterCollection parameters);
}
}
}

View File

@ -0,0 +1,266 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Blazor.Layouts;
using Microsoft.AspNetCore.Blazor.RenderTree;
using Microsoft.AspNetCore.Blazor.Test.Helpers;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Test
{
public class LayoutTest
{
private TestRenderer _renderer = new TestRenderer();
private LayoutDisplay _layoutDisplayComponent = new LayoutDisplay();
private int _layoutDisplayComponentId;
public LayoutTest()
{
_renderer = new TestRenderer();
_layoutDisplayComponent = new LayoutDisplay();
_layoutDisplayComponentId = _renderer.AssignComponentId(_layoutDisplayComponent);
}
[Fact]
public void DisplaysComponentInsideLayout()
{
// Arrange/Act
_layoutDisplayComponent.SetParameters(new Dictionary<string, object>
{
{ nameof(LayoutDisplay.Page), typeof(ComponentWithLayout) }
});
// Assert
var batch = _renderer.Batches.Single();
Assert.Collection(batch.DiffsInOrder,
diff =>
{
// First is the LayoutDisplay component, which contains a RootLayout
var singleEdit = diff.Edits.Single();
Assert.Equal(RenderTreeEditType.PrependFrame, singleEdit.Type);
AssertFrame.Component<RootLayout>(
batch.ReferenceFrames[singleEdit.ReferenceFrameIndex]);
},
diff =>
{
// ... then a RootLayout which contains a ComponentWithLayout
// First is the LayoutDisplay component, which contains a RootLayout
Assert.Collection(diff.Edits,
edit =>
{
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
AssertFrame.Text(
batch.ReferenceFrames[edit.ReferenceFrameIndex],
"RootLayout starts here");
},
edit =>
{
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
AssertFrame.Component<ComponentWithLayout>(
batch.ReferenceFrames[edit.ReferenceFrameIndex]);
},
edit =>
{
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
AssertFrame.Text(
batch.ReferenceFrames[edit.ReferenceFrameIndex],
"RootLayout ends here");
});
},
diff =>
{
// ... then the ComponentWithLayout
var singleEdit = diff.Edits.Single();
Assert.Equal(RenderTreeEditType.PrependFrame, singleEdit.Type);
AssertFrame.Text(
batch.ReferenceFrames[singleEdit.ReferenceFrameIndex],
$"{nameof(ComponentWithLayout)} is here.");
});
}
[Fact]
public void DisplaysComponentInsideNestedLayout()
{
// Arrange/Act
_layoutDisplayComponent.SetParameters(new Dictionary<string, object>
{
{ nameof(LayoutDisplay.Page), typeof(ComponentWithNestedLayout) }
});
// Assert
var batch = _renderer.Batches.Single();
Assert.Collection(batch.DiffsInOrder,
// First, a LayoutDisplay containing a RootLayout
diff => AssertFrame.Component<RootLayout>(
batch.ReferenceFrames[diff.Edits[0].ReferenceFrameIndex]),
// Then a RootLayout containing a NestedLayout
diff => AssertFrame.Component<NestedLayout>(
batch.ReferenceFrames[diff.Edits[1].ReferenceFrameIndex]),
// Then a NestedLayout containing a ComponentWithNestedLayout
diff => AssertFrame.Component<ComponentWithNestedLayout>(
batch.ReferenceFrames[diff.Edits[1].ReferenceFrameIndex]),
// Then the ComponentWithNestedLayout
diff => AssertFrame.Text(
batch.ReferenceFrames[diff.Edits[0].ReferenceFrameIndex],
$"{nameof(ComponentWithNestedLayout)} is here."));
}
[Fact]
public void CanChangeDisplayedPageWithSameLayout()
{
// Arrange
_layoutDisplayComponent.SetParameters(new Dictionary<string, object>
{
{ nameof(LayoutDisplay.Page), typeof(ComponentWithLayout) }
});
// Act
_layoutDisplayComponent.SetParameters(new Dictionary<string, object>
{
{ nameof(LayoutDisplay.Page), typeof(DifferentComponentWithLayout) }
});
// Assert
Assert.Equal(2, _renderer.Batches.Count);
var batch = _renderer.Batches[1];
Assert.Equal(1, batch.DisposedComponentIDs.Count); // Disposed only the inner page component
Assert.Collection(batch.DiffsInOrder,
diff => Assert.Empty(diff.Edits), // LayoutDisplay rerendered, but with no changes
diff =>
{
// RootLayout rerendered
Assert.Collection(diff.Edits,
edit =>
{
// Removed old page
Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type);
Assert.Equal(1, edit.SiblingIndex);
},
edit =>
{
// Inserted new one
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
Assert.Equal(1, edit.SiblingIndex);
AssertFrame.Component<DifferentComponentWithLayout>(
batch.ReferenceFrames[edit.ReferenceFrameIndex]);
});
},
diff =>
{
// New page rendered
var singleEdit = diff.Edits.Single();
Assert.Equal(RenderTreeEditType.PrependFrame, singleEdit.Type);
AssertFrame.Text(
batch.ReferenceFrames[singleEdit.ReferenceFrameIndex],
$"{nameof(DifferentComponentWithLayout)} is here.");
});
}
[Fact]
public void CanChangeDisplayedPageWithDifferentLayout()
{
// Arrange
_layoutDisplayComponent.SetParameters(new Dictionary<string, object>
{
{ nameof(LayoutDisplay.Page), typeof(ComponentWithLayout) }
});
// Act
_layoutDisplayComponent.SetParameters(new Dictionary<string, object>
{
{ nameof(LayoutDisplay.Page), typeof(ComponentWithNestedLayout) }
});
// Assert
Assert.Equal(2, _renderer.Batches.Count);
var batch = _renderer.Batches[1];
Assert.Equal(1, batch.DisposedComponentIDs.Count); // Disposed only the inner page component
Assert.Collection(batch.DiffsInOrder,
diff => Assert.Empty(diff.Edits), // LayoutDisplay rerendered, but with no changes
diff =>
{
// RootLayout rerendered
Assert.Collection(diff.Edits,
edit =>
{
// Removed old page
Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type);
Assert.Equal(1, edit.SiblingIndex);
},
edit =>
{
// Inserted new nested layout
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
Assert.Equal(1, edit.SiblingIndex);
AssertFrame.Component<NestedLayout>(
batch.ReferenceFrames[edit.ReferenceFrameIndex]);
});
},
diff =>
{
// New nested layout rendered
var edit = diff.Edits[1];
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
AssertFrame.Component<ComponentWithNestedLayout>(
batch.ReferenceFrames[edit.ReferenceFrameIndex]);
},
diff =>
{
// New inner page rendered
var singleEdit = diff.Edits.Single();
Assert.Equal(RenderTreeEditType.PrependFrame, singleEdit.Type);
AssertFrame.Text(
batch.ReferenceFrames[singleEdit.ReferenceFrameIndex],
$"{nameof(ComponentWithNestedLayout)} is here.");
});
}
private class RootLayout : AutoRenderComponent, ILayoutComponent
{
public RenderFragment Body { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddContent(0, "RootLayout starts here");
builder.AddContent(1, Body);
builder.AddContent(2, "RootLayout ends here");
}
}
[Layout(typeof(RootLayout))]
private class NestedLayout : AutoRenderComponent, ILayoutComponent
{
public RenderFragment Body { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddContent(0, "NestedLayout starts here");
builder.AddContent(1, Body);
builder.AddContent(2, "NestedLayout ends here");
}
}
[Layout(typeof(RootLayout))]
private class ComponentWithLayout : AutoRenderComponent
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
=> builder.AddContent(0, $"{nameof(ComponentWithLayout)} is here.");
}
[Layout(typeof(RootLayout))]
private class DifferentComponentWithLayout : AutoRenderComponent
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
=> builder.AddContent(0, $"{nameof(DifferentComponentWithLayout)} is here.");
}
[Layout(typeof(NestedLayout))]
private class ComponentWithNestedLayout : AutoRenderComponent
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
=> builder.AddContent(0, $"{nameof(ComponentWithNestedLayout)} is here.");
}
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Blazor.Components;
using Microsoft.AspNetCore.Blazor.RenderTree;
using Xunit;