using AcDream.App.UI; using AcDream.App.UI.Layout; namespace AcDream.App.Tests.UI; public class UiButtonTests { private static (uint, int, int) NoTex(uint _) => (0, 0, 0); private bool _clicked; [Fact] public void Click_InvokesOnClick() { var b = new UiButton(new ElementInfo { Type = 1, Width = 46, Height = 18 }, NoTex) { OnClick = () => _clicked = true }; b.OnEvent(new UiEvent(0, null, UiEventType.Click)); Assert.True(_clicked); } [Fact] public void NotClickThrough_SoItReceivesClicks() { var b = new UiButton(new ElementInfo { Type = 1 }, NoTex); Assert.False(b.ClickThrough); } [Fact] public void PointerTransitions_UseRetailNormalStates() { var b = ButtonWithStates("Normal", "Normal_rollover", "Normal_pressed"); b.OnEvent(new UiEvent(0, b, UiEventType.HoverEnter)); Assert.Equal("Normal_rollover", b.ActiveState); b.OnEvent(new UiEvent(0, b, UiEventType.MouseDown, Data1: 5, Data2: 5)); Assert.Equal("Normal_pressed", b.ActiveState); b.OnEvent(new UiEvent(0, b, UiEventType.MouseMove, Data1: 50, Data2: 50)); Assert.Equal("Normal_rollover", b.ActiveState); b.OnEvent(new UiEvent(0, b, UiEventType.MouseMove, Data1: 5, Data2: 5)); Assert.Equal("Normal_pressed", b.ActiveState); b.OnEvent(new UiEvent(0, b, UiEventType.MouseUp, Data1: 5, Data2: 5)); Assert.Equal("Normal_rollover", b.ActiveState); } [Fact] public void ToggleRelease_SelectsHighlightState() { var info = ButtonInfo("Normal", "Highlight"); AddBoolProperty(info, 0x0Bu, true); var b = CreateButton(info); b.OnEvent(new UiEvent(0, b, UiEventType.MouseDown, Data1: 5, Data2: 5)); b.OnEvent(new UiEvent(0, b, UiEventType.MouseUp, Data1: 5, Data2: 5)); Assert.True(b.Selected); Assert.Equal("Highlight", b.ActiveState); } [Fact] public void DisabledProperty_SelectsGhostedAndSuppressesClick() { var info = ButtonInfo("Normal", "Ghosted"); AddBoolProperty(info, 0x0Du, true); var b = CreateButton(info); b.OnClick = () => _clicked = true; b.OnEvent(new UiEvent(0, b, UiEventType.Click)); Assert.False(b.Enabled); Assert.Equal("Ghosted", b.ActiveState); Assert.False(_clicked); } [Fact] public void MissingStandardState_PreservesCustomSemanticState() { var info = ButtonInfo("LockedUI"); info.DefaultStateName = "LockedUI"; var b = CreateButton(info); b.OnEvent(new UiEvent(0, b, UiEventType.HoverEnter)); b.OnEvent(new UiEvent(0, b, UiEventType.MouseDown, Data1: 5, Data2: 5)); Assert.Equal("LockedUI", b.ActiveState); } [Fact] public void HotClick_FiresImmediatelyRepeatsAndSuppressesReleaseClick() { var info = ButtonInfo("Normal"); AddBoolProperty(info, 0x0Fu, true); AddFloatProperty(info, 0x10u, 0.10f); AddFloatProperty(info, 0x11u, 0.05f); int clicks = 0; var b = CreateButton(info); b.OnClick = () => clicks++; b.OnEvent(new UiEvent(0, b, UiEventType.MouseDown, Data1: 5, Data2: 5)); Assert.Equal(1, clicks); b.OnGlobalUiTime(1.00); b.OnGlobalUiTime(1.09); Assert.Equal(1, clicks); b.OnGlobalUiTime(1.11); Assert.Equal(2, clicks); b.OnEvent(new UiEvent(0, b, UiEventType.MouseUp, Data1: 5, Data2: 5)); b.OnEvent(new UiEvent(0, b, UiEventType.Click, Data1: 5, Data2: 5)); Assert.Equal(2, clicks); } private static UiButton ButtonWithStates(params string[] states) { var info = ButtonInfo(states); AddBoolProperty(info, 0x13u, true); return CreateButton(info); } private static ElementInfo ButtonInfo(params string[] states) { var info = new ElementInfo { Type = 1, Width = 20, Height = 20 }; uint file = 1; foreach (string state in states) info.StateMedia[state] = (file++, 1); if (states.Length > 0) info.DefaultStateName = states[0]; return info; } private static void AddBoolProperty(ElementInfo info, uint id, bool value) { if (!info.States.TryGetValue(UiStateInfo.DirectStateId, out var state)) { state = new UiStateInfo { Id = UiStateInfo.DirectStateId }; info.States[UiStateInfo.DirectStateId] = state; } state.Properties.Values[id] = new UiPropertyValue { Kind = UiPropertyKind.Bool, BoolValue = value, }; } private static void AddFloatProperty(ElementInfo info, uint id, float value) { if (!info.States.TryGetValue(UiStateInfo.DirectStateId, out var state)) { state = new UiStateInfo { Id = UiStateInfo.DirectStateId }; info.States[UiStateInfo.DirectStateId] = state; } state.Properties.Values[id] = new UiPropertyValue { Kind = UiPropertyKind.Float, FloatValue = value, }; } private static UiButton CreateButton(ElementInfo info) => new(info, NoTex) { Width = info.Width, Height = info.Height }; }