using AcDream.Core.Chat;
using AcDream.UI.Abstractions.Panels.Chat;
namespace AcDream.UI.Abstractions.Tests.Panels.Chat;
///
/// Phase K.2 — Tab fires ,
/// which calls . The chat panel honors
/// the request on the very next by emitting
/// a SetKeyboardFocusHere immediately before the input field. After
/// it fires once, subsequent renders without another FocusInput
/// call must not re-fire (one-shot semantics) — otherwise the chat field
/// would steal focus on every frame and the user could never click out.
///
public sealed class ChatPanelFocusTests
{
private sealed class NullBus : AcDream.UI.Abstractions.ICommandBus
{
public void Publish(T command) where T : notnull { }
}
[Fact]
public void FocusInput_NextRender_EmitsSetKeyboardFocusHereBeforeInput()
{
var panel = new ChatPanel(new ChatVM(new ChatLog()));
var renderer = new FakePanelRenderer();
panel.FocusInput();
panel.Render(new PanelContext(0.016f, new NullBus()), renderer);
// Find the SetKeyboardFocusHere call; it must come before the
// InputTextSubmit call so ImGui applies the focus to that widget.
int focusIdx = -1, inputIdx = -1;
for (int i = 0; i < renderer.Calls.Count; i++)
{
if (renderer.Calls[i].Method == "SetKeyboardFocusHere") focusIdx = i;
else if (renderer.Calls[i].Method == "InputTextSubmit") inputIdx = i;
}
Assert.True(focusIdx >= 0, "ChatPanel must call SetKeyboardFocusHere when FocusInput requested.");
Assert.True(inputIdx >= 0, "ChatPanel must still render the InputTextSubmit field.");
Assert.True(focusIdx < inputIdx, "SetKeyboardFocusHere must precede the InputTextSubmit it targets.");
}
[Fact]
public void Render_WithoutFocusInputCall_DoesNotEmitSetKeyboardFocusHere()
{
var panel = new ChatPanel(new ChatVM(new ChatLog()));
var renderer = new FakePanelRenderer();
panel.Render(new PanelContext(0.016f, new NullBus()), renderer);
Assert.DoesNotContain(renderer.Calls, c => c.Method == "SetKeyboardFocusHere");
}
[Fact]
public void FocusInput_OnlyAffectsTheNextRender_OneShot()
{
var panel = new ChatPanel(new ChatVM(new ChatLog()));
// Frame 1 — FocusInput requested → expect a SetKeyboardFocusHere.
var r1 = new FakePanelRenderer();
panel.FocusInput();
panel.Render(new PanelContext(0.016f, new NullBus()), r1);
Assert.Contains(r1.Calls, c => c.Method == "SetKeyboardFocusHere");
// Frame 2 — no further FocusInput call → must NOT re-fire.
var r2 = new FakePanelRenderer();
panel.Render(new PanelContext(0.016f, new NullBus()), r2);
Assert.DoesNotContain(r2.Calls, c => c.Method == "SetKeyboardFocusHere");
}
}