maui-linux/Xamarin.Forms.Core.UnitTests/NavigationUnitTest.cs

655 строки
16 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
namespace Xamarin.Forms.Core.UnitTests
{
[TestFixture]
public class NavigationUnitTest : BaseTestFixture
{
[Test]
public async Task TestNavigationImplPush ()
{
NavigationPage nav = new NavigationPage ();
Assert.IsNull(nav.RootPage);
Assert.IsNull (nav.CurrentPage);
Label child = new Label {Text = "Label"};
Page childRoot = new ContentPage {Content = child};
await nav.Navigation.PushAsync (childRoot);
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
public async Task TestNavigationImplPop ()
{
NavigationPage nav = new NavigationPage ();
Label child = new Label ();
Page childRoot = new ContentPage {Content = child};
Label child2 = new Label ();
Page childRoot2 = new ContentPage {Content = child2};
await nav.Navigation.PushAsync (childRoot);
await nav.Navigation.PushAsync (childRoot2);
bool fired = false;
nav.Popped += (sender, e) => fired = true;
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreNotSame(childRoot2, nav.RootPage);
Assert.AreNotSame(nav.RootPage, nav.CurrentPage);
var popped = await nav.Navigation.PopAsync ();
Assert.True (fired);
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
Assert.AreEqual (childRoot2, popped);
await nav.PopAsync ();
var last = await nav.Navigation.PopAsync ();
Assert.IsNull (last);
Assert.IsNotNull(nav.RootPage);
Assert.IsNotNull(nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
public async Task TestPushRoot ()
{
NavigationPage nav = new NavigationPage ();
Assert.IsNull(nav.RootPage);
Assert.IsNull (nav.CurrentPage);
Label child = new Label {Text = "Label"};
Page childRoot = new ContentPage {Content = child};
await nav.PushAsync (childRoot);
Assert.AreSame (childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
public async Task TestPushEvent ()
{
NavigationPage nav = new NavigationPage ();
Label child = new Label ();
Page childRoot = new ContentPage {Content = child};
bool fired = false;
nav.Pushed += (sender, e) => fired = true;
await nav.PushAsync (childRoot);
Assert.True (fired);
}
[Test]
public async Task TestDoublePush ()
{
NavigationPage nav = new NavigationPage ();
Label child = new Label ();
Page childRoot = new ContentPage {Content = child};
await nav.PushAsync (childRoot);
bool fired = false;
nav.Pushed += (sender, e) => fired = true;
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
await nav.PushAsync (childRoot);
Assert.False (fired);
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
public async Task TestPop ()
{
NavigationPage nav = new NavigationPage ();
Label child = new Label ();
Page childRoot = new ContentPage {Content = child};
Label child2 = new Label ();
Page childRoot2 = new ContentPage {Content = child2};
await nav.PushAsync (childRoot);
await nav.PushAsync (childRoot2);
bool fired = false;
nav.Popped += (sender, e) => fired = true;
var popped = await nav.PopAsync ();
Assert.True (fired);
Assert.AreSame (childRoot, nav.CurrentPage);
Assert.AreEqual (childRoot2, popped);
await nav.PopAsync ();
var last = await nav.PopAsync ();
Assert.IsNull (last);
}
[Test]
public void TestTint ()
{
var nav = new NavigationPage ();
Assert.AreEqual (Color.Default, nav.Tint);
bool signaled = false;
nav.PropertyChanged += (sender, args) => {
if (args.PropertyName == "Tint")
signaled = true;
};
nav.Tint = new Color (1, 0, 0);
Assert.AreEqual (new Color (1, 0, 0), nav.Tint);
Assert.True (signaled);
}
[Test]
public void TestTintDoubleSet ()
{
var nav = new NavigationPage ();
bool signaled = false;
nav.PropertyChanged += (sender, args) => {
if (args.PropertyName == "Tint")
signaled = true;
};
nav.Tint = nav.Tint;
Assert.False (signaled);
}
[Test]
public async Task TestPopToRoot ()
{
var nav = new NavigationPage ();
bool signaled = false;
nav.PoppedToRoot += (sender, args) => signaled = true;
var root = new ContentPage {Content = new View ()};
var child1 = new ContentPage {Content = new View ()};
var child2 = new ContentPage {Content = new View ()};
await nav.PushAsync (root);
await nav.PushAsync (child1);
await nav.PushAsync (child2);
nav.PopToRootAsync ();
Assert.True (signaled);
Assert.AreSame (root, nav.RootPage);
Assert.AreSame(root, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
public async Task TestPopToRootEventArgs ()
{
var nav = new NavigationPage ();
List<Page> poppedChildren = null;
nav.PoppedToRoot += (sender, args) => poppedChildren = (args as PoppedToRootEventArgs).PoppedPages.ToList();
var root = new ContentPage {Content = new View ()};
var child1 = new ContentPage {Content = new View ()};
var child2 = new ContentPage {Content = new View ()};
await nav.PushAsync (root);
await nav.PushAsync (child1);
await nav.PushAsync (child2);
await nav.PopToRootAsync ();
Assert.IsNotNull (poppedChildren);
Assert.AreEqual (2, poppedChildren.Count);
Assert.Contains (child1, poppedChildren);
Assert.Contains (child2, poppedChildren);
Assert.AreSame(root, nav.RootPage);
Assert.AreSame(root, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
public async Task PeekOne()
{
var nav = new NavigationPage();
bool signaled = false;
nav.PoppedToRoot += (sender, args) => signaled = true;
var root = new ContentPage { Content = new View() };
var child1 = new ContentPage { Content = new View() };
var child2 = new ContentPage { Content = new View() };
await nav.PushAsync(root);
await nav.PushAsync(child1);
await nav.PushAsync(child2);
Assert.AreEqual(((INavigationPageController)nav).Peek(1), child1);
}
[Test]
public async Task PeekZero()
{
var nav = new NavigationPage();
bool signaled = false;
nav.PoppedToRoot += (sender, args) => signaled = true;
var root = new ContentPage { Content = new View() };
var child1 = new ContentPage { Content = new View() };
var child2 = new ContentPage { Content = new View() };
await nav.PushAsync(root);
await nav.PushAsync(child1);
await nav.PushAsync(child2);
Assert.AreEqual(((INavigationPageController)nav).Peek(0), child2);
Assert.AreEqual(((INavigationPageController)nav).Peek(), child2);
}
[Test]
public async Task PeekPastStackDepth()
{
var nav = new NavigationPage();
bool signaled = false;
nav.PoppedToRoot += (sender, args) => signaled = true;
var root = new ContentPage { Content = new View() };
var child1 = new ContentPage { Content = new View() };
var child2 = new ContentPage { Content = new View() };
await nav.PushAsync(root);
await nav.PushAsync(child1);
await nav.PushAsync(child2);
Assert.AreEqual(((INavigationPageController)nav).Peek(3), null);
}
[Test]
public async Task PeekShallow()
{
var nav = new NavigationPage();
bool signaled = false;
nav.PoppedToRoot += (sender, args) => signaled = true;
var root = new ContentPage { Content = new View() };
var child1 = new ContentPage { Content = new View() };
var child2 = new ContentPage { Content = new View() };
await nav.PushAsync(root);
await nav.PushAsync(child1);
await nav.PushAsync(child2);
Assert.AreEqual(((INavigationPageController)nav).Peek(-1), null);
}
[Test]
public async Task PeekEmpty([Range(0, 3)] int depth)
{
var nav = new NavigationPage();
bool signaled = false;
nav.PoppedToRoot += (sender, args) => signaled = true;
Assert.AreEqual(((INavigationPageController)nav).Peek(depth), null);
}
[Test]
public void ConstructWithRoot ()
{
var root = new ContentPage ();
var nav = new NavigationPage (root);
Assert.AreEqual (1, ((INavigationPageController)nav).StackDepth);
Assert.AreEqual (root, ((IElementController)nav).LogicalChildren[0]);
}
[Test]
public void TitleViewSetProperty()
{
var root = new ContentPage();
var nav = new NavigationPage(root);
View target = new View();
NavigationPage.SetTitleView(root, target);
var result = NavigationPage.GetTitleView(root);
Assert.AreSame(result, target);
}
[Test]
public void TitleViewSetsParentWhenAdded()
{
var root = new ContentPage();
var nav = new NavigationPage(root);
View target = new View();
NavigationPage.SetTitleView(root, target);
Assert.AreSame(root, target.Parent);
}
[Test]
public void TitleViewClearsParentWhenRemoved()
{
var root = new ContentPage();
var nav = new NavigationPage(root);
View target = new View();
NavigationPage.SetTitleView(root, target);
NavigationPage.SetTitleView(root, null);
Assert.IsNull(target.Parent);
}
[Test]
public async Task NavigationChangedEventArgs ()
{
var rootPage = new ContentPage { Title = "Root" };
var navPage = new NavigationPage (rootPage);
var rootArg = new Page ();
navPage.Pushed += (s, e) => {
rootArg = e.Page;
};
var pushPage = new ContentPage {
Title = "Page 2"
};
await navPage.PushAsync (pushPage);
Assert.AreEqual (rootArg, pushPage);
var secondPushPage = new ContentPage {
Title = "Page 3"
};
await navPage.PushAsync (secondPushPage);
Assert.AreEqual (rootArg, secondPushPage);
}
[Test]
public async Task CurrentPageChanged()
{
var root = new ContentPage { Title = "Root" };
var navPage = new NavigationPage (root);
bool changing = false;
navPage.PropertyChanging += (object sender, PropertyChangingEventArgs e) => {
if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName) {
Assert.That (navPage.CurrentPage, Is.SameAs (root));
changing = true;
}
};
var next = new ContentPage { Title = "Next" };
bool changed = false;
navPage.PropertyChanged += (sender, e) => {
if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName) {
Assert.That (navPage.CurrentPage, Is.SameAs (next));
changed = true;
}
};
await navPage.PushAsync (next);
Assert.That (changing, Is.True, "PropertyChanging was not raised for 'CurrentPage'");
Assert.That (changed, Is.True, "PropertyChanged was not raised for 'CurrentPage'");
}
[Test]
public async Task HandlesPopToRoot ()
{
var root = new ContentPage { Title = "Root" };
var navPage = new NavigationPage (root);
await navPage.PushAsync (new ContentPage ());
await navPage.PushAsync (new ContentPage ());
bool popped = false;
navPage.PoppedToRoot += (sender, args) => {
popped = true;
};
await navPage.Navigation.PopToRootAsync ();
Assert.True (popped);
}
[Test]
public void SendsBackButtonEventToCurrentPage ()
{
var current = new BackButtonPage ();
var navPage = new NavigationPage (current);
var emitted = false;
current.BackPressed += (sender, args) => emitted = true;
navPage.SendBackButtonPressed ();
Assert.True (emitted);
}
[Test]
public void DoesNotSendBackEventToNonCurrentPage ()
{
var current = new BackButtonPage ();
var navPage = new NavigationPage (current);
navPage.PushAsync (new ContentPage ());
var emitted = false;
current.BackPressed += (sender, args) => emitted = true;
navPage.SendBackButtonPressed ();
Assert.False (emitted);
}
[Test]
public async Task NavigatesBackWhenBackButtonPressed ()
{
var root = new ContentPage { Title = "Root" };
var navPage = new NavigationPage (root);
await navPage.PushAsync (new ContentPage ());
var result = navPage.SendBackButtonPressed ();
Assert.AreEqual (root, navPage.CurrentPage);
Assert.True (result);
}
[Test]
public async Task DoesNotNavigatesBackWhenBackButtonPressedIfHandled ()
{
var root = new BackButtonPage { Title = "Root" };
var second = new BackButtonPage () {Handle = true};
var navPage = new NavigationPage (root);
await navPage.PushAsync (second);
navPage.SendBackButtonPressed ();
Assert.AreEqual (second, navPage.CurrentPage);
}
[Test]
public void DoesNotHandleBackButtonWhenNoNavStack ()
{
var root = new ContentPage { Title = "Root" };
var navPage = new NavigationPage (root);
var result = navPage.SendBackButtonPressed ();
Assert.False (result);
}
[Test]
public void TestInsertPage()
{
var root = new ContentPage { Title = "Root" };
var newPage = new ContentPage();
var navPage = new NavigationPage(root);
navPage.Navigation.InsertPageBefore(newPage, navPage.RootPage);
Assert.AreSame(newPage, navPage.RootPage);
Assert.AreNotSame(newPage, navPage.CurrentPage);
Assert.AreNotSame(navPage.RootPage, navPage.CurrentPage);
Assert.AreSame(root, navPage.CurrentPage);
Assert.Throws<ArgumentException>(() =>
{
navPage.Navigation.InsertPageBefore(new ContentPage(), new ContentPage());
});
Assert.Throws<ArgumentException>(() =>
{
navPage.Navigation.InsertPageBefore(navPage.RootPage, navPage.CurrentPage);
});
Assert.Throws<ArgumentNullException>(() =>
{
navPage.Navigation.InsertPageBefore(null, navPage.CurrentPage);
});
Assert.Throws<ArgumentNullException>(() =>
{
navPage.Navigation.InsertPageBefore(new ContentPage(), null);
});
}
[Test]
public async Task TestRemovePage()
{
var root = new ContentPage { Title = "Root" };
var newPage = new ContentPage();
var navPage = new NavigationPage(root);
await navPage.PushAsync(newPage);
navPage.Navigation.RemovePage(root);
Assert.AreSame(newPage, navPage.RootPage);
Assert.AreSame(newPage, navPage.CurrentPage);
Assert.AreSame(navPage.RootPage, navPage.CurrentPage);
Assert.AreNotSame(root, navPage.CurrentPage);
Assert.Throws<ArgumentException>(() =>
{
navPage.Navigation.RemovePage(root);
});
Assert.Throws<InvalidOperationException>(() =>
{
navPage.Navigation.RemovePage(newPage);
});
Assert.Throws<ArgumentNullException>(() =>
{
navPage.Navigation.RemovePage(null);
});
}
[Test (Description = "CurrentPage should not be set to null when you attempt to pop the last page")]
[Property ("Bugzilla", 28335)]
public async Task CurrentPageNotNullPoppingRoot()
{
var root = new ContentPage { Title = "Root" };
var navPage = new NavigationPage (root);
var popped = await navPage.PopAsync ();
Assert.That (popped, Is.Null);
Assert.That (navPage.CurrentPage, Is.SameAs (root));
}
[Test]
[Property("Bugzilla", 31171)]
public async Task ReleasesPoppedPage()
{
var root = new ContentPage { Title = "Root" };
var navPage = new NavigationPage(root);
var isFinalized = false;
await navPage.PushAsync(new PageWithFinalizer(() => isFinalized = true));
await navPage.PopAsync();
await Task.Delay(100);
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.IsTrue(isFinalized);
}
}
internal class BackButtonPage : ContentPage
{
public event EventHandler BackPressed;
public bool Handle = false;
protected override bool OnBackButtonPressed ()
{
if (BackPressed != null)
BackPressed (this, EventArgs.Empty);
return Handle;
}
}
internal class PageWithFinalizer : Page
{
Action OnFinalize;
public PageWithFinalizer(Action onFinalize)
{
OnFinalize = onFinalize;
}
~PageWithFinalizer()
{
OnFinalize();
}
}
}