diff --git a/tests/Elastic.Documentation.Tests/Testing/NavigationDumpTests.cs b/tests/Elastic.Documentation.Tests/Testing/NavigationDumpTests.cs new file mode 100644 index 0000000000..9ee7ec3afd --- /dev/null +++ b/tests/Elastic.Documentation.Tests/Testing/NavigationDumpTests.cs @@ -0,0 +1,119 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using AwesomeAssertions; +using Elastic.Documentation.Navigation; +using Elastic.Documentation.Testing; +using Nullean.Snapshots; + +namespace Elastic.Documentation.Tests.Testing; + +/// +/// Navigation.Tests snapshots , so a bug here would be accepted into every one of those snapshots. +/// In particular a broken [wrong parent] check would hide the regression it exists to catch. +/// +public class NavigationDumpTests +{ + [Test] + public void ToText_ListsTheIndexFirstThenTheChildren_IndentedByDepth_WithFlagsAndTrimmedTypeNames() + { + var island = new FakeNode("/docs/island", "Island", "Island index") { IsIsland = true }; + var root = new FakeNode("/docs", "Docs", "Docs index"); + root.Add(new FakeLeaf("/docs/a", "A")); + root.Add(new FakeLeaf("/docs/b", "B") { Hidden = true }); + root.Add(island); + island.Add(new FakeGenericLeaf("/docs/island/x", "X")); + + NavigationDump + .ToText(root) + .Should() + .MatchInlineSnapshot( + """ + FakeNode /docs "Docs" + index: FakeLeaf /docs "Docs index" + FakeLeaf /docs/a "A" + FakeLeaf /docs/b "B" [hidden] + FakeNode /docs/island "Island" [island] + index: FakeLeaf /docs/island "Island index" + FakeGenericLeaf /docs/island/x "X" + """ + ); + } + + [Test] + public void ToText_ChildWhoseParentIsAnotherNode_IsFlaggedWrongParent() + { + var other = new FakeNode("/docs/other", "Other", "Other index"); + var root = new FakeNode("/docs", "Docs", "Docs index"); + root.Add(new FakeLeaf("/docs/fine", "Fine")); + // listed under root, but it points back at another node + root.Add(new FakeLeaf("/docs/stray", "Stray"), parent: other); + root.Add(other); + + NavigationDump + .ToText(root) + .Should() + .MatchInlineSnapshot( + """ + FakeNode /docs "Docs" + index: FakeLeaf /docs "Docs index" + FakeLeaf /docs/fine "Fine" + FakeLeaf /docs/stray "Stray" [wrong parent] + FakeNode /docs/other "Other" + index: FakeLeaf /docs/other "Other index" + """ + ); + } + + [Test] + public void ToText_IndexPage_IsNotCheckedForItsParent() + { + // a virtual file's index has a different parent than its node, so it must not be flagged + var root = new FakeNode("/docs", "Docs", "Docs index"); + root.Index.Parent = new FakeNode("/elsewhere", "Elsewhere", "Elsewhere index"); + + NavigationDump + .ToText(root) + .Should() + .MatchInlineSnapshot(""" + FakeNode /docs "Docs" + index: FakeLeaf /docs "Docs index" + """); + } + + private sealed class FakeModel : INavigationModel; + + private class FakeLeaf(string url, string title) : ILeafNavigationItem + { + public string Url { get; } = url; + public string NavigationTitle { get; } = title; + public IRootNavigationItem NavigationRoot => null!; + public INodeNavigationItem? Parent { get; set; } + public bool Hidden { get; init; } + public bool IsIsland { get; init; } + public int NavigationIndex { get; set; } + public INavigationModel Model { get; } = new FakeModel(); + } + + private sealed class FakeGenericLeaf(string url, string title) : FakeLeaf(url, title); + + private sealed class FakeNode : FakeLeaf, INodeNavigationItem + { + private readonly List _children = []; + + public FakeNode(string url, string title, string indexTitle) : base(url, title) => + Index = new FakeLeaf(url, indexTitle) { Parent = null }; + + public string Id => Url; + public FakeLeaf Index { get; } + ILeafNavigationItem INodeNavigationItem.Index => Index; + public IReadOnlyCollection NavigationItems => _children; + + public void Add(FakeLeaf child, INodeNavigationItem? parent = null) + { + child.Parent = parent ?? this; + _children.Add(child); + } + } +}