Files
Terminal.Gui/Tests/UnitTestsParallelizable/Input/InputBindingTests.cs
Copilot f2d260a853 Add TryGetSource extension methods for WeakReference<View> access (#4694)
* Initial plan

* CommandContext infrastructure: WeakReference and extension methods

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Align CommandContext infrastructure with PR #4620

- Update ViewExtensions.cs to use Terminal.Gui.ViewBase namespace
- Update WeakReferenceExtensions.cs to match PR #4620 format
- Change CommandContext constructor to take WeakReference<View>? directly
- Add CommandContext.ToString() implementation
- Update ICommandContext.Source documentation
- Update View.Command.cs to explicitly create WeakReference
- Update Shortcut.cs to handle WeakReference Source
- Update ComboBox.cs Source comparison
- Update Dialog.cs and DialogTResult.cs pattern matching
- Update MenuBar.cs and PopoverMenu.cs to work with WeakReference
- Update ScrollSlider.cs and OptionSelector.cs

Remaining: Fix Examples code and tests

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Fix Examples code for WeakReference Source

- Update UICatalogRunnable.cs to use TryGetTarget for Data access
- Update Menus.cs to use ToIdentifyingString() and TryGetTarget
- Update MouseTester.cs to use ToIdentifyingString() for all Source.Id access

All Examples now build successfully

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Update tests for WeakReference Source

- Fix CommandContextTests.cs to wrap Source in WeakReference
- Fix InputBindingTests.cs to wrap Source in WeakReference
- Update assertions to use TryGetTarget for safe access
- All CommandContext and InputBinding tests pass

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Add TryGetSource extension methods and replace usage

- Add TryGetSource extension to WeakReferenceExtensions.cs
- Add CommandContextExtensions.cs with TryGetSource for ICommandContext
- Replace 14 instances of Source?.TryGetTarget pattern across codebase
- Updated Terminal.Gui files: ComboBox, Dialog, DialogTResult, MenuBar, PopoverMenu, OptionSelector, Shortcut
- Updated Examples files: UICatalogRunnable, Menus
- All files build successfully

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Add tests for TryGetSource extension methods

- Add 6 tests for TryGetSource extension methods
- Test WeakReference<View>.TryGetSource with valid/null references
- Test ICommandContext.TryGetSource with valid/null contexts
- Test pattern matching usage with TryGetSource
- All 23 CommandContext tests pass
- Full test suite: 15,094 passed

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* code cleanup

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: Tig <tig@users.noreply.github.com>
2026-02-06 14:44:04 -07:00

252 lines
7.2 KiB
C#

namespace InputTests;
/// <summary>
/// Tests for <see cref="InputBinding"/> record struct.
/// </summary>
/// <remarks>
/// Copilot generated.
/// </remarks>
public class InputBindingTests
{
#region Constructor Tests
[Fact]
public void Constructor_WithCommands_SetsCommands ()
{
Command [] commands = [Command.Activate, Command.Accept];
InputBinding binding = new (commands);
Assert.Equal (commands, binding.Commands);
Assert.Null (binding.Source);
Assert.Null (binding.Data);
}
[Fact]
public void Constructor_WithCommandsAndSource_SetsBothProperties ()
{
Command [] commands = [Command.Activate];
View source = new () { Id = "sourceView" };
InputBinding binding = new (commands, source);
Assert.Equal (commands, binding.Commands);
Assert.Equal (source, binding.Source);
Assert.Null (binding.Data);
}
[Fact]
public void Constructor_WithAllParameters_SetsAllProperties ()
{
Command [] commands = [Command.Accept];
View source = new () { Id = "sourceView" };
object data = "test data";
InputBinding binding = new (commands, source, data);
Assert.Equal (commands, binding.Commands);
Assert.Equal (source, binding.Source);
Assert.Equal ("test data", binding.Data);
}
#endregion
#region Property Tests
[Fact]
public void Commands_CanBeModified ()
{
InputBinding binding = new ([Command.Activate]);
binding.Commands = [Command.Accept, Command.Cancel];
Assert.Equal (2, binding.Commands.Length);
Assert.Equal (Command.Accept, binding.Commands [0]);
Assert.Equal (Command.Cancel, binding.Commands [1]);
}
[Fact]
public void Source_CanBeModified ()
{
InputBinding binding = new ([Command.Activate]);
View source = new () { Id = "newSource" };
binding.Source = source;
Assert.Equal ("newSource", binding.Source?.Id);
}
[Fact]
public void Data_CanBeModified ()
{
InputBinding binding = new ([Command.Activate]);
binding.Data = 42;
Assert.Equal (42, binding.Data);
}
#endregion
#region IInputBinding Interface Tests
[Fact]
public void ImplementsIInputBinding ()
{
InputBinding binding = new ([Command.Activate]) { Source = new View { Id = "test" }, Data = "data" };
IInputBinding iBinding = binding;
Assert.Equal (binding.Commands, iBinding.Commands);
Assert.Equal (binding.Source, iBinding.Source);
Assert.Equal (binding.Data, iBinding.Data);
}
[Fact]
public void CanBeUsedPolymorphically ()
{
IInputBinding binding = new InputBinding ([Command.Accept], new View { Id = "polymorphic" });
Assert.Single (binding.Commands);
Assert.Equal (Command.Accept, binding.Commands [0]);
Assert.Equal ("polymorphic", binding.Source?.Id);
}
#endregion
#region Pattern Matching Tests
[Fact]
public void PatternMatching_CanDistinguishFromKeyBinding ()
{
IInputBinding inputBinding = new InputBinding ([Command.Activate]);
IInputBinding keyBinding = new KeyBinding ([Command.Activate]) { Key = Key.Enter };
Assert.True (inputBinding is InputBinding);
Assert.False (inputBinding is KeyBinding);
Assert.True (keyBinding is KeyBinding);
Assert.False (keyBinding is InputBinding);
}
[Fact]
public void PatternMatching_CanDistinguishFromMouseBinding ()
{
IInputBinding inputBinding = new InputBinding ([Command.Activate]);
IInputBinding mouseBinding = new MouseBinding ([Command.Activate], MouseFlags.LeftButtonClicked);
Assert.True (inputBinding is InputBinding);
Assert.False (inputBinding is MouseBinding);
Assert.True (mouseBinding is MouseBinding);
Assert.False (mouseBinding is InputBinding);
}
[Fact]
public void PatternMatching_SwitchExpression_Works ()
{
IInputBinding binding = new InputBinding ([Command.Accept], new View { Id = "source" });
string bindingType = binding switch
{
KeyBinding => "key",
MouseBinding => "mouse",
InputBinding => "input",
_ => "unknown"
};
Assert.Equal ("input", bindingType);
}
#endregion
#region CommandContext Integration Tests
[Fact]
public void CanBeUsedWithCommandContext ()
{
View source = new () { Id = "contextSource" };
InputBinding binding = new ([Command.Activate], source, "contextData");
CommandContext ctx = new () { Command = Command.Activate, Source = new WeakReference<View>(source), Binding = binding };
Assert.Equal (Command.Activate, ctx.Command);
Assert.NotNull (ctx.Source);
Assert.True (ctx.Source.TryGetTarget (out View? view));
Assert.Equal (source, view);
Assert.NotNull (ctx.Binding);
if (ctx.Binding is InputBinding ib)
{
Assert.Equal ("contextData", ib.Data);
}
else
{
Assert.Fail ("Binding should be InputBinding");
}
}
[Fact]
public void Binding_Property_ReturnsIInputBinding ()
{
InputBinding binding = new ([Command.Accept]);
CommandContext ctx = new () { Command = Command.Accept, Binding = binding };
// Binding property (from ICommandContext) returns IInputBinding
Assert.NotNull (ctx.Binding);
Assert.IsType<InputBinding> (ctx.Binding);
}
[Fact]
public void PatternMatching_ThroughICommandContext_Works ()
{
InputBinding binding = new ([Command.Accept], new View { Id = "test" });
ICommandContext ctx = new CommandContext { Command = Command.Accept, Binding = binding };
// Can pattern match the binding from the interface
if (ctx.Binding is InputBinding ib)
{
Assert.Equal ("test", ib.Source?.Id);
}
else
{
Assert.Fail ("Should be able to pattern match InputBinding from ICommandContext.Binding");
}
}
#endregion
#region Record Equality Tests
[Fact]
public void RecordEquality_SameValues_AreEqual ()
{
Command [] commands = [Command.Activate];
View source = new () { Id = "source" };
InputBinding binding1 = new (commands, source, "data");
InputBinding binding2 = new (commands, source, "data");
Assert.Equal (binding1, binding2);
}
[Fact]
public void RecordEquality_DifferentCommands_AreNotEqual ()
{
InputBinding binding1 = new ([Command.Activate]);
InputBinding binding2 = new ([Command.Accept]);
Assert.NotEqual (binding1, binding2);
}
[Fact]
public void RecordEquality_DifferentSources_AreNotEqual ()
{
InputBinding binding1 = new ([Command.Activate], new View { Id = "source1" });
InputBinding binding2 = new ([Command.Activate], new View { Id = "source2" });
Assert.NotEqual (binding1, binding2);
}
#endregion
}