using Xunit;
using Terminal.Gui.App;
using Terminal.Gui.ViewBase;
using Terminal.Gui.Views;
namespace Terminal.Gui.ViewTests;
///
/// Tests for Phase 2 of the IRunnable migration: Toplevel, Dialog, MessageBox, and Wizard implementing IRunnable pattern.
/// These tests verify that the migrated components work correctly with the new IRunnable architecture.
///
public class Phase2RunnableMigrationTests
{
[Fact]
public void Toplevel_ImplementsIRunnable()
{
// Arrange
Toplevel toplevel = new ();
// Act & Assert
Assert.IsAssignableFrom (toplevel);
}
[Fact]
public void Dialog_ImplementsIRunnableInt()
{
// Arrange
Dialog dialog = new ();
// Act & Assert
Assert.IsAssignableFrom> (dialog);
}
[Fact]
public void Dialog_Result_DefaultsToNull()
{
// Arrange
Dialog dialog = new ();
// Act & Assert
Assert.Null (dialog.Result);
}
[Fact]
public void Dialog_Result_SetInOnIsRunningChanging()
{
// Arrange
IApplication app = Application.Create ();
app.Init ();
Dialog dialog = new ()
{
Title = "Test Dialog",
Buttons =
[
new Button { Text = "OK" },
new Button { Text = "Cancel" }
]
};
int? extractedResult = null;
// Subscribe to verify Result is set before IsRunningChanged fires
((IRunnable)dialog).IsRunningChanged += (s, e) =>
{
if (!e.Value) // Stopped
{
extractedResult = dialog.Result;
}
};
// Act
// Simulate clicking the first button (index 0)
app.Run (dialog);
dialog.Buttons [0].SetFocus ();
app.RequestStop (dialog);
// Assert
Assert.NotNull (extractedResult);
Assert.Equal (0, extractedResult);
Assert.Equal (0, dialog.Result);
dialog.Dispose ();
app.Shutdown ();
}
[Fact]
public void Dialog_Result_IsNullWhenCanceled()
{
// Arrange
IApplication app = Application.Create ();
app.Init ();
Dialog dialog = new ()
{
Title = "Test Dialog",
Buttons =
[
new Button { Text = "OK" }
]
};
// Act
app.Run (dialog);
// Don't focus any button - simulate cancel (ESC pressed)
app.RequestStop (dialog);
// Assert
Assert.Null (dialog.Result);
dialog.Dispose ();
app.Shutdown ();
}
[Fact]
public void Dialog_Canceled_PropertyMatchesResult()
{
// Arrange
IApplication app = Application.Create ();
app.Init ();
Dialog dialog = new ()
{
Title = "Test Dialog",
Buttons = [new Button { Text = "OK" }]
};
// Act - Cancel the dialog
app.Run (dialog);
app.RequestStop (dialog);
// Assert
Assert.True (dialog.Canceled);
Assert.Null (dialog.Result);
dialog.Dispose ();
app.Shutdown ();
}
[Fact]
public void MessageBox_Query_ReturnsDialogResult()
{
// Arrange
IApplication app = Application.Create ();
app.Init ();
// Act
// MessageBox.Query creates a Dialog internally and returns its Result
// We can't easily test this without actually running the UI, but we can verify the pattern
// Create a Dialog similar to what MessageBox creates
Dialog dialog = new ()
{
Title = "Test",
Text = "Message",
Buttons =
[
new Button { Text = "Yes" },
new Button { Text = "No" }
]
};
app.Run (dialog);
dialog.Buttons [1].SetFocus (); // Focus "No" button (index 1)
app.RequestStop (dialog);
int result = dialog.Result ?? -1;
// Assert
Assert.Equal (1, result);
Assert.Equal (1, dialog.Result);
dialog.Dispose ();
app.Shutdown ();
}
[Fact]
public void MessageBox_Clicked_PropertyUpdated()
{
// Arrange & Act
// MessageBox.Clicked is updated from Dialog.Result for backward compatibility
// Since we can't easily run MessageBox.Query without UI, we verify the pattern is correct
// The implementation should be:
// int result = dialog.Result ?? -1;
// MessageBox.Clicked = result;
// Assert
// This test verifies the property exists and has the expected type
int clicked = MessageBox.Clicked;
Assert.True (clicked is int);
}
[Fact]
public void Wizard_InheritsFromDialog_ImplementsIRunnable()
{
// Arrange
Wizard wizard = new ();
// Act & Assert
Assert.IsAssignableFrom