F1: the telemetry session id is new at every login. The original made one per load of its assembly and its loader reloaded it at every login; the backend counts new kills per (session id, character), so reusing one id across a relog under-counted kills until the reset counter passed the old total. F5/F6: .NET Framework never wrote a negative zero, and its fixed-point formats (F7, F2, F0) rounded at fifteen significant digits, half away from zero. Spawn and portal coordinates, kills_per_hour and the !report line now format that way; the round-trip converter maps -0 to 0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
114 lines
3.8 KiB
C#
114 lines
3.8 KiB
C#
using AcDream.Plugin.Abstractions;
|
|
using OpenAC.MosswartMassacre.Tests.Fakes;
|
|
|
|
namespace OpenAC.MosswartMassacre.Tests;
|
|
|
|
public sealed class PluginLifecycleTests
|
|
{
|
|
[Fact]
|
|
public void Enable_registers_the_mm_verb_and_login_loads_that_characters_settings()
|
|
{
|
|
var host = new FakeHost();
|
|
host.Automation.IsAvailable = true;
|
|
host.Automation.Character.Name = "Mossy";
|
|
var plugin = new MosswartMassacrePlugin();
|
|
plugin.Initialize(host);
|
|
plugin.Enable();
|
|
|
|
Assert.True(host.Commands.Handlers.ContainsKey("mm"));
|
|
|
|
host.Automation.Character.IsInWorld = true;
|
|
host.Events.RaiseLoginComplete();
|
|
|
|
Assert.True(plugin.Context!.IsLoggedIn);
|
|
Assert.Equal("Mossy", plugin.Context.CharacterName);
|
|
Assert.Contains("[Mosswart Massacre] Mosswart Massacre has started!", host.ChatLines);
|
|
Assert.NotNull(host.Storage.ReadText("settings.json"));
|
|
|
|
plugin.Disable();
|
|
Assert.False(host.Commands.Handlers.ContainsKey("mm"));
|
|
}
|
|
|
|
[Fact]
|
|
public void A_second_login_is_a_relog_that_switches_character()
|
|
{
|
|
using var harness = new PluginHarness("Mossy");
|
|
harness.Login();
|
|
harness.Host.Automation.Character.Name = "Horan";
|
|
|
|
harness.Plugin.OnLogin();
|
|
|
|
Assert.Equal("Horan", harness.Context.CharacterName);
|
|
Assert.Equal("Horan", harness.Context.Settings.CharacterName);
|
|
}
|
|
|
|
[Fact]
|
|
public void Each_login_gets_a_new_telemetry_session_id()
|
|
{
|
|
// The backend counts new kills per (session id, character); the kill
|
|
// counter restarts at every login, so the id must too.
|
|
using var harness = new PluginHarness("Mossy");
|
|
harness.Login();
|
|
string first = harness.Context.TelemetrySessionId;
|
|
|
|
harness.Plugin.OnLogin();
|
|
|
|
Assert.NotEqual(first, harness.Context.TelemetrySessionId);
|
|
Assert.Equal(32, harness.Context.TelemetrySessionId.Length);
|
|
}
|
|
|
|
[Fact]
|
|
public void Mm_without_a_subcommand_prints_usage_and_unknown_is_reported()
|
|
{
|
|
using var harness = new PluginHarness();
|
|
harness.Login();
|
|
|
|
harness.Context.Commands.Dispatch("");
|
|
harness.Context.Commands.Dispatch("bogus");
|
|
|
|
Assert.Contains("[Mosswart Massacre] Usage: /mm <command>. Try /mm help", harness.ChatLines);
|
|
Assert.Contains("[Mosswart Massacre] Unknown /mm command: bogus. Try /mm help", harness.ChatLines);
|
|
}
|
|
|
|
[Fact]
|
|
public void Ws_secret_and_url_are_stored_in_settings_not_code()
|
|
{
|
|
using var harness = new PluginHarness();
|
|
harness.Login();
|
|
|
|
harness.Context.Commands.Dispatch("ws secret abc 123");
|
|
harness.Context.Commands.Dispatch("ws url wss://example.test/websocket/");
|
|
|
|
Assert.Equal("abc 123", harness.Context.Settings.Current.BackendSecret);
|
|
Assert.Equal("wss://example.test/websocket/", harness.Context.Settings.Current.BackendUrl);
|
|
string stored = harness.Host.Storage.ReadText("settings.json")!;
|
|
Assert.Contains("\"backend_secret\": \"abc 123\"", stored);
|
|
}
|
|
|
|
[Fact]
|
|
public void Frames_are_not_sent_while_streaming_is_off()
|
|
{
|
|
using var harness = new PluginHarness(webSocketEnabled: false);
|
|
harness.Login();
|
|
|
|
harness.Context.Send(new { type = "x" });
|
|
|
|
Assert.Empty(harness.Frames);
|
|
}
|
|
|
|
[Fact]
|
|
public void The_mm_verb_routes_through_the_host_command_registry()
|
|
{
|
|
var host = new FakeHost();
|
|
host.Automation.IsAvailable = true;
|
|
host.Automation.Character.Name = "Mossy";
|
|
var plugin = new MosswartMassacrePlugin();
|
|
plugin.Initialize(host);
|
|
plugin.Enable();
|
|
|
|
host.Commands.Handlers["mm"](new PluginCommand("mm", "help", "/mm help"));
|
|
|
|
Assert.Contains("[Mosswart Massacre] Mosswart Massacre Commands:", host.ChatLines);
|
|
plugin.Disable();
|
|
}
|
|
}
|