Xamarin.Forms/Xamarin.Forms.Core.UnitTests/VisualStateManagerTests.cs

418 строки
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Core.UnitTests
{
[TestFixture]
public class VisualStateManagerTests
{
const string NormalStateName = "Normal";
const string InvalidStateName = "Invalid";
const string FocusedStateName = "Focused";
const string DisabledStateName = "Disabled";
const string CommonStatesName = "CommonStates";
static VisualStateGroupList CreateTestStateGroups()
{
var stateGroups = new VisualStateGroupList();
var visualStateGroup = new VisualStateGroup { Name = CommonStatesName };
var normalState = new VisualState { Name = NormalStateName };
var invalidState = new VisualState { Name = InvalidStateName };
var focusedState = new VisualState { Name = FocusedStateName };
var disabledState = new VisualState { Name = DisabledStateName };
visualStateGroup.States.Add(normalState);
visualStateGroup.States.Add(invalidState);
visualStateGroup.States.Add(focusedState);
visualStateGroup.States.Add(disabledState);
stateGroups.Add(visualStateGroup);
return stateGroups;
}
static VisualStateGroupList CreateStateGroupsWithoutNormalState()
{
var stateGroups = new VisualStateGroupList();
var visualStateGroup = new VisualStateGroup { Name = CommonStatesName };
var invalidState = new VisualState { Name = InvalidStateName };
visualStateGroup.States.Add(invalidState);
stateGroups.Add(visualStateGroup);
return stateGroups;
}
[Test]
public void InitialStateIsNormalIfAvailable()
{
var label1 = new Label();
VisualStateManager.SetVisualStateGroups(label1, CreateTestStateGroups());
var groups1 = VisualStateManager.GetVisualStateGroups(label1);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(NormalStateName));
}
[Test]
public void InitialStateIsNullIfNormalNotAvailable()
{
var label1 = new Label();
VisualStateManager.SetVisualStateGroups(label1, CreateStateGroupsWithoutNormalState());
var groups1 = VisualStateManager.GetVisualStateGroups(label1);
Assert.Null(groups1[0].CurrentState);
}
[Test]
public void VisualElementsStateGroupsAreDistinct()
{
var label1 = new Label();
var label2 = new Label();
VisualStateManager.SetVisualStateGroups(label1, CreateTestStateGroups());
VisualStateManager.SetVisualStateGroups(label2, CreateTestStateGroups());
var groups1 = VisualStateManager.GetVisualStateGroups(label1);
var groups2 = VisualStateManager.GetVisualStateGroups(label2);
Assert.AreNotSame(groups1, groups2);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(NormalStateName));
Assert.That(groups2[0].CurrentState.Name, Is.EqualTo(NormalStateName));
VisualStateManager.GoToState(label1, InvalidStateName);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(InvalidStateName));
Assert.That(groups2[0].CurrentState.Name, Is.EqualTo(NormalStateName));
}
[Test]
public void VisualStateGroupsFromSettersAreDistinct()
{
var x = new Setter();
x.Property = VisualStateManager.VisualStateGroupsProperty;
x.Value = CreateTestStateGroups();
var label1 = new Label();
var label2 = new Label();
x.Apply(label1);
x.Apply(label2);
var groups1 = VisualStateManager.GetVisualStateGroups(label1);
var groups2 = VisualStateManager.GetVisualStateGroups(label2);
Assert.NotNull(groups1);
Assert.NotNull(groups2);
Assert.AreNotSame(groups1, groups2);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(NormalStateName));
Assert.That(groups2[0].CurrentState.Name, Is.EqualTo(NormalStateName));
VisualStateManager.GoToState(label1, InvalidStateName);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(InvalidStateName));
Assert.That(groups2[0].CurrentState.Name, Is.EqualTo(NormalStateName));
}
[Test]
public void ElementsDoNotHaveVisualStateGroupsCollectionByDefault()
{
var label1 = new Label();
Assert.False(label1.HasVisualStateGroups());
var vsg = VisualStateManager.GetVisualStateGroups(label1);
Assert.False(label1.HasVisualStateGroups());
vsg.Add(new VisualStateGroup());
Assert.True(label1.HasVisualStateGroups());
}
[Test]
public void StateNamesMustBeUniqueWithinGroup()
{
IList<VisualStateGroup> vsgs = CreateTestStateGroups();
var duplicate = new VisualState { Name = NormalStateName };
Assert.Throws<InvalidOperationException>(() => vsgs[0].States.Add(duplicate));
}
[Test]
public void StateNamesMustBeUniqueWithinGroupList()
{
IList<VisualStateGroup> vsgs = CreateTestStateGroups();
// Create and add a second VisualStateGroup
var secondGroup = new VisualStateGroup { Name = "Foo" };
vsgs.Add(secondGroup);
// Create a VisualState with the same name as one in another group in this list
var duplicate = new VisualState { Name = NormalStateName };
Assert.Throws<InvalidOperationException>(() => secondGroup.States.Add(duplicate));
}
[Test]
public void StateNamesMustBeUniqueWithinGroupListWhenAddingGroup()
{
IList<VisualStateGroup> vsgs = CreateTestStateGroups();
// Create and add a second VisualStateGroup
var secondGroup = new VisualStateGroup { Name = "Foo" };
// Create a VisualState with the same name as one in another group in the list
var duplicate = new VisualState { Name = NormalStateName };
secondGroup.States.Add(duplicate);
Assert.Throws<InvalidOperationException>(() => vsgs.Add(secondGroup));
}
[Test]
public void GroupNamesMustBeUniqueWithinGroupList()
{
IList<VisualStateGroup> vsgs = CreateTestStateGroups();
var secondGroup = new VisualStateGroup { Name = CommonStatesName };
Assert.Throws<InvalidOperationException>(() => vsgs.Add(secondGroup));
}
[Test]
public void StateNamesInGroupMayNotBeNull()
{
IList<VisualStateGroup> vsgs = CreateTestStateGroups();
var nullStateName = new VisualState();
Assert.Throws<InvalidOperationException>(() => vsgs[0].States.Add(nullStateName));
}
[Test]
public void StateNamesInGroupMayNotBeEmpty()
{
IList<VisualStateGroup> vsgs = CreateTestStateGroups();
var emptyStateName = new VisualState { Name = "" };
Assert.Throws<InvalidOperationException>(() => vsgs[0].States.Add(emptyStateName));
}
[Test]
public void VerifyVisualStateChanges()
{
var label1 = new Label();
VisualStateManager.SetVisualStateGroups(label1, CreateTestStateGroups());
var groups1 = VisualStateManager.GetVisualStateGroups(label1);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(NormalStateName));
label1.IsEnabled = false;
groups1 = VisualStateManager.GetVisualStateGroups(label1);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(DisabledStateName));
label1.SetValue(VisualElement.IsFocusedPropertyKey, true);
groups1 = VisualStateManager.GetVisualStateGroups(label1);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(DisabledStateName));
label1.IsEnabled = true;
groups1 = VisualStateManager.GetVisualStateGroups(label1);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(FocusedStateName));
label1.SetValue(VisualElement.IsFocusedPropertyKey, false);
groups1 = VisualStateManager.GetVisualStateGroups(label1);
Assert.That(groups1[0].CurrentState.Name, Is.EqualTo(NormalStateName));
}
[Test]
public void VisualElementGoesToCorrectStateWhenAvailable()
{
var label = new Label();
double targetBottomMargin = 1.5;
var group = new VisualStateGroup();
var list = new VisualStateGroupList();
var normalState = new VisualState { Name = NormalStateName };
normalState.Setters.Add(new Setter { Property = View.MarginBottomProperty, Value = targetBottomMargin });
list.Add(group);
group.States.Add(normalState);
VisualStateManager.SetVisualStateGroups(label, list);
Assert.That(label.Margin.Bottom, Is.EqualTo(targetBottomMargin));
}
[Test]
public void VisualElementGoesToCorrectStateWhenAvailableFromSetter()
{
double targetBottomMargin = 1.5;
var group = new VisualStateGroup();
var list = new VisualStateGroupList();
var normalState = new VisualState { Name = NormalStateName };
normalState.Setters.Add(new Setter { Property = View.MarginBottomProperty, Value = targetBottomMargin });
var x = new Setter
{
Property = VisualStateManager.VisualStateGroupsProperty,
Value = list
};
list.Add(group);
group.States.Add(normalState);
var label1 = new Label();
var label2 = new Label();
x.Apply(label1);
x.Apply(label2);
Assert.That(label1.Margin.Bottom, Is.EqualTo(targetBottomMargin));
Assert.That(label2.Margin.Bottom, Is.EqualTo(targetBottomMargin));
}
[Test]
public void VisualElementGoesToCorrectStateWhenSetterHasTarget()
{
double defaultMargin = default(double);
double targetMargin = 1.5;
var label1 = new Label();
var label2 = new Label();
INameScope nameScope = new NameScope();
NameScope.SetNameScope(label1, nameScope);
nameScope.RegisterName("Label1", label1);
NameScope.SetNameScope(label2, nameScope);
nameScope.RegisterName("Label2", label2);
var list = new VisualStateGroupList
{
new VisualStateGroup
{
States =
{
new VisualState
{
Name = NormalStateName,
Setters =
{
new Setter { Property = View.MarginBottomProperty, Value = targetMargin },
new Setter { TargetName = "Label2", Property = View.MarginTopProperty, Value = targetMargin }
}
}
}
}
};
VisualStateManager.SetVisualStateGroups(label1, list);
Assert.That(label1.Margin.Top, Is.EqualTo(defaultMargin));
Assert.That(label1.Margin.Bottom, Is.EqualTo(targetMargin));
Assert.That(label1.Margin.Left, Is.EqualTo(defaultMargin));
Assert.That(label2.Margin.Top, Is.EqualTo(targetMargin));
Assert.That(label2.Margin.Bottom, Is.EqualTo(defaultMargin));
}
[Test]
public void CanRemoveAStateAndAddANewStateWithTheSameName()
{
var stateGroups = new VisualStateGroupList();
var visualStateGroup = new VisualStateGroup { Name = CommonStatesName };
var normalState = new VisualState { Name = NormalStateName };
var invalidState = new VisualState { Name = InvalidStateName };
stateGroups.Add(visualStateGroup);
visualStateGroup.States.Add(normalState);
visualStateGroup.States.Add(invalidState);
var name = visualStateGroup.States[0].Name;
visualStateGroup.States.Remove(visualStateGroup.States[0]);
visualStateGroup.States.Add(new VisualState { Name = name });
}
[Test]
public void CanRemoveAGroupAndAddANewGroupWithTheSameName()
{
var stateGroups = new VisualStateGroupList();
var visualStateGroup = new VisualStateGroup { Name = CommonStatesName };
var secondVisualStateGroup = new VisualStateGroup { Name = "Whatevs" };
var normalState = new VisualState { Name = NormalStateName };
var invalidState = new VisualState { Name = InvalidStateName };
stateGroups.Add(visualStateGroup);
visualStateGroup.States.Add(normalState);
visualStateGroup.States.Add(invalidState);
stateGroups.Add(secondVisualStateGroup);
var name = stateGroups[0].Name;
stateGroups.Remove(stateGroups[0]);
stateGroups.Add(new VisualStateGroup { Name = name });
}
[Test]
[Explicit("This test was created to check performance characteristics; leaving it in because it may be useful again.")]
[TestCase(1, 10)]
[TestCase(1, 10000)]
[TestCase(10, 100)]
[TestCase(10, 10000)]
public void ValidatePerformance(int groups, int states)
{
IList<VisualStateGroup> vsgs = new VisualStateGroupList();
var groupList = new List<VisualStateGroup>();
for (int n = 0; n < groups; n++)
{
groupList.Add(new VisualStateGroup { Name = n.ToString() });
}
var watch = new Stopwatch();
watch.Start();
foreach (var group in groupList)
{
vsgs.Add(group);
}
watch.Stop();
double iterations = states;
var random = new Random();
for (int n = 0; n < iterations; n++)
{
var state = new VisualState { Name = n.ToString() };
var group = groupList[random.Next(0, groups - 1)];
watch.Start();
group.States.Add(state);
watch.Stop();
}
var average = watch.ElapsedMilliseconds / iterations;
Debug.WriteLine($">>>>> VisualStateManagerTests ValidatePerformance: {watch.ElapsedMilliseconds}ms over {iterations} iterations; average of {average}ms");
}
}
}