From 949f35defda75b9496cd18dfe4142960ddf5d188 Mon Sep 17 00:00:00 2001 From: Nils Andresen <nils@nils-andresen.de> Date: Thu, 14 Oct 2021 08:07:31 +0200 Subject: [PATCH] (#502) Added GetParent and GetParents to MultiSelectionPrompt So it it possible to find the parent(s) of a given item. --- .../Prompts/MultiSelectionPrompt.cs | 35 ++++++++++ .../Unit/Prompts/MultiSelectionPromptTests.cs | 70 +++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/src/Spectre.Console/Prompts/MultiSelectionPrompt.cs b/src/Spectre.Console/Prompts/MultiSelectionPrompt.cs index 69a504e..8b92b16 100644 --- a/src/Spectre.Console/Prompts/MultiSelectionPrompt.cs +++ b/src/Spectre.Console/Prompts/MultiSelectionPrompt.cs @@ -112,6 +112,41 @@ namespace Spectre.Console .ToList(); } + /// <summary> + /// Returns all parent items of the given <paramref name="item"/>. + /// </summary> + /// <param name="item">The item for which to find the parents.</param> + /// <returns>The parent items, or an empty list, if the given item has no parents.</returns> + public IEnumerable<T> GetParents(T item) + { + var promptItem = Tree.Find(item); + if (promptItem == null) + { + throw new ArgumentOutOfRangeException(nameof(item), "item not found in tree."); + } + + var parents = new List<ListPromptItem<T>>(); + while (promptItem.Parent != null) + { + promptItem = promptItem.Parent; + parents.Add(promptItem); + } + + return parents + .ReverseEnumerable() + .Select(x => x.Data); + } + + /// <summary> + /// Returns the parent item of the given <paramref name="item"/>. + /// </summary> + /// <param name="item">The item for which to find the parent.</param> + /// <returns>The parent item, or <c>null</c> if the given item has no parent.</returns> + public T? GetParent(T item) + { + return GetParents(item).LastOrDefault(); + } + /// <inheritdoc/> ListPromptInputResult IListPromptStrategy<T>.HandleInput(ConsoleKeyInfo key, ListPromptState<T> state) { diff --git a/test/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs b/test/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs index b9bdcb5..a0ac81a 100644 --- a/test/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs +++ b/test/Spectre.Console.Tests/Unit/Prompts/MultiSelectionPromptTests.cs @@ -82,5 +82,75 @@ namespace Spectre.Console.Tests.Unit // Then choice.IsSelected.ShouldBeTrue(); } + + [Fact] + public void Should_Get_The_Direct_Parent() + { + // Given + var prompt = new MultiSelectionPrompt<string>(); + prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item"); + + // When + var actual = prompt.GetParent("item"); + + // Then + actual.ShouldBe("level-2"); + } + + [Fact] + public void Should_Get_The_List_Of_All_Parents() + { + // Given + var prompt = new MultiSelectionPrompt<string>(); + prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item"); + + // When + var actual = prompt.GetParents("item"); + + // Then + actual.ShouldBe(new []{"root", "level-1", "level-2"}); + } + + [Fact] + public void Should_Get_An_Empty_List_Of_Parents_For_Root_Node() + { + // Given + var prompt = new MultiSelectionPrompt<string>(); + prompt.AddChoice("root"); + + // When + var actual = prompt.GetParents("root"); + + // Then + actual.ShouldBeEmpty(); + } + + [Fact] + public void Should_Get_Null_As_Direct_Parent_Of_Root_Node() + { + // Given + var prompt = new MultiSelectionPrompt<string>(); + prompt.AddChoice("root"); + + // When + var actual = prompt.GetParent("root"); + + // Then + actual.ShouldBeNull(); + } + + [Fact] + public void Should_Throw_When_Getting_Parents_Of_Non_Existing_Node() + { + // Given + var prompt = new MultiSelectionPrompt<string>(); + prompt.AddChoice("root").AddChild("level-1").AddChild("level-2").AddChild("item"); + + // When + Action action = () => prompt.GetParents("non-existing"); + + // Then + action.ShouldThrow<ArgumentOutOfRangeException>(); + } } }