@ -2,15 +2,21 @@
using System.Collections.Generic ;
using System.Text ;
using System.Windows.Input ;
using Avalonia.Collections ;
using Avalonia.Controls.Primitives ;
using Avalonia.Data ;
using Avalonia.Input ;
using Avalonia.Platform ;
using Avalonia.UnitTests ;
using Moq ;
using Xunit ;
namespace Avalonia.Controls.UnitTests
{
public class MenuItemTests
{
private Mock < IPopupImpl > popupImpl ;
[Fact]
public void Header_Of_Minus_Should_Apply_Separator_Pseudoclass ( )
{
@ -79,7 +85,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void MenuItem_Is_Enabled_When_Bound_Command_Is_Added ( )
public void MenuItem_Is_Enabled_When_Added_To_Logical_Tree_And_ Bound_Command_Is_Added ( )
{
var viewModel = new
{
@ -91,7 +97,8 @@ namespace Avalonia.Controls.UnitTests
DataContext = new object ( ) ,
[!MenuItem.CommandProperty] = new Binding ( "Command" ) ,
} ;
var root = new TestRoot { Child = target } ;
Assert . True ( target . IsEnabled ) ;
Assert . False ( target . IsEffectivelyEnabled ) ;
@ -158,10 +165,11 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void MenuItem_Invokes_CanExecute_When_CommandParameter_Changed ( )
public void MenuItem_Invokes_CanExecute_When_Added_To_Logical_Tree_And_ CommandParameter_Changed ( )
{
var command = new TestCommand ( p = > p is bool value & & value ) ;
var target = new MenuItem { Command = command } ;
var root = new TestRoot { Child = target } ;
target . CommandParameter = true ;
Assert . True ( target . IsEffectivelyEnabled ) ;
@ -169,6 +177,151 @@ namespace Avalonia.Controls.UnitTests
target . CommandParameter = false ;
Assert . False ( target . IsEffectivelyEnabled ) ;
}
[Fact]
public void MenuItem_Does_Not_Invoke_CanExecute_When_ContextMenu_Closed ( )
{
using ( Application ( ) )
{
var canExecuteCallCount = 0 ;
var command = new TestCommand ( _ = >
{
canExecuteCallCount + + ;
return true ;
} ) ;
var target = new MenuItem ( ) ;
var contextMenu = new ContextMenu { Items = new AvaloniaList < MenuItem > { target } } ;
var window = new Window { Content = new Panel { ContextMenu = contextMenu } } ;
window . ApplyTemplate ( ) ;
window . Presenter . ApplyTemplate ( ) ;
Assert . True ( target . IsEffectivelyEnabled ) ;
target . Command = command ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
target . CommandParameter = false ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
command . RaiseCanExecuteChanged ( ) ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
contextMenu . Open ( ) ;
Assert . Equal ( 2 , canExecuteCallCount ) ; //2 because popup is changing logical child
command . RaiseCanExecuteChanged ( ) ;
Assert . Equal ( 3 , canExecuteCallCount ) ;
target . CommandParameter = true ;
Assert . Equal ( 4 , canExecuteCallCount ) ;
}
}
[Fact]
public void MenuItem_Does_Not_Invoke_CanExecute_When_MenuFlyout_Closed ( )
{
using ( Application ( ) )
{
var canExecuteCallCount = 0 ;
var command = new TestCommand ( _ = >
{
canExecuteCallCount + + ;
return true ;
} ) ;
var target = new MenuItem ( ) ;
var flyout = new MenuFlyout { Items = new AvaloniaList < MenuItem > { target } } ;
var button = new Button { Flyout = flyout } ;
var window = new Window { Content = button } ;
window . ApplyTemplate ( ) ;
window . Presenter . ApplyTemplate ( ) ;
Assert . True ( target . IsEffectivelyEnabled ) ;
target . Command = command ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
target . CommandParameter = false ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
command . RaiseCanExecuteChanged ( ) ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
flyout . ShowAt ( button ) ;
Assert . Equal ( 2 , canExecuteCallCount ) ;
command . RaiseCanExecuteChanged ( ) ;
Assert . Equal ( 3 , canExecuteCallCount ) ;
target . CommandParameter = true ;
Assert . Equal ( 4 , canExecuteCallCount ) ;
}
}
[Fact]
public void MenuItem_Does_Not_Invoke_CanExecute_When_Parent_MenuItem_Closed ( )
{
using ( Application ( ) )
{
var canExecuteCallCount = 0 ;
var command = new TestCommand ( _ = >
{
canExecuteCallCount + + ;
return true ;
} ) ;
var target = new MenuItem ( ) ;
var parentMenuItem = new MenuItem { Items = new AvaloniaList < MenuItem > { target } } ;
var contextMenu = new ContextMenu { Items = new AvaloniaList < MenuItem > { parentMenuItem } } ;
var window = new Window { Content = new Panel { ContextMenu = contextMenu } } ;
window . ApplyTemplate ( ) ;
window . Presenter . ApplyTemplate ( ) ;
contextMenu . Open ( ) ;
Assert . True ( target . IsEffectivelyEnabled ) ;
target . Command = command ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
target . CommandParameter = false ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
command . RaiseCanExecuteChanged ( ) ;
Assert . Equal ( 0 , canExecuteCallCount ) ;
try
{
parentMenuItem . IsSubMenuOpen = true ;
}
catch ( InvalidOperationException )
{
//popup host creation failed exception
}
Assert . Equal ( 1 , canExecuteCallCount ) ;
command . RaiseCanExecuteChanged ( ) ;
Assert . Equal ( 2 , canExecuteCallCount ) ;
target . CommandParameter = true ;
Assert . Equal ( 3 , canExecuteCallCount ) ;
}
}
private IDisposable Application ( )
{
var screen = new PixelRect ( new PixelPoint ( ) , new PixelSize ( 1 0 0 , 1 0 0 ) ) ;
var screenImpl = new Mock < IScreenImpl > ( ) ;
screenImpl . Setup ( x = > x . ScreenCount ) . Returns ( 1 ) ;
screenImpl . Setup ( X = > X . AllScreens ) . Returns ( new [ ] { new Screen ( 1 , screen , screen , true ) } ) ;
var windowImpl = MockWindowingPlatform . CreateWindowMock ( ) ;
popupImpl = MockWindowingPlatform . CreatePopupMock ( windowImpl . Object ) ;
popupImpl . SetupGet ( x = > x . RenderScaling ) . Returns ( 1 ) ;
windowImpl . Setup ( x = > x . CreatePopup ( ) ) . Returns ( popupImpl . Object ) ;
windowImpl . Setup ( x = > x . Screen ) . Returns ( screenImpl . Object ) ;
var services = TestServices . StyledWindow . With (
inputManager : new InputManager ( ) ,
windowImpl : windowImpl . Object ,
windowingPlatform : new MockWindowingPlatform ( ( ) = > windowImpl . Object , x = > popupImpl . Object ) ) ;
return UnitTestApplication . Start ( services ) ;
}
private class TestCommand : ICommand
{
@ -198,6 +351,8 @@ namespace Avalonia.Controls.UnitTests
public bool CanExecute ( object parameter ) = > _ canExecute ( parameter ) ;
public void Execute ( object parameter ) = > _ execute ( parameter ) ;
public void RaiseCanExecuteChanged ( ) = > _ canExecuteChanged ? . Invoke ( this , EventArgs . Empty ) ;
}
}
}