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

@ -0,0 +1,51 @@
using System.Collections.Generic;
using Dalamud.IoC;
using Dalamud.IoC.Internal;
using Dalamud.Plugin.Internal.Types;
namespace Dalamud.Plugin.SelfTest.Internal;
/// <summary>
/// Plugin-scoped version of SelfTestRegistry.
/// </summary>
[PluginInterface]
[ServiceManager.ScopedService]
[ResolveVia<ISelfTestRegistry>]
internal class SelfTestRegistryPluginScoped : ISelfTestRegistry, IInternalDisposableService
{
[ServiceManager.ServiceDependency]
private readonly SelfTestRegistry selfTestRegistry = Service<SelfTestRegistry>.Get();
private readonly LocalPlugin plugin;
/// <summary>
/// Initializes a new instance of the <see cref="SelfTestRegistryPluginScoped"/> class.
/// </summary>
/// <param name="plugin">The plugin this service belongs to.</param>
[ServiceManager.ServiceConstructor]
public SelfTestRegistryPluginScoped(LocalPlugin plugin)
{
this.plugin = plugin;
}
/// <summary>
/// Gets the plugin name.
/// </summary>
public string PluginName { get; private set; }
/// <summary>
/// Registers test steps for this plugin.
/// </summary>
/// <param name="steps">The test steps to register.</param>
public void RegisterTestSteps(IEnumerable<ISelfTestStep> steps)
{
this.selfTestRegistry.RegisterPluginSelfTestSteps(this.plugin, steps);
}
/// <inheritdoc/>
void IInternalDisposableService.DisposeService()
{
this.selfTestRegistry.UnregisterPluginSelfTestSteps(this.plugin);
}
}