diff --git a/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml b/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml
index 2c27fdd2ce..fdaa838201 100644
--- a/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml
+++ b/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml
@@ -18,7 +18,7 @@
-
+
diff --git a/Content.Client/Administration/UI/Notes/AdminNotesControl.xaml b/Content.Client/Administration/UI/Notes/AdminNotesControl.xaml
index 326e4bf3a3..09d36af1b0 100644
--- a/Content.Client/Administration/UI/Notes/AdminNotesControl.xaml
+++ b/Content.Client/Administration/UI/Notes/AdminNotesControl.xaml
@@ -5,7 +5,7 @@
-
+
diff --git a/Content.Client/Administration/UI/Notes/NoteEdit.xaml b/Content.Client/Administration/UI/Notes/NoteEdit.xaml
index 72b2c55ce8..793d84113d 100644
--- a/Content.Client/Administration/UI/Notes/NoteEdit.xaml
+++ b/Content.Client/Administration/UI/Notes/NoteEdit.xaml
@@ -3,7 +3,7 @@
Title="Loading..."
MinSize="400 200">
-
+
-
+
diff --git a/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs b/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs
index c8e3afeb22..0c27d9d646 100644
--- a/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs
+++ b/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs
@@ -133,7 +133,7 @@ public sealed partial class NoteEdit : FancyWindow
private bool IsSecret { get; set; }
private NoteType NoteType { get; set; }
- private NoteSeverity? NoteSeverity
+ public NoteSeverity? NoteSeverity
{
get => _noteSeverity;
set
diff --git a/Content.Client/AssemblyInfo.cs b/Content.Client/AssemblyInfo.cs
index 54b2cd50ac..513ab37ab2 100644
--- a/Content.Client/AssemblyInfo.cs
+++ b/Content.Client/AssemblyInfo.cs
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Content.Tests")]
+[assembly: InternalsVisibleTo("Content.IntegrationTests")]
diff --git a/Content.IntegrationTests/Tests/Administration/Logs/LogWindowTest.cs b/Content.IntegrationTests/Tests/Administration/Logs/LogWindowTest.cs
new file mode 100644
index 0000000000..80236c7d90
--- /dev/null
+++ b/Content.IntegrationTests/Tests/Administration/Logs/LogWindowTest.cs
@@ -0,0 +1,60 @@
+using System.Linq;
+using Content.Client.Administration.UI;
+using Content.Client.Administration.UI.CustomControls;
+using Content.Client.Administration.UI.Logs;
+using Content.Client.UserInterface.Controls;
+using Content.Client.UserInterface.Systems.MenuBar.Widgets;
+using Content.IntegrationTests.Tests.Interaction;
+using Content.Server.Administration.Commands;
+using Content.Server.Administration.Logs;
+using Content.Shared.Database;
+
+namespace Content.IntegrationTests.Tests.Administration.Logs;
+
+public sealed class LogWindowTest : InteractionTest
+{
+ protected override PoolSettings Settings => new() { Connected = true, Dirty = true, AdminLogsEnabled = true, DummyTicker = false };
+
+ [Test]
+ public async Task TestAdminLogsWindow()
+ {
+ // First, generate a new log
+ var log = Server.Resolve();
+ var guid = Guid.NewGuid();
+ await Server.WaitPost(() => log.Add(LogType.Unknown, $"{SPlayer} test log 1: {guid}"));
+
+ // Click the admin button in the menu bar
+ await ClickWidgetControl(nameof(GameTopMenuBar.AdminButton));
+ var adminWindow = GetWindow();
+
+ // Find and click the "open logs" button.
+ Assert.That(TryGetControlFromChildren(x => x.Command == OpenAdminLogsCommand.Cmd, adminWindow, out var btn));
+ await ClickControl(btn!);
+ var logWindow = GetWindow();
+
+ // Find the log search field and refresh buttons
+ var search = logWindow.Logs.LogSearch;
+ var refresh = logWindow.Logs.RefreshButton;
+ var cont = logWindow.Logs.LogsContainer;
+
+ // Search for the log we added earlier.
+ await Client.WaitPost(() => search.Text = guid.ToString());
+ await ClickControl(refresh);
+ await RunTicks(5);
+ var searchResult = cont.Children.Where(x => x.Visible && x is AdminLogLabel).Cast().ToArray();
+ Assert.That(searchResult.Length, Is.EqualTo(1));
+ Assert.That(searchResult[0].Log.Message, Contains.Substring($" test log 1: {guid}"));
+
+ // Add a new log
+ guid = Guid.NewGuid();
+ await Server.WaitPost(() => log.Add(LogType.Unknown, $"{SPlayer} test log 2: {guid}"));
+
+ // Update the search and refresh
+ await Client.WaitPost(() => search.Text = guid.ToString());
+ await ClickControl(refresh);
+ await RunTicks(5);
+ searchResult = cont.Children.Where(x => x.Visible && x is AdminLogLabel).Cast().ToArray();
+ Assert.That(searchResult.Length, Is.EqualTo(1));
+ Assert.That(searchResult[0].Log.Message, Contains.Substring($" test log 2: {guid}"));
+ }
+}
diff --git a/Content.IntegrationTests/Tests/Administration/Notes/NotesControlTest.cs b/Content.IntegrationTests/Tests/Administration/Notes/NotesControlTest.cs
new file mode 100644
index 0000000000..c8dd637c05
--- /dev/null
+++ b/Content.IntegrationTests/Tests/Administration/Notes/NotesControlTest.cs
@@ -0,0 +1,56 @@
+using System.Linq;
+using Content.Client.Administration.UI.Bwoink;
+using Content.Client.Administration.UI.CustomControls;
+using Content.Client.Administration.UI.Notes;
+using Content.Client.UserInterface.Controls;
+using Content.Client.UserInterface.Systems.MenuBar.Widgets;
+using Content.IntegrationTests.Tests.Interaction;
+using Content.Shared.Database;
+using Robust.Shared.Utility;
+
+namespace Content.IntegrationTests.Tests.Administration.Notes;
+
+///
+/// Test that the admin notes UI can be used to add a new note.
+///
+public sealed class NotesControlTest : InteractionTest
+{
+ protected override PoolSettings Settings => new() {Connected = true, Dirty = true, AdminLogsEnabled = true, DummyTicker = false};
+
+ [Test]
+ public async Task TestNotesControl()
+ {
+ // Click the ahelp button in the menu bar
+ await ClickWidgetControl(nameof(GameTopMenuBar.AHelpButton));
+ var bwoink = GetWindow();
+
+ // Damn, if only I had an excuse to use bwoink.Bwoink.BwoinkArea
+ var players = bwoink.Bwoink.ChannelSelector.PlayerListContainer;
+
+ // Check that the player is in the menu, and make sure it is selected
+ var entry = players.Data.Cast().Single(x => x.Info.SessionId == ServerSession.UserId);
+ await Client.WaitPost(() => players.Select(entry));
+
+ // Open their notes
+ await ClickControl(bwoink.Bwoink.Notes);
+ var noteCtrl = GetWindow().Notes;
+ Assert.That(noteCtrl.Notes.ChildCount, Is.EqualTo(0));
+
+ // Add a new note
+ await ClickControl(noteCtrl.NewNoteButton);
+ var addNoteWindow = GetWindow();
+ var msg = $"note: {Guid.NewGuid()}";
+ await Client.WaitPost(() => addNoteWindow.NoteTextEdit.TextRope = new Rope.Leaf(msg));
+ addNoteWindow.NoteSeverity = NoteSeverity.None;
+
+ // Have to click submit twice for confirmation?
+ await ClickControl(addNoteWindow.SubmitButton);
+ await ClickControl(addNoteWindow.SubmitButton);
+
+ // Check that the new note exists
+ await RunTicks(5);
+ Assert.That(noteCtrl.Notes.ChildCount, Is.EqualTo(1));
+ var note = (AdminNotesLine)noteCtrl.Notes.Children[0];
+ Assert.That(note.Note.Message, Is.EqualTo(msg));
+ }
+}
diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs
index eff0ed3a0c..4a33fdc03b 100644
--- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs
+++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.cs
@@ -156,10 +156,13 @@ public abstract partial class InteractionTest
- type: CombatMode
";
+ protected static PoolSettings Default => new() { Connected = true, Dirty = true };
+ protected virtual PoolSettings Settings => Default;
+
[SetUp]
public virtual async Task Setup()
{
- Pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true, Dirty = true });
+ Pair = await PoolManager.GetServerClient(Settings);
// server dependencies
SEntMan = Server.ResolveDependency();
diff --git a/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs b/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs
index 1beaaa928e..df437fcc2d 100644
--- a/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs
+++ b/Content.Server/Administration/Commands/OpenAdminLogsCommand.cs
@@ -10,7 +10,8 @@ public sealed class OpenAdminLogsCommand : LocalizedEntityCommands
{
[Dependency] private readonly EuiManager _euiManager = default!;
- public override string Command => "adminlogs";
+ public override string Command => Cmd;
+ public const string Cmd = "adminlogs";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{