mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 20:33:32 +08:00
1740 lines
58 KiB
TypeScript
1740 lines
58 KiB
TypeScript
import { NavController, Tabs, NavOptions, Config, ViewController, App, Platform } from '../../../../src';
|
|
|
|
export function run() {
|
|
describe('NavController', () => {
|
|
|
|
describe('pop', () => {
|
|
|
|
it('should do nothing if its the first view in the stack', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_ACTIVE;
|
|
nav.views = [view1];
|
|
|
|
expect(nav.length()).toBe(1);
|
|
|
|
nav.pop();
|
|
|
|
expect(nav.length()).toBe(1);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_ACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
});
|
|
|
|
});
|
|
|
|
describe('popToRoot', () => {
|
|
|
|
it('should go back to root', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INACTIVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INACTIVE;
|
|
let view4 = new ViewController(Page4);
|
|
view4.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2, view3, view4];
|
|
|
|
nav.popToRoot();
|
|
expect(nav.length()).toBe(2);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page4);
|
|
|
|
expect(view2.state).toBe(STATE_REMOVE);
|
|
expect(view3.state).toBe(STATE_REMOVE);
|
|
});
|
|
|
|
});
|
|
|
|
describe('popTo', () => {
|
|
|
|
it('should go back two views', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INACTIVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INACTIVE;
|
|
let view4 = new ViewController(Page4);
|
|
view4.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2, view3, view4];
|
|
|
|
nav.popTo(view2);
|
|
|
|
expect(nav.length()).toBe(3);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(view3.state).toBe(STATE_REMOVE);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page4);
|
|
});
|
|
|
|
});
|
|
|
|
describe('remove', () => {
|
|
|
|
it('should create opts if passed in arg is undefined or null', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2];
|
|
|
|
nav.remove(1, 1, null);
|
|
});
|
|
|
|
});
|
|
|
|
describe('_remove', () => {
|
|
|
|
it('should reassign activily transitioning leave that isnt getting removed, to become force active', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_TRANS_LEAVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_TRANS_ENTER;
|
|
nav.views = [view1, view2, view3];
|
|
|
|
nav._remove(2, 1);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_FORCE_ACTIVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_REMOVE_AFTER_TRANS);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page3);
|
|
});
|
|
|
|
it('should reassign activily transitioning views that should be removed to STATE_REMOVE_AFTER_TRANS', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_TRANS_ENTER;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_TRANS_LEAVE;
|
|
nav.views = [view1, view2, view3];
|
|
|
|
nav._remove(1, 2);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_REMOVE_AFTER_TRANS);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_REMOVE_AFTER_TRANS);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page3);
|
|
});
|
|
|
|
it('should keep same init leave, but set previous init enter to inactive', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INIT_ENTER;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INIT_LEAVE;
|
|
nav.views = [view1, view2, view3];
|
|
|
|
nav._remove(1, 1);
|
|
expect(nav.length()).toBe(3);
|
|
expect(view1.state).toBe(STATE_INIT_ENTER);
|
|
expect(view2.state).toBe(STATE_CANCEL_ENTER);
|
|
expect(view3.state).toBe(STATE_INIT_LEAVE);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_CANCEL_ENTER);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page3);
|
|
});
|
|
|
|
it('should set to pop the active and enter the previous', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2];
|
|
|
|
nav._remove(1, 1);
|
|
expect(view1.state).toBe(STATE_INIT_ENTER);
|
|
expect(view2.state).toBe(STATE_INIT_LEAVE);
|
|
});
|
|
|
|
it('should set to remove 2 views before active one, active stays the same', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INACTIVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INACTIVE;
|
|
let view4 = new ViewController(Page4);
|
|
view4.state = STATE_INACTIVE;
|
|
let view5 = new ViewController(Page5);
|
|
view5.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2, view3, view4, view5];
|
|
|
|
nav._remove(2, 2);
|
|
expect(nav.length()).toBe(3);
|
|
expect(view1.state).toBe(STATE_INACTIVE);
|
|
expect(view2.state).toBe(STATE_INACTIVE);
|
|
expect(view3.state).toBe(STATE_REMOVE);
|
|
expect(view4.state).toBe(STATE_REMOVE);
|
|
expect(view5.state).toBe(STATE_ACTIVE);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_ACTIVE);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page5);
|
|
});
|
|
|
|
it('should set to remove all views other than the first', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INACTIVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INACTIVE;
|
|
let view4 = new ViewController(Page4);
|
|
view4.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2, view3, view4];
|
|
|
|
nav._remove(1, 9999);
|
|
expect(nav.length()).toBe(2);
|
|
expect(view1.state).toBe(STATE_INIT_ENTER);
|
|
expect(view2.state).toBe(STATE_REMOVE);
|
|
expect(view3.state).toBe(STATE_REMOVE);
|
|
expect(view4.state).toBe(STATE_INIT_LEAVE);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page4);
|
|
});
|
|
|
|
it('should set to remove 3 views and enter the first inactive one, remove includes active one', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INACTIVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INACTIVE;
|
|
let view4 = new ViewController(Page4);
|
|
view4.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2, view3, view4];
|
|
|
|
nav._remove(1, 3);
|
|
expect(nav.length()).toBe(2);
|
|
expect(view1.state).toBe(STATE_INIT_ENTER);
|
|
expect(view2.state).toBe(STATE_REMOVE);
|
|
expect(view3.state).toBe(STATE_REMOVE);
|
|
expect(view4.state).toBe(STATE_INIT_LEAVE);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page4);
|
|
});
|
|
|
|
it('should set to remove the active and enter the previous', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2];
|
|
|
|
nav._remove(1, 1);
|
|
expect(view1.state).toBe(STATE_INIT_ENTER);
|
|
expect(view2.state).toBe(STATE_INIT_LEAVE);
|
|
});
|
|
|
|
it('should set to remove the only view in the stack', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_ACTIVE;
|
|
nav.views = [view1];
|
|
|
|
nav._remove(0, 1);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_LEAVE);
|
|
});
|
|
|
|
it('should call willLeave/didLeave/destroy on views with STATE_REMOVE', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INACTIVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INACTIVE;
|
|
let view4 = new ViewController(Page4);
|
|
view4.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2, view3, view4];
|
|
|
|
spyOn(view1, 'fireWillLeave');
|
|
spyOn(view1, 'fireDidLeave');
|
|
spyOn(view1, 'destroy');
|
|
|
|
spyOn(view2, 'fireWillLeave');
|
|
spyOn(view2, 'fireDidLeave');
|
|
spyOn(view2, 'destroy');
|
|
|
|
spyOn(view3, 'fireWillLeave');
|
|
spyOn(view3, 'fireDidLeave');
|
|
spyOn(view3, 'destroy');
|
|
|
|
spyOn(view4, 'fireWillLeave');
|
|
spyOn(view4, 'fireDidLeave');
|
|
spyOn(view4, 'destroy');
|
|
|
|
nav._remove(1, 3);
|
|
expect(nav.length()).toBe(2);
|
|
expect(view1.state).toBe(STATE_INIT_ENTER);
|
|
expect(view2.state).toBe(STATE_REMOVE);
|
|
expect(view3.state).toBe(STATE_REMOVE);
|
|
expect(view4.state).toBe(STATE_INIT_LEAVE);
|
|
|
|
expect(view1.fireWillLeave).not.toHaveBeenCalled();
|
|
expect(view1.fireDidLeave).not.toHaveBeenCalled();
|
|
expect(view1.destroy).not.toHaveBeenCalled();
|
|
|
|
expect(view2.fireWillLeave).toHaveBeenCalled();
|
|
expect(view2.fireDidLeave).toHaveBeenCalled();
|
|
expect(view2.destroy).toHaveBeenCalled();
|
|
|
|
expect(view3.fireWillLeave).toHaveBeenCalled();
|
|
expect(view3.fireDidLeave).toHaveBeenCalled();
|
|
expect(view3.destroy).toHaveBeenCalled();
|
|
|
|
expect(view4.fireWillLeave).not.toHaveBeenCalled();
|
|
expect(view4.fireDidLeave).not.toHaveBeenCalled();
|
|
expect(view4.destroy).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('_cleanup', () => {
|
|
it('should destroy views that are inactive after the active view', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_ACTIVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INACTIVE;
|
|
let view4 = new ViewController(Page4);
|
|
view4.state = STATE_TRANS_ENTER;
|
|
let view5 = new ViewController(Page5);
|
|
view5.state = STATE_INACTIVE;
|
|
nav.views = [view1, view2, view3, view4, view5];
|
|
nav._cleanup();
|
|
|
|
expect(nav.length()).toBe(3);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_ACTIVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_TRANS_ENTER);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page4);
|
|
});
|
|
|
|
it('should not destroy any views since the last is active', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2];
|
|
nav._cleanup();
|
|
expect(nav.length()).toBe(2);
|
|
});
|
|
|
|
it('should call destroy for each view to be destroyed', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_ACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INACTIVE;
|
|
let view3 = new ViewController(Page3);
|
|
view3.state = STATE_INACTIVE;
|
|
nav.views = [view1, view2, view3];
|
|
|
|
spyOn(view1, 'destroy');
|
|
spyOn(view2, 'destroy');
|
|
spyOn(view3, 'destroy');
|
|
|
|
nav._cleanup();
|
|
|
|
expect(nav.length()).toBe(1);
|
|
expect(view1.destroy).not.toHaveBeenCalled();
|
|
expect(view2.destroy).toHaveBeenCalled();
|
|
expect(view3.destroy).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should reset zIndexes if their is a negative zindex', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.setPageRef( getElementRef() );
|
|
view1.state = STATE_INACTIVE;
|
|
view1.zIndex = -1;
|
|
|
|
let view2 = new ViewController(Page2);
|
|
view2.setPageRef( getElementRef() );
|
|
view2.state = STATE_INACTIVE;
|
|
view2.zIndex = 0;
|
|
|
|
let view3 = new ViewController(Page3);
|
|
view3.setPageRef( getElementRef() );
|
|
view3.state = STATE_ACTIVE;
|
|
view3.zIndex = 1;
|
|
|
|
nav.views = [view1, view2, view3];
|
|
nav._cleanup();
|
|
|
|
expect(view1.zIndex).toEqual(100);
|
|
expect(view2.zIndex).toEqual(101);
|
|
expect(view3.zIndex).toEqual(102);
|
|
});
|
|
});
|
|
|
|
describe('_postRender', () => {
|
|
it('should immediately call done when enteringView state is inactive', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
var wasCalled = false;
|
|
var done = () => {
|
|
wasCalled = true;
|
|
};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
|
|
nav._postRender(1, view1, null, false, null, done);
|
|
|
|
expect(wasCalled).toBe(true);
|
|
});
|
|
|
|
it('should call willEnter on entering view', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
var navOptions: NavOptions = {};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
|
|
spyOn(enteringView, 'fireWillEnter');
|
|
|
|
nav._postRender(1, enteringView, leavingView, false, navOptions, done);
|
|
|
|
expect(enteringView.fireWillEnter).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not call willEnter on entering view when it is being preloaded', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
var navOptions: NavOptions = {
|
|
preload: true
|
|
};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
|
|
spyOn(enteringView, 'fireWillEnter');
|
|
|
|
nav._postRender(1, enteringView, leavingView, false, navOptions, done);
|
|
|
|
expect(enteringView.fireWillEnter).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should call willLeave on leaving view', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
var navOptions: NavOptions = {};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
|
|
spyOn(leavingView, 'fireWillLeave');
|
|
|
|
nav._postRender(1, enteringView, leavingView, false, navOptions, done);
|
|
|
|
expect(leavingView.fireWillLeave).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not call willEnter when the leaving view has fireOtherLifecycles not true', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
var navOptions: NavOptions = {};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
|
|
spyOn(enteringView, 'fireWillEnter');
|
|
spyOn(leavingView, 'fireWillLeave');
|
|
|
|
leavingView.fireOtherLifecycles = false;
|
|
|
|
nav._postRender(1, enteringView, leavingView, false, navOptions, done);
|
|
|
|
expect(enteringView.fireWillEnter).not.toHaveBeenCalled();
|
|
expect(leavingView.fireWillLeave).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not call willLeave when the entering view has fireOtherLifecycles not true', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
var navOptions: NavOptions = {};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
|
|
spyOn(enteringView, 'fireWillEnter');
|
|
spyOn(leavingView, 'fireWillLeave');
|
|
|
|
enteringView.fireOtherLifecycles = false;
|
|
|
|
nav._postRender(1, enteringView, leavingView, false, navOptions, done);
|
|
|
|
expect(enteringView.fireWillEnter).toHaveBeenCalled();
|
|
expect(leavingView.fireWillLeave).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not call willLeave on leaving view when it is being preloaded', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
var navOptions: NavOptions = {
|
|
preload: true
|
|
};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
|
|
spyOn(leavingView, 'fireWillLeave');
|
|
|
|
nav._postRender(1, enteringView, leavingView, false, navOptions, done);
|
|
|
|
expect(leavingView.fireWillLeave).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should set animate false when preloading', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
var navOptions: NavOptions = {
|
|
preload: true
|
|
};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
|
|
nav._postRender(1, enteringView, leavingView, false, navOptions, done);
|
|
|
|
expect(navOptions.animate).toBe(false);
|
|
});
|
|
|
|
it('should set domShow true when isAlreadyTransitioning', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
let isAlreadyTransitioning = true;
|
|
var navOptions: NavOptions = {};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
nav._renderer = null;
|
|
|
|
spyOn(enteringView, 'domShow');
|
|
spyOn(leavingView, 'domShow');
|
|
|
|
nav._postRender(1, enteringView, leavingView, isAlreadyTransitioning, navOptions, done);
|
|
|
|
expect(enteringView.domShow).toHaveBeenCalledWith(true, nav._renderer);
|
|
expect(leavingView.domShow).toHaveBeenCalledWith(true, nav._renderer);
|
|
});
|
|
|
|
it('should set domShow true when isAlreadyTransitioning false for the entering/leaving views', () => {
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
let view3 = new ViewController(Page3);
|
|
let isAlreadyTransitioning = false;
|
|
var navOptions: NavOptions = {};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
nav._renderer = null;
|
|
nav.views = [view1, view2, view3];
|
|
|
|
spyOn(view1, 'domShow');
|
|
spyOn(view2, 'domShow');
|
|
spyOn(view3, 'domShow');
|
|
|
|
nav._postRender(1, view3, view2, isAlreadyTransitioning, navOptions, done);
|
|
|
|
expect(view1.domShow).toHaveBeenCalledWith(false, nav._renderer);
|
|
expect(view2.domShow).toHaveBeenCalledWith(true, nav._renderer);
|
|
expect(view3.domShow).toHaveBeenCalledWith(true, nav._renderer);
|
|
});
|
|
|
|
it('should set domShow true when isAlreadyTransitioning false for views when a view has isOverlay=true', () => {
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
let view3 = new ViewController(Page3);
|
|
let view4 = new ViewController(Page4);
|
|
let isAlreadyTransitioning = false;
|
|
var navOptions: NavOptions = {};
|
|
var done = () => {};
|
|
nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
|
|
nav._renderer = null;
|
|
nav.views = [view1, view2, view3, view4];
|
|
|
|
view3.isOverlay = true;
|
|
|
|
spyOn(view1, 'domShow');
|
|
spyOn(view2, 'domShow');
|
|
spyOn(view3, 'domShow');
|
|
spyOn(view4, 'domShow');
|
|
|
|
nav._postRender(1, view4, view3, isAlreadyTransitioning, navOptions, done);
|
|
|
|
expect(view1.domShow).toHaveBeenCalledWith(false, nav._renderer);
|
|
expect(view2.domShow).toHaveBeenCalledWith(true, nav._renderer);
|
|
expect(view3.domShow).toHaveBeenCalledWith(true, nav._renderer);
|
|
expect(view4.domShow).toHaveBeenCalledWith(true, nav._renderer);
|
|
});
|
|
|
|
});
|
|
|
|
describe('_setZIndex', () => {
|
|
|
|
it('should set zIndex off of the previous view to the entering view is loaded and the leavingView is not loaded', () => {
|
|
let leavingView = new ViewController();
|
|
leavingView.zIndex = 100;
|
|
leavingView._loaded = true;
|
|
let enteringView = new ViewController();
|
|
enteringView.setPageRef({});
|
|
|
|
nav.views = [leavingView, enteringView];
|
|
|
|
nav._setZIndex(enteringView, leavingView, 'forward');
|
|
expect(enteringView.zIndex).toEqual(101);
|
|
});
|
|
|
|
it('should set zIndex 100 when leaving view is not loaded', () => {
|
|
let leavingView = new ViewController();
|
|
leavingView._loaded = false;
|
|
let enteringView = new ViewController();
|
|
enteringView.setPageRef({});
|
|
|
|
nav.views = [leavingView, enteringView];
|
|
|
|
nav._setZIndex(enteringView, leavingView, 'forward');
|
|
expect(enteringView.zIndex).toEqual(100);
|
|
});
|
|
|
|
it('should set zIndex 100 on first entering view', () => {
|
|
let enteringView = new ViewController();
|
|
enteringView.setPageRef({});
|
|
nav._setZIndex(enteringView, null, 'forward');
|
|
expect(enteringView.zIndex).toEqual(100);
|
|
});
|
|
|
|
it('should set zIndex 1 on second entering view', () => {
|
|
let leavingView = new ViewController();
|
|
leavingView.zIndex = 0;
|
|
leavingView._loaded = true;
|
|
let enteringView = new ViewController();
|
|
enteringView.setPageRef({});
|
|
nav._setZIndex(enteringView, leavingView, 'forward');
|
|
expect(enteringView.zIndex).toEqual(1);
|
|
});
|
|
|
|
it('should set zIndex 0 on entering view going back', () => {
|
|
let leavingView = new ViewController();
|
|
leavingView.zIndex = 1;
|
|
leavingView._loaded = true;
|
|
let enteringView = new ViewController();
|
|
enteringView.setPageRef({});
|
|
nav._setZIndex(enteringView, leavingView, 'back');
|
|
expect(enteringView.zIndex).toEqual(0);
|
|
});
|
|
|
|
it('should set zIndex 9999 on first entering portal view', () => {
|
|
let enteringView = new ViewController();
|
|
enteringView.setPageRef({});
|
|
nav.isPortal = true;
|
|
nav._setZIndex(enteringView, null, 'forward');
|
|
expect(enteringView.zIndex).toEqual(9999);
|
|
});
|
|
|
|
it('should set zIndex 10000 on second entering portal view', () => {
|
|
let leavingView = new ViewController();
|
|
leavingView.zIndex = 9999;
|
|
leavingView._loaded = true;
|
|
let enteringView = new ViewController();
|
|
enteringView.setPageRef({});
|
|
nav._portal = null;
|
|
nav._setZIndex(enteringView, leavingView, 'forward');
|
|
expect(enteringView.zIndex).toEqual(10000);
|
|
});
|
|
|
|
it('should set zIndex 9999 on entering portal view going back', () => {
|
|
let leavingView = new ViewController();
|
|
leavingView.zIndex = 10000;
|
|
leavingView._loaded = true;
|
|
let enteringView = new ViewController();
|
|
enteringView.setPageRef({});
|
|
nav._portal = null;
|
|
nav._setZIndex(enteringView, leavingView, 'back');
|
|
expect(enteringView.zIndex).toEqual(9999);
|
|
});
|
|
|
|
});
|
|
|
|
describe('_setAnimate', () => {
|
|
|
|
it('should be unchanged when the nav is a portal', () => {
|
|
nav.views = [new ViewController()];
|
|
nav._init = false;
|
|
nav.isPortal = true;
|
|
let opts: NavOptions = {};
|
|
nav._setAnimate(opts);
|
|
expect(opts.animate).toBeUndefined();
|
|
});
|
|
|
|
it('should not animate when theres only 1 view, and nav hasnt initialized yet', () => {
|
|
nav.views = [new ViewController()];
|
|
nav._init = false;
|
|
let opts: NavOptions = {};
|
|
nav._setAnimate(opts);
|
|
expect(opts.animate).toEqual(false);
|
|
});
|
|
|
|
it('should be unchanged when theres only 1 view, and nav has already initialized', () => {
|
|
nav.views = [new ViewController()];
|
|
nav._init = true;
|
|
let opts: NavOptions = {};
|
|
nav._setAnimate(opts);
|
|
expect(opts.animate).toBeUndefined();
|
|
});
|
|
|
|
it('should not animate with config animate = false, and has initialized', () => {
|
|
config.set('animate', false);
|
|
nav._init = true;
|
|
let opts: NavOptions = {};
|
|
nav._setAnimate(opts);
|
|
expect(opts.animate).toEqual(false);
|
|
});
|
|
|
|
it('should not animate with config animate = false, and has not initialized', () => {
|
|
config.set('animate', false);
|
|
nav._init = false;
|
|
let opts: NavOptions = {};
|
|
nav._setAnimate(opts);
|
|
expect(opts.animate).toEqual(false);
|
|
});
|
|
|
|
});
|
|
|
|
describe('_afterTrans', () => {
|
|
|
|
it('should call didEnter/didLeave', () => {
|
|
let enteringView = new ViewController();
|
|
let leavingView = new ViewController();
|
|
let navOpts: NavOptions = {};
|
|
let hasCompleted = true;
|
|
let doneCalled = false;
|
|
let done = () => {doneCalled = true;}
|
|
|
|
spyOn(enteringView, 'fireDidEnter');
|
|
spyOn(leavingView, 'fireDidLeave');
|
|
|
|
nav._init = true;
|
|
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
|
|
|
|
expect(enteringView.fireDidEnter).toHaveBeenCalled();
|
|
expect(leavingView.fireDidLeave).toHaveBeenCalled();
|
|
expect(doneCalled).toBe(true);
|
|
});
|
|
|
|
it('should not call didEnter/didLeave when preloaded', () => {
|
|
let enteringView = new ViewController();
|
|
let leavingView = new ViewController();
|
|
let navOpts: NavOptions = {
|
|
preload: true
|
|
};
|
|
let hasCompleted = true;
|
|
let doneCalled = false;
|
|
let done = () => {doneCalled = true;}
|
|
|
|
spyOn(enteringView, 'fireDidEnter');
|
|
spyOn(leavingView, 'fireDidLeave');
|
|
|
|
nav._init = true;
|
|
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
|
|
|
|
expect(enteringView.fireDidEnter).not.toHaveBeenCalled();
|
|
expect(leavingView.fireDidLeave).not.toHaveBeenCalled();
|
|
expect(doneCalled).toBe(true);
|
|
});
|
|
|
|
it('should not call didLeave when enteringView set fireOtherLifecycles to false', () => {
|
|
let enteringView = new ViewController();
|
|
let leavingView = new ViewController();
|
|
let navOpts: NavOptions = {};
|
|
let hasCompleted = true;
|
|
let doneCalled = false;
|
|
let done = () => {doneCalled = true;}
|
|
|
|
enteringView.fireOtherLifecycles = false;
|
|
|
|
spyOn(enteringView, 'fireDidEnter');
|
|
spyOn(leavingView, 'fireDidLeave');
|
|
|
|
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
|
|
|
|
expect(enteringView.fireDidEnter).toHaveBeenCalled();
|
|
expect(leavingView.fireDidLeave).not.toHaveBeenCalled();
|
|
expect(doneCalled).toBe(true);
|
|
});
|
|
|
|
it('should not call didEnter when leavingView set fireOtherLifecycles to false', () => {
|
|
let enteringView = new ViewController();
|
|
let leavingView = new ViewController();
|
|
let navOpts: NavOptions = {};
|
|
let hasCompleted = true;
|
|
let doneCalled = false;
|
|
let done = () => {doneCalled = true;}
|
|
|
|
leavingView.fireOtherLifecycles = false;
|
|
|
|
spyOn(enteringView, 'fireDidEnter');
|
|
spyOn(leavingView, 'fireDidLeave');
|
|
|
|
nav._init = true;
|
|
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
|
|
|
|
expect(enteringView.fireDidEnter).not.toHaveBeenCalled();
|
|
expect(leavingView.fireDidLeave).toHaveBeenCalled();
|
|
expect(doneCalled).toBe(true);
|
|
});
|
|
|
|
it('should not call didEnter/didLeave when not hasCompleted', () => {
|
|
let enteringView = new ViewController();
|
|
let leavingView = new ViewController();
|
|
let navOpts: NavOptions = {};
|
|
let hasCompleted = false;
|
|
let doneCalled = false;
|
|
let done = () => {doneCalled = true;}
|
|
|
|
spyOn(enteringView, 'fireDidEnter');
|
|
spyOn(leavingView, 'fireDidLeave');
|
|
|
|
nav._afterTrans(enteringView, leavingView, navOpts, hasCompleted, done);
|
|
|
|
expect(enteringView.fireDidEnter).not.toHaveBeenCalled();
|
|
expect(leavingView.fireDidLeave).not.toHaveBeenCalled();
|
|
expect(doneCalled).toBe(true);
|
|
});
|
|
|
|
});
|
|
|
|
describe('_transFinish', () => {
|
|
|
|
it('should remove entering view if it was already set to cancel', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
let leavingView = new ViewController(Page2);
|
|
enteringView.state = STATE_CANCEL_ENTER;
|
|
|
|
spyOn(nav, 'remove');
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'forward', true);
|
|
|
|
expect(nav.remove).toHaveBeenCalled();
|
|
expect(enteringView.state).toBe(STATE_CANCEL_ENTER);
|
|
});
|
|
|
|
it('should not entering/leaving state, after transition that isnt the most recent, and state already changed', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = 'somethingelse';
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = 'somethingelse';
|
|
|
|
nav._transIds = 2;
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'forward', true);
|
|
|
|
expect(enteringView.state).toBe('somethingelse');
|
|
expect(leavingView.state).toBe('somethingelse');
|
|
});
|
|
|
|
it('should set entering/leaving to inactive, after transition that isnt the most recent', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = STATE_TRANS_ENTER;
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = STATE_TRANS_LEAVE;
|
|
|
|
nav._transIds = 2;
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'forward', true);
|
|
|
|
expect(enteringView.state).toBe(STATE_INACTIVE);
|
|
expect(leavingView.state).toBe(STATE_INACTIVE);
|
|
});
|
|
|
|
it('should set entering active, leaving inactive, after transition', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = STATE_TRANS_ENTER;
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = STATE_TRANS_LEAVE;
|
|
|
|
nav._transIds = 1;
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'forward', true);
|
|
|
|
expect(enteringView.state).toBe(STATE_ACTIVE);
|
|
expect(leavingView.state).toBe(STATE_INACTIVE);
|
|
});
|
|
|
|
it('should set entering inactive, leaving active, after transition has not completed', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = STATE_TRANS_ENTER;
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = STATE_TRANS_LEAVE;
|
|
|
|
nav._transIds = 1;
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'back', false);
|
|
|
|
expect(enteringView.state).toBe(STATE_INACTIVE);
|
|
expect(leavingView.state).toBe(STATE_ACTIVE);
|
|
});
|
|
|
|
it('should run cleanup when most recent transition and has completed', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = STATE_TRANS_ENTER;
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = STATE_TRANS_LEAVE;
|
|
let hasCompleted = true;
|
|
|
|
spyOn(nav, '_cleanup');
|
|
|
|
nav._transIds = 1;
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'back', hasCompleted);
|
|
|
|
expect(nav._cleanup).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not run cleanup when most not recent transition', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = STATE_TRANS_ENTER;
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = STATE_TRANS_LEAVE;
|
|
let hasCompleted = true;
|
|
|
|
spyOn(nav, '_cleanup');
|
|
|
|
nav._transIds = 1;
|
|
|
|
nav._transFinish(2, enteringView, leavingView, 'back', hasCompleted);
|
|
|
|
expect(nav._cleanup).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not run cleanup when it hasnt completed transition, but is the most recent', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = STATE_TRANS_ENTER;
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = STATE_TRANS_LEAVE;
|
|
let hasCompleted = false;
|
|
|
|
spyOn(nav, '_cleanup');
|
|
|
|
nav._transIds = 1;
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'back', hasCompleted);
|
|
|
|
expect(nav._cleanup).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should set transitioning is over when most recent transition finishes', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = STATE_TRANS_ENTER;
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = STATE_TRANS_LEAVE;
|
|
let hasCompleted = true;
|
|
|
|
spyOn(nav, 'setTransitioning');
|
|
|
|
nav._transIds = 1;
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'back', hasCompleted);
|
|
|
|
expect(nav.setTransitioning).toHaveBeenCalledWith(false);
|
|
});
|
|
|
|
it('should set transitioning is not over if its not the most recent transition', () => {
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = STATE_TRANS_ENTER;
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = STATE_TRANS_LEAVE;
|
|
let hasCompleted = true;
|
|
|
|
spyOn(nav, 'setTransitioning');
|
|
|
|
nav._transIds = 2;
|
|
|
|
nav._transFinish(1, enteringView, leavingView, 'back', hasCompleted);
|
|
|
|
expect(nav.setTransitioning).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should set not run domShow when when any view in the stack has isOverlay=true', () => {
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
let view3 = new ViewController(Page3);
|
|
let view4 = new ViewController(Page4);
|
|
let hasCompleted = true;
|
|
nav.views = [view1, view2, view3, view4];
|
|
|
|
view1.isOverlay = true;
|
|
|
|
nav._transIds = 1;
|
|
|
|
spyOn(view1, 'domShow');
|
|
spyOn(view2, 'domShow');
|
|
spyOn(view3, 'domShow');
|
|
spyOn(view4, 'domShow');
|
|
|
|
nav._transFinish(1, view4, view3, 'forward', hasCompleted);
|
|
|
|
expect(view1.domShow).not.toHaveBeenCalled();
|
|
expect(view2.domShow).not.toHaveBeenCalled();
|
|
expect(view3.domShow).not.toHaveBeenCalled();
|
|
expect(view4.domShow).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should re-enable the app when transition time <= 0', () => {
|
|
// arrange
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = 'somethingelse';
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = 'somethingelse';
|
|
nav._transIds = 1;
|
|
nav._app = {
|
|
setEnabled: () => {}
|
|
};
|
|
|
|
spyOn(nav._app, 'setEnabled');
|
|
spyOn(nav, 'setTransitioning');
|
|
|
|
// act
|
|
nav._transFinish(nav._transIds, enteringView, leavingView, 'forward', true);
|
|
|
|
// assert
|
|
expect(nav._app.setEnabled).toHaveBeenCalledWith(true);
|
|
expect(nav.setTransitioning).toHaveBeenCalledWith(false);
|
|
});
|
|
|
|
it('should not re-enable app when transition time > 0', () => {
|
|
// arrange
|
|
let enteringView = new ViewController(Page1);
|
|
enteringView.state = 'somethingelse';
|
|
let leavingView = new ViewController(Page2);
|
|
leavingView.state = 'somethingelse';
|
|
nav._transIds = 1;
|
|
nav._app = {
|
|
setEnabled: () => {}
|
|
};
|
|
|
|
spyOn(nav._app, 'setEnabled');
|
|
spyOn(nav, 'setTransitioning');
|
|
|
|
nav._getLongestTrans = () => { return 50 };
|
|
|
|
// act
|
|
nav._transFinish(nav._transIds, enteringView, leavingView, 'forward', true);
|
|
|
|
// assert
|
|
expect(nav._app.setEnabled).not.toHaveBeenCalled();
|
|
expect(nav.setTransitioning).toHaveBeenCalledWith(false);
|
|
});
|
|
|
|
});
|
|
|
|
describe('_insert', () => {
|
|
|
|
it('should push page when previous transition is still actively transitioning', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_TRANS_ENTER;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_TRANS_LEAVE;
|
|
nav.views = [view1, view2];
|
|
|
|
let view3 = new ViewController(Page3);
|
|
nav._insert(-1, [view3]);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_TRANS_ENTER);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_TRANS_LEAVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page3);
|
|
});
|
|
|
|
it('should push page when previous transition views init, but havent transitioned yet', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INIT_LEAVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INIT_ENTER;
|
|
nav.views = [view1, view2];
|
|
|
|
let view3 = new ViewController(Page3);
|
|
nav._insert(-1, [view3]);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page3);
|
|
});
|
|
|
|
it('should insert multiple pages, back to back, with a starting active page', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_ACTIVE;
|
|
nav.views = [view1];
|
|
|
|
let view2 = new ViewController(Page2);
|
|
nav._insert(-1, [view2]);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
|
|
let view3 = new ViewController(Page3);
|
|
nav._insert(-1, [view3]);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page3);
|
|
});
|
|
|
|
it('should insert multiple pages, back to back, no starting active page', () => {
|
|
let view1 = new ViewController(Page1);
|
|
nav._insert(-1, [view1]);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
|
|
let view2 = new ViewController(Page2);
|
|
nav._insert(-1, [view2]);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
|
|
let view3 = new ViewController(Page3);
|
|
nav._insert(1, [view3]);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page3);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page2);
|
|
});
|
|
|
|
it('should push a page, and abort previous init', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INIT_LEAVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INIT_ENTER;
|
|
nav.views = [view1, view2];
|
|
|
|
let view3 = new ViewController(Page3);
|
|
nav._insert(-1, [view3]);
|
|
expect(nav.length()).toBe(3);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page3);
|
|
});
|
|
|
|
it('should insert a page between the first and second', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_ACTIVE;
|
|
nav.views = [view1, view2];
|
|
|
|
let view3 = new ViewController(Page3);
|
|
nav._insert(1, [view3]);
|
|
expect(nav.length()).toBe(3);
|
|
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page3);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page2);
|
|
});
|
|
|
|
it('should insert a page before the first', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_ACTIVE;
|
|
nav.views = [view1];
|
|
|
|
let view2 = new ViewController(Page2);
|
|
nav._insert(0, [view2]);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page1);
|
|
});
|
|
|
|
it('should insert 3 pages', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_ACTIVE;
|
|
nav.views = [view1];
|
|
|
|
let insertViews = [
|
|
new ViewController(Page2),
|
|
new ViewController(Page3),
|
|
new ViewController(Page4)
|
|
];
|
|
nav._insert(-1, insertViews);
|
|
expect(nav.length()).toBe(4);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
expect(nav.getByIndex(2).state).toBe(STATE_INACTIVE);
|
|
expect(nav.getByIndex(2).componentType).toBe(Page3);
|
|
expect(nav.getByIndex(3).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(3).componentType).toBe(Page4);
|
|
});
|
|
|
|
it('should push the second page', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_ACTIVE;
|
|
nav.views = [view1];
|
|
|
|
let view2 = new ViewController(Page2)
|
|
nav._insert(-1, [view2]);
|
|
expect(nav.length()).toBe(2);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_LEAVE);
|
|
expect(nav.getByIndex(0).componentType).toBe(Page1);
|
|
expect(nav.getByIndex(1).state).toBe(STATE_INIT_ENTER);
|
|
expect(nav.getByIndex(1).componentType).toBe(Page2);
|
|
});
|
|
|
|
it('should push the first page, using a number greater than the length', () => {
|
|
let view1 = new ViewController(Page1)
|
|
nav._insert(8675309, [view1]);
|
|
|
|
expect(nav.length()).toBe(1);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
|
|
});
|
|
|
|
it('should push the first page, using -1', () => {
|
|
let view1 = new ViewController(Page1)
|
|
nav._insert(-1, [view1]);
|
|
|
|
expect(nav.getByIndex(0).id).toBeDefined();
|
|
expect(nav.length()).toBe(1);
|
|
expect(nav.getByIndex(0).state).toBe(STATE_INIT_ENTER);
|
|
});
|
|
|
|
});
|
|
|
|
describe('getActive', () => {
|
|
it('should getActive()', () => {
|
|
expect(nav.getActive()).toBe(null);
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INIT_ENTER;
|
|
nav.views = [view1];
|
|
expect(nav.getActive()).toBe(null);
|
|
view1.state = STATE_ACTIVE;
|
|
expect(nav.getActive()).toBe(view1);
|
|
});
|
|
});
|
|
|
|
describe('getByState', () => {
|
|
it('should getByState()', () => {
|
|
expect(nav.getByState(null)).toBe(null);
|
|
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INIT_ENTER;
|
|
let view2 = new ViewController(Page2);
|
|
view2.state = STATE_INIT_ENTER;
|
|
nav.views = [view1, view2];
|
|
|
|
expect(nav.getByState('whatever')).toBe(null);
|
|
expect(nav.getByState(STATE_INIT_ENTER)).toBe(view2);
|
|
|
|
view2.state = STATE_INACTIVE;
|
|
expect(nav.getByState(STATE_INIT_ENTER)).toBe(view1);
|
|
|
|
view2.state = STATE_ACTIVE;
|
|
expect(nav.getActive()).toBe(view2);
|
|
});
|
|
});
|
|
|
|
describe('getPrevious', () => {
|
|
it('should getPrevious()', () => {
|
|
expect(nav.getPrevious(null)).toBe(null);
|
|
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
nav.views = [view1, view2];
|
|
|
|
expect(nav.getPrevious(view1)).toBe(null);
|
|
expect(nav.getPrevious(view2)).toBe(view1);
|
|
});
|
|
});
|
|
|
|
describe('first', () => {
|
|
it('should get first()', () => {
|
|
expect(nav.first()).toBe(null);
|
|
let view1 = new ViewController(Page1);
|
|
view1.setNav(nav);
|
|
let view2 = new ViewController(Page2);
|
|
view2.setNav(nav);
|
|
nav.views = [view1];
|
|
|
|
expect(nav.first()).toBe(view1);
|
|
expect(view1.isFirst()).toBe(true);
|
|
|
|
nav.views = [view1, view2];
|
|
expect(nav.first()).toBe(view1);
|
|
expect(view1.isFirst()).toBe(true);
|
|
expect(view2.isFirst()).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('last', () => {
|
|
it('should get last()', () => {
|
|
expect(nav.last()).toBe(null);
|
|
let view1 = new ViewController(Page1);
|
|
view1.setNav(nav);
|
|
let view2 = new ViewController(Page2);
|
|
view2.setNav(nav);
|
|
nav.views = [view1];
|
|
|
|
expect(nav.last()).toBe(view1);
|
|
expect(view1.isLast()).toBe(true);
|
|
|
|
nav.views = [view1, view2];
|
|
expect(nav.last()).toBe(view2);
|
|
expect(view1.isLast()).toBe(false);
|
|
expect(view2.isLast()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('indexOf', () => {
|
|
it('should get indexOf()', () => {
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
|
|
expect(nav.length()).toBe(0);
|
|
expect(nav.indexOf(view1)).toBe(-1);
|
|
|
|
nav.views = [view1, view2];
|
|
expect(nav.indexOf(view1)).toBe(0);
|
|
expect(nav.indexOf(view2)).toBe(1);
|
|
expect(nav.length()).toBe(2);
|
|
});
|
|
});
|
|
|
|
describe('getByIndex', () => {
|
|
it('should get getByIndex()', () => {
|
|
expect(nav.getByIndex(-99)).toBe(null);
|
|
expect(nav.getByIndex(99)).toBe(null);
|
|
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
nav.views = [view1, view2];
|
|
|
|
expect(nav.getByIndex(-1)).toBe(null);
|
|
expect(nav.getByIndex(0)).toBe(view1);
|
|
expect(nav.getByIndex(1)).toBe(view2);
|
|
expect(nav.getByIndex(2)).toBe(null);
|
|
});
|
|
});
|
|
|
|
/* private method */
|
|
describe('_beforeTrans', () => {
|
|
|
|
it('shouldnt disable app on short transition', () => {
|
|
// arrange
|
|
let executeAssertions = () => {
|
|
// assertions triggerd by callbacks
|
|
expect(app.setEnabled).toHaveBeenCalledWith(true, 50);
|
|
expect(nav.setTransitioning).toHaveBeenCalledWith(false, 50);
|
|
};
|
|
let mockTransition = {
|
|
play: () => {
|
|
executeAssertions();
|
|
},
|
|
getDuration: () => { return 50},
|
|
onFinish: () => {}
|
|
};
|
|
nav._createTrans = () => {
|
|
return mockTransition;
|
|
};
|
|
nav.config = {
|
|
platform : {
|
|
isRTL: () => {}
|
|
}
|
|
};
|
|
let app = {
|
|
setEnabled: () => {}
|
|
};
|
|
nav._app = app;
|
|
|
|
spyOn(app, 'setEnabled');
|
|
spyOn(nav, 'setTransitioning');
|
|
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
|
|
// act
|
|
nav._beforeTrans(view1, view2, {}, () => {});
|
|
});
|
|
|
|
it('should disable app on longer transition', () => {
|
|
// arrange
|
|
let executeAssertions = () => {
|
|
// assertions triggerd by callbacks
|
|
expect(app.setEnabled).toHaveBeenCalledWith(false, 200);
|
|
expect(nav.setTransitioning).toHaveBeenCalledWith(true, 200);
|
|
};
|
|
let mockTransition = {
|
|
play: () => {
|
|
executeAssertions();
|
|
},
|
|
getDuration: () => { return 200},
|
|
onFinish: () => {}
|
|
};
|
|
nav._createTrans = () => {
|
|
return mockTransition;
|
|
};
|
|
nav.config = {
|
|
platform : {
|
|
isRTL: () => {}
|
|
}
|
|
};
|
|
let app = {
|
|
setEnabled: () => {}
|
|
};
|
|
nav._app = app;
|
|
|
|
spyOn(app, 'setEnabled');
|
|
spyOn(nav, 'setTransitioning');
|
|
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
|
|
// act
|
|
nav._beforeTrans(view1, view2, {}, () => {});
|
|
});
|
|
|
|
it('should disable app w/ padding when keyboard is open', () => {
|
|
// arrange
|
|
let executeAssertions = () => {
|
|
// assertions triggerd by callbacks
|
|
expect(app.setEnabled.calls.mostRecent().args[0]).toEqual(false);
|
|
expect(app.setEnabled.calls.mostRecent().args[1]).toBeGreaterThan(200);
|
|
|
|
expect(nav.setTransitioning.calls.mostRecent().args[0]).toEqual(true);
|
|
expect(nav.setTransitioning.calls.mostRecent().args[1]).toBeGreaterThan(200);
|
|
};
|
|
let mockTransition = {
|
|
play: () => {
|
|
executeAssertions();
|
|
},
|
|
getDuration: () => { return 200},
|
|
onFinish: () => {}
|
|
};
|
|
nav._createTrans = () => {
|
|
return mockTransition;
|
|
};
|
|
nav.config = {
|
|
platform : {
|
|
isRTL: () => {}
|
|
}
|
|
};
|
|
let app = {
|
|
setEnabled: () => {}
|
|
};
|
|
nav._app = app;
|
|
nav._keyboard = {
|
|
isOpen: () => true
|
|
};
|
|
|
|
spyOn(app, 'setEnabled');
|
|
spyOn(nav, 'setTransitioning');
|
|
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
|
|
// act
|
|
nav._beforeTrans(view1, view2, {}, () => {});
|
|
});
|
|
|
|
it('shouldnt update app enabled when parent transition is occurring', () => {
|
|
// arrange
|
|
let executeAssertions = () => {
|
|
// assertions triggerd by callbacks
|
|
expect(app.setEnabled).not.toHaveBeenCalled();
|
|
expect(nav.setTransitioning.calls.mostRecent().args[0]).toEqual(true);
|
|
};
|
|
let mockTransition = {
|
|
play: () => {
|
|
executeAssertions();
|
|
},
|
|
getDuration: () => { return 200},
|
|
onFinish: () => {}
|
|
};
|
|
nav._createTrans = () => {
|
|
return mockTransition;
|
|
};
|
|
nav.config = {
|
|
platform : {
|
|
isRTL: () => {}
|
|
}
|
|
};
|
|
let app = {
|
|
setEnabled: () => {}
|
|
};
|
|
nav._app = app;
|
|
|
|
spyOn(app, 'setEnabled');
|
|
spyOn(nav, 'setTransitioning');
|
|
|
|
nav._getLongestTrans = () => { return Date.now() + 100 };
|
|
|
|
let view1 = new ViewController(Page1);
|
|
let view2 = new ViewController(Page2);
|
|
|
|
// act
|
|
nav._beforeTrans(view1, view2, {}, () => {});
|
|
});
|
|
|
|
it('should not begin transition when entering stated is inactive', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_INACTIVE;
|
|
|
|
let wasDoneCalled = false;
|
|
let done = () => {
|
|
wasDoneCalled = true;
|
|
};
|
|
|
|
nav._beforeTrans(view1, null, {}, done);
|
|
|
|
expect(wasDoneCalled).toEqual(true);
|
|
expect(view1.state).toEqual(STATE_INACTIVE);
|
|
});
|
|
|
|
it('should not begin transition when entering state is canceled', () => {
|
|
let view1 = new ViewController(Page1);
|
|
view1.state = STATE_CANCEL_ENTER;
|
|
|
|
let wasDoneCalled = false;
|
|
let done = () => {
|
|
wasDoneCalled = true;
|
|
};
|
|
|
|
nav._beforeTrans(view1, null, {}, done);
|
|
|
|
expect(wasDoneCalled).toEqual(true);
|
|
expect(view1.state).toEqual(STATE_CANCEL_ENTER);
|
|
});
|
|
});
|
|
|
|
/* private method */
|
|
describe('_getLongestTrans', () => {
|
|
it('should return 0 when transition end time is less than 0', () => {
|
|
// arrange
|
|
nav.parent = null;
|
|
// act
|
|
let returnedValue = nav._getLongestTrans(Date.now());
|
|
// asssert
|
|
expect(returnedValue).toEqual(0);
|
|
});
|
|
|
|
it('should return 0 when transition end time is less than now', () => {
|
|
// arrange
|
|
nav.parent = {
|
|
_trnsTime: Date.now() - 5
|
|
};
|
|
// act
|
|
let returnedValue = nav._getLongestTrans(Date.now());
|
|
// asssert
|
|
expect(returnedValue).toEqual(0);
|
|
});
|
|
|
|
it('should return 0 when parent transition time not set', () => {
|
|
// arrange
|
|
nav.parent = {
|
|
_trnsTime: undefined
|
|
};
|
|
// act
|
|
let returnedValue = nav._getLongestTrans(Date.now());
|
|
// asssert
|
|
expect(returnedValue).toEqual(0);
|
|
});
|
|
|
|
it('should return transitionEndTime when transition end time is greater than now', () => {
|
|
// arrange
|
|
let expectedReturnValue = Date.now() + 100;
|
|
nav.parent = {
|
|
_trnsTime: expectedReturnValue
|
|
};
|
|
// act
|
|
let returnedValue = nav._getLongestTrans(Date.now());
|
|
// asssert
|
|
expect(returnedValue).toEqual(expectedReturnValue);
|
|
});
|
|
|
|
it('should return the greatest end of transition time if found on first parent', () => {
|
|
// arrange
|
|
let expectedReturnValue = Date.now() + 100;
|
|
let firstParent = {
|
|
_trnsTime: expectedReturnValue
|
|
};
|
|
let secondParent = {
|
|
_trnsTime: Date.now() + 50
|
|
};
|
|
let thirdParent = {
|
|
_trnsTime: Date.now()
|
|
};
|
|
let fourthParent = {
|
|
_trnsTime: Date.now() + 20
|
|
};
|
|
firstParent.parent = secondParent;
|
|
secondParent.parent = thirdParent;
|
|
thirdParent.parent = fourthParent;
|
|
nav.parent = firstParent;
|
|
// act
|
|
let returnedValue = nav._getLongestTrans(Date.now());
|
|
// asssert
|
|
expect(returnedValue).toEqual(expectedReturnValue);
|
|
});
|
|
|
|
it('should return the greatest end of transition time if found on middle parent', () => {
|
|
// arrange
|
|
let expectedReturnValue = Date.now() + 100;
|
|
let firstParent = {
|
|
_trnsTime: Date.now()
|
|
};
|
|
let secondParent = {
|
|
_trnsTime: Date.now() + 50
|
|
};
|
|
let thirdParent = {
|
|
_trnsTime: expectedReturnValue
|
|
};
|
|
let fourthParent = {
|
|
_trnsTime: Date.now() + 20
|
|
};
|
|
firstParent.parent = secondParent;
|
|
secondParent.parent = thirdParent;
|
|
thirdParent.parent = fourthParent;
|
|
nav.parent = firstParent;
|
|
// act
|
|
let returnedValue = nav._getLongestTrans(Date.now());
|
|
// asssert
|
|
expect(returnedValue).toEqual(expectedReturnValue);
|
|
});
|
|
|
|
it('should return the greatest end of transition time if found on last parent', () => {
|
|
// arrange
|
|
let expectedReturnValue = Date.now() + 100;
|
|
let firstParent = {
|
|
_trnsTime: Date.now()
|
|
};
|
|
let secondParent = {
|
|
_trnsTime: Date.now() + 50
|
|
};
|
|
let thirdParent = {
|
|
_trnsTime: Date.now() + 20
|
|
};
|
|
let fourthParent = {
|
|
_trnsTime: expectedReturnValue
|
|
};
|
|
firstParent.parent = secondParent;
|
|
secondParent.parent = thirdParent;
|
|
thirdParent.parent = fourthParent;
|
|
nav.parent = firstParent;
|
|
// act
|
|
let returnedValue = nav._getLongestTrans(Date.now());
|
|
// asssert
|
|
expect(returnedValue).toEqual(expectedReturnValue);
|
|
});
|
|
});
|
|
|
|
// setup stuff
|
|
let nav: MockNavController;
|
|
let config = new Config();
|
|
let platform = new Platform();
|
|
|
|
class Page1 {}
|
|
class Page2 {}
|
|
class Page3 {}
|
|
class Page4 {}
|
|
class Page5 {}
|
|
|
|
beforeEach(() => {
|
|
nav = mockNav();
|
|
});
|
|
|
|
function mockNav(): MockNavController {
|
|
let elementRef = getElementRef();
|
|
|
|
let app = new App(config, platform);
|
|
let nav = new MockNavController(null, app, config, null, elementRef, null, null, null);
|
|
|
|
nav._keyboard = {
|
|
isOpen: function() {
|
|
return false;
|
|
}
|
|
};
|
|
nav._zone = {
|
|
run: function(cb) {
|
|
cb();
|
|
},
|
|
runOutsideAngular: function(cb) {
|
|
cb();
|
|
}
|
|
};
|
|
nav._renderer = {
|
|
setElementAttribute: function(){},
|
|
setElementClass: function(){},
|
|
setElementStyle: function(){}
|
|
};
|
|
|
|
return nav;
|
|
}
|
|
|
|
function getElementRef() {
|
|
return {
|
|
nativeElement: document.createElement('div')
|
|
}
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
class MockNavController extends NavController {
|
|
|
|
get views(): ViewController[] {
|
|
return this._views;
|
|
}
|
|
set views(views: ViewController[]) {
|
|
this._views = views;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
const STATE_ACTIVE = 1;
|
|
const STATE_INACTIVE = 2;
|
|
const STATE_INIT_ENTER = 3;
|
|
const STATE_INIT_LEAVE = 4;
|
|
const STATE_TRANS_ENTER = 5;
|
|
const STATE_TRANS_LEAVE = 6;
|
|
const STATE_REMOVE = 7;
|
|
const STATE_REMOVE_AFTER_TRANS = 8;
|
|
const STATE_CANCEL_ENTER = 9;
|
|
const STATE_FORCE_ACTIVE = 10;
|