Merge pull request #2155 from NativeScript/new-trans

Fixed: Navigating with clearHistory / transition
This commit is contained in:
Rossen Hristov
2016-05-25 11:03:52 +03:00
14 changed files with 485 additions and 290 deletions

View File

@@ -39,25 +39,26 @@ export class NavPage extends Page implements definition.ControlsPage {
var that = this;
that.on(View.loadedEvent, (args) => {
console.log(`Loaded ${args.object}`);
console.log(`NavPage: Loaded ${args.object}`);
if (topmostFrame().android) {
console.log(`NavPage: topmostFrame().android.cachePagesOnNavigate = true;`);
topmostFrame().android.cachePagesOnNavigate = true;
}
});
that.on(View.unloadedEvent, (args) => {
console.log(`Unloaded ${args.object}`);
console.log(`NavPage: Unloaded ${args.object}`);
});
that.on(Page.navigatingFromEvent, (args: NavigatedData) => {
console.log(`NavigatING FROM ${args.object}, isBackNavigation: ${args.isBackNavigation}`);
console.log(`NavPage: NavigatING FROM ${args.object}, isBackNavigation: ${args.isBackNavigation}`);
});
that.on(Page.navigatedFromEvent, (args: NavigatedData) => {
console.log(`NaviagatED FROM ${args.object}, isBackNavigation: ${args.isBackNavigation}`);
console.log(`NavPage: NaviagatED FROM ${args.object}, isBackNavigation: ${args.isBackNavigation}`);
});
that.on(Page.navigatingToEvent, (args: NavigatedData) => {
console.log(`NavigatING TO ${args.object}, isBackNavigation: ${args.isBackNavigation}`);
console.log(`NavPage: NavigatING TO ${args.object}, isBackNavigation: ${args.isBackNavigation}`);
});
that.on(Page.navigatedToEvent, (args: NavigatedData) => {
console.log(`NavigatED TO ${args.object}, isBackNavigation: ${args.isBackNavigation}`);
console.log(`NavPage: NavigatED TO ${args.object}, isBackNavigation: ${args.isBackNavigation}`);
(<any>topmostFrame())._printFrameBackStack();
if (topmostFrame().android) {
(<any>topmostFrame())._printNativeBackStack();

View File

@@ -60,7 +60,7 @@ var runTest = function (testInfo: TestInfoEntry) {
if (testInfo.isTest) {
duration = time() - start;
testInfo.duration = duration;
write("--- [" + testInfo.testName + "] OK, duration: " + duration, trace.messageType.info);
write(`--- [${testInfo.testName}] OK, duration: ${duration}`, trace.messageType.info);
testInfo.isPassed = true;
}
}
@@ -68,7 +68,7 @@ var runTest = function (testInfo: TestInfoEntry) {
if (testInfo.isTest) {
duration = time() - start;
testInfo.duration = duration;
write("--- [" + testInfo.testName + "] FAILED: " + e.message + ", duration: " + duration, trace.messageType.error);
write(`--- [${testInfo.testName}] FAILED: ${e.message}, duration: ${duration}`, trace.messageType.error);
testInfo.isPassed = false;
testInfo.errorMessage = e.message;
}

View File

@@ -6,6 +6,16 @@ import {Label} from "ui/label";
trace.enable();
trace.addCategories(trace.categories.Test + "," + trace.categories.Error);
// When debugging
//trace.setCategories(trace.categories.concat(
// trace.categories.Test,
// trace.categories.Navigation,
// trace.categories.Transition,
// trace.categories.NativeLifecycle,
// trace.categories.ViewHierarchy,
// trace.categories.VisualTreeEvents
//));
let page = new Page();
page.id = "mainPage";

View File

@@ -4,63 +4,92 @@ import {topmost as topmostFrame, NavigationTransition} from "ui/frame";
import {Color} from "color";
// Creates a random colorful page full of meaningless stuff.
var pageFactory = function(): Page {
var id = 0;
var pageFactory = function (): Page {
var page = new Page();
page.actionBarHidden = true;
page.id = `NavTestPage${id++}`;
page.style.backgroundColor = new Color(255, Math.round(Math.random() * 255), Math.round(Math.random() * 255), Math.round(Math.random() * 255));
return page;
};
function waitUntilNavigatedFrom(oldPage: Page) {
let topmost = topmostFrame();
TKUnit.waitUntilReady(() => {
return topmost.currentPage
&& topmost.currentPage !== oldPage
&& topmost.currentPage.isLoaded
&& !oldPage.isLoaded
;
});
}
function androidGC() {
let topmost = topmostFrame();
if (topmost.android) {
gc();
java.lang.System.gc();
}
}
function _test_backstackVisible(transition?: NavigationTransition) {
let topmost = topmostFrame();
let mainTestPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== mainTestPage; });
topmost.navigate({ create: pageFactory, transition: transition, animated: true });
waitUntilNavigatedFrom(mainTestPage);
// page1 should not be added to the backstack
let page0 = topmost.currentPage;
topmost.navigate({ create: pageFactory, backstackVisible: false, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== page0; });
topmost.navigate({ create: pageFactory, backstackVisible: false, transition: transition, animated: true });
waitUntilNavigatedFrom(page0);
let page1 = topmost.currentPage;
topmost.navigate({ create: pageFactory, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== page1; });
topmost.navigate({ create: pageFactory, transition: transition, animated: true });
waitUntilNavigatedFrom(page1);
let page2 = topmost.currentPage;
topmost.goBack();
TKUnit.waitUntilReady(() => { return topmost.currentPage !== page2; });
waitUntilNavigatedFrom(page2);
// From page2 we have to go directly to page0, skipping page1.
TKUnit.assert(topmost.currentPage === page0, "Page 1 should be skipped when going back.");
topmost.goBack();
TKUnit.waitUntilReady(() => { return topmost.currentPage === mainTestPage; });
waitUntilNavigatedFrom(page0);
TKUnit.assertEqual(topmost.currentPage, mainTestPage, "We should be on the main test page at the end of the test.");
}
export var test_backstackVisible = function () {
androidGC();
_test_backstackVisible();
}
export var test_backstackVisible_WithTransition = function () {
androidGC();
_test_backstackVisible({name: "fade"});
}
function _test_backToEntry(transition?: NavigationTransition) {
let topmost = topmostFrame();
let page = (tag) => () => {
var p = new Page();
p.actionBarHidden = true;
p.id = `NavTestPage${id++}`;
p["tag"] = tag;
return p;
}
let topmost = topmostFrame();
let wait = tag => TKUnit.waitUntilReady(() => topmost.currentPage["tag"] === tag, 1);
let mainTestPage = topmost.currentPage;
let waitFunc = tag => TKUnit.waitUntilReady(() => topmost.currentPage["tag"] === tag, 1);
let navigate = tag => {
topmost.navigate({ create: page(tag), transition: transition });
wait(tag)
topmost.navigate({ create: page(tag), transition: transition, animated: true });
waitFunc(tag);
}
let back = pages => {
topmost.goBack(topmost.backStack[topmost.backStack.length - pages]);
}
let currentPageMustBe = tag => {
wait(tag); // TODO: Add a timeout...
waitFunc(tag); // TODO: Add a timeout...
TKUnit.assert(topmost.currentPage["tag"] === tag, "Expected current page to be " + tag + " it was " + topmost.currentPage["tag"] + " instead.");
}
@@ -81,14 +110,19 @@ function _test_backToEntry(transition?: NavigationTransition) {
currentPageMustBe("page1.1");
back(1);
currentPageMustBe("page1");
let page1 = topmost.currentPage;
back(1);
waitUntilNavigatedFrom(page1);
TKUnit.assertEqual(topmost.currentPage, mainTestPage, "We should be on the main test page at the end of the test.");
}
export var test_backToEntry = function () {
androidGC();
_test_backToEntry();
}
export var test_backToEntry_WithTransition = function () {
androidGC();
_test_backToEntry({name: "flip"});
}
@@ -102,85 +136,148 @@ function _test_ClearHistory(transition?: NavigationTransition) {
var currentPage: Page;
currentPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, clearHistory: true, transition: transition});
TKUnit.waitUntilReady(() => { return topmost.currentPage !== currentPage; });
topmost.navigate({ create: pageFactory, clearHistory: true, transition: transition, animated: true });
waitUntilNavigatedFrom(currentPage);
TKUnit.assertEqual(topmost.backStack.length, 0, "1.topmost.backStack.length");
TKUnit.assertEqual(topmost.canGoBack(), false, "1.topmost.canGoBack().");
currentPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== currentPage; });
topmost.navigate({ create: pageFactory, transition: transition, animated: true });
waitUntilNavigatedFrom(currentPage);
TKUnit.assertEqual(topmost.backStack.length, 1, "2.topmost.backStack.length");
TKUnit.assertEqual(topmost.canGoBack(), true, "2.topmost.canGoBack().");
currentPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== currentPage; });
topmost.navigate({ create: pageFactory, transition: transition, animated: true });
waitUntilNavigatedFrom(currentPage);
TKUnit.assertEqual(topmost.backStack.length, 2, "3.topmost.backStack.length");
TKUnit.assertEqual(topmost.canGoBack(), true, "3.topmost.canGoBack().");
currentPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== currentPage; });
topmost.navigate({ create: pageFactory, clearHistory: true, transition: transition, animated: true });
waitUntilNavigatedFrom(currentPage);
TKUnit.assertEqual(topmost.backStack.length, 0, "4.topmost.backStack.length");
TKUnit.assertEqual(topmost.canGoBack(), false, "4.topmost.canGoBack().");
TKUnit.assert(topmost.canGoBack(), "Frame should be able to go back.");
TKUnit.assert(topmost.backStack.length === 3, "Back stack should have 3 entries.");
// Navigate with clear history.
currentPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, clearHistory: true, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== currentPage; });
topmost.navigate({ create: mainPageFactory, clearHistory: true, animated: false });
waitUntilNavigatedFrom(currentPage);
TKUnit.assertEqual(topmost.backStack.length, 0, "5.topmost.backStack.length");
TKUnit.assertEqual(topmost.canGoBack(), false, "5.topmost.canGoBack().");
TKUnit.assert(!topmost.canGoBack(), "Frame should NOT be able to go back.");
TKUnit.assert(topmost.backStack.length === 0, "Back stack should have 0 entries.");
topmost.navigate({ create: mainPageFactory, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage === mainTestPage; });
TKUnit.assertEqual(topmost.currentPage, mainTestPage, "We should be on the main test page at the end of the test.");
TKUnit.assertEqual(topmost.backStack.length, 0, "Back stack should be empty at the end of the test.");
}
// Clearing the history messes up the tests app.
export var test_ClearHistory = function () {
androidGC();
_test_ClearHistory();
}
export var test_ClearHistory_WithTransition = function () {
_test_ClearHistory({ name: "slide" });
androidGC();
_test_ClearHistory({ name: "fade" });
}
export var test_ClearHistory_WithTransition_WithCachePagesOnNavigate = function () {
androidGC();
let topmost = topmostFrame();
if (!topmost.android) {
return;
}
let originalCachePagesOnNavigate = topmost.android.cachePagesOnNavigate;
topmostFrame().android.cachePagesOnNavigate = true;
_test_ClearHistory({ name: "fade" });
topmostFrame().android.cachePagesOnNavigate = originalCachePagesOnNavigate;
}
// Test case for https://github.com/NativeScript/NativeScript/issues/1948
export var test_ClearHistoryWithTransitionDoesNotBreakNavigation = function () {
androidGC();
let topmost = topmostFrame();
let mainTestPage = topmost.currentPage;
let mainPageFactory = function (): Page {
return mainTestPage;
};
// Go to details-page
topmost.navigate({ create: pageFactory, clearHistory: false });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== mainTestPage; });
topmost.navigate({ create: pageFactory, clearHistory: false, animated: true });
waitUntilNavigatedFrom(mainTestPage);
// Go back to main-page with clearHistory
var detailsPage: Page;
detailsPage = topmost.currentPage;
topmost.transition = { name: "fade" };
topmost.navigate({ create: mainPageFactory, clearHistory: true });
TKUnit.waitUntilReady(() => { return topmost.currentPage === mainTestPage; });
topmost.navigate({ create: mainPageFactory, clearHistory: true, animated: true });
waitUntilNavigatedFrom(detailsPage);
// Go to details-page AGAIN
topmost.navigate({ create: pageFactory, clearHistory: false });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== mainTestPage; });
topmost.navigate({ create: pageFactory, clearHistory: false, animated: true });
waitUntilNavigatedFrom(mainTestPage);
// Go back to main-page with clearHistory
detailsPage = topmost.currentPage;
topmost.transition = { name: "fade" };
topmost.navigate({ create: mainPageFactory, clearHistory: true });
TKUnit.waitUntilReady(() => { return topmost.currentPage === mainTestPage; });
topmost.navigate({ create: mainPageFactory, clearHistory: true, animated: true });
waitUntilNavigatedFrom(detailsPage);
// Clean up
topmost.transition = undefined;
TKUnit.assertEqual(topmost.currentPage, mainTestPage, "We should be on the main test page at the end of the test.");
TKUnit.assertEqual(topmost.backStack.length, 0, "Back stack should be empty at the end of the test.");
}
export var test_ClearHistoryWithTransitionDoesNotBreakNavigation_WithLocalTransition = function () {
androidGC();
let topmost = topmostFrame();
let originalCachePagesOnNavigate: boolean;
if (topmost.android) {
originalCachePagesOnNavigate = topmost.android.cachePagesOnNavigate;
topmostFrame().android.cachePagesOnNavigate = true;
}
let mainTestPage = topmost.currentPage;
let mainPageFactory = function (): Page {
return mainTestPage;
};
// Go to 1st page
var currentPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, clearHistory: false, transition: { name: "fade" }, animated: true });
waitUntilNavigatedFrom(currentPage);
// Go to 2nd page
currentPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, clearHistory: false, transition: { name: "fade" }, animated: true });
waitUntilNavigatedFrom(currentPage);
// Go to 3rd page with clearHistory
currentPage = topmost.currentPage;
topmost.navigate({ create: pageFactory, clearHistory: true, transition: { name: "fade" }, animated: true });
waitUntilNavigatedFrom(currentPage);
// Go back to main
currentPage = topmost.currentPage;
topmost.navigate({ create: mainPageFactory, clearHistory: true, transition: { name: "fade" }, animated: true });
waitUntilNavigatedFrom(currentPage);
if (topmost.android) {
topmostFrame().android.cachePagesOnNavigate = originalCachePagesOnNavigate;
}
TKUnit.assertEqual(topmost.currentPage, mainTestPage, "We should be on the main test page at the end of the test.");
TKUnit.assertEqual(topmost.backStack.length, 0, "Back stack should be empty at the end of the test.");
}
function _test_NavigationEvents(transition?: NavigationTransition) {
let topmost = topmostFrame();
let argsToString = (args: NavigatedData) => {
return `${(<Page>args.object).id} ${args.eventName} ${(args.isBackNavigation ? "back" : "forward") }`
};
let topmost = topmostFrame();
let mainTestPage = topmost.currentPage;
let originalMainPageId = mainTestPage.id;
mainTestPage.id = "main-page";
@@ -193,6 +290,7 @@ function _test_NavigationEvents(transition?: NavigationTransition) {
let actualSecondPageEvents = new Array<string>();
let secondPageFactory = function (): Page {
var secondPage = new Page();
secondPage.actionBarHidden = true;
secondPage.id = "second-page"
secondPage.on(Page.navigatingFromEvent, (args: NavigatedData) => { actualSecondPageEvents.push(argsToString(args)); });
secondPage.on(Page.navigatedFromEvent, (args: NavigatedData) => { actualSecondPageEvents.push(argsToString(args)); });
@@ -203,12 +301,14 @@ function _test_NavigationEvents(transition?: NavigationTransition) {
};
// Go to other page
topmost.navigate({ create: secondPageFactory, transition: transition });
TKUnit.waitUntilReady(() => { return topmost.currentPage !== mainTestPage; });
topmost.navigate({ create: secondPageFactory, transition: transition, animated: true });
waitUntilNavigatedFrom(mainTestPage);
// Go back to main
let currentPage = topmost.currentPage;
topmost.goBack();
TKUnit.waitUntilReady(() => { return topmost.currentPage === mainTestPage; });
waitUntilNavigatedFrom(currentPage);
mainTestPage.id = originalMainPageId;
let expectedMainPageEvents = [
@@ -227,12 +327,15 @@ function _test_NavigationEvents(transition?: NavigationTransition) {
];
TKUnit.arrayAssert(actualSecondPageEvents, expectedSecondPageEvents, "Actual second-page events are different from expected.");
TKUnit.assertEqual(topmost.currentPage, mainTestPage, "We should be on the main test page at the end of the test.");
}
export var test_NavigationEvents = function () {
androidGC();
_test_NavigationEvents();
}
export var test_NavigationEvents_WithTransition = function () {
_test_NavigationEvents({ name: "slide" });
androidGC();
_test_NavigationEvents({ name: "fade" });
}

View File

@@ -3,7 +3,7 @@ import * as helper from "../ui/helper";
import * as platform from "platform";
import * as trace from "trace";
import {Color} from "color";
import {NavigationEntry, NavigationTransition} from "ui/frame";
import {NavigationEntry, NavigationTransition, topmost as topmostFrame} from "ui/frame";
import {Page} from "ui/page";
import {AnimationCurve} from "ui/enums"
@@ -29,6 +29,12 @@ function _testTransition(navigationTransition: NavigationTransition) {
// Extremely slow. Run only if needed.
export var test_Transitions = function () {
let topmost = topmostFrame();
let mainTestPage = topmost.currentPage;
let mainPageFactory = function (): Page {
return mainTestPage;
};
helper.navigate(() => {
var page = new Page();
page.id = "TransitionsTestPage_MAIN"
@@ -77,4 +83,14 @@ export var test_Transitions = function () {
var customTransition = new customTransitionModule.CustomTransition();
_testTransition({ instance: customTransition });
}
var oldPage = topmost.currentPage;
topmost.navigate({ create: mainPageFactory, clearHistory: true, animated: false });
TKUnit.waitUntilReady(() => {
return topmost.currentPage
&& topmost.currentPage !== oldPage
&& topmost.currentPage.isLoaded
&& !oldPage.isLoaded
;
});
}