267 lines
11 KiB
C#
267 lines
11 KiB
C#
// 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.");
|
|
}
|
|
}
|
|
}
|