XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEWarframe

【WinUI】基于Warframe游戏本体的公开服务器以及安装器

公开
关注 0 Fork 0 Star 0
UTF-8
using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Automation.Provider;
using Newtonsoft.Json.Linq;

namespace XFEWarframe.Desktop.Editing;

internal static class OverviewActionsVerification
{
    internal static async Task VerifyAsync(OverviewActionsView view, OverviewActionsModel model, Func<Task<JObject>> inventory, bool dialogs)
    {
        view.UpdateLayout();
        await UntilAsync(() => ReferenceEquals(view.Model, model) && view.ActionButtons.Count == model.Actions.Count, "Overview bindings did not finish loading.");
        if (model.Actions.Count != 16 || view.ActionButtons.Count != 16 || view.ActionButtons.Select(x => (string)x.Tag).Distinct().Count() != 16)
            throw new InvalidOperationException($"The overview must expose each of the 16 progress operations as its own button: actions={model.Actions.Count}, buttons={view.ActionButtons.Count}, message={model.Message}.");
        if (DialogVerification.Children<ListView>(view).Any()) throw new InvalidOperationException("Progress operations are still rendered as an item list.");
        var snapshot = await inventory();
        var pending = await model.PrepareAsync("unlock.intrinsics") ?? throw new InvalidOperationException(model.Message);
        model.Reset(pending.Target with { AccountId = "another-account" });
        await model.ExecuteAsync(pending);
        if (string.IsNullOrEmpty(model.Message) || !JToken.DeepEquals(snapshot, await inventory())) throw new InvalidOperationException("A prepared operation followed an account switch.");
        model.Reset(pending.Target); await model.RefreshAsync();
        if (!dialogs) return;
        foreach (var expander in DialogVerification.Children<SettingsExpander>(view)) expander.IsExpanded = true;
        view.UpdateLayout();
        await Task.Delay(400);
        foreach (var button in view.ActionButtons.ToArray())
        {
            if (button.CornerRadius.TopLeft != 8 || button.MinHeight != 40) throw new InvalidOperationException("Overview buttons did not inherit the shared Fluent style.");
            var opening = button.OpenAsync();
            await UntilAsync(() => button.ActiveDialog?.IsLoaded == true, "Overview action dialog failed to open: " + button.Tag);
            if (button.ActiveDialog!.Title?.ToString() != model.Actions.Single(x => x.Key == (string)button.Tag).Label)
                throw new InvalidOperationException("Action dialog showed another operation.");
            Click(button.ActiveDialog, "CloseButton"); await opening;
        }
        if (!JToken.DeepEquals(snapshot, await inventory())) throw new InvalidOperationException("Canceling overview actions changed the save.");
        foreach (var key in new[] { "unlock.intrinsics", "syndicate" })
        {
            await UntilAsync(() => !model.IsBusy, "Overview did not return to idle.");
            var button = view.ActionButtons.Single(x => (string)x.Tag == key);
            var opening = button.OpenAsync();
            await UntilAsync(() => button.ActiveDialog?.IsLoaded == true, "Overview action dialog failed to open.");
            var dialog = button.ActiveDialog!; dialog.UpdateLayout();
            string? selected = null;
            if (key == "syndicate")
            {
                var field = DialogVerification.Children<EditorForm>(dialog).Single().Fields!.Single();
                var option = field.Options.First(x => x.Value.ToString().Length > 0); selected = option.Value.ToString();
                var input = DialogVerification.Children<AutoSuggestBox>(dialog).Single(); input.Focus(FocusState.Programmatic);
                await SuggestionVerification.TypeAsync(input, selected); await SuggestionVerification.SubmitAsync(input);
            }
            Click(dialog, "PrimaryButton"); await opening;
            await UntilAsync(() => !model.IsBusy, "Overview operation did not finish.");
            if (model.Message.Length > 0) throw new InvalidOperationException(model.Message);
            var result = await inventory();
            if (key == "unlock.intrinsics" && (result["PlayerSkills"] is not JObject skills || skills.Count == 0 || skills.Properties().Any(x => x.Value.Value<int>() <= 0)))
                throw new InvalidOperationException("The direct intrinsic button did not update the selected save.");
            if (key == "syndicate" && result.Value<string>("SupportedSyndicate") != selected)
                throw new InvalidOperationException("The overview group selector did not persist its chosen value.");
        }
        foreach (var expander in DialogVerification.Children<SettingsExpander>(view)) expander.IsExpanded = false;
        await Task.Delay(400);
        var report = Environment.GetCommandLineArgs().First(x => x.StartsWith("--verify-ui=", StringComparison.Ordinal))["--verify-ui=".Length..];
        await OverviewSnapshot.SaveAsync(view.XamlRoot.Content, Path.ChangeExtension(report, ".overview.png"));
    }
    private static void Click(ContentDialog dialog, string name)
    {
        var button = DialogVerification.Children<Button>(dialog).Last(x => x.Name == name && x.Visibility == Visibility.Visible && x.ActualHeight > 0);
        ((IInvokeProvider)new ButtonAutomationPeer(button).GetPattern(PatternInterface.Invoke)).Invoke();
    }
    private static async Task UntilAsync(Func<bool> condition, string error)
    {
        for (var i = 0; i < 500 && !condition(); i++) await Task.Delay(10);
        if (!condition()) throw new InvalidOperationException(error);
    }
}