using Annulus;
using Azimuth;
using Clave;
using System;
using System.Collections.Generic;
using UnitTestSharp;
namespace Glass.UnitTests
{
public class PopupMenuTests : TestFixture
{
[Flags]
public enum TestChoice
{
First = 1,
Second = 2,
Third = 4,
}
public enum NotFlags
{
Only = 1,
}
///
/// Spacing of 4 and a 50 by 20 item for each of the first three bits.
///
public static readonly PopupMenuMaterial Measurements = new PopupMenuMaterial
{
Background = null,
Spacing = 4,
Items = new[] { ItemOf(46, 16), ItemOf(46, 16), ItemOf(46, 16) },
};
///
/// An item whose body wants exactly this much room, inside a 2 thick border.
///
public static ButtonMaterial ItemOf(Scalar width, Scalar height)
{
Material body = new ScrollViewTests.SizedSolidMaterial(new Vector(width, height));
return new ButtonMaterial(ScrollViewTests.Bordered(2, "item").Framing(body));
}
public static Rect Box(Scalar x, Scalar y, Scalar width, Scalar height)
{
return Rect.FromPositionAndSize(new Vector(x, y), new Vector(width, height));
}
public static PopupMenu NewMenu(
TestChoice choices = TestChoice.First | TestChoice.Second | TestChoice.Third,
PopupMenuMaterial? material = null)
{
var returnMe = new PopupMenu(choices, DialogBehavior.Default);
returnMe.PopupMenuMaterial = material ?? Measurements;
return returnMe;
}
public static PopupMenu OpenedAt(Vector position, Vector? screenSize = null)
{
PopupMenu returnMe = NewMenu();
returnMe.OpenAt(position);
PopupTests.Tick(returnMe, Box(0, 0, 10, 10), screenSize);
return returnMe;
}
public static void Click(Button item)
{
item.Click(default, MouseButtonFlags.Left, 1, NoKeys.Held, NoKeys.Manager);
}
public class CtorTests : TestFixture
{
public void Always_BuildsAnItemForEachBitAskedFor()
{
var menu = new PopupMenu(TestChoice.First | TestChoice.Third, DialogBehavior.Default);
CheckNotNull(menu.ItemFor(TestChoice.First));
CheckNotNull(menu.ItemFor(TestChoice.Third));
}
public void Always_StartsClosed()
{
CheckFalse(NewMenu().IsOpen);
}
public void AChoiceNotAskedFor_HasNoItem()
{
var menu = new PopupMenu(TestChoice.First, DialogBehavior.Default);
CheckThrow(typeof(ArgumentException));
menu.ItemFor(TestChoice.Second);
}
public void NoChoices_Throws()
{
CheckThrow(typeof(ArgumentException));
new PopupMenu(0, DialogBehavior.Default);
}
public void AnEnumWithoutFlags_Throws()
{
CheckThrow(typeof(ArgumentException));
new PopupMenu(NotFlags.Only, DialogBehavior.Default);
}
public void NullBehavior_Throws()
{
CheckThrow(typeof(ArgumentNullException));
new PopupMenu(TestChoice.First, null);
}
public void TheBehaviorsOutsidePressSetting_IsTaken()
{
var dismissing = new DialogBehavior(
DialogBehaviorTests.Pressing(KeyCode.MainEnter, KeyCode.NumpadEnter),
DialogBehaviorTests.Pressing(KeyCode.Escape), dismissOnOutsidePress: true);
CheckTrue(new PopupMenu(TestChoice.First, dismissing).DismissOnOutsidePress);
CheckFalse(new PopupMenu(TestChoice.First, DialogBehavior.Default).DismissOnOutsidePress);
}
}
public class MaterialTests : TestFixture
{
public void Setting_GivesEachItemTheLookAtItsBit()
{
var looks = new[] { DropdownTests.Arrow(1, 1), DropdownTests.Arrow(2, 2), DropdownTests.Arrow(3, 3) };
var menu = new PopupMenu(TestChoice.First | TestChoice.Third, DialogBehavior.Default);
menu.PopupMenuMaterial = Measurements with { Items = looks };
CheckEqual(looks[0], menu.ItemFor(TestChoice.First).ButtonMaterial);
CheckEqual(looks[2], menu.ItemFor(TestChoice.Third).ButtonMaterial);
}
public void ALookTheArrayDoesNotReach_LeavesTheItemUnstyled()
{
var menu = new PopupMenu(TestChoice.First | TestChoice.Second, DialogBehavior.Default);
menu.PopupMenuMaterial = Measurements with { Items = new[] { DropdownTests.Arrow(1, 1) } };
CheckEqual(default(ButtonMaterial), menu.ItemFor(TestChoice.Second).ButtonMaterial);
}
public void NoItemLooks_LeavesEveryItemUnstyled()
{
PopupMenu menu = NewMenu(material: new PopupMenuMaterial
{
Background = null,
Spacing = 4,
});
CheckEqual(default(ButtonMaterial), menu.ItemFor(TestChoice.First).ButtonMaterial);
}
public void Getting_ReturnsWhatWasSet()
{
PopupMenu menu = NewMenu();
CheckEqual(Measurements.Spacing, menu.PopupMenuMaterial.Spacing);
CheckEqual(Measurements.Items, menu.PopupMenuMaterial.Items);
}
public void ABackground_FramesTheMenu()
{
Material background = DropdownTests.Bordered3;
PopupMenu menu = NewMenu(material: Measurements with { Background = background });
CheckEqual(background, menu.Material);
CheckEqual(new Vector(64, 82), menu.Bounds.Size);
}
public void WithItemOnTheMaterial_PlacesTheLookAtTheChoicesBit()
{
ButtonMaterial look = DropdownTests.Arrow(5, 5);
PopupMenuMaterial material = new PopupMenuMaterial
{
Background = null,
}.WithItem(TestChoice.Third, look);
CheckEqual(3, material.Items.Length);
CheckEqual(look, material.Items[2]);
}
public void WithItemOnTheMaterial_KeepsTheLooksAlreadyThere()
{
ButtonMaterial first = DropdownTests.Arrow(1, 1);
ButtonMaterial third = DropdownTests.Arrow(3, 3);
PopupMenuMaterial material = new PopupMenuMaterial { Background = null }
.WithItem(TestChoice.Third, third)
.WithItem(TestChoice.First, first);
CheckEqual(3, material.Items.Length);
CheckEqual(first, material.Items[0]);
CheckEqual(third, material.Items[2]);
}
public void WithItemOnTheMaterial_LeavesTheOriginalAlone()
{
PopupMenuMaterial original = Measurements;
PopupMenuMaterial changed = original.WithItem(TestChoice.First, DropdownTests.Arrow(9, 9));
CheckFalse(ReferenceEquals(original.Items, changed.Items));
CheckFalse(changed.Items[0].Equals(original.Items[0]));
}
}
public class LayoutTests : TestFixture
{
public void TheItems_StackTopToBottomByBit()
{
PopupMenu menu = NewMenu();
CheckEqual(Box(4, 4, 50, 20), menu.ItemFor(TestChoice.First).Bounds);
CheckEqual(Box(4, 28, 50, 20), menu.ItemFor(TestChoice.Second).Bounds);
CheckEqual(Box(4, 52, 50, 20), menu.ItemFor(TestChoice.Third).Bounds);
}
public void TheMenu_FitsItsItemsAndTheSpacing()
{
CheckEqual(new Vector(58, 76), NewMenu().Bounds.Size);
}
public void EveryItem_IsAsWideAsTheWidestItem()
{
PopupMenu menu = NewMenu(material: Measurements with
{
Items = new[] { ItemOf(46, 16), ItemOf(86, 16), ItemOf(46, 16) },
});
CheckEqual(90, menu.ItemFor(TestChoice.First).Bounds.Width);
CheckEqual(90, menu.ItemFor(TestChoice.Third).Bounds.Width);
CheckEqual(98, menu.Bounds.Width);
}
public void ItemsOfDifferentHeights_KeepTheirOwn()
{
PopupMenu menu = NewMenu(material: Measurements with
{
Items = new[] { ItemOf(46, 16), ItemOf(46, 36), ItemOf(46, 16) },
});
CheckEqual(Box(4, 28, 50, 40), menu.ItemFor(TestChoice.Second).Bounds);
CheckEqual(Box(4, 72, 50, 20), menu.ItemFor(TestChoice.Third).Bounds);
CheckEqual(96, menu.Bounds.Height);
}
public void ChangingTheMaterial_ResizesTheMenuKeepingItsPosition()
{
PopupMenu menu = OpenedAt(new Vector(100, 100));
menu.PopupMenuMaterial = Measurements with { Spacing = 10 };
CheckEqual(new Vector(100, 100), menu.Bounds.Position);
CheckEqual(new Vector(70, 100), menu.Bounds.Size);
}
}
public class OpenAtTests : TestFixture
{
public void Always_IsOpenAtOnce()
{
PopupMenu menu = NewMenu();
menu.OpenAt(new Vector(100, 100));
CheckTrue(menu.IsOpen);
}
public void AfterAnUpdate_PutsTheTopLeftCornerAtThePosition()
{
PopupMenu menu = OpenedAt(new Vector(300, 200));
CheckTrue(menu.Visible);
CheckEqual(Box(300, 200, 58, 76), menu.Bounds);
}
public void NearTheRightEdge_SlidesLeftToStayOnScreen()
{
CheckEqual(Box(742, 200, 58, 76), OpenedAt(new Vector(790, 200)).Bounds);
}
public void NearTheBottomEdge_SlidesUpToStayOnScreen()
{
CheckEqual(Box(300, 524, 58, 76), OpenedAt(new Vector(300, 590)).Bounds);
}
public void OpeningAgainElsewhere_MovesIt()
{
PopupMenu menu = OpenedAt(new Vector(300, 200));
menu.Close();
menu.OpenAt(new Vector(50, 60));
PopupTests.Tick(menu, Box(0, 0, 10, 10));
CheckEqual(Box(50, 60, 58, 76), menu.Bounds);
}
public void TheFirstEnabledItem_StartsWithFocus()
{
PopupMenu menu = NewMenu();
menu.OpenAt(new Vector(10, 10));
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.First), menu.FocusScope.InitialFocus));
}
public void WithTheFirstItemDisabled_FocusStartsOnTheNext()
{
PopupMenu menu = NewMenu();
menu.ItemFor(TestChoice.First).Enabled = false;
menu.OpenAt(new Vector(10, 10));
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.Second), menu.FocusScope.InitialFocus));
}
public void WithEveryItemDisabled_FocusStartsNowhere()
{
PopupMenu menu = NewMenu();
menu.ItemFor(TestChoice.First).Enabled = false;
menu.ItemFor(TestChoice.Second).Enabled = false;
menu.ItemFor(TestChoice.Third).Enabled = false;
menu.OpenAt(new Vector(10, 10));
CheckNull(menu.FocusScope.InitialFocus);
}
public void OpeningAfterTheFirstItemWasEnabledAgain_FocusesItAgain()
{
PopupMenu menu = NewMenu();
menu.ItemFor(TestChoice.First).Enabled = false;
menu.OpenAt(new Vector(10, 10));
menu.Close();
menu.ItemFor(TestChoice.First).Enabled = true;
menu.OpenAt(new Vector(10, 10));
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.First), menu.FocusScope.InitialFocus));
}
}
public class ChoosingTests : TestFixture
{
public void ActivatingAnItem_RaisesItsChoiceAndClosesTheMenu()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
var chosen = new List();
menu.OnChosen += (choice, keys) => chosen.Add(choice);
Click(menu.ItemFor(TestChoice.Second));
CheckEqual(new List { TestChoice.Second }, chosen);
CheckFalse(menu.IsOpen);
CheckFalse(menu.Visible);
}
public void TheHandler_IsGivenTheManagerThatActivatedTheItem()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
KeyboardManager given = null;
var activating = new KeyboardManager();
menu.OnChosen += (choice, keys) => given = keys;
menu.ItemFor(TestChoice.First).Click(
default, MouseButtonFlags.Left, 1, NoKeys.Held, activating);
CheckTrue(ReferenceEquals(activating, given));
}
public void TheMenu_IsStillOpenWhileTheHandlerRuns()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
bool wasOpen = false;
menu.OnChosen += (choice, keys) => wasOpen = menu.IsOpen;
Click(menu.ItemFor(TestChoice.First));
CheckTrue(wasOpen);
}
public void ADisabledItem_ChoosesNothing()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
menu.ItemFor(TestChoice.Second).Enabled = false;
int chosen = 0;
menu.OnChosen += (choice, keys) => ++chosen;
Click(menu.ItemFor(TestChoice.Second));
CheckEqual(0, chosen);
CheckTrue(menu.IsOpen);
}
public void NoHandler_StillClosesTheMenu()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
Click(menu.ItemFor(TestChoice.Third));
CheckFalse(menu.IsOpen);
}
}
public class KeyTests : TestFixture
{
[IgnoreTest]
private static FocusedKeys FocusOn(PopupMenu menu, TestChoice choice)
{
return new FocusedKeys(menu, menu.ItemFor(choice));
}
public void Escape_ClosesTheMenuChoosingNothing()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.First);
int chosen = 0;
menu.OnChosen += (choice, manager) => ++chosen;
CheckTrue(keys.Press(KeyCode.Escape));
CheckFalse(menu.IsOpen);
CheckEqual(0, chosen);
}
public void Enter_ChoosesTheFocusedItem()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.Second);
var chosen = new List();
menu.OnChosen += (choice, manager) => chosen.Add(choice);
keys.Press(KeyCode.MainEnter);
keys.Release(KeyCode.MainEnter);
CheckEqual(new List { TestChoice.Second }, chosen);
}
public void ArrowDown_MovesFocusToTheNextItem()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.First);
CheckTrue(keys.Press(KeyCode.ArrowDown));
keys.Manager.Refresh();
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.Second), keys.Manager.Focused));
}
public void ArrowUp_MovesFocusToThePreviousItem()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.Third);
CheckTrue(keys.Press(KeyCode.ArrowUp));
keys.Manager.Refresh();
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.Second), keys.Manager.Focused));
}
public void ArrowDownFromTheLastItem_WrapsToTheFirst()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.Third);
keys.Press(KeyCode.ArrowDown);
keys.Manager.Refresh();
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.First), keys.Manager.Focused));
}
public void ArrowUpFromTheFirstItem_WrapsToTheLast()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.First);
keys.Press(KeyCode.ArrowUp);
keys.Manager.Refresh();
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.Third), keys.Manager.Focused));
}
public void ArrowDown_SkipsADisabledItem()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.First);
menu.ItemFor(TestChoice.Second).Enabled = false;
keys.Press(KeyCode.ArrowDown);
keys.Manager.Refresh();
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.Third), keys.Manager.Focused));
}
public void ArrowDown_WithTheOnlyEnabledItemFocused_StaysThere()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.First);
menu.ItemFor(TestChoice.Second).Enabled = false;
menu.ItemFor(TestChoice.Third).Enabled = false;
keys.Press(KeyCode.ArrowDown);
keys.Manager.Refresh();
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.First), keys.Manager.Focused));
}
public void AnotherKey_IsLeftAlone()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
FocusedKeys keys = FocusOn(menu, TestChoice.First);
keys.Press(KeyCode.Q);
CheckTrue(menu.IsOpen);
}
public void ABehaviorWithNoKeys_StillMovesWithTheArrows()
{
var menu = new PopupMenu(TestChoice.First | TestChoice.Second, DialogBehavior.NoKeys);
menu.PopupMenuMaterial = Measurements;
menu.OpenAt(new Vector(10, 10));
PopupTests.Tick(menu, Box(0, 0, 10, 10));
var keys = new FocusedKeys(menu, menu.ItemFor(TestChoice.First));
keys.Press(KeyCode.ArrowDown);
keys.Manager.Refresh();
CheckTrue(ReferenceEquals(menu.ItemFor(TestChoice.Second), keys.Manager.Focused));
}
public void ABehaviorWithNoKeys_IgnoresEscape()
{
var menu = new PopupMenu(TestChoice.First, DialogBehavior.NoKeys);
menu.PopupMenuMaterial = Measurements;
menu.OpenAt(new Vector(10, 10));
PopupTests.Tick(menu, Box(0, 0, 10, 10));
var keys = new FocusedKeys(menu, menu.ItemFor(TestChoice.First));
keys.Press(KeyCode.Escape);
CheckTrue(menu.IsOpen);
}
}
public class MouseTests : TestFixture
{
public void APressOutside_ClosesItWhenDismissingIsOn()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
menu.DismissOnOutsidePress = true;
int chosen = 0;
menu.OnChosen += (choice, keys) => ++chosen;
menu.MouseDown(PopupTests.At(PopupTests.OutsideThePopup), MouseButtonFlags.Left,
NoKeys.Held, NoKeys.Manager);
CheckFalse(menu.IsOpen);
CheckEqual(0, chosen);
}
public void APressOutside_LeavesItOpenWhenDismissingIsOff()
{
PopupMenu menu = OpenedAt(new Vector(10, 10));
menu.MouseDown(PopupTests.At(PopupTests.OutsideThePopup), MouseButtonFlags.Left,
NoKeys.Held, NoKeys.Manager);
CheckTrue(menu.IsOpen);
}
}
}
}