mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 04:14:21 +08:00
fix(navcontroller): lazy loading is queued
This commit is contained in:
@ -85,6 +85,7 @@ function karmaTest(watch: boolean, done: Function) {
|
|||||||
|
|
||||||
let karmaConfig = {
|
let karmaConfig = {
|
||||||
configFile: join(SCRIPTS_ROOT, 'karma/karma.conf.js'),
|
configFile: join(SCRIPTS_ROOT, 'karma/karma.conf.js'),
|
||||||
|
singleRun: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (watch) {
|
if (watch) {
|
||||||
@ -96,6 +97,9 @@ function karmaTest(watch: boolean, done: Function) {
|
|||||||
args: ['--grep', argv.testGrep]
|
args: ['--grep', argv.testGrep]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (typeof argv.debug !== 'undefined') {
|
||||||
|
karmaConfig.singleRun = false;
|
||||||
|
}
|
||||||
|
|
||||||
new karma.Server(karmaConfig, done).start();
|
new karma.Server(karmaConfig, done).start();
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
|
|||||||
|
|
||||||
// disable console debugs/errors/warns from printing out
|
// disable console debugs/errors/warns from printing out
|
||||||
console.debug = () => {};
|
console.debug = () => {};
|
||||||
console.error = () => {};
|
// console.error = () => {};
|
||||||
console.warn = () => {};
|
console.warn = () => {};
|
||||||
|
|
||||||
__karma__.loaded = function () {};
|
__karma__.loaded = function () {};
|
||||||
|
@ -103,6 +103,13 @@ export class Animation {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the animation is a root one.
|
||||||
|
*/
|
||||||
|
isRoot(): boolean {
|
||||||
|
return !this.parent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the duration for this animation.
|
* Set the duration for this animation.
|
||||||
*/
|
*/
|
||||||
|
@ -167,8 +167,9 @@ describe('App', () => {
|
|||||||
expect(plt.exitApp).not.toHaveBeenCalled();
|
expect(plt.exitApp).not.toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should pop the second view in the root nav', () => {
|
it('should pop the second view in the root nav', () => {
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Toggle Can Leave</ion-label>
|
<ion-label>Toggle Can Leave</ion-label>
|
||||||
<ion-toggle (click)="canLeave = !canLeave"></ion-toggle>
|
<ion-toggle [(ngModel)]="canLeave"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<button ion-item (click)="viewDismiss()">View Dismiss</button>
|
<button ion-item (click)="viewDismiss()">View Dismiss</button>
|
||||||
<button ion-item (click)="quickPush()">New push during transition</button>
|
<button ion-item (click)="quickPush()">New push during transition</button>
|
||||||
|
@ -34,6 +34,7 @@ describe('Nav', () => {
|
|||||||
expect(nav.setPages).toHaveBeenCalledWith(knownViews, null, null);
|
expect(nav.setPages).toHaveBeenCalledWith(knownViews, null, null);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -56,6 +57,7 @@ describe('Nav', () => {
|
|||||||
expect(nav.setPages).toHaveBeenCalledWith(knownViews, null, null);
|
expect(nav.setPages).toHaveBeenCalledWith(knownViews, null, null);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -72,7 +74,8 @@ describe('Nav', () => {
|
|||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
expect(nav.push).toHaveBeenCalled();
|
expect(nav.push).toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -292,7 +292,7 @@ export class Tab extends NavControllerBase {
|
|||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
load(opts: NavOptions, done?: Function) {
|
load(opts: NavOptions, done?: () => void) {
|
||||||
if (!this._loaded && this.root) {
|
if (!this._loaded && this.root) {
|
||||||
this.setElementClass('show-tab', true);
|
this.setElementClass('show-tab', true);
|
||||||
this.push(this.root, this.rootParams, opts, done);
|
this.push(this.root, this.rootParams, opts, done);
|
||||||
@ -305,7 +305,7 @@ export class Tab extends NavControllerBase {
|
|||||||
this._dom.read(() => {
|
this._dom.read(() => {
|
||||||
this.resize();
|
this.resize();
|
||||||
});
|
});
|
||||||
done(true);
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +162,6 @@ describe('Tabs', () => {
|
|||||||
it('should get the tab', () => {
|
it('should get the tab', () => {
|
||||||
var tabs = mockTabs();
|
var tabs = mockTabs();
|
||||||
var tab0 = mockTab(tabs);
|
var tab0 = mockTab(tabs);
|
||||||
tab0.setRoot(<any>{});
|
|
||||||
var tab1 = mockTab(tabs);
|
var tab1 = mockTab(tabs);
|
||||||
|
|
||||||
expect(tabs.getIndex(tab0)).toEqual(0);
|
expect(tabs.getIndex(tab0)).toEqual(0);
|
||||||
|
@ -3,8 +3,8 @@ import { ComponentRef, Input, ComponentFactoryResolver, ElementRef, EventEmitter
|
|||||||
import { AnimationOptions } from '../animations/animation';
|
import { AnimationOptions } from '../animations/animation';
|
||||||
import { App } from '../components/app/app';
|
import { App } from '../components/app/app';
|
||||||
import { Config } from '../config/config';
|
import { Config } from '../config/config';
|
||||||
import { convertToView, convertToViews, NavOptions, DIRECTION_BACK, DIRECTION_FORWARD, INIT_ZINDEX,
|
import { convertToViews, NavOptions, NavResult, DIRECTION_BACK, DIRECTION_FORWARD, INIT_ZINDEX,
|
||||||
TransitionResolveFn, TransitionInstruction, STATE_NEW, STATE_INITIALIZED, STATE_ATTACHED, STATE_DESTROYED } from './nav-util';
|
TransitionInstruction, STATE_NEW, STATE_INITIALIZED, STATE_ATTACHED, STATE_DESTROYED } from './nav-util';
|
||||||
import { setZIndex } from './nav-util';
|
import { setZIndex } from './nav-util';
|
||||||
import { DeepLinker } from './deep-linker';
|
import { DeepLinker } from './deep-linker';
|
||||||
import { DomController } from '../platform/dom-controller';
|
import { DomController } from '../platform/dom-controller';
|
||||||
@ -80,40 +80,31 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
this.id = 'n' + (++ctrlIds);
|
this.id = 'n' + (++ctrlIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
push(page: any, params?: any, opts?: NavOptions, done?: Function): Promise<any> {
|
push(page: any, params?: any, opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
return convertToView(this._linker, page, params).then(viewController => {
|
return this._queueTrns({
|
||||||
return this._queueTrns({
|
insertStart: -1,
|
||||||
insertStart: -1,
|
insertViews: [{ page: page, params: params }],
|
||||||
insertViews: [viewController],
|
opts: opts,
|
||||||
opts: opts,
|
}, done);
|
||||||
}, done);
|
|
||||||
}).catch((err: Error) => {
|
|
||||||
console.error('Failed to navigate: ', err.message);
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
insert(insertIndex: number, page: any, params?: any, opts?: NavOptions, done?: Function): Promise<any> {
|
insert(insertIndex: number, page: any, params?: any, opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
return convertToView(this._linker, page, params).then(viewController => {
|
return this._queueTrns({
|
||||||
return this._queueTrns({
|
insertStart: insertIndex,
|
||||||
insertStart: insertIndex,
|
insertViews: [{ page: page, params: params }],
|
||||||
insertViews: [viewController],
|
opts: opts,
|
||||||
opts: opts,
|
}, done);
|
||||||
}, done);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
insertPages(insertIndex: number, insertPages: any[], opts?: NavOptions, done?: Function): Promise<any> {
|
insertPages(insertIndex: number, insertPages: any[], opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
return convertToViews(this._linker, insertPages).then(viewControllers => {
|
return this._queueTrns({
|
||||||
return this._queueTrns({
|
insertStart: insertIndex,
|
||||||
insertStart: insertIndex,
|
insertViews: insertPages,
|
||||||
insertViews: viewControllers,
|
opts: opts,
|
||||||
opts: opts,
|
}, done);
|
||||||
}, done);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pop(opts?: NavOptions, done?: Function): Promise<any> {
|
pop(opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
return this._queueTrns({
|
return this._queueTrns({
|
||||||
removeStart: -1,
|
removeStart: -1,
|
||||||
removeCount: 1,
|
removeCount: 1,
|
||||||
@ -121,7 +112,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}, done);
|
}, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
popTo(indexOrViewCtrl: any, opts?: NavOptions, done?: Function): Promise<any> {
|
popTo(indexOrViewCtrl: any, opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
let config: TransitionInstruction = {
|
let config: TransitionInstruction = {
|
||||||
removeStart: -1,
|
removeStart: -1,
|
||||||
removeCount: -1,
|
removeCount: -1,
|
||||||
@ -136,7 +127,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
return this._queueTrns(config, done);
|
return this._queueTrns(config, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
popToRoot(opts?: NavOptions, done?: Function): Promise<any> {
|
popToRoot(opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
return this._queueTrns({
|
return this._queueTrns({
|
||||||
removeStart: 1,
|
removeStart: 1,
|
||||||
removeCount: -1,
|
removeCount: -1,
|
||||||
@ -152,7 +143,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(startIndex: number, removeCount: number = 1, opts?: NavOptions, done?: Function): Promise<any> {
|
remove(startIndex: number, removeCount: number = 1, opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
return this._queueTrns({
|
return this._queueTrns({
|
||||||
removeStart: startIndex,
|
removeStart: startIndex,
|
||||||
removeCount: removeCount,
|
removeCount: removeCount,
|
||||||
@ -160,7 +151,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}, done);
|
}, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeView(viewController: ViewController, opts?: NavOptions, done?: Function): Promise<any> {
|
removeView(viewController: ViewController, opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
return this._queueTrns({
|
return this._queueTrns({
|
||||||
removeView: viewController,
|
removeView: viewController,
|
||||||
removeStart: 0,
|
removeStart: 0,
|
||||||
@ -169,19 +160,12 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}, done);
|
}, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
setRoot(pageOrViewCtrl: any, params?: any, opts?: NavOptions, done?: Function): Promise<any> {
|
setRoot(pageOrViewCtrl: any, params?: any, opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
return convertToView(this._linker, pageOrViewCtrl, params).then((viewController) => {
|
return this.setPages([{ page: pageOrViewCtrl, params: params }], opts, done);
|
||||||
return this._setPages([viewController], opts, done);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setPages(pages: any[], opts?: NavOptions, done?: Function): Promise<any> {
|
|
||||||
return convertToViews(this._linker, pages).then(viewControllers => {
|
|
||||||
return this._setPages(viewControllers, opts, done);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_setPages(viewControllers: ViewController[], opts?: NavOptions, done?: Function): Promise<any> {
|
setPages(viewControllers: any[], opts?: NavOptions, done?: () => void): Promise<any> {
|
||||||
if (isBlank(opts)) {
|
if (isBlank(opts)) {
|
||||||
opts = {};
|
opts = {};
|
||||||
}
|
}
|
||||||
@ -208,81 +192,68 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
// 7. _transitionStart(): called once the transition actually starts, it initializes the Animation underneath.
|
// 7. _transitionStart(): called once the transition actually starts, it initializes the Animation underneath.
|
||||||
// 8. _transitionFinish(): called once the transition finishes
|
// 8. _transitionFinish(): called once the transition finishes
|
||||||
// 9. _cleanup(): syncs the navigation internal state with the DOM. For example it removes the pages from the DOM or hides/show them.
|
// 9. _cleanup(): syncs the navigation internal state with the DOM. For example it removes the pages from the DOM or hides/show them.
|
||||||
_queueTrns(ti: TransitionInstruction, done: Function): Promise<any> {
|
_queueTrns(ti: TransitionInstruction, done: () => void): Promise<boolean> {
|
||||||
let promise: Promise<any>;
|
const promise = new Promise<boolean>((resolve, reject) => {
|
||||||
let resolve: Function = done;
|
ti.resolve = resolve;
|
||||||
let reject: Function = done;
|
ti.reject = reject;
|
||||||
|
});
|
||||||
|
ti.done = done;
|
||||||
|
|
||||||
if (done === undefined) {
|
// Normalize empty
|
||||||
// only create a promise if a done callback wasn't provided
|
if (ti.insertViews && ti.insertViews.length === 0) {
|
||||||
// done can be a null, which avoids any functions
|
ti.insertViews = undefined;
|
||||||
promise = new Promise((res, rej) => {
|
|
||||||
resolve = res;
|
|
||||||
reject = rej;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ti.resolve() is called when the navigation transition is finished successfully
|
|
||||||
ti.resolve = (hasCompleted: boolean, isAsync: boolean, enteringName: string, leavingName: string, direction: string) => {
|
|
||||||
this._trnsId = null;
|
|
||||||
this._init = true;
|
|
||||||
resolve && resolve(hasCompleted, isAsync, enteringName, leavingName, direction);
|
|
||||||
|
|
||||||
// let's see if there's another to kick off
|
|
||||||
this.setTransitioning(false);
|
|
||||||
this._swipeBackCheck();
|
|
||||||
this._nextTrns();
|
|
||||||
};
|
|
||||||
|
|
||||||
// ti.reject() is called when the navigation transition fails. ie. it is rejected at some point.
|
|
||||||
ti.reject = (rejectReason: any, transition: Transition) => {
|
|
||||||
this._trnsId = null;
|
|
||||||
this._queue.length = 0;
|
|
||||||
|
|
||||||
// walk through the transition views so they are destroyed
|
|
||||||
while (transition) {
|
|
||||||
var enteringView = transition.enteringView;
|
|
||||||
if (enteringView && (enteringView._state === STATE_ATTACHED)) {
|
|
||||||
this._destroyView(enteringView);
|
|
||||||
}
|
|
||||||
if (transition.isRoot()) {
|
|
||||||
this._trnsCtrl.destroy(transition.trnsId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
transition = transition.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
reject && reject(false, false, rejectReason);
|
|
||||||
|
|
||||||
// let's see if there's another to kick off
|
|
||||||
this.setTransitioning(false);
|
|
||||||
this._swipeBackCheck();
|
|
||||||
this._nextTrns();
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ti.insertViews) {
|
|
||||||
// ensure we've got good views to insert
|
|
||||||
ti.insertViews = ti.insertViews.filter(v => v !== null);
|
|
||||||
if (ti.insertViews.length === 0) {
|
|
||||||
ti.reject('invalid views to insert');
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (isPresent(ti.removeStart) && this._views.length === 0 && !this._isPortal) {
|
|
||||||
ti.reject('no views in the stack to be removed');
|
|
||||||
return promise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enqueue transition instruction
|
||||||
this._queue.push(ti);
|
this._queue.push(ti);
|
||||||
|
|
||||||
// if there isn't a transition already happening
|
// if there isn't a transition already happening
|
||||||
// then this will kick off this transition
|
// then this will kick off this transition
|
||||||
this._nextTrns();
|
this._nextTrns();
|
||||||
|
|
||||||
// promise is undefined if a done callbacks was provided
|
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_success(result: NavResult, ti: TransitionInstruction) {
|
||||||
|
this._init = true;
|
||||||
|
this._trnsId = null;
|
||||||
|
|
||||||
|
// let's see if there's another to kick off
|
||||||
|
this.setTransitioning(false);
|
||||||
|
this._swipeBackCheck();
|
||||||
|
this._nextTrns();
|
||||||
|
|
||||||
|
if (ti.done) {
|
||||||
|
ti.done(
|
||||||
|
result.hasCompleted,
|
||||||
|
result.requiresTransition,
|
||||||
|
result.enteringName,
|
||||||
|
result.leavingName,
|
||||||
|
result.direction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ti.resolve(result.hasCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
_failed(rejectReason: any, ti: TransitionInstruction) {
|
||||||
|
this._trnsId = null;
|
||||||
|
this._queue.length = 0;
|
||||||
|
|
||||||
|
// let's see if there's another to kick off
|
||||||
|
this.setTransitioning(false);
|
||||||
|
this._swipeBackCheck();
|
||||||
|
this._nextTrns();
|
||||||
|
|
||||||
|
if (ti.done) {
|
||||||
|
ti.done(false, false, rejectReason);
|
||||||
|
}
|
||||||
|
if (ti.reject) {
|
||||||
|
ti.reject(rejectReason);
|
||||||
|
} else {
|
||||||
|
ti.resolve(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_nextTrns(): boolean {
|
_nextTrns(): boolean {
|
||||||
// this is the framework's bread 'n butta function
|
// this is the framework's bread 'n butta function
|
||||||
// only one transition is allowed at any given time
|
// only one transition is allowed at any given time
|
||||||
@ -292,68 +263,53 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
|
|
||||||
// there is no transition happening right now
|
// there is no transition happening right now
|
||||||
// get the next instruction
|
// get the next instruction
|
||||||
const ti = this._nextTI();
|
const ti = this._queue.shift();
|
||||||
if (!ti) {
|
if (!ti) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure any of the inserted view are used
|
|
||||||
const insertViews = ti.insertViews;
|
|
||||||
if (insertViews) {
|
|
||||||
for (var i = 0; i < insertViews.length; i++) {
|
|
||||||
var nav = insertViews[i]._nav;
|
|
||||||
if (nav && nav !== this || insertViews[i]._state === STATE_DESTROYED) {
|
|
||||||
ti.reject('leavingView and enteringView are null. stack is already empty');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get entering and leaving views
|
|
||||||
const leavingView = this.getActive();
|
|
||||||
const enteringView = this._getEnteringView(ti, leavingView);
|
|
||||||
|
|
||||||
if (!leavingView && !enteringView) {
|
|
||||||
ti.reject('leavingView and enteringView are null. stack is already empty');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set that this nav is actively transitioning
|
// set that this nav is actively transitioning
|
||||||
this.setTransitioning(true);
|
let enteringView: ViewController;
|
||||||
|
let leavingView: ViewController;
|
||||||
|
|
||||||
// Initialize enteringView
|
this._startTI(ti)
|
||||||
if (enteringView && enteringView._state === STATE_NEW) {
|
.then(() => this._loadLazyLoading(ti))
|
||||||
// render the entering view, and all child navs and views
|
.then(() => {
|
||||||
// ******** DOM WRITE ****************
|
leavingView = this.getActive();
|
||||||
this._viewInit(enteringView);
|
enteringView = this._getEnteringView(ti, leavingView);
|
||||||
}
|
|
||||||
|
|
||||||
// Only test canLeave/canEnter if there is transition
|
if (!leavingView && !enteringView) {
|
||||||
const requiresTransition = ti.requiresTransition = (ti.enteringRequiresTransition || ti.leavingRequiresTransition) && enteringView !== leavingView;
|
throw 'no views in the stack to be removed';
|
||||||
if (requiresTransition) {
|
}
|
||||||
// views have been initialized, now let's test
|
|
||||||
// to see if the transition is even allowed or not
|
if (enteringView && enteringView._state === STATE_NEW) {
|
||||||
return this._viewTest(enteringView, leavingView, ti);
|
this._viewInit(enteringView);
|
||||||
} else {
|
}
|
||||||
return this._postViewInit(enteringView, leavingView, ti);
|
|
||||||
}
|
// Needs transition?
|
||||||
|
ti.requiresTransition = (ti.enteringRequiresTransition || ti.leavingRequiresTransition) && enteringView !== leavingView;
|
||||||
|
})
|
||||||
|
.then(() => this._viewTest(enteringView, leavingView, ti))
|
||||||
|
.then(() => this._postViewInit(enteringView, leavingView, ti))
|
||||||
|
.then(() => this._transition(enteringView, leavingView, ti))
|
||||||
|
.then((result) => this._success(result, ti))
|
||||||
|
.catch((rejectReason) => this._failed(rejectReason, ti));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_nextTI(): TransitionInstruction {
|
_startTI(ti: TransitionInstruction): Promise<void> {
|
||||||
const ti = this._queue.shift();
|
|
||||||
if (!ti) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const viewsLength = this._views.length;
|
const viewsLength = this._views.length;
|
||||||
|
|
||||||
if (isPresent(ti.removeView)) {
|
if (isPresent(ti.removeView)) {
|
||||||
assert(isPresent(ti.removeStart), 'removeView needs removeStart');
|
assert(isPresent(ti.removeStart), 'removeView needs removeStart');
|
||||||
assert(isPresent(ti.removeCount), 'removeView needs removeCount');
|
assert(isPresent(ti.removeCount), 'removeView needs removeCount');
|
||||||
|
|
||||||
var index = this._views.indexOf(ti.removeView);
|
const index = this.indexOf(ti.removeView);
|
||||||
if (index >= 0) {
|
if (index < 0) {
|
||||||
ti.removeStart += index;
|
return Promise.reject('removeView was not found');
|
||||||
}
|
}
|
||||||
|
ti.removeStart += index;
|
||||||
}
|
}
|
||||||
if (isPresent(ti.removeStart)) {
|
if (isPresent(ti.removeStart)) {
|
||||||
if (ti.removeStart < 0) {
|
if (ti.removeStart < 0) {
|
||||||
@ -373,7 +329,35 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}
|
}
|
||||||
ti.enteringRequiresTransition = (ti.insertStart === viewsLength);
|
ti.enteringRequiresTransition = (ti.insertStart === viewsLength);
|
||||||
}
|
}
|
||||||
return ti;
|
this.setTransitioning(true);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadLazyLoading(ti: TransitionInstruction): Promise<void> {
|
||||||
|
const insertViews = ti.insertViews;
|
||||||
|
if (insertViews) {
|
||||||
|
assert(insertViews.length > 0, 'length can not be zero');
|
||||||
|
return convertToViews(this._linker, insertViews).then((viewControllers) => {
|
||||||
|
assert(insertViews.length === viewControllers.length, 'lengths does not match');
|
||||||
|
|
||||||
|
// Check all the inserted view are correct
|
||||||
|
for (var i = 0; i < viewControllers.length; i++) {
|
||||||
|
var view = viewControllers[i];
|
||||||
|
if (!view) {
|
||||||
|
throw 'invalid views to insert';
|
||||||
|
}
|
||||||
|
var nav = view._nav;
|
||||||
|
if (nav && nav !== this) {
|
||||||
|
throw 'inserted view was already inserted';
|
||||||
|
}
|
||||||
|
if (viewControllers[i]._state === STATE_DESTROYED) {
|
||||||
|
throw 'inserted view was already destroyed';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ti.insertViews = viewControllers;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
_getEnteringView(ti: TransitionInstruction, leavingView: ViewController): ViewController {
|
_getEnteringView(ti: TransitionInstruction, leavingView: ViewController): ViewController {
|
||||||
@ -435,10 +419,10 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
console.warn(`You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.`,
|
console.warn(`You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.`,
|
||||||
this, this.getNativeElement());
|
this, this.getNativeElement());
|
||||||
|
|
||||||
ti.reject('navigation stack needs at least one root page');
|
throw 'navigation stack needs at least one root page';
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At this point the transition can not be rejected, any throw should be an error
|
||||||
// there are views to insert
|
// there are views to insert
|
||||||
if (insertViews) {
|
if (insertViews) {
|
||||||
// manually set the new view's id if an id was passed in the options
|
// manually set the new view's id if an id was passed in the options
|
||||||
@ -479,27 +463,15 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ti.requiresTransition) {
|
|
||||||
// transition is not required, so we are already done!
|
|
||||||
// they're inserting/removing the views somewhere in the middle or
|
|
||||||
// beginning, so visually nothing needs to animate/transition
|
|
||||||
// resolve immediately because there's no animation that's happening
|
|
||||||
ti.resolve(true, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set which animation it should use if it wasn't set yet
|
// set which animation it should use if it wasn't set yet
|
||||||
if (!opts.animation) {
|
if (ti.requiresTransition && !opts.animation) {
|
||||||
if (isPresent(ti.removeStart)) {
|
if (isPresent(ti.removeStart)) {
|
||||||
opts.animation = (leavingView || enteringView).getTransitionName(opts.direction);
|
opts.animation = (leavingView || enteringView).getTransitionName(opts.direction);
|
||||||
} else {
|
} else {
|
||||||
opts.animation = (enteringView || leavingView).getTransitionName(opts.direction);
|
opts.animation = (enteringView || leavingView).getTransitionName(opts.direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ti.opts = opts;
|
||||||
// huzzah! let us transition these views
|
|
||||||
this._transitionInit(enteringView, leavingView, opts, ti.resolve);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -509,6 +481,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
assert(enteringView, 'enteringView must be non null');
|
assert(enteringView, 'enteringView must be non null');
|
||||||
assert(enteringView._state === STATE_NEW, 'enteringView state must be NEW');
|
assert(enteringView._state === STATE_NEW, 'enteringView state must be NEW');
|
||||||
|
|
||||||
|
// render the entering view, and all child navs and views
|
||||||
// entering view has not been initialized yet
|
// entering view has not been initialized yet
|
||||||
const componentProviders = ReflectiveInjector.resolve([
|
const componentProviders = ReflectiveInjector.resolve([
|
||||||
{ provide: NavController, useValue: this },
|
{ provide: NavController, useValue: this },
|
||||||
@ -551,52 +524,52 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
this._zone.run(this._didLoad.bind(this, view));
|
this._zone.run(this._didLoad.bind(this, view));
|
||||||
}
|
}
|
||||||
|
|
||||||
_viewTest(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction): boolean {
|
_viewTest(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction): Promise<void> {
|
||||||
|
// Only test canLeave/canEnter if there is transition
|
||||||
|
if (!ti.requiresTransition) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
const promises: Promise<any>[] = [];
|
const promises: Promise<any>[] = [];
|
||||||
|
|
||||||
if (leavingView) {
|
if (leavingView) {
|
||||||
var leavingTestResult = leavingView._lifecycleTest('Leave');
|
promises.push(leavingView._lifecycleTest('Leave'));
|
||||||
|
|
||||||
if (leavingTestResult === false) {
|
|
||||||
// synchronous reject
|
|
||||||
ti.reject((leavingTestResult !== false ? leavingTestResult : `ionViewCanLeave rejected`));
|
|
||||||
return false;
|
|
||||||
} else if (leavingTestResult instanceof Promise) {
|
|
||||||
// async promise
|
|
||||||
promises.push(leavingTestResult);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enteringView) {
|
if (enteringView) {
|
||||||
var enteringTestResult = enteringView._lifecycleTest('Enter');
|
promises.push(enteringView._lifecycleTest('Enter'));
|
||||||
|
}
|
||||||
|
|
||||||
if (enteringTestResult === false) {
|
if (promises.length === 0) {
|
||||||
// synchronous reject
|
return Promise.resolve();
|
||||||
ti.reject((enteringTestResult !== false ? enteringTestResult : `ionViewCanEnter rejected`));
|
}
|
||||||
return false;
|
|
||||||
} else if (enteringTestResult instanceof Promise) {
|
// darn, async promises, gotta wait for them to resolve
|
||||||
// async promise
|
return Promise.all(promises).then((values: any[]) => {
|
||||||
promises.push(enteringTestResult);
|
if (values.some(result => result === false)) {
|
||||||
|
throw 'canEnter/Leave returned false';
|
||||||
}
|
}
|
||||||
}
|
}).catch((reason) => {
|
||||||
|
// Do not
|
||||||
if (promises.length) {
|
ti.reject = null;
|
||||||
// darn, async promises, gotta wait for them to resolve
|
throw reason;
|
||||||
Promise.all(promises).then((values: any[]) => {
|
});
|
||||||
if (values.some(result => result === false)) {
|
|
||||||
ti.reject(`ionViewCanEnter rejected`);
|
|
||||||
} else {
|
|
||||||
this._postViewInit(enteringView, leavingView, ti);
|
|
||||||
}
|
|
||||||
}).catch(ti.reject);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// synchronous and all tests passed! let's move on already
|
|
||||||
return this._postViewInit(enteringView, leavingView, ti);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_transitionInit(enteringView: ViewController, leavingView: ViewController, opts: NavOptions, resolve: TransitionResolveFn) {
|
_transition(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction): Promise<NavResult> {
|
||||||
|
|
||||||
|
if (!ti.requiresTransition) {
|
||||||
|
// transition is not required, so we are already done!
|
||||||
|
// they're inserting/removing the views somewhere in the middle or
|
||||||
|
// beginning, so visually nothing needs to animate/transition
|
||||||
|
// resolve immediately because there's no animation that's happening
|
||||||
|
return Promise.resolve({
|
||||||
|
hasCompleted: true,
|
||||||
|
requiresTransition: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const opts = ti.opts;
|
||||||
|
|
||||||
// figure out if this transition is the root one or a
|
// figure out if this transition is the root one or a
|
||||||
// child of a parent nav that has the root transition
|
// child of a parent nav that has the root transition
|
||||||
this._trnsId = this._trnsCtrl.getRootTrnsId(this);
|
this._trnsId = this._trnsCtrl.getRootTrnsId(this);
|
||||||
@ -630,11 +603,8 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// transition start has to be registered before attaching the view to the DOM!
|
// transition start has to be registered before attaching the view to the DOM!
|
||||||
transition.registerStart(() => {
|
const promise = new Promise<void>(resolve => transition.registerStart(resolve)).then(() => {
|
||||||
this._transitionStart(transition, enteringView, leavingView, opts, resolve);
|
return this._transitionStart(transition, enteringView, leavingView, opts);
|
||||||
if (transition.parent) {
|
|
||||||
transition.parent.start();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (enteringView && (enteringView._state === STATE_INITIALIZED)) {
|
if (enteringView && (enteringView._state === STATE_INITIALIZED)) {
|
||||||
@ -645,13 +615,15 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
this._viewAttachToDOM(enteringView, enteringView._cmp, this._viewport);
|
this._viewAttachToDOM(enteringView, enteringView._cmp, this._viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!transition.hasChildren) {
|
if (!transition.hasChildren) {
|
||||||
// lowest level transition, so kick it off and let it bubble up to start all of them
|
// lowest level transition, so kick it off and let it bubble up to start all of them
|
||||||
transition.start();
|
transition.start();
|
||||||
}
|
}
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
_transitionStart(transition: Transition, enteringView: ViewController, leavingView: ViewController, opts: NavOptions, resolve: TransitionResolveFn) {
|
_transitionStart(transition: Transition, enteringView: ViewController, leavingView: ViewController, opts: NavOptions): Promise<NavResult> {
|
||||||
assert(this.isTransitioning(), 'isTransitioning() has to be true');
|
assert(this.isTransitioning(), 'isTransitioning() has to be true');
|
||||||
|
|
||||||
this._trnsId = null;
|
this._trnsId = null;
|
||||||
@ -689,15 +661,14 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
// that will fire off the willEnter/Leave lifecycle events at the right time
|
// that will fire off the willEnter/Leave lifecycle events at the right time
|
||||||
transition.beforeAddRead(this._viewsWillLifecycles.bind(this, enteringView, leavingView));
|
transition.beforeAddRead(this._viewsWillLifecycles.bind(this, enteringView, leavingView));
|
||||||
|
|
||||||
// create a callback for when the animation is done
|
|
||||||
transition.onFinish(() => {
|
|
||||||
// transition animation has ended
|
|
||||||
this._zone.run(this._transitionFinish.bind(this, transition, opts, resolve));
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the set duration of this transition
|
// get the set duration of this transition
|
||||||
const duration = transition.getDuration();
|
const duration = transition.getDuration();
|
||||||
|
|
||||||
|
// create a callback for when the animation is done
|
||||||
|
const promise = new Promise(resolve => {
|
||||||
|
transition.onFinish(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
if (transition.isRoot()) {
|
if (transition.isRoot()) {
|
||||||
// this is the top most, or only active transition, so disable the app
|
// this is the top most, or only active transition, so disable the app
|
||||||
// add XXms to the duration the app is disabled when the keyboard is open
|
// add XXms to the duration the app is disabled when the keyboard is open
|
||||||
@ -723,9 +694,14 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
transition.play();
|
transition.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return promise.then(() => this._zone.run(() => {
|
||||||
|
return this._transitionFinish(transition, opts);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
_transitionFinish(transition: Transition, opts: NavOptions, resolve: TransitionResolveFn) {
|
_transitionFinish(transition: Transition, opts: NavOptions): NavResult {
|
||||||
|
|
||||||
const hasCompleted = transition.hasCompleted;
|
const hasCompleted = transition.hasCompleted;
|
||||||
const enteringView = transition.enteringView;
|
const enteringView = transition.enteringView;
|
||||||
const leavingView = transition.leavingView;
|
const leavingView = transition.leavingView;
|
||||||
@ -774,8 +750,13 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// congrats, we did it!
|
return {
|
||||||
resolve(hasCompleted, true, enteringName, leavingName, opts.direction);
|
hasCompleted: hasCompleted,
|
||||||
|
requiresTransition: true,
|
||||||
|
enteringName: enteringName,
|
||||||
|
leavingName: leavingName,
|
||||||
|
direction: opts.direction
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_viewsWillLifecycles(enteringView: ViewController, leavingView: ViewController) {
|
_viewsWillLifecycles(enteringView: ViewController, leavingView: ViewController) {
|
||||||
|
@ -8,7 +8,7 @@ import { NavControllerBase } from './nav-controller-base';
|
|||||||
import { Transition } from '../transitions/transition';
|
import { Transition } from '../transitions/transition';
|
||||||
|
|
||||||
|
|
||||||
export function getComponent(linker: DeepLinker, nameOrPageOrView: any, params?: any) {
|
export function getComponent(linker: DeepLinker, nameOrPageOrView: any, params?: any): Promise<ViewController> {
|
||||||
if (typeof nameOrPageOrView === 'function') {
|
if (typeof nameOrPageOrView === 'function') {
|
||||||
return Promise.resolve(
|
return Promise.resolve(
|
||||||
new ViewController(nameOrPageOrView, params)
|
new ViewController(nameOrPageOrView, params)
|
||||||
@ -24,7 +24,7 @@ export function getComponent(linker: DeepLinker, nameOrPageOrView: any, params?:
|
|||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertToView(linker: DeepLinker, nameOrPageOrView: any, params: any) {
|
export function convertToView(linker: DeepLinker, nameOrPageOrView: any, params: any): Promise<ViewController> {
|
||||||
if (nameOrPageOrView) {
|
if (nameOrPageOrView) {
|
||||||
if (isViewController(nameOrPageOrView)) {
|
if (isViewController(nameOrPageOrView)) {
|
||||||
// is already a ViewController
|
// is already a ViewController
|
||||||
@ -34,11 +34,10 @@ export function convertToView(linker: DeepLinker, nameOrPageOrView: any, params:
|
|||||||
return getComponent(linker, nameOrPageOrView, params);
|
return getComponent(linker, nameOrPageOrView, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(`invalid page component: ${nameOrPageOrView}`);
|
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertToViews(linker: DeepLinker, pages: any[]) {
|
export function convertToViews(linker: DeepLinker, pages: any[]): Promise<ViewController[]> {
|
||||||
const views: Promise<ViewController>[] = [];
|
const views: Promise<ViewController>[] = [];
|
||||||
if (isArray(pages)) {
|
if (isArray(pages)) {
|
||||||
for (var i = 0; i < pages.length; i++) {
|
for (var i = 0; i < pages.length; i++) {
|
||||||
@ -147,6 +146,14 @@ export interface NavLink {
|
|||||||
defaultHistory?: any[];
|
defaultHistory?: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NavResult {
|
||||||
|
hasCompleted: boolean;
|
||||||
|
requiresTransition: boolean;
|
||||||
|
enteringName?: string;
|
||||||
|
leavingName?: string;
|
||||||
|
direction?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface NavSegment {
|
export interface NavSegment {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
@ -188,12 +195,13 @@ export interface TransitionRejectFn {
|
|||||||
export interface TransitionInstruction {
|
export interface TransitionInstruction {
|
||||||
opts: NavOptions;
|
opts: NavOptions;
|
||||||
insertStart?: number;
|
insertStart?: number;
|
||||||
insertViews?: ViewController[];
|
insertViews?: any[];
|
||||||
removeView?: ViewController;
|
removeView?: ViewController;
|
||||||
removeStart?: number;
|
removeStart?: number;
|
||||||
removeCount?: number;
|
removeCount?: number;
|
||||||
resolve?: TransitionResolveFn;
|
resolve?: (hasCompleted: boolean) => void;
|
||||||
reject?: TransitionRejectFn;
|
reject?: (rejectReason: string) => void;
|
||||||
|
done?: Function;
|
||||||
leavingRequiresTransition?: boolean;
|
leavingRequiresTransition?: boolean;
|
||||||
enteringRequiresTransition?: boolean;
|
enteringRequiresTransition?: boolean;
|
||||||
requiresTransition?: boolean;
|
requiresTransition?: boolean;
|
||||||
|
@ -284,6 +284,7 @@ describe('DeepLinker', () => {
|
|||||||
expect(result.length).toEqual(1);
|
expect(result.length).toEqual(1);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -60,7 +60,7 @@ describe('NavController', () => {
|
|||||||
expect(nav.getByIndex(2).component).toEqual(MockView3);
|
expect(nav.getByIndex(2).component).toEqual(MockView3);
|
||||||
expect(nav.getByIndex(3).component).toEqual(MockView4);
|
expect(nav.getByIndex(3).component).toEqual(MockView4);
|
||||||
// Pop 1
|
// Pop 1
|
||||||
nav.pop({ animate: false }, pop1Done);
|
return nav.pop({ animate: false }, pop1Done);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
expect(pop1Done).toHaveBeenCalledWith(
|
expect(pop1Done).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, 'MockView3', 'MockView4', DIRECTION_BACK
|
hasCompleted, requiresTransition, 'MockView3', 'MockView4', DIRECTION_BACK
|
||||||
@ -88,9 +88,10 @@ describe('NavController', () => {
|
|||||||
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('push', () => {
|
describe('push', () => {
|
||||||
@ -108,9 +109,10 @@ describe('NavController', () => {
|
|||||||
expect(nav.isTransitioning()).toEqual(false);
|
expect(nav.isTransitioning()).toEqual(false);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should push a component as the second view at the end', (done: Function) => {
|
it('should push a component as the second view at the end', (done: Function) => {
|
||||||
mockViews(nav, [mockView(MockView1)]);
|
mockViews(nav, [mockView(MockView1)]);
|
||||||
@ -128,9 +130,10 @@ describe('NavController', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should push a ViewController as the second view and fire lifecycles', (done: Function) => {
|
it('should push a ViewController as the second view and fire lifecycles', (done: Function) => {
|
||||||
let view1 = mockView();
|
let view1 = mockView();
|
||||||
@ -169,20 +172,26 @@ describe('NavController', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('insert', () => {
|
describe('insert', () => {
|
||||||
|
|
||||||
it('should not modify the view id', () => {
|
it('should not modify the view id', (done) => {
|
||||||
let view = mockView(MockView4);
|
let view = mockView(MockView4);
|
||||||
view.id = 'custom_id';
|
view.id = 'custom_id';
|
||||||
nav.insert(0, view);
|
nav.insert(0, view).then(() => {
|
||||||
|
expect(view.id).toEqual('custom_id');
|
||||||
|
done();
|
||||||
|
}).catch(err => {
|
||||||
|
fail(err);
|
||||||
|
done();
|
||||||
|
});
|
||||||
expect(view.id).toEqual('custom_id');
|
expect(view.id).toEqual('custom_id');
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
|
|
||||||
it('should insert at the begining with no async transition', (done: Function) => {
|
it('should insert at the begining with no async transition', (done: Function) => {
|
||||||
@ -213,9 +222,10 @@ describe('NavController', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should insert at the end when given -1', (done: Function) => {
|
it('should insert at the end when given -1', (done: Function) => {
|
||||||
let opts: NavOptions = {};
|
let opts: NavOptions = {};
|
||||||
@ -231,9 +241,10 @@ describe('NavController', () => {
|
|||||||
expect(nav.last().component).toEqual(MockView2);
|
expect(nav.last().component).toEqual(MockView2);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should insert at the end when given a number greater than actual length', (done: Function) => {
|
it('should insert at the end when given a number greater than actual length', (done: Function) => {
|
||||||
mockViews(nav, [mockView(MockView1)]);
|
mockViews(nav, [mockView(MockView1)]);
|
||||||
@ -249,25 +260,28 @@ describe('NavController', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should not insert if null view', (done: Function) => {
|
it('should not insert if null view', (done: Function) => {
|
||||||
mockViews(nav, [mockView(MockView1)]);
|
mockViews(nav, [mockView(MockView1)]);
|
||||||
|
|
||||||
nav.insert(-1, null, null, null, trnsDone).then(() => {
|
nav.insert(-1, null, null, null, trnsDone).then(() => {
|
||||||
|
fail('it should not succeed');
|
||||||
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
let hasCompleted = false;
|
let hasCompleted = false;
|
||||||
let requiresTransition = false;
|
let requiresTransition = false;
|
||||||
let rejectReason = 'invalid views to insert';
|
let rejectReason = 'invalid views to insert';
|
||||||
|
expect(err).toEqual(rejectReason);
|
||||||
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, rejectReason);
|
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, rejectReason);
|
||||||
expect(nav.length()).toEqual(1);
|
expect(nav.length()).toEqual(1);
|
||||||
expect(nav.last().component).toEqual(MockView1);
|
expect(nav.last().component).toEqual(MockView1);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
|
||||||
done(err);
|
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should not insert any view in the stack if canLeave returns false', (done: Function) => {
|
it('should not insert any view in the stack if canLeave returns false', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
@ -292,12 +306,11 @@ describe('NavController', () => {
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
expect(nav.length()).toEqual(3);
|
expect(nav.length()).toEqual(3);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch(err => fail(err));
|
||||||
done(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not remove any view from the stack if canLeave returns false', () => {
|
}, 10000);
|
||||||
|
|
||||||
|
it('should not remove any view from the stack if canLeave returns false', (done) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
mockViews(nav, [view1, view2]);
|
mockViews(nav, [view1, view2]);
|
||||||
@ -310,15 +323,17 @@ describe('NavController', () => {
|
|||||||
return (count === 3);
|
return (count === 3);
|
||||||
};
|
};
|
||||||
|
|
||||||
nav.pop();
|
nav.pop().then(() => {
|
||||||
expect(nav.length()).toEqual(2);
|
expect(nav.length()).toEqual(2);
|
||||||
|
return nav.pop();
|
||||||
nav.pop();
|
}).then(() => {
|
||||||
expect(nav.length()).toEqual(2);
|
expect(nav.length()).toEqual(2);
|
||||||
|
return nav.pop();
|
||||||
nav.pop();
|
}).then(() => {
|
||||||
expect(nav.length()).toEqual(1);
|
expect(nav.length()).toEqual(1);
|
||||||
});
|
done();
|
||||||
|
}).catch(err => fail(err));
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -356,104 +371,126 @@ describe('NavController', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('pop', () => {
|
describe('pop', () => {
|
||||||
|
|
||||||
it('should not pop when no views in the stack', () => {
|
it('should not pop when no views in the stack', (done) => {
|
||||||
nav.pop(null, trnsDone);
|
nav.pop(null, trnsDone).then(() => {
|
||||||
|
fail('it should not succeed');
|
||||||
|
done();
|
||||||
|
}).catch((err) => {
|
||||||
|
let hasCompleted = false;
|
||||||
|
let requiresTransition = false;
|
||||||
|
let rejectReason = 'no views in the stack to be removed';
|
||||||
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
|
hasCompleted, requiresTransition, rejectReason
|
||||||
|
);
|
||||||
|
expect(err).toEqual(rejectReason);
|
||||||
|
expect(nav.length()).toEqual(0);
|
||||||
|
expect(nav.isTransitioning()).toEqual(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
let hasCompleted = false;
|
it('should remove the last view and fire lifecycles', (done: Function) => {
|
||||||
let requiresTransition = false;
|
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
|
||||||
hasCompleted, requiresTransition, 'no views in the stack to be removed'
|
|
||||||
);
|
|
||||||
expect(nav.length()).toEqual(0);
|
|
||||||
expect(nav.isTransitioning()).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove the last view and fire lifecycles', () => {
|
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
mockViews(nav, [view1, view2]);
|
mockViews(nav, [view1, view2]);
|
||||||
let instance1 = spyOnLifecycles(view1);
|
let instance1 = spyOnLifecycles(view1);
|
||||||
let instance2 = spyOnLifecycles(view2);
|
let instance2 = spyOnLifecycles(view2);
|
||||||
|
|
||||||
nav.pop(null, trnsDone);
|
nav.pop(null, trnsDone).then(() => {
|
||||||
|
|
||||||
expect(instance1.ionViewDidLoad).toHaveBeenCalled();
|
expect(instance1.ionViewDidLoad).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanEnter).toHaveBeenCalled();
|
expect(instance1.ionViewCanEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillEnter).toHaveBeenCalled();
|
expect(instance1.ionViewWillEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidEnter).toHaveBeenCalled();
|
expect(instance1.ionViewDidEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanLeave).toHaveBeenCalled();
|
expect(instance2.ionViewCanLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance2.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance2.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance2.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
let hasCompleted = true;
|
let hasCompleted = true;
|
||||||
let requiresTransition = true;
|
let requiresTransition = true;
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, 'MockView1', 'MockView2', DIRECTION_BACK
|
hasCompleted, requiresTransition, 'MockView1', 'MockView2', DIRECTION_BACK
|
||||||
);
|
);
|
||||||
expect(nav.length()).toEqual(1);
|
expect(nav.length()).toEqual(1);
|
||||||
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
||||||
expect(nav.isTransitioning()).toEqual(false);
|
expect(nav.isTransitioning()).toEqual(false);
|
||||||
});
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('popTo', () => {
|
describe('popTo', () => {
|
||||||
|
|
||||||
it('should pop to a view', () => {
|
it('should pop to a view', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
let view3 = mockView(MockView3);
|
let view3 = mockView(MockView3);
|
||||||
mockViews(nav, [view1, view2, view3]);
|
mockViews(nav, [view1, view2, view3]);
|
||||||
|
|
||||||
nav.popTo(view2, null, trnsDone);
|
nav.popTo(view2, null, trnsDone).then(() => {
|
||||||
|
|
||||||
let hasCompleted = true;
|
let hasCompleted = true;
|
||||||
let requiresTransition = true;
|
let requiresTransition = true;
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, 'MockView2', 'MockView3', DIRECTION_BACK
|
hasCompleted, requiresTransition, 'MockView2', 'MockView3', DIRECTION_BACK
|
||||||
);
|
);
|
||||||
expect(nav.length()).toEqual(2);
|
expect(nav.length()).toEqual(2);
|
||||||
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
||||||
expect(nav.getByIndex(1).component).toEqual(MockView2);
|
expect(nav.getByIndex(1).component).toEqual(MockView2);
|
||||||
});
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
it('should pop to using an index number', () => {
|
it('should pop to using an index number', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
let view3 = mockView(MockView3);
|
let view3 = mockView(MockView3);
|
||||||
let view4 = mockView(MockView4);
|
let view4 = mockView(MockView4);
|
||||||
mockViews(nav, [view1, view2, view3, view4]);
|
mockViews(nav, [view1, view2, view3, view4]);
|
||||||
|
|
||||||
nav.popTo(1, null, trnsDone);
|
nav.popTo(1, null, trnsDone).then(() => {
|
||||||
|
|
||||||
let hasCompleted = true;
|
let hasCompleted = true;
|
||||||
let requiresTransition = true;
|
let requiresTransition = true;
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, 'MockView2', 'MockView4', DIRECTION_BACK
|
hasCompleted, requiresTransition, 'MockView2', 'MockView4', DIRECTION_BACK
|
||||||
);
|
);
|
||||||
expect(nav.length()).toEqual(2);
|
expect(nav.length()).toEqual(2);
|
||||||
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
||||||
expect(nav.getByIndex(1).component).toEqual(MockView2);
|
expect(nav.getByIndex(1).component).toEqual(MockView2);
|
||||||
});
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
it('should pop to first using an index number', () => {
|
it('should pop to first using an index number', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
let view3 = mockView(MockView3);
|
let view3 = mockView(MockView3);
|
||||||
@ -465,58 +502,63 @@ describe('NavController', () => {
|
|||||||
let instance3 = spyOnLifecycles(view3);
|
let instance3 = spyOnLifecycles(view3);
|
||||||
let instance4 = spyOnLifecycles(view4);
|
let instance4 = spyOnLifecycles(view4);
|
||||||
|
|
||||||
nav.popTo(0, null, trnsDone);
|
nav.popTo(0, null, trnsDone).then(() => {
|
||||||
|
|
||||||
expect(instance1.ionViewDidLoad).toHaveBeenCalled();
|
expect(instance1.ionViewDidLoad).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanEnter).toHaveBeenCalled();
|
expect(instance1.ionViewCanEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillEnter).toHaveBeenCalled();
|
expect(instance1.ionViewWillEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidEnter).toHaveBeenCalled();
|
expect(instance1.ionViewDidEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance2.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance2.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance2.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanLeave).toHaveBeenCalled();
|
expect(instance4.ionViewCanLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance4.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance4.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance4.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
let hasCompleted = true;
|
let hasCompleted = true;
|
||||||
let requiresTransition = true;
|
let requiresTransition = true;
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, 'MockView1', 'MockView4', DIRECTION_BACK
|
hasCompleted, requiresTransition, 'MockView1', 'MockView4', DIRECTION_BACK
|
||||||
);
|
);
|
||||||
expect(nav.length()).toEqual(1);
|
expect(nav.length()).toEqual(1);
|
||||||
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
||||||
});
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('popToRoot', () => {
|
describe('popToRoot', () => {
|
||||||
|
|
||||||
it('should pop to the first view', () => {
|
it('should pop to the first view', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
let view3 = mockView(MockView3);
|
let view3 = mockView(MockView3);
|
||||||
@ -528,58 +570,63 @@ describe('NavController', () => {
|
|||||||
let instance3 = spyOnLifecycles(view3);
|
let instance3 = spyOnLifecycles(view3);
|
||||||
let instance4 = spyOnLifecycles(view4);
|
let instance4 = spyOnLifecycles(view4);
|
||||||
|
|
||||||
nav.popToRoot(null, trnsDone);
|
nav.popToRoot(null, trnsDone).then(() => {
|
||||||
|
|
||||||
expect(instance1.ionViewDidLoad).toHaveBeenCalled();
|
expect(instance1.ionViewDidLoad).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanEnter).toHaveBeenCalled();
|
expect(instance1.ionViewCanEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillEnter).toHaveBeenCalled();
|
expect(instance1.ionViewWillEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidEnter).toHaveBeenCalled();
|
expect(instance1.ionViewDidEnter).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance2.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance2.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance2.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanLeave).toHaveBeenCalled();
|
expect(instance4.ionViewCanLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance4.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance4.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance4.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
let hasCompleted = true;
|
let hasCompleted = true;
|
||||||
let requiresTransition = true;
|
let requiresTransition = true;
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, 'MockView1', 'MockView4', DIRECTION_BACK
|
hasCompleted, requiresTransition, 'MockView1', 'MockView4', DIRECTION_BACK
|
||||||
);
|
);
|
||||||
expect(nav.length()).toEqual(1);
|
expect(nav.length()).toEqual(1);
|
||||||
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
||||||
});
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('remove', () => {
|
describe('remove', () => {
|
||||||
|
|
||||||
it('should remove the first three views in the beginning, no last view transition', () => {
|
it('should remove the first three views in the beginning, no last view transition', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
let view3 = mockView(MockView3);
|
let view3 = mockView(MockView3);
|
||||||
@ -591,54 +638,59 @@ describe('NavController', () => {
|
|||||||
let instance3 = spyOnLifecycles(view3);
|
let instance3 = spyOnLifecycles(view3);
|
||||||
let instance4 = spyOnLifecycles(view4);
|
let instance4 = spyOnLifecycles(view4);
|
||||||
|
|
||||||
nav.remove(0, 3, null, trnsDone);
|
nav.remove(0, 3, null, trnsDone).then(() => {
|
||||||
|
|
||||||
expect(instance1.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance1.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance1.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance1.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance2.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance2.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance2.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance4.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance4.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance4.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
let hasCompleted = true;
|
let hasCompleted = true;
|
||||||
let requiresTransition = false;
|
let requiresTransition = false;
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, undefined, undefined, undefined
|
hasCompleted, requiresTransition, undefined, undefined, undefined
|
||||||
);
|
);
|
||||||
expect(nav.length()).toEqual(1);
|
expect(nav.length()).toEqual(1);
|
||||||
expect(nav.getByIndex(0).component).toEqual(MockView4);
|
expect(nav.getByIndex(0).component).toEqual(MockView4);
|
||||||
});
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
it('should remove two views in the middle', () => {
|
it('should remove two views in the middle', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
let view3 = mockView(MockView3);
|
let view3 = mockView(MockView3);
|
||||||
@ -652,65 +704,70 @@ describe('NavController', () => {
|
|||||||
let instance4 = spyOnLifecycles(view4);
|
let instance4 = spyOnLifecycles(view4);
|
||||||
let instance5 = spyOnLifecycles(view5);
|
let instance5 = spyOnLifecycles(view5);
|
||||||
|
|
||||||
nav.remove(2, 2, null, trnsDone);
|
nav.remove(2, 2, null, trnsDone).then(() => {
|
||||||
|
|
||||||
expect(instance1.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance4.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance4.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance4.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance4.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance5.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance5.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance5.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance5.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance5.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance5.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance5.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance5.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance5.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance5.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance5.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance5.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance5.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance5.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance5.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance5.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
let hasCompleted = true;
|
let hasCompleted = true;
|
||||||
let requiresTransition = false;
|
let requiresTransition = false;
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, undefined, undefined, undefined
|
hasCompleted, requiresTransition, undefined, undefined, undefined
|
||||||
);
|
);
|
||||||
expect(nav.length()).toEqual(3);
|
expect(nav.length()).toEqual(3);
|
||||||
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
||||||
expect(nav.getByIndex(1).component).toEqual(MockView2);
|
expect(nav.getByIndex(1).component).toEqual(MockView2);
|
||||||
expect(nav.getByIndex(2).component).toEqual(MockView5);
|
expect(nav.getByIndex(2).component).toEqual(MockView5);
|
||||||
});
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
it('should remove the last two views at the end', () => {
|
it('should remove the last two views at the end', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
let view2 = mockView(MockView2);
|
let view2 = mockView(MockView2);
|
||||||
let view3 = mockView(MockView3);
|
let view3 = mockView(MockView3);
|
||||||
@ -722,53 +779,58 @@ describe('NavController', () => {
|
|||||||
let instance3 = spyOnLifecycles(view3);
|
let instance3 = spyOnLifecycles(view3);
|
||||||
let instance4 = spyOnLifecycles(view4);
|
let instance4 = spyOnLifecycles(view4);
|
||||||
|
|
||||||
nav.remove(2, 2, null, trnsDone);
|
nav.remove(2, 2, null, trnsDone).then(() => {
|
||||||
|
|
||||||
expect(instance1.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance1.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance1.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance2.ionViewDidLoad).toHaveBeenCalled();
|
expect(instance2.ionViewDidLoad).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanEnter).toHaveBeenCalled();
|
expect(instance2.ionViewCanEnter).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillEnter).toHaveBeenCalled();
|
expect(instance2.ionViewWillEnter).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidEnter).toHaveBeenCalled();
|
expect(instance2.ionViewDidEnter).toHaveBeenCalled();
|
||||||
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewDidLeave).not.toHaveBeenCalled();
|
expect(instance2.ionViewDidLeave).not.toHaveBeenCalled();
|
||||||
expect(instance2.ionViewWillUnload).not.toHaveBeenCalled();
|
expect(instance2.ionViewWillUnload).not.toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance3.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
expect(instance3.ionViewCanLeave).not.toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance3.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance3.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance3.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidLoad).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewCanEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewWillEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
expect(instance4.ionViewDidEnter).not.toHaveBeenCalled();
|
||||||
expect(instance4.ionViewCanLeave).toHaveBeenCalled();
|
expect(instance4.ionViewCanLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillLeave).toHaveBeenCalled();
|
expect(instance4.ionViewWillLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewDidLeave).toHaveBeenCalled();
|
expect(instance4.ionViewDidLeave).toHaveBeenCalled();
|
||||||
expect(instance4.ionViewWillUnload).toHaveBeenCalled();
|
expect(instance4.ionViewWillUnload).toHaveBeenCalled();
|
||||||
|
|
||||||
let hasCompleted = true;
|
let hasCompleted = true;
|
||||||
let requiresTransition = true;
|
let requiresTransition = true;
|
||||||
expect(trnsDone).toHaveBeenCalledWith(
|
expect(trnsDone).toHaveBeenCalledWith(
|
||||||
hasCompleted, requiresTransition, 'MockView2', 'MockView4', DIRECTION_BACK
|
hasCompleted, requiresTransition, 'MockView2', 'MockView4', DIRECTION_BACK
|
||||||
);
|
);
|
||||||
expect(nav.length()).toEqual(2);
|
expect(nav.length()).toEqual(2);
|
||||||
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
expect(nav.getByIndex(0).component).toEqual(MockView1);
|
||||||
expect(nav.getByIndex(1).component).toEqual(MockView2);
|
expect(nav.getByIndex(1).component).toEqual(MockView2);
|
||||||
});
|
done();
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -821,9 +883,10 @@ describe('NavController', () => {
|
|||||||
expect(nav.getByIndex(0).component).toEqual(MockView3);
|
expect(nav.getByIndex(0).component).toEqual(MockView3);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should set a ViewController as the root when its the middle view, with transition', (done: Function) => {
|
it('should set a ViewController as the root when its the middle view, with transition', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
@ -873,9 +936,10 @@ describe('NavController', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should set a ViewController as the root when its the first view, with transition', (done: Function) => {
|
it('should set a ViewController as the root when its the first view, with transition', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
@ -925,9 +989,10 @@ describe('NavController', () => {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('should set a page component as the root, with transition', (done: Function) => {
|
it('should set a page component as the root, with transition', (done: Function) => {
|
||||||
let view1 = mockView(MockView1);
|
let view1 = mockView(MockView1);
|
||||||
@ -953,9 +1018,10 @@ describe('NavController', () => {
|
|||||||
expect(nav.getByIndex(0).component).toEqual(MockView4);
|
expect(nav.getByIndex(0).component).toEqual(MockView4);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('setPages', () => {
|
describe('setPages', () => {
|
||||||
@ -982,9 +1048,10 @@ describe('NavController', () => {
|
|||||||
expect(nav.getByIndex(1).component).toEqual(MockView5);
|
expect(nav.getByIndex(1).component).toEqual(MockView5);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ describe('Overlay Proxy', () => {
|
|||||||
expect(instance.overlay.dismiss).toHaveBeenCalled();
|
expect(instance.overlay.dismiss).toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -69,6 +70,7 @@ describe('Overlay Proxy', () => {
|
|||||||
expect(knownOverlay.onWillDismiss).toHaveBeenCalledWith(handler);
|
expect(knownOverlay.onWillDismiss).toHaveBeenCalledWith(handler);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -91,6 +93,7 @@ describe('Overlay Proxy', () => {
|
|||||||
expect(deepLinker.getComponentFromName).not.toHaveBeenCalled();
|
expect(deepLinker.getComponentFromName).not.toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -112,6 +115,7 @@ describe('Overlay Proxy', () => {
|
|||||||
expect(deepLinker.getComponentFromName).toHaveBeenCalledWith(componentName);
|
expect(deepLinker.getComponentFromName).toHaveBeenCalledWith(componentName);
|
||||||
done();
|
done();
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
|
fail(err);
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -541,26 +541,24 @@ export class ViewController {
|
|||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
_lifecycleTest(lifecycle: string): boolean | Promise<any> {
|
_lifecycleTest(lifecycle: string): Promise<any> {
|
||||||
const instance = this.instance;
|
const instance = this.instance;
|
||||||
const methodName = 'ionViewCan' + lifecycle;
|
const methodName = 'ionViewCan' + lifecycle;
|
||||||
if (instance && instance[methodName]) {
|
if (instance && instance[methodName]) {
|
||||||
try {
|
try {
|
||||||
var result = instance[methodName]();
|
var result = instance[methodName]();
|
||||||
if (result === false) {
|
if (result instanceof Promise) {
|
||||||
return false;
|
|
||||||
} else if (result instanceof Promise) {
|
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
// Any value but explitic false, should be true
|
||||||
|
return Promise.resolve(result !== false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`${this.name} ${methodName} error: ${e.message}`);
|
return Promise.reject(`${this.name} ${methodName} error: ${e.message}`);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_lifecycle(lifecycle: string) {
|
_lifecycle(lifecycle: string) {
|
||||||
|
@ -20,12 +20,12 @@ export class TransitionController {
|
|||||||
constructor(public plt: Platform, private _config: Config) {}
|
constructor(public plt: Platform, private _config: Config) {}
|
||||||
|
|
||||||
getRootTrnsId(nav: NavControllerBase): number {
|
getRootTrnsId(nav: NavControllerBase): number {
|
||||||
let parent = <NavControllerBase>nav.parent;
|
nav = <NavControllerBase>nav.parent;
|
||||||
while (parent) {
|
while (nav) {
|
||||||
if (isPresent(parent._trnsId)) {
|
if (isPresent(nav._trnsId)) {
|
||||||
return parent._trnsId;
|
return nav._trnsId;
|
||||||
}
|
}
|
||||||
parent = parent.parent;
|
nav = nav.parent;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,12 @@ export class Transition extends Animation {
|
|||||||
parent: Transition;
|
parent: Transition;
|
||||||
trnsId: number;
|
trnsId: number;
|
||||||
|
|
||||||
constructor(plt: Platform, public enteringView: ViewController, public leavingView: ViewController, opts: AnimationOptions) {
|
constructor(
|
||||||
|
plt: Platform,
|
||||||
|
public enteringView: ViewController,
|
||||||
|
public leavingView: ViewController,
|
||||||
|
opts: AnimationOptions
|
||||||
|
) {
|
||||||
super(plt, null, opts);
|
super(plt, null, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,13 +39,12 @@ export class Transition extends Animation {
|
|||||||
this._trnsStart = trnsStart;
|
this._trnsStart = trnsStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
isRoot(): boolean {
|
|
||||||
return !this.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this._trnsStart && this._trnsStart();
|
this._trnsStart && this._trnsStart();
|
||||||
this._trnsStart = null;
|
this._trnsStart = null;
|
||||||
|
|
||||||
|
// bubble up start
|
||||||
|
this.parent && this.parent.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
@ -19,7 +19,8 @@ describe('module-loader', () => {
|
|||||||
promise.then((response) => {
|
promise.then((response) => {
|
||||||
expect(ngModuleLoader.load).toHaveBeenCalledWith(pathPrefix, exportSuffix);
|
expect(ngModuleLoader.load).toHaveBeenCalledWith(pathPrefix, exportSuffix);
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
done(err);
|
fail(err);
|
||||||
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user