fix-next: ensure proper events on tab change (#5468)

This commit is contained in:
Martin Yankov
2018-02-28 10:40:05 +02:00
committed by GitHub
parent 949a99ec35
commit 27622d83ba
7 changed files with 141 additions and 25 deletions

View File

@ -1,4 +1,5 @@
import * as TKUnit from "../TKUnit";
import * as helper from "../ui/helper";
import { Page } from "tns-core-modules/ui/page";
import { Frame, NavigationEntry, stack } from "tns-core-modules/ui/frame";
import { _resetRootView, getRootView } from "tns-core-modules/application";
@ -47,8 +48,7 @@ function createTestTabRootEntry() {
export function test_reset_frame_to_frame() {
const testFrameRoot1 = createTestFrameRootEntry();
_resetRootView(testFrameRoot1.entry);
TKUnit.waitUntilReady(() => testFrameRoot1.page.isLoaded);
helper.waitUntilNavigatedTo(testFrameRoot1.page, () => _resetRootView(testFrameRoot1.entry));
const rootView1 = getRootView();
const frameStack1 = stack();
@ -57,8 +57,7 @@ export function test_reset_frame_to_frame() {
const testFrameRoot2 = createTestFrameRootEntry();
_resetRootView(testFrameRoot2.entry);
TKUnit.waitUntilReady(() => testFrameRoot2.page.isLoaded);
helper.waitUntilNavigatedTo(testFrameRoot2.page, () => _resetRootView(testFrameRoot2.entry));
const rootView2 = getRootView();
const frameStack2 = stack();
@ -69,8 +68,7 @@ export function test_reset_frame_to_frame() {
export function test_reset_frame_to_tab() {
const testFrameRoot = createTestFrameRootEntry();
_resetRootView(testFrameRoot.entry);
TKUnit.waitUntilReady(() => testFrameRoot.page.isLoaded);
helper.waitUntilNavigatedTo(testFrameRoot.page, () => _resetRootView(testFrameRoot.entry));
const rootView1 = getRootView();
const frameStack1 = stack();
@ -79,8 +77,7 @@ export function test_reset_frame_to_tab() {
const testTabRoot = createTestTabRootEntry();
_resetRootView(testTabRoot.entry);
TKUnit.waitUntilReady(() => testTabRoot.page.isLoaded);
helper.waitUntilNavigatedTo(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
const rootView2 = getRootView();
const frameStack2 = stack();
@ -91,8 +88,7 @@ export function test_reset_frame_to_tab() {
export function test_reset_tab_to_frame() {
const testTabRoot = createTestTabRootEntry();
_resetRootView(testTabRoot.entry);
TKUnit.waitUntilReady(() => testTabRoot.page.isLoaded);
helper.waitUntilNavigatedTo(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
const rootView2 = getRootView();
const frameStack2 = stack();
@ -101,8 +97,7 @@ export function test_reset_tab_to_frame() {
const testFrameRoot = createTestFrameRootEntry();
_resetRootView(testFrameRoot.entry);
TKUnit.waitUntilReady(() => testFrameRoot.page.isLoaded);
helper.waitUntilNavigatedTo(testFrameRoot.page, () => _resetRootView(testFrameRoot.entry));
const rootView1 = getRootView();
const frameStack1 = stack();
@ -113,8 +108,7 @@ export function test_reset_tab_to_frame() {
export function test_reset_tab_to_tab() {
const testTabRoot1 = createTestTabRootEntry();
_resetRootView(testTabRoot1.entry);
TKUnit.waitUntilReady(() => testTabRoot1.page.isLoaded);
helper.waitUntilNavigatedTo(testTabRoot1.page, () => _resetRootView(testTabRoot1.entry));
const rootView1 = getRootView();
const frameStack1 = stack();
@ -123,8 +117,7 @@ export function test_reset_tab_to_tab() {
const testTabRoot2 = createTestTabRootEntry();
_resetRootView(testTabRoot2.entry);
TKUnit.waitUntilReady(() => testTabRoot2.page.isLoaded);
helper.waitUntilNavigatedTo(testTabRoot2.page, () => _resetRootView(testTabRoot2.entry));
const rootView2 = getRootView();
const frameStack2 = stack();
@ -132,6 +125,20 @@ export function test_reset_tab_to_tab() {
TKUnit.assertEqual(frameStack2.length, 2);
};
export function test_reset_during_tab_index_change() {
const testTabRoot = createTestTabRootEntry();
helper.waitUntilNavigatedTo(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
testTabRoot.root.selectedIndex = 1;
const testFrameRoot = createTestFrameRootEntry();
helper.waitUntilNavigatedTo(testFrameRoot.page, () => _resetRootView(testFrameRoot.entry));
TKUnit.assertTrue(true);
}
export function tearDownModule() {
// reset the root to frame for other tests
const resetFrameRoot = createTestFrameRootEntry();

View File

@ -165,6 +165,9 @@ allTests["TAB-VIEW"] = tabViewTests;
import * as tabViewNavigationTests from "./ui/tab-view/tab-view-navigation-tests";
allTests["TAB-VIEW-NAVIGATION"] = tabViewNavigationTests;
import * as tabViewRootTests from "./ui/tab-view/tab-view-root-tests";
allTests["TAB-VIEW-ROOT"] = tabViewRootTests;
import * as imageTests from "./ui/image/image-tests";
allTests["IMAGE"] = imageTests;

View File

@ -154,6 +154,18 @@ export function getClearCurrentPage(): Page {
return page;
}
export function waitUntilNavigatedTo(page: Page, action: Function) {
let completed = false;
function navigatedTo(args) {
args.object.page.off("navigatedTo", navigatedTo);
completed = true;
}
page.on("navigatedTo", navigatedTo);
action();
TKUnit.waitUntilReady(() => completed, 100);
}
export function waitUntilNavigatedFrom(action: Function) {
const currentPage = frame.topmost().currentPage;
let completed = false;

View File

@ -0,0 +1,91 @@
import * as helper from "../helper";
import TKUnit = require("../../TKUnit");
import { _resetRootView } from "tns-core-modules/application/";
import { Frame, NavigationEntry } from "tns-core-modules/ui/frame";
import { Page } from "tns-core-modules/ui/page";
import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view";
export function test_whenChangingTabsWithFramesCorrectEventsAreRaised() {
const actualEventsRaised = [];
function attachPageEventHandlers(page: Page) {
page.on(Page.loadedEvent, () => actualEventsRaised.push(`${page.id} loaded`));
page.on(Page.unloadedEvent, () => actualEventsRaised.push(`${page.id} unloaded`));
page.on(Page.navigatingToEvent, () => actualEventsRaised.push(`${page.id} navigatingTo`));
page.on(Page.navigatingFromEvent, () => actualEventsRaised.push(`${page.id} navigatingFrom`));
page.on(Page.navigatedToEvent, () => actualEventsRaised.push(`${page.id} navigatedTo`));
page.on(Page.navigatedFromEvent, () => actualEventsRaised.push(`${page.id} navigatedFrom`));
}
function attachFrameEventHandlers(frame: Frame) {
frame.on(Frame.loadedEvent, () => actualEventsRaised.push(`${frame.id} loaded`));
frame.on(Frame.unloadedEvent, () => actualEventsRaised.push(`${frame.id} unloaded`));
}
const page1 = new Page();
page1.id = "Tab1 Frame1 Page1";
attachPageEventHandlers(page1);
const frame1 = new Frame();
frame1.navigate(() => page1);
frame1.id = "Tab1 Frame1";
attachFrameEventHandlers(frame1);
const page2 = new Page();
page2.id = "Tab2 Frame2 Page2";
attachPageEventHandlers(page2);
const frame2 = new Frame();
frame2.navigate(() => page2);
frame2.id = "Tab2 Frame2";
attachFrameEventHandlers(frame2);
const tabView = new TabView();
const tabEntry1 = new TabViewItem();
tabEntry1.title = "frame1";
tabEntry1.view = frame1;
const tabEntry2 = new TabViewItem();
tabEntry2.title = "frame2";
tabEntry2.view = frame2;
tabView.items = [tabEntry1, tabEntry2];
const entry: NavigationEntry = {
create: () => tabView
};
helper.waitUntilNavigatedTo(page1, () => _resetRootView(entry));
helper.waitUntilNavigatedTo(page2, () => tabView.selectedIndex = 1);
tabView.selectedIndex = 0;
TKUnit.waitUntilReady(() => page1.isLoaded);
const expectedEventsRaised = [
"Tab1 Frame1 loaded",
"Tab1 Frame1 Page1 navigatingTo",
"Tab1 Frame1 Page1 loaded",
"Tab1 Frame1 Page1 navigatedTo",
"Tab1 Frame1 Page1 unloaded",
"Tab1 Frame1 unloaded",
"Tab2 Frame2 loaded",
"Tab2 Frame2 Page2 navigatingTo",
"Tab2 Frame2 Page2 loaded",
"Tab2 Frame2 Page2 navigatedTo",
"Tab2 Frame2 Page2 unloaded",
"Tab2 Frame2 unloaded",
"Tab1 Frame1 Page1 loaded",
"Tab1 Frame1 loaded"
];
TKUnit.arrayAssert(actualEventsRaised, expectedEventsRaised);
}
export function tearDownModule() {
const page = new Page();
const frame = new Frame();
frame.navigate(() => page);
const entry: NavigationEntry = {
create: () => frame
};
helper.waitUntilNavigatedTo(page, () => _resetRootView(entry));
}

View File

@ -201,9 +201,7 @@ export class Frame extends FrameBase {
const currentEntryChanged = current !== entry;
if (currentEntryChanged) {
this._updateBackstack(entry, isBack);
}
if (currentEntryChanged) {
// If activity was destroyed we need to destroy fragment and UI
// of current and new entries.
if (this._tearDownPending) {
@ -936,7 +934,9 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
public resetActivityContent(activity: android.app.Activity): void {
if (this._rootView) {
// if we already have a root view, we reset it.
const manager = this._rootView._getFragmentManager();
manager.executePendingTransactions();
this._rootView._onRootViewReset();
}
// Delete previously cached root view in order to recreate it.

View File

@ -38,11 +38,13 @@ export class Frame extends FrameBase {
}
public setCurrent(entry: BackstackEntry, isBack: boolean): void {
if (entry !== this._currentEntry) {
const current = this._currentEntry;
const currentEntryChanged = current !== entry;
if (currentEntryChanged) {
this._updateBackstack(entry, isBack);
}
super.setCurrent(entry, isBack);
super.setCurrent(entry, isBack);
}
}
@profile

View File

@ -32,7 +32,7 @@ class UITabBarControllerImpl extends UITabBarController {
public viewWillAppear(animated: boolean): void {
super.viewWillAppear(animated);
const owner = this._owner.get();
if(!owner){
if (!owner) {
return;
}
@ -147,7 +147,7 @@ function updateItemIconPosition(tabBarItem: UITabBarItem): void {
export class TabViewItem extends TabViewItemBase {
private __controller: UIViewController;
public setViewController(controller: UIViewController, nativeView: UIView) {
this.__controller = controller;
this.setNativeView(nativeView);
@ -295,7 +295,7 @@ export class TabView extends TabViewBase {
private getViewController(item: TabViewItem): UIViewController {
let newController: UIViewController = item.view ? item.view.viewController : null;
if (newController) {
item.setViewController(newController, newController.view);
return newController;
@ -399,6 +399,7 @@ export class TabView extends TabViewBase {
}
if (value > -1) {
(<any>this._ios)._willSelectViewController = this._ios.viewControllers[value];
this._ios.selectedIndex = value;
}
}