Plugin-registerable self tests

The goal of this change is to let plugins register their own self-tests. 

We do this through the `ISelfTestRegistry` interface. For a plugin it
would look like this:

```csharp
[PluginService]
public ISelfTestRegistry SelfTestRegistry

// Somewhere that gets called by your plugin
SelfTestRegistry.RegisterTestSteps([
  new MySelfTestStep(),
  new MyOtherSelfTestStep()
])
```

Where `MySelfTest` and `MyOtherSelfTest` are instances of
the existing `ISelfTestStep` interface.

The biggest changes are to `SelfTestWindow` and the introduction of
`SelfTestWithResults`. I wanted to make sure test state wasn't lost when
changing the dropdown state and I was finding it a bit annoying to work
with the Dictionary now that we can't just rely on the index of the
item.

To fix this I moved all the "test run" state into `SelfTestWithResults`,
most of the changes to `SelfTestWindow` are derived from that, other
then the addition of the combo box.

The documentation for this service is a bit sparse, but I wanted to put
it up for review first before I invest a bunch of time making nice
documentation. 

I'm keen to hear if we think this is useful or if any changes are
needed.
This commit is contained in:
GrittyFrog 2025-10-11 16:50:29 +11:00
parent 4ac4505d72
commit ae777000e2
41 changed files with 674 additions and 133 deletions

View file

@ -1,27 +0,0 @@
namespace Dalamud.Interface.Internal.Windows.SelfTest;
/// <summary>
/// Enum declaring result states of tests.
/// </summary>
internal enum SelfTestStepResult
{
/// <summary>
/// Test was not ran.
/// </summary>
NotRan,
/// <summary>
/// Test is waiting for completion.
/// </summary>
Waiting,
/// <summary>
/// Test has failed.
/// </summary>
Fail,
/// <summary>
/// Test has passed.
/// </summary>
Pass,
}

View file

