665 строки
16 KiB
C#
665 строки
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();
|
|
}
|
|
}
|
|
}
|