using AcDream.App.UI; using AcDream.App.UI.Layout; namespace AcDream.App.Tests.UI.Layout; public sealed class RetailDialogFactoryTests { [Theory] [InlineData(RetailDialogType.Confirmation, 0x15u)] [InlineData(RetailDialogType.Wait, 0x31u)] [InlineData(RetailDialogType.Message, 0x24u)] [InlineData(RetailDialogType.TextInput, 0x28u)] [InlineData(RetailDialogType.ConfirmationTextInput, 0x2Cu)] [InlineData(RetailDialogType.Menu, 0x1Bu)] [InlineData(RetailDialogType.ConfirmationMenu, 0x1Fu)] public void DialogTypesMapToRetailCatalogRoots( RetailDialogType type, uint expectedRoot) => Assert.Equal(expectedRoot, RetailDialogFactory.RootElementId(type)); [Fact] public void FixtureBuildsProductionConfirmationWidgets() { var layout = FixtureLoader.LoadConfirmationDialog(); Assert.IsType(layout.Root); Assert.IsType(layout.FindElement(RetailConfirmationDialogView.MessageElementId)); Assert.IsType(layout.FindElement(RetailConfirmationDialogView.AcceptButtonId)); Assert.IsType(layout.FindElement(RetailConfirmationDialogView.RejectButtonId)); } [Fact] public void ConfirmationCreatesFreshCenteredRootAndReturnsPropertyResult() { var root = new UiRoot { Width = 1024f, Height = 768f }; var layouts = new List(); var factory = CreateFactory(root, layouts); bool? result = null; factory.MakeConfirmation( "Do you really want to kill your character?", data => result = data.GetBoolean(RetailDialogProperty.ConfirmationResult)); ImportedLayout layout = Assert.Single(layouts); Assert.Same(layout.Root, root.Modal); var popup = Assert.IsAssignableFrom( layout.FindElement(RetailConfirmationDialogView.PopupElementId)); Assert.Equal(MathF.Round((1024f - popup.Width) * 0.5f), popup.Left); Assert.Equal(MathF.Round((768f - popup.Height) * 0.5f), popup.Top); Accept(layout); Assert.True(result); Assert.Null(root.Modal); Assert.False(factory.IsOpen); } [Fact] public void SameQueuePresentsFifoUsingFreshLiveRoots() { var root = new UiRoot { Width = 800f, Height = 600f }; var layouts = new List(); var factory = CreateFactory(root, layouts); var results = new List(); factory.MakeConfirmation("first", data => results.Add($"first:{data.GetBoolean(RetailDialogProperty.ConfirmationResult)}")); factory.MakeConfirmation("second", data => results.Add($"second:{data.GetBoolean(RetailDialogProperty.ConfirmationResult)}")); Assert.Equal(1, factory.PendingCount); Reject(layouts[0]); Assert.Equal(["first:False"], results); Assert.Equal(2, layouts.Count); Assert.NotSame(layouts[0].Root, layouts[1].Root); Assert.Same(layouts[1].Root, root.Modal); Assert.Equal("second", Message(layouts[1])); Accept(layouts[1]); Assert.Equal(["first:False", "second:True"], results); Assert.False(factory.IsOpen); } [Fact] public void QueueGroupsAndNonQueuedDialogsCanBeActiveTogether() { var root = new UiRoot { Width = 800f, Height = 600f }; var layouts = new List(); var factory = CreateFactory(root, layouts); uint first = factory.MakeConfirmation("queue two", queueKey: 2u); uint second = factory.MakeConfirmation("queue three", queueKey: 3u); uint third = factory.MakeConfirmation("nonqueued", queueKey: 1u); Assert.Equal(3, factory.ActiveCount); Assert.Equal(0, factory.PendingCount); Assert.Same(layouts[2].Root, root.Modal); Assert.True(factory.CloseDialog(third)); Assert.Same(layouts[1].Root, root.Modal); Assert.True(factory.CloseDialog(second)); Assert.Same(layouts[0].Root, root.Modal); Assert.True(factory.CloseDialog(first)); Assert.Null(root.Modal); } [Fact] public void PriorityDialogSuspendsCurrentAndRestoresItBeforeOlderPendingWork() { var root = new UiRoot { Width = 800f, Height = 600f }; var layouts = new List(); var factory = CreateFactory(root, layouts); factory.MakeConfirmation("current"); factory.MakeConfirmation("ordinary pending"); factory.MakeConfirmation("priority", priority: true); Assert.Equal(2, factory.PendingCount); Assert.Equal("priority", Message(layouts[1])); Assert.DoesNotContain(layouts[0].Root, root.Children); Reject(layouts[1]); Assert.Equal(3, layouts.Count); Assert.Equal("current", Message(layouts[2])); Assert.Equal(1, factory.PendingCount); Assert.NotSame(layouts[0].Root, layouts[2].Root); } [Fact] public void CallbackPrecedesCloseNoticeAndCustomLabelsAreApplied() { var root = new UiRoot { Width = 800f, Height = 600f }; var layouts = new List(); var factory = CreateFactory(root, layouts); var order = new List(); factory.DialogClosed += (_, _) => order.Add("notice"); RetailDialogData data = RetailDialogData.Confirmation("Proceed?") .Set(RetailDialogProperty.AcceptLabel, "Yes") .Set(RetailDialogProperty.RejectLabel, "No"); factory.MakeDialog(data, _ => order.Add("callback")); Assert.Equal("Yes", Button(layouts[0], RetailConfirmationDialogView.AcceptButtonId).Label); Assert.Equal("No", Button(layouts[0], RetailConfirmationDialogView.RejectButtonId).Label); Accept(layouts[0]); Assert.Equal(["callback", "notice"], order); } [Fact] public void PendingContextCanBeClosedWithoutDisturbingActiveDialog() { var root = new UiRoot { Width = 800f, Height = 600f }; var layouts = new List(); var factory = CreateFactory(root, layouts); var completed = new List(); uint active = factory.MakeConfirmation("active"); uint pending = 0u; pending = factory.MakeConfirmation("pending", _ => completed.Add(pending)); Assert.True(factory.CloseDialog(pending)); Assert.Equal([pending], completed); Assert.Equal(0, factory.PendingCount); Assert.Same(layouts[0].Root, root.Modal); Assert.True(factory.CloseDialog(active)); } [Fact] public void ResetCompletesActiveAndPendingContexts() { var root = new UiRoot { Width = 800f, Height = 600f }; var layouts = new List(); var factory = CreateFactory(root, layouts); var completed = new List(); var notices = new List(); factory.DialogClosed += (context, _) => notices.Add(context); uint active = factory.MakeConfirmation("active", _ => completed.Add("active")); uint pending = factory.MakeConfirmation("pending", _ => completed.Add("pending")); factory.Reset(); Assert.Equal(["active", "pending"], completed); Assert.Equal([active, pending], notices); Assert.False(factory.IsOpen); Assert.Equal(0, factory.PendingCount); Assert.Null(root.Modal); } private static RetailDialogFactory CreateFactory( UiRoot root, List layouts) => new(root, type => { Assert.Equal(RetailDialogType.Confirmation, type); ImportedLayout layout = FixtureLoader.LoadConfirmationDialog(); layouts.Add(layout); return layout; }); private static UiButton Button(ImportedLayout layout, uint id) => Assert.IsType(layout.FindElement(id)); private static void Accept(ImportedLayout layout) => Button(layout, RetailConfirmationDialogView.AcceptButtonId).OnClick!(); private static void Reject(ImportedLayout layout) => Button(layout, RetailConfirmationDialogView.RejectButtonId).OnClick!(); private static string Message(ImportedLayout layout) => string.Join(" ", Assert.IsType(layout.FindElement( RetailConfirmationDialogView.MessageElementId)).LinesProvider().Select(static line => line.Text)); }