@ -6,11 +6,13 @@ using System.Numerics;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
using Dalamud.Interface.Internal.Windows.SelfTest.Steps;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Interface.Windowing;
using Dalamud.Logging.Internal;
using Dalamud.Plugin.SelfTest;
using Dalamud.Plugin.SelfTest.Internal;
using Dalamud.Utility;
using Lumina.Excel.Sheets;
namespace Dalamud.Interface.Internal.Windows.SelfTest;
@ -22,49 +24,14 @@ internal class SelfTestWindow : Window
{
private static readonly ModuleLog Log = new("AGING");
private readonly List<ISelfTestStep> steps =
[
new LoginEventSelfTestStep(),
new WaitFramesSelfTestStep(1000),
new FrameworkTaskSchedulerSelfTestStep(),
new EnterTerritorySelfTestStep(148, "Central Shroud"),
new ItemPayloadSelfTestStep(),
new ContextMenuSelfTestStep(),
new NamePlateSelfTestStep(),
new ActorTableSelfTestStep(),
new FateTableSelfTestStep(),
new AetheryteListSelfTestStep(),
new ConditionSelfTestStep(),
new ToastSelfTestStep(),
new TargetSelfTestStep(),
new KeyStateSelfTestStep(),
new GamepadStateSelfTestStep(),
new ChatSelfTestStep(),
new HoverSelfTestStep(),
new LuminaSelfTestStep<Item>(true),
new LuminaSelfTestStep<Level>(true),
new LuminaSelfTestStep<Lumina.Excel.Sheets.Action>(true),
new LuminaSelfTestStep<Quest>(true),
new LuminaSelfTestStep<TerritoryType>(false),
new AddonLifecycleSelfTestStep(),
new PartyFinderSelfTestStep(),
new HandledExceptionSelfTestStep(),
new DutyStateSelfTestStep(),
new GameConfigSelfTestStep(),
new MarketBoardSelfTestStep(),
new SheetRedirectResolverSelfTestStep(),
new NounProcessorSelfTestStep(),
new SeStringEvaluatorSelfTestStep(),
new CompletionSelfTestStep(),
new LogoutEventSelfTestStep()
];
private readonly SelfTestRegistry selfTestRegistry;
private readonly Dictionary<int, (SelfTestStepResult Result, TimeSpan? Duration)> testIndexToResult = new();
private List<SelfTestWithResults> visibleSteps = new();
private bool selfTestRunning = false;
private int currentStep = 0;
private int scrollToStep = -1;
private DateTimeOffset lastTestStart;
private SelfTestGroup? currentTestGroup = null;
private SelfTestWithResults? currentStep = null;
private SelfTestWithResults? scrollToStep = null;
/// <summary>
/// Initializes a new instance of the <see cref="SelfTestWindow"/> class.
@ -72,6 +39,7 @@ internal class SelfTestWindow : Window
public SelfTestWindow()
: base("Dalamud Self-Test", ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse)
{
this.selfTestRegistry = Service<SelfTestRegistry>.Get();
this.Size = new Vector2(800, 800);
this.SizeCondition = ImGuiCond.FirstUseEver;
@ -81,6 +49,55 @@ internal class SelfTestWindow : Window
/// <inheritdoc/>
public override void Draw()
{
// Initialize to first group if not set (first time drawing)
if (this.currentTestGroup == null)
{
this.currentTestGroup = this.selfTestRegistry.SelfTestGroups.FirstOrDefault(); // Should always be "Dalamud"
if (this.currentTestGroup != null)
{
this.SelectTestGroup(this.currentTestGroup);
}
}
// Update visible steps based on current group
if (this.currentTestGroup != null)
{
this.visibleSteps = this.selfTestRegistry.SelfTests
.Where(test => test.Group == this.currentTestGroup.Name).ToList();
// Stop tests if no steps available or if current step is no longer valid
if (this.visibleSteps.Count == 0 || (this.currentStep != null && !this.visibleSteps.Contains(this.currentStep)))
{
this.StopTests();
}
}
using (var dropdown = ImRaii.Combo("###SelfTestGroupCombo"u8, this.currentTestGroup?.Name ?? string.Empty))
{
if (dropdown)
{
foreach (var testGroup in this.selfTestRegistry.SelfTestGroups)
{
if (ImGui.Selectable(testGroup.Name))
{
this.SelectTestGroup(testGroup);
}
if (!testGroup.Loaded)
{
ImGui.SameLine();
this.DrawUnloadedIcon();
}
}
}
}
if (this.currentTestGroup?.Loaded == false)
{
ImGui.SameLine();
this.DrawUnloadedIcon();
}
if (this.selfTestRunning)
{
if (ImGuiComponents.IconButton(FontAwesomeIcon.Stop))
@ -92,13 +109,10 @@ internal class SelfTestWindow : Window
if (ImGuiComponents.IconButton(FontAwesomeIcon.StepForward))
{
this.testIndexToResult[this.currentStep] = (SelfTestStepResult.NotRan, null);
this.steps[this.currentStep].CleanUp();
this.currentStep++;
this.currentStep.Reset();
this.MoveToNextTest();
this.scrollToStep = this.currentStep;
this.lastTestStart = DateTimeOffset.Now;
if (this.currentStep >= this.steps.Count)
if (this.currentStep == null)
{
this.StopTests();
}
@ -106,38 +120,50 @@ internal class SelfTestWindow : Window
}
else
{
var canRunTests = this.currentTestGroup?.Loaded == true && this.visibleSteps.Count > 0;
using var disabled = ImRaii.Disabled(!canRunTests);
if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
{
this.selfTestRunning = true;
this.currentStep = 0;
this.currentStep = this.visibleSteps.FirstOrDefault();
this.scrollToStep = this.currentStep;
this.testIndexToResult.Clear();
this.lastTestStart = DateTimeOffset.Now;
foreach (var test in this.visibleSteps)
{
test.Reset();
}
}
}
ImGui.SameLine();
ImGui.Text($"Step: {this.currentStep} / {this.steps.Count}");
var stepNumber = this.currentStep != null ? this.visibleSteps.IndexOf(this.currentStep) : 0;
ImGui.Text($"Step: {stepNumber} / {this.visibleSteps.Count}");
ImGui.Spacing();
if (this.currentTestGroup?.Loaded == false)
{
ImGui.TextColoredWrapped(ImGuiColors.DalamudGrey, $"Plugin '{this.currentTestGroup.Name}' is unloaded. No tests available.");
ImGui.Spacing();
}
this.DrawResultTable();
ImGui.Spacing();
if (this.currentStep >= this.steps.Count)
if (this.currentStep == null)
{
if (this.selfTestRunning)
{
this.StopTests();
}
if (this.testIndexToResult.Any(x => x.Value.Result == SelfTestStepResult.Fail))
if (this.visibleSteps.Any(test => test.Result == SelfTestStepResult.Fail))
{
ImGui.TextColoredWrapped(ImGuiColors.DalamudRed, "One or more checks failed!"u8);
}
else
else if (this.visibleSteps.All(test => test.Result == SelfTestStepResult.Pass))
{
ImGui.TextColoredWrapped(ImGuiColors.HealerGreen, "All checks passed!"u8);
}
@ -153,30 +179,14 @@ internal class SelfTestWindow : Window
using var resultChild = ImRaii.Child("SelfTestResultChild"u8, ImGui.GetContentRegionAvail());
if (!resultChild) return;
var step = this.steps[this.currentStep];
ImGui.Text($"Current: {step.Name}");
ImGui.Text($"Current: {this.currentStep.Name}");
ImGuiHelpers.ScaledDummy(10);
SelfTestStepResult result;
try
this.currentStep.DrawAndStep();
if (this.currentStep.Result != SelfTestStepResult.Waiting)
{
result = step.RunStep();
}
catch (Exception ex)
{
Log.Error(ex, $"Step failed: {step.Name}");
result = SelfTestStepResult.Fail;
}
if (result != SelfTestStepResult.Waiting)
{
var duration = DateTimeOffset.Now - this.lastTestStart;
this.testIndexToResult[this.currentStep] = (result, duration);
this.currentStep++;
this.scrollToStep = this.currentStep;
this.lastTestStart = DateTimeOffset.Now;
this.MoveToNextTest();
}
}
@ -202,85 +212,62 @@ internal class SelfTestWindow : Window
ImGui.TableSetupScrollFreeze(0, 1);
ImGui.TableHeadersRow();
for (var i = 0; i < this.steps.Count; i++)
foreach (var (step, index) in this.visibleSteps.WithIndex())
{
var step = this.steps[i];
ImGui.TableNextRow();
if (this.selfTestRunning && this.currentStep == i)
if (this.selfTestRunning && this.currentStep == step)
{
ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, ImGui.GetColorU32(ImGuiCol.TableRowBgAlt));
}
ImGui.TableSetColumnIndex(0);
ImGui.AlignTextToFramePadding();
ImGui.Text(i.ToString());
ImGui.Text(index.ToString());
if (this.selfTestRunning && this.scrollToStep == i)
if (this.selfTestRunning && this.scrollToStep == step)
{
ImGui.SetScrollHereY();
this.scrollToStep = -1;
this.scrollToStep = null;
}
ImGui.TableSetColumnIndex(1);
ImGui.AlignTextToFramePadding();
ImGui.Text(step.Name);
if (this.testIndexToResult.TryGetValue(i, out var result))
ImGui.TableSetColumnIndex(2);
ImGui.AlignTextToFramePadding();
switch (step.Result)
{
ImGui.TableSetColumnIndex(2);
ImGui.AlignTextToFramePadding();
switch (result.Result)
{
case SelfTestStepResult.Pass:
ImGui.TextColored(ImGuiColors.HealerGreen, "PASS"u8);
break;
case SelfTestStepResult.Fail:
ImGui.TextColored(ImGuiColors.DalamudRed, "FAIL"u8);
break;
default:
ImGui.TextColored(ImGuiColors.DalamudGrey, "NR"u8);
break;
}
ImGui.TableSetColumnIndex(3);
if (result.Duration.HasValue)
{
ImGui.AlignTextToFramePadding();
ImGui.Text(this.FormatTimeSpan(result.Duration.Value));
}
}
else
{
ImGui.TableSetColumnIndex(2);
ImGui.AlignTextToFramePadding();
if (this.selfTestRunning && this.currentStep == i)
{
case SelfTestStepResult.Pass:
ImGui.TextColored(ImGuiColors.HealerGreen, "PASS"u8);
break;
case SelfTestStepResult.Fail:
ImGui.TextColored(ImGuiColors.DalamudRed, "FAIL"u8);
break;
case SelfTestStepResult.Waiting:
ImGui.TextColored(ImGuiColors.DalamudGrey, "WAIT"u8);
}
else
{
break;
default:
ImGui.TextColored(ImGuiColors.DalamudGrey, "NR"u8);
}
break;
}
ImGui.TableSetColumnIndex(3);
ImGui.TableSetColumnIndex(3);
if (step.Duration.HasValue)
{
ImGui.AlignTextToFramePadding();
if (this.selfTestRunning && this.currentStep == i)
{
ImGui.Text(this.FormatTimeSpan(DateTimeOffset.Now - this.lastTestStart));
}
ImGui.Text(this.FormatTimeSpan(step.Duration.Value));
}
ImGui.TableSetColumnIndex(4);
using var id = ImRaii.PushId($"selfTest{i}");
using var id = ImRaii.PushId($"selfTest{index}");
if (ImGuiComponents.IconButton(FontAwesomeIcon.FastForward))
{
this.StopTests();
this.testIndexToResult.Remove(i);
this.currentStep = i;
this.currentStep = step;
this.currentStep.Reset();
this.selfTestRunning = true;
this.lastTestStart = DateTimeOffset.Now;
}
if (ImGui.IsItemHovered())
@ -293,12 +280,14 @@ internal class SelfTestWindow : Window
private void StopTests()
{
this.selfTestRunning = false;
this.currentStep = null;
this.scrollToStep = null;
foreach (var agingStep in this.steps)
foreach (var agingStep in this.visibleSteps)
{
try
{
agingStep.CleanUp();
agingStep.Finish();
}
catch (Exception ex)
{
@ -307,6 +296,46 @@ internal class SelfTestWindow : Window
}
}
/// <summary>
/// Makes <paramref name="testGroup"/> the active test group.
/// </summary>
/// <param name="testGroup">The test group to make active.</param>
private void SelectTestGroup(SelfTestGroup testGroup)
{
this.currentTestGroup = testGroup;
this.StopTests();
}
/// <summary>
/// Move `currentTest` to the next test. If there are no tests left, set `currentTest` to null.
/// </summary>
private void MoveToNextTest()
{
if (this.currentStep == null)
{
this.currentStep = this.visibleSteps.FirstOrDefault();
return;
}
var currentIndex = this.visibleSteps.IndexOf(this.currentStep);
this.currentStep = this.visibleSteps.ElementAtOrDefault(currentIndex + 1);
}
/// <summary>
/// Draws the unloaded plugin icon with tooltip.
/// </summary>
private void DrawUnloadedIcon()
{
ImGui.PushFont(UiBuilder.IconFont);
ImGui.TextColored(ImGuiColors.DalamudGrey, FontAwesomeIcon.Unlink.ToIconString());
ImGui.PopFont();
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Plugin is unloaded");
}
}
private string FormatTimeSpan(TimeSpan ts)
{
var str = ts.ToString("g", CultureInfo.InvariantCulture);

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Plugin.SelfTest;
using Dalamud.Utility;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -3,6 +3,7 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Aetherytes;
using Dalamud.Plugin.SelfTest;
using Dalamud.Utility;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -2,6 +2,7 @@ using Dalamud.Bindings.ImGui;
using Dalamud.Game.Gui;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,6 +1,7 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Command;
using Dalamud.Interface.Utility;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin.SelfTest;
using Serilog;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -8,6 +8,7 @@ using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.Gui.ContextMenu;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.SelfTest;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Serilog;

View file

@ -0,0 +1,51 @@
using Dalamud.Plugin.SelfTest.Internal;
using Lumina.Excel.Sheets;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;
/// <summary>
/// Class handling Dalamud self-test registration.
/// </summary>
[ServiceManager.EarlyLoadedService]
internal class DalamudSelfTest : IServiceType
{
[ServiceManager.ServiceConstructor]
private DalamudSelfTest(SelfTestRegistry registry)
{
registry.RegisterDalamudSelfTestSteps([
new LoginEventSelfTestStep(),
new WaitFramesSelfTestStep(1000),
new FrameworkTaskSchedulerSelfTestStep(),
new EnterTerritorySelfTestStep(148, "Central Shroud"),
new ItemPayloadSelfTestStep(),
new ContextMenuSelfTestStep(),
new NamePlateSelfTestStep(),
new ActorTableSelfTestStep(),
new FateTableSelfTestStep(),
new AetheryteListSelfTestStep(),
new ConditionSelfTestStep(),
new ToastSelfTestStep(),
new TargetSelfTestStep(),
new KeyStateSelfTestStep(),
new GamepadStateSelfTestStep(),
new ChatSelfTestStep(),
new HoverSelfTestStep(),
new LuminaSelfTestStep<Item>(true),
new LuminaSelfTestStep<Level>(true),
new LuminaSelfTestStep<Lumina.Excel.Sheets.Action>(true),
new LuminaSelfTestStep<Quest>(true),
new LuminaSelfTestStep<TerritoryType>(false),
new AddonLifecycleSelfTestStep(),
new PartyFinderSelfTestStep(),
new HandledExceptionSelfTestStep(),
new DutyStateSelfTestStep(),
new GameConfigSelfTestStep(),
new MarketBoardSelfTestStep(),
new SheetRedirectResolverSelfTestStep(),
new NounProcessorSelfTestStep(),
new SeStringEvaluatorSelfTestStep(),
new CompletionSelfTestStep(),
new LogoutEventSelfTestStep()
]);
}
}

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.DutyState;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Fates;
using Dalamud.Plugin.SelfTest;
using Dalamud.Utility;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,6 +1,7 @@
using System.Threading.Tasks;
using Dalamud.Game;
using Dalamud.Plugin.SelfTest;
using Dalamud.Utility;
using Microsoft.VisualBasic.Logging;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Config;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -2,7 +2,7 @@ using System.Linq;
using Dalamud.Game.ClientState.GamePad;
using Dalamud.Interface.Utility;
using Dalamud.Plugin.SelfTest;
using Lumina.Text.Payloads;
using LSeStringBuilder = Lumina.Text.SeStringBuilder;

View file

@ -1,5 +1,7 @@
using System.Runtime.InteropServices;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;
/// <summary>

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Gui;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,23 +0,0 @@
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;
/// <summary>
/// Interface for test implementations.
/// </summary>
internal interface ISelfTestStep
{
/// <summary>
/// Gets the name of the test.
/// </summary>
public string Name { get; }
/// <summary>
/// Run the test step, once per frame it is active.
/// </summary>
/// <returns>The result of this frame, test is discarded once a result other than <see cref="SelfTestStepResult.Waiting"/> is returned.</returns>
public SelfTestStepResult RunStep();
/// <summary>
/// Clean up this test.
/// </summary>
public void CleanUp();
}

View file

@ -1,6 +1,7 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Gui;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.SelfTest;
using Dalamud.Utility;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,4 +1,5 @@
using Dalamud.Data;
using Dalamud.Plugin.SelfTest;
using Dalamud.Utility;
using Lumina.Excel;

View file

@ -5,6 +5,7 @@ using Dalamud.Bindings.ImGui;
using Dalamud.Game.MarketBoard;
using Dalamud.Game.Network.Structures;
using Dalamud.Interface.Utility;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -4,6 +4,7 @@ using Dalamud.Bindings.ImGui;
using Dalamud.Game.Gui.NamePlate;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -2,6 +2,7 @@ using Dalamud.Bindings.ImGui;
using Dalamud.Game;
using Dalamud.Game.Text.Noun;
using Dalamud.Game.Text.Noun.Enums;
using Dalamud.Plugin.SelfTest;
using LSheets = Lumina.Excel.Sheets;

View file

@ -1,6 +1,7 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Gui.PartyFinder;
using Dalamud.Game.Gui.PartyFinder.Types;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -3,7 +3,7 @@ using Dalamud.Configuration.Internal;
using Dalamud.Game.ClientState;
using Dalamud.Game.Text.Evaluator;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Plugin.SelfTest;
using Lumina.Text.ReadOnly;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -3,6 +3,7 @@ using System.Runtime.InteropServices;
using Dalamud.Bindings.ImGui;
using Dalamud.Game;
using Dalamud.Game.Text.Evaluator.Internal;
using Dalamud.Plugin.SelfTest;
using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Client.UI.Misc;

View file

@ -2,6 +2,7 @@ using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,5 +1,6 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Gui.Toast;
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;

View file

@ -1,3 +1,5 @@
using Dalamud.Plugin.SelfTest;
namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps;
/// <summary>