Public Access
Flatten the hosts screen into one board of sections
This commit is contained in:
@@ -287,7 +287,7 @@ public sealed class ScreenLayoutTests : IAsyncLifetime
|
||||
|
||||
await OnTheHostsScreenAsync((screen, window) =>
|
||||
{
|
||||
var card = screen.HostGrid.GetVisualDescendants()
|
||||
var card = screen.GetVisualDescendants()
|
||||
.OfType<ListBoxItem>()
|
||||
.First(item => item.DataContext is HostRowViewModel);
|
||||
|
||||
@@ -332,22 +332,22 @@ public sealed class ScreenLayoutTests : IAsyncLifetime
|
||||
{
|
||||
await OnTheHostsScreenAsync((screen, _) =>
|
||||
{
|
||||
screen.KeyboardTarget.ShouldBeSameAs(screen.HostGrid);
|
||||
screen.KeyboardTarget.Focus().ShouldBeTrue("the grid has cards in it");
|
||||
screen.KeyboardTarget.ShouldBeSameAs(screen.Board);
|
||||
screen.KeyboardTarget.Focus().ShouldBeTrue("the board has cards on it");
|
||||
});
|
||||
|
||||
vault.HostFilter = "nothing matches this";
|
||||
vault.HasVisibleHosts.ShouldBeFalse();
|
||||
vault.HasHostBoardEntries.ShouldBeFalse();
|
||||
|
||||
await OnTheHostsScreenAsync((screen, _) =>
|
||||
{
|
||||
screen.KeyboardTarget.ShouldBeSameAs(screen.HostFilter);
|
||||
screen.KeyboardTarget.Focus().ShouldBeTrue("the grid is empty, so the find box takes it");
|
||||
screen.KeyboardTarget.Focus().ShouldBeTrue("the board is empty, so the find box takes it");
|
||||
});
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// The editor open with the grid still on screen beside it, which is the state a user is most likely to
|
||||
/// The editor open with the board still on screen beside it, which is the state a user is most likely to
|
||||
/// leave this screen in — so it is the state the keyboard answer most has to hold in.
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
@@ -357,56 +357,61 @@ public sealed class ScreenLayoutTests : IAsyncLifetime
|
||||
|
||||
await OnTheHostsScreenAsync((screen, _) =>
|
||||
{
|
||||
screen.HostGrid.IsEffectivelyVisible.ShouldBeTrue();
|
||||
screen.Board.IsEffectivelyVisible.ShouldBeTrue();
|
||||
screen.KeyboardTarget.Focus().ShouldBeTrue();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The grid is cards and nothing else, whatever the vault has been filed into.
|
||||
/// v5: each section's own card list holds cards and nothing else — the heading is a sibling, not a row.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// It used to hold the group headings too — a full-width fold-away bar between the cards for each group
|
||||
/// — and in a wrap of cards that read as a dropdown somebody had left open. They are the phone's now.
|
||||
/// This asserts the grid's contents rather than only measuring them, because a heading that came back
|
||||
/// would lay out perfectly cleanly: the harness asks whether a control is inside the window, and a bar
|
||||
/// that spans the width is as inside it as a card is.
|
||||
/// This used to hold for one flat grid: no group headings were mixed into the host rows, because the
|
||||
/// group cards above it were where a group's name was drawn. The board replaces that grid with one
|
||||
/// section per group — see <c>VaultViewModel.HostSections</c> — and the invariant moves down a level
|
||||
/// with it: it is each section's own <c>ListBox</c> (<c>Classes="sectioncards"</c>) that must hold only
|
||||
/// <see cref="HostRowViewModel"/>s, because <c>HostsScreen.axaml.cs</c> finds every card by walking every
|
||||
/// list wearing that class and would misfire on a heading it found mixed in.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Measured with every host filed and that group open, which is the shape that used to produce the most
|
||||
/// headings. Open, because the grid holds one level of the tree — a host inside a group is drawn inside
|
||||
/// that group and nowhere else — so measuring at the outermost level would be measuring an empty grid.
|
||||
/// See <c>VaultViewModel.Matches</c>.
|
||||
/// Measured with every host filed under one group, which is the shape that puts the most rows behind one
|
||||
/// heading.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public async Task TheHostsGridHoldsCardsAndNoGroupHeadings()
|
||||
public async Task EachSectionsCardListHoldsCardsAndNothingElse()
|
||||
{
|
||||
await SeedGroupsAsync(3);
|
||||
|
||||
// Filed through the host editor, same as SeedGroupsAsync itself does — the drag this used to exercise
|
||||
// left with the group cards in v5; see VaultViewModel.EditGroup's own remarks.
|
||||
foreach (var host in vault.Hosts.ToArray())
|
||||
{
|
||||
await vault.MoveHostToGroupCommand.ExecuteAsync(
|
||||
new HostGroupMove(host, vault.Groups[0].EntityId));
|
||||
}
|
||||
vault.SelectedHost = host;
|
||||
vault.EditSelectedHostCommand.Execute(null);
|
||||
|
||||
vault.OpenGroupCommand.Execute(vault.Groups[0]);
|
||||
vault.EditorSelectedGroup = vault.EditorGroupChoices
|
||||
.First(choice => choice.EntityId == vault.Groups[0].EntityId);
|
||||
|
||||
await vault.SaveHostCommand.ExecuteAsync(null);
|
||||
}
|
||||
|
||||
await OnTheHostsScreenAsync((screen, _) =>
|
||||
{
|
||||
var rows = screen.HostGrid
|
||||
.GetVisualDescendants()
|
||||
.OfType<ListBoxItem>()
|
||||
var rows = screen.GetVisualDescendants()
|
||||
.OfType<ListBox>()
|
||||
.Where(list => list.Classes.Contains("sectioncards"))
|
||||
.SelectMany(list => list.GetVisualDescendants().OfType<ListBoxItem>())
|
||||
.Select(item => item.DataContext)
|
||||
.ToList();
|
||||
|
||||
rows.ShouldNotBeEmpty("the seed has to put hosts in the grid");
|
||||
rows.ShouldNotBeEmpty("the seed has to put hosts in one of the sections");
|
||||
rows.ShouldAllBe(row => row is HostRowViewModel);
|
||||
});
|
||||
|
||||
await MeasureHostsAsync(
|
||||
faults => faults.ShouldBeEmpty("with every host filed and the group holding them open"));
|
||||
faults => faults.ShouldBeEmpty("with every host filed under one group and four sections drawn"));
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
@@ -447,15 +452,14 @@ public sealed class ScreenLayoutTests : IAsyncLifetime
|
||||
|
||||
await OnTheHostsScreenAsync((screen, window) =>
|
||||
{
|
||||
var cards = screen.HostGrid
|
||||
.GetVisualDescendants()
|
||||
var cards = screen.GetVisualDescendants()
|
||||
.OfType<ListBoxItem>()
|
||||
.Where(item => item.DataContext is HostRowViewModel)
|
||||
.Select(item => item.TranslatePoint(default, window)
|
||||
?? throw new InvalidOperationException("a card is not in this window's tree"))
|
||||
.ToList();
|
||||
|
||||
cards.Count.ShouldBeGreaterThan(1, "the seed has to put more than one host in the grid");
|
||||
cards.Count.ShouldBeGreaterThan(1, "the seed has to put more than one host on the board");
|
||||
|
||||
cards.GroupBy(point => Math.Round(point.Y))
|
||||
.Max(row => row.Count())
|
||||
@@ -589,8 +593,9 @@ public sealed class ScreenLayoutTests : IAsyncLifetime
|
||||
{
|
||||
await SeedGroupsAsync(3);
|
||||
|
||||
vault.SelectedGroup = vault.Groups[0];
|
||||
vault.DeleteGroupCommand.Execute(null);
|
||||
// Passed directly, the way DeleteGroupFromHeading resolves and hands in a row now that there is no
|
||||
// group-card selection to fall back on.
|
||||
vault.DeleteGroupCommand.Execute(vault.Groups[0]);
|
||||
|
||||
vault.IsConfirmingGroupDeletion.ShouldBeTrue("the question has to be up for this to measure it");
|
||||
vault.PendingDeletion.ShouldNotBeNull().HasChoice
|
||||
@@ -617,8 +622,6 @@ public sealed class ScreenLayoutTests : IAsyncLifetime
|
||||
{
|
||||
await SeedGroupsAsync(3);
|
||||
|
||||
vault.SelectedGroup = vault.Groups[0];
|
||||
|
||||
vault.MoveGroupVaultChoices.Add(
|
||||
new VaultChoiceViewModel(Guid.CreateVersion7(), "Platform Engineering secrets", false));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user