The backend's quest panel shows the stipend, blank aug gem and insatiable jaw timers from the `quest` frame, so the port reads /myquests the way the original did (a three-second window of chat lines matched by its regex) and streams the three priority stamps every 30 s with the same five-field frame and the same countdown strings. The name table is copied as it was, so the duplicate insatiableeaterjaw entry still resolves to the later name. Timers run on the tick scheduler instead of thread-pool timers. The session tests clear the login-time /myquests before counting the commands the backend ran. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
121 lines
4.3 KiB
C#
121 lines
4.3 KiB
C#
using Newtonsoft.Json.Linq;
|
|
|
|
namespace OpenAC.MosswartMassacre.Tests.Backend;
|
|
|
|
public sealed class BackendSessionTests
|
|
{
|
|
[Fact]
|
|
public void A_command_for_this_character_runs_as_typed_on_the_next_tick()
|
|
{
|
|
using var harness = new PluginHarness("Mossy");
|
|
harness.Login();
|
|
// Login itself submits /myquests; these tests count only what the backend ran.
|
|
harness.Host.Automation.Chat.Submitted.Clear();
|
|
|
|
harness.Receive("{\"player_name\":\"mossy\",\"command\":\"/a hello\"}");
|
|
Assert.Empty(harness.Host.Automation.Chat.Submitted);
|
|
|
|
harness.Tick(0.01);
|
|
|
|
Assert.Equal(["/a hello"], harness.Host.Automation.Chat.Submitted);
|
|
}
|
|
|
|
[Fact]
|
|
public void A_command_for_another_character_is_ignored()
|
|
{
|
|
using var harness = new PluginHarness("Mossy");
|
|
harness.Login();
|
|
// Login itself submits /myquests; these tests count only what the backend ran.
|
|
harness.Host.Automation.Chat.Submitted.Clear();
|
|
|
|
harness.Receive("{\"player_name\":\"Horan\",\"command\":\"/a hello\"}");
|
|
harness.Tick(0.01);
|
|
|
|
Assert.Empty(harness.Host.Automation.Chat.Submitted);
|
|
}
|
|
|
|
[Fact]
|
|
public void Commands_run_one_per_tick_in_arrival_order()
|
|
{
|
|
using var harness = new PluginHarness("Mossy");
|
|
harness.Login();
|
|
// Login itself submits /myquests; these tests count only what the backend ran.
|
|
harness.Host.Automation.Chat.Submitted.Clear();
|
|
|
|
harness.Receive("{\"player_name\":\"Mossy\",\"command\":\"/one\"}");
|
|
harness.Receive("{\"player_name\":\"Mossy\",\"command\":\"/two\"}");
|
|
harness.Tick(0.01);
|
|
Assert.Equal(["/one"], harness.Host.Automation.Chat.Submitted);
|
|
harness.Tick(0.01);
|
|
Assert.Equal(["/one", "/two"], harness.Host.Automation.Chat.Submitted);
|
|
}
|
|
|
|
[Fact]
|
|
public void Radar_commands_toggle_the_radar_instead_of_chat()
|
|
{
|
|
using var harness = new PluginHarness("Mossy");
|
|
harness.Login();
|
|
// Login itself submits /myquests; these tests count only what the backend ran.
|
|
harness.Host.Automation.Chat.Submitted.Clear();
|
|
var toggles = new List<bool>();
|
|
harness.Session.RadarToggle = on => toggles.Add(on);
|
|
|
|
harness.Receive("{\"player_name\":\"Mossy\",\"command\":\"start_radar\"}");
|
|
harness.Receive("{\"player_name\":\"Mossy\",\"command\":\"stop_radar\"}");
|
|
harness.Tick(0.01);
|
|
harness.Tick(0.01);
|
|
|
|
Assert.Equal([true, false], toggles);
|
|
Assert.Empty(harness.Host.Automation.Chat.Submitted);
|
|
}
|
|
|
|
[Fact]
|
|
public void Share_frames_go_to_the_share_handlers_whoever_they_name()
|
|
{
|
|
using var harness = new PluginHarness("Mossy");
|
|
var seen = new List<string>();
|
|
harness.Session.AddShareHandler(new RecordingShareHandler(seen));
|
|
harness.Login();
|
|
// Login itself submits /myquests; these tests count only what the backend ran.
|
|
harness.Host.Automation.Chat.Submitted.Clear();
|
|
|
|
harness.Receive("{\"type\":\"share_vital_update\",\"character_name\":\"Horan\"}");
|
|
|
|
Assert.Equal(["share_vital_update"], seen);
|
|
harness.Tick(0.01);
|
|
Assert.Empty(harness.Host.Automation.Chat.Submitted);
|
|
}
|
|
|
|
[Fact]
|
|
public void Malformed_frames_are_skipped()
|
|
{
|
|
using var harness = new PluginHarness("Mossy");
|
|
harness.Login();
|
|
// Login itself submits /myquests; these tests count only what the backend ran.
|
|
harness.Host.Automation.Chat.Submitted.Clear();
|
|
|
|
harness.Receive("not json");
|
|
harness.Receive("[1,2,3]");
|
|
harness.Tick(0.01);
|
|
|
|
Assert.Empty(harness.Host.Automation.Chat.Submitted);
|
|
}
|
|
|
|
[Fact]
|
|
public void Connecting_sets_the_per_connection_session_id()
|
|
{
|
|
using var harness = new PluginHarness("Mossy");
|
|
harness.Login();
|
|
// Login itself submits /myquests; these tests count only what the backend ran.
|
|
harness.Host.Automation.Chat.Submitted.Clear();
|
|
|
|
harness.Session.OnConnected(new DateTime(2026, 9, 25, 8, 5, 9, DateTimeKind.Utc));
|
|
|
|
Assert.Equal("Mossy-20260925-080509", harness.Context.ConnectionSessionId);
|
|
}
|
|
|
|
private sealed class RecordingShareHandler(List<string> seen) : IShareFrameHandler
|
|
{
|
|
public void HandleShareFrame(string type, JObject frame) => seen.Add(type);
|
|
}
|
|
}
|