csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
578 lines
19 KiB
578 lines
19 KiB
using Avalonia.Input;
|
|
using Avalonia.UnitTests;
|
|
using Avalonia.VisualTree;
|
|
using Avalonia.Interactivity;
|
|
using Avalonia.Layout;
|
|
using Avalonia.Controls.Primitives;
|
|
using Avalonia.Controls.Templates;
|
|
using System.Linq;
|
|
using Xunit;
|
|
|
|
namespace Avalonia.Controls.UnitTests
|
|
{
|
|
public class PipsPagerTests : ScopedTestBase
|
|
{
|
|
[Fact]
|
|
public void NumberOfPages_Should_Update_Pips()
|
|
{
|
|
var target = new PipsPager();
|
|
|
|
target.NumberOfPages = 5;
|
|
|
|
Assert.Equal(5, target.TemplateSettings.Pips.Count);
|
|
Assert.Equal(1, target.TemplateSettings.Pips[0]);
|
|
Assert.Equal(5, target.TemplateSettings.Pips[4]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Decreasing_NumberOfPages_Should_Update_Pips()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 5;
|
|
|
|
target.NumberOfPages = 3;
|
|
|
|
Assert.Equal(3, target.TemplateSettings.Pips.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Decreasing_NumberOfPages_Should_Update_SelectedPageIndex()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 5;
|
|
target.SelectedPageIndex = 4;
|
|
|
|
target.NumberOfPages = 3;
|
|
|
|
Assert.Equal(2, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectedPageIndex_Should_Be_Clamped_To_Zero()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 5;
|
|
|
|
target.SelectedPageIndex = -1;
|
|
|
|
Assert.Equal(0, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectedPageIndex_Change_Should_Raise_Event()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 5;
|
|
var raised = false;
|
|
target.SelectedIndexChanged += (s, e) => raised = true;
|
|
|
|
target.SelectedPageIndex = 2;
|
|
|
|
Assert.True(raised);
|
|
}
|
|
|
|
[Fact]
|
|
public void Next_Button_Should_Increment_Index()
|
|
{
|
|
using var unittestApplication = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 5,
|
|
SelectedPageIndex = 1,
|
|
IsNextButtonVisible = true,
|
|
Template = GetTemplate()
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
var nextButton = target.GetVisualDescendants().OfType<Button>().FirstOrDefault(b => b.Name == "PART_NextButton");
|
|
Assert.NotNull(nextButton);
|
|
|
|
nextButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
|
|
|
|
Assert.Equal(2, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Previous_Button_Should_Decrement_Index()
|
|
{
|
|
using var unittestApplication = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 5,
|
|
SelectedPageIndex = 3,
|
|
IsPreviousButtonVisible = true,
|
|
Template = GetTemplate()
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
var prevButton = target.GetVisualDescendants().OfType<Button>().FirstOrDefault(b => b.Name == "PART_PreviousButton");
|
|
Assert.NotNull(prevButton);
|
|
|
|
prevButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
|
|
|
|
Assert.Equal(2, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Keyboard_Navigation_Should_Work()
|
|
{
|
|
using var unittestApplication = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 5,
|
|
SelectedPageIndex = 1,
|
|
Orientation = Orientation.Horizontal
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
target.RaiseEvent(new KeyEventArgs { Key = Key.Right, RoutedEvent = InputElement.KeyDownEvent });
|
|
Assert.Equal(2, target.SelectedPageIndex);
|
|
|
|
target.RaiseEvent(new KeyEventArgs { Key = Key.Left, RoutedEvent = InputElement.KeyDownEvent });
|
|
Assert.Equal(1, target.SelectedPageIndex);
|
|
|
|
target.Orientation = Orientation.Vertical;
|
|
|
|
target.RaiseEvent(new KeyEventArgs { Key = Key.Down, RoutedEvent = InputElement.KeyDownEvent });
|
|
Assert.Equal(2, target.SelectedPageIndex);
|
|
|
|
target.RaiseEvent(new KeyEventArgs { Key = Key.Up, RoutedEvent = InputElement.KeyDownEvent });
|
|
Assert.Equal(1, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Orientation_PseudoClasses_Should_Be_Set()
|
|
{
|
|
var target = new PipsPager();
|
|
|
|
target.Orientation = Orientation.Horizontal;
|
|
Assert.True(target.Classes.Contains(":horizontal"));
|
|
Assert.False(target.Classes.Contains(":vertical"));
|
|
|
|
target.Orientation = Orientation.Vertical;
|
|
Assert.False(target.Classes.Contains(":horizontal"));
|
|
Assert.True(target.Classes.Contains(":vertical"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Clamping_Logic_Works()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 5;
|
|
|
|
target.SelectedPageIndex = 10;
|
|
Assert.Equal(4, target.SelectedPageIndex);
|
|
|
|
target.SelectedPageIndex = -5;
|
|
Assert.Equal(0, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Manual_Button_Visibility_Should_Be_Respected()
|
|
{
|
|
using var unittestApplication = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 5,
|
|
IsPreviousButtonVisible = false,
|
|
IsNextButtonVisible = false,
|
|
Template = GetTemplate()
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
Assert.False(target.IsPreviousButtonVisible);
|
|
Assert.False(target.IsNextButtonVisible);
|
|
|
|
target.IsPreviousButtonVisible = true;
|
|
target.IsNextButtonVisible = true;
|
|
Assert.True(target.IsPreviousButtonVisible);
|
|
Assert.True(target.IsNextButtonVisible);
|
|
}
|
|
|
|
[Fact]
|
|
public void Rapid_Page_Changes_Should_Maintain_Integrity()
|
|
{
|
|
var target = new PipsPager { NumberOfPages = 100 };
|
|
var list = new System.Collections.Generic.List<int>();
|
|
target.SelectedIndexChanged += (s, e) => list.Add(e.NewIndex);
|
|
|
|
for (int i = 1; i <= 50; i++)
|
|
{
|
|
target.SelectedPageIndex = i;
|
|
}
|
|
|
|
Assert.Equal(50, list.Count);
|
|
Assert.Equal(50, target.SelectedPageIndex);
|
|
Assert.Equal(50, list.Last());
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectedIndexChanged_Event_Should_Have_Correct_Args()
|
|
{
|
|
var target = new PipsPager { NumberOfPages = 5, SelectedPageIndex = 1 };
|
|
int oldIdx = -1;
|
|
int newIdx = -1;
|
|
target.SelectedIndexChanged += (s, e) =>
|
|
{
|
|
oldIdx = e.OldIndex;
|
|
newIdx = e.NewIndex;
|
|
};
|
|
|
|
target.SelectedPageIndex = 3;
|
|
Assert.Equal(1, oldIdx);
|
|
Assert.Equal(3, newIdx);
|
|
}
|
|
|
|
[Fact]
|
|
public void Pager_Size_Should_Update_Based_On_Orientation_And_MaxVisiblePips()
|
|
{
|
|
using var unittestApplication = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 10,
|
|
MaxVisiblePips = 5,
|
|
Orientation = Orientation.Horizontal,
|
|
Template = GetTemplate()
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
var pipsList = target.GetVisualDescendants().OfType<ListBox>().First(i => i.Name == "PART_PipsPagerList");
|
|
|
|
Assert.Equal(60, pipsList.Width);
|
|
|
|
target.Orientation = Orientation.Vertical;
|
|
Assert.Equal(60, pipsList.Height);
|
|
}
|
|
|
|
[Fact]
|
|
public void NumberOfPages_Reduction_Should_Clamp_SelectedPageIndex()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 10;
|
|
target.SelectedPageIndex = 8;
|
|
|
|
target.NumberOfPages = 5;
|
|
Assert.Equal(4, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Page_PseudoClasses_Should_Be_Set()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 5;
|
|
|
|
target.SelectedPageIndex = 0;
|
|
Assert.True(target.Classes.Contains(":first-page"));
|
|
Assert.False(target.Classes.Contains(":last-page"));
|
|
|
|
target.SelectedPageIndex = 2;
|
|
Assert.False(target.Classes.Contains(":first-page"));
|
|
Assert.False(target.Classes.Contains(":last-page"));
|
|
|
|
target.SelectedPageIndex = 4;
|
|
Assert.False(target.Classes.Contains(":first-page"));
|
|
Assert.True(target.Classes.Contains(":last-page"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Navigation_Buttons_IsEnabled_Should_Update()
|
|
{
|
|
using var unittestApplication = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 3,
|
|
Template = GetTemplate()
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
var prevButton = target.GetVisualDescendants().OfType<Button>().First(b => b.Name == "PART_PreviousButton");
|
|
var nextButton = target.GetVisualDescendants().OfType<Button>().First(b => b.Name == "PART_NextButton");
|
|
|
|
target.SelectedPageIndex = 0;
|
|
Assert.False(prevButton.IsEnabled);
|
|
Assert.True(nextButton.IsEnabled);
|
|
|
|
target.SelectedPageIndex = 1;
|
|
Assert.True(prevButton.IsEnabled);
|
|
Assert.True(nextButton.IsEnabled);
|
|
|
|
target.SelectedPageIndex = 2;
|
|
Assert.True(prevButton.IsEnabled);
|
|
Assert.False(nextButton.IsEnabled);
|
|
}
|
|
|
|
[Fact]
|
|
public void Horizontal_Keyboard_Navigation_Should_Work()
|
|
{
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 5,
|
|
SelectedPageIndex = 1,
|
|
Orientation = Orientation.Horizontal
|
|
};
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.Right });
|
|
Assert.Equal(2, target.SelectedPageIndex);
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.Left });
|
|
Assert.Equal(1, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Vertical_Keyboard_Navigation_Should_Work()
|
|
{
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 5,
|
|
SelectedPageIndex = 1,
|
|
Orientation = Orientation.Vertical
|
|
};
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.Down });
|
|
Assert.Equal(2, target.SelectedPageIndex);
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.Up });
|
|
Assert.Equal(1, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void NumberOfPages_Zero_Should_Clamp_Index()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 0;
|
|
target.SelectedPageIndex = 5;
|
|
|
|
Assert.Equal(0, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Home_Key_Should_Navigate_To_First_Page()
|
|
{
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 10,
|
|
SelectedPageIndex = 7,
|
|
Orientation = Orientation.Horizontal
|
|
};
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.Home });
|
|
|
|
Assert.Equal(0, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void End_Key_Should_Navigate_To_Last_Page()
|
|
{
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 10,
|
|
SelectedPageIndex = 3,
|
|
Orientation = Orientation.Horizontal
|
|
};
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.End });
|
|
|
|
Assert.Equal(9, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Home_End_Keys_Should_Work_In_Vertical_Orientation()
|
|
{
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 10,
|
|
SelectedPageIndex = 5,
|
|
Orientation = Orientation.Vertical
|
|
};
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.Home });
|
|
Assert.Equal(0, target.SelectedPageIndex);
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.End });
|
|
Assert.Equal(9, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Negative_NumberOfPages_Should_Be_Coerced_To_Zero()
|
|
{
|
|
var target = new PipsPager();
|
|
|
|
target.NumberOfPages = -5;
|
|
|
|
Assert.Equal(0, target.NumberOfPages);
|
|
Assert.Equal(0, target.TemplateSettings.Pips.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Next_Button_At_Last_Page_Should_Not_Change_Index()
|
|
{
|
|
using var unittestApplication = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 3,
|
|
SelectedPageIndex = 2,
|
|
Template = GetTemplate()
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
var nextButton = target.GetVisualDescendants().OfType<Button>().First(b => b.Name == "PART_NextButton");
|
|
nextButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
|
|
|
|
Assert.Equal(2, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Previous_Button_At_First_Page_Should_Not_Change_Index()
|
|
{
|
|
using var unittestApplication = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 3,
|
|
SelectedPageIndex = 0,
|
|
Template = GetTemplate()
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
var prevButton = target.GetVisualDescendants().OfType<Button>().First(b => b.Name == "PART_PreviousButton");
|
|
prevButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
|
|
|
|
Assert.Equal(0, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Arrow_Keys_At_Boundaries_Should_Not_Change_Index()
|
|
{
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 5,
|
|
SelectedPageIndex = 0,
|
|
Orientation = Orientation.Horizontal
|
|
};
|
|
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.Left });
|
|
Assert.Equal(0, target.SelectedPageIndex);
|
|
|
|
target.SelectedPageIndex = 4;
|
|
target.RaiseEvent(new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = Key.Right });
|
|
Assert.Equal(4, target.SelectedPageIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectedPageIndex_Default_Binding_Mode_Should_Be_TwoWay()
|
|
{
|
|
Assert.Equal(Data.BindingMode.TwoWay, PipsPager.SelectedPageIndexProperty.GetMetadata(typeof(PipsPager)).DefaultBindingMode);
|
|
}
|
|
|
|
[Fact]
|
|
public void TemplateSettings_Should_Not_Be_Externally_Settable()
|
|
{
|
|
var target = new PipsPager();
|
|
|
|
// TemplateSettings property should have a private setter (compile-time enforcement).
|
|
// Verify the property is readable and initialized.
|
|
Assert.NotNull(target.TemplateSettings);
|
|
Assert.IsType<PipsPagerTemplateSettings>(target.TemplateSettings);
|
|
}
|
|
|
|
[Fact]
|
|
public void NumberOfPages_To_Zero_Should_Clamp_SelectedPageIndex()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 5;
|
|
target.SelectedPageIndex = 3;
|
|
|
|
target.NumberOfPages = 0;
|
|
|
|
Assert.Equal(0, target.SelectedPageIndex);
|
|
Assert.Equal(0, target.TemplateSettings.Pips.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Negative_NumberOfPages_After_Having_Pages_Should_Coerce()
|
|
{
|
|
var target = new PipsPager();
|
|
target.NumberOfPages = 5;
|
|
Assert.Equal(5, target.TemplateSettings.Pips.Count);
|
|
|
|
target.NumberOfPages = -1;
|
|
|
|
Assert.Equal(0, target.NumberOfPages);
|
|
Assert.Equal(0, target.TemplateSettings.Pips.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Preselected_Index_Should_Be_Preserved_After_Template_Apply()
|
|
{
|
|
using var app = UnitTestApplication.Start(TestServices.StyledWindow);
|
|
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 20,
|
|
MaxVisiblePips = 5,
|
|
SelectedPageIndex = 15,
|
|
Template = GetTemplate()
|
|
};
|
|
|
|
var root = new TestRoot(target);
|
|
target.ApplyTemplate();
|
|
|
|
Assert.Equal(15, target.SelectedPageIndex);
|
|
Assert.True(target.Classes.Contains(":last-page") == false);
|
|
Assert.True(target.Classes.Contains(":first-page") == false);
|
|
}
|
|
|
|
[Fact]
|
|
public void Preselected_Last_Index_Should_Set_LastPage_PseudoClass()
|
|
{
|
|
var target = new PipsPager
|
|
{
|
|
NumberOfPages = 10,
|
|
SelectedPageIndex = 9
|
|
};
|
|
|
|
Assert.Equal(9, target.SelectedPageIndex);
|
|
Assert.True(target.Classes.Contains(":last-page"));
|
|
Assert.False(target.Classes.Contains(":first-page"));
|
|
}
|
|
|
|
private static FuncControlTemplate<PipsPager> GetTemplate()
|
|
{
|
|
return new FuncControlTemplate<PipsPager>((parent, scope) =>
|
|
{
|
|
return new StackPanel
|
|
{
|
|
Children =
|
|
{
|
|
new Button { Name = "PART_PreviousButton" }.RegisterInNameScope(scope),
|
|
new ListBox { Name = "PART_PipsPagerList" }.RegisterInNameScope(scope),
|
|
new Button { Name = "PART_NextButton" }.RegisterInNameScope(scope)
|
|
}
|
|
};
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|