[Navigator]: Add method `indexOf` and `slice` to NavigationRouteStack

This commit is contained in:
Hedger Wang 2015-07-22 11:46:43 -07:00
parent 214c47ed76
commit 280347d66a
2 changed files with 83 additions and 29 deletions

View File

@ -52,6 +52,16 @@ class RouteStack {
return this._routes.get(index);
}
indexOf(route: any): number {
return this._routes.indexOf(route);
}
slice(begin: ?number, end: ?number): RouteStack {
var routes = this._routes.slice(begin, end);
var index = Math.min(this._index, routes.size - 1);
return this._update(index, routes);
}
/**
* Returns a new stack with the provided route appended,
* starting at this stack size.
@ -71,7 +81,7 @@ class RouteStack {
list.slice(0, this._index + 1).push(route);
});
return new RouteStack(routes.size - 1, routes);
return this._update(routes.size - 1, routes);
}
/**
@ -83,7 +93,7 @@ class RouteStack {
// When popping, removes the rest of the routes past the current index.
var routes = this._routes.slice(0, this._index);
return new RouteStack(routes.size - 1, routes);
return this._update(routes.size - 1, routes);
}
jumpToIndex(index: number): RouteStack {
@ -92,11 +102,7 @@ class RouteStack {
'index out of bound'
);
if (index === this._index) {
return this;
}
return new RouteStack(index, this._routes);
return this._update(index, this._routes);
}
/**
@ -129,7 +135,14 @@ class RouteStack {
);
var routes = this._routes.set(index, route);
return new RouteStack(this._index, routes);
return this._update(this._index, routes);
}
_update(index: number, routes: List): RouteStack {
if (this._index === index && this._routes === routes) {
return this;
}
return new RouteStack(index, routes);
}
}

View File

@ -36,17 +36,17 @@ describe('NavigationRouteStack:', () => {
// Basic
it('gets index', () => {
var stack = new NavigationRouteStack(1, ['a', 'b', 'c']);
expect(stack.index).toEqual(1);
expect(stack.index).toBe(1);
});
it('gets size', () => {
var stack = new NavigationRouteStack(1, ['a', 'b', 'c']);
expect(stack.size).toEqual(3);
expect(stack.size).toBe(3);
});
it('gets route', () => {
var stack = new NavigationRouteStack(0, ['a', 'b', 'c']);
expect(stack.get(2)).toEqual('c');
expect(stack.get(2)).toBe('c');
});
it('converts to an array', () => {
@ -57,7 +57,7 @@ describe('NavigationRouteStack:', () => {
it('creates a new stack after mutation', () => {
var stack1 = new NavigationRouteStack(0, ['a', 'b']);
var stack2 = stack1.push('c');
expect(stack1).not.toEqual(stack2);
expect(stack1).not.toBe(stack2);
});
it('throws at index out of bound', () => {
@ -70,15 +70,57 @@ describe('NavigationRouteStack:', () => {
}).toThrow();
});
it('finds index', () => {
var stack = new NavigationRouteStack(0, ['a', 'b']);
expect(stack.indexOf('b')).toBe(1);
expect(stack.indexOf('c')).toBe(-1);
});
it('slices', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c', 'd']);
var stack2 = stack1.slice(1, 3);
expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['b', 'c']);
});
it('may update index after slicing', () => {
var stack = new NavigationRouteStack(2, ['a', 'b', 'c']);
expect(stack.slice().index).toBe(2);
expect(stack.slice(0, 1).index).toBe(0);
expect(stack.slice(0, 2).index).toBe(1);
expect(stack.slice(0, 3).index).toBe(2);
expect(stack.slice(0, 100).index).toBe(2);
expect(stack.slice(-2).index).toBe(1);
});
it('slices without specifying params', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c']);
var stack2 = stack1.slice();
expect(stack2).toBe(stack1);
});
it('slices to from the end', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c', 'd']);
var stack2 = stack1.slice(-2);
expect(stack2.toArray()).toEqual(['c', 'd']);
});
it('throws when slicing to empty', () => {
expect(() => {
var stack = new NavigationRouteStack(1, ['a', 'b']);
stack.slice(100);
}).toThrow();
});
// Push
it('pushes route', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b']);
var stack2 = stack1.push('c');
expect(stack2).not.toEqual(stack1);
expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a', 'b', 'c']);
expect(stack2.index).toEqual(2);
expect(stack2.size).toEqual(3);
expect(stack2.index).toBe(2);
expect(stack2.size).toBe(3);
});
it('throws when pushing empty route', () => {
@ -101,27 +143,27 @@ describe('NavigationRouteStack:', () => {
it('replaces routes on push', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c']);
var stack2 = stack1.push('d');
expect(stack2).not.toEqual(stack1);
expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a', 'b', 'd']);
expect(stack2.index).toEqual(2);
expect(stack2.index).toBe(2);
});
// Pop
it('pops route', () => {
var stack1 = new NavigationRouteStack(2, ['a', 'b', 'c']);
var stack2 = stack1.pop();
expect(stack2).not.toEqual(stack1);
expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a', 'b']);
expect(stack2.index).toEqual(1);
expect(stack2.size).toEqual(2);
expect(stack2.index).toBe(1);
expect(stack2.size).toBe(2);
});
it('replaces routes on pop', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c']);
var stack2 = stack1.pop();
expect(stack2).not.toEqual(stack1);
expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a']);
expect(stack2.index).toEqual(0);
expect(stack2.index).toBe(0);
});
it('throws when popping to empty stack', () => {
@ -136,8 +178,8 @@ describe('NavigationRouteStack:', () => {
var stack1 = new NavigationRouteStack(0, ['a', 'b', 'c']);
var stack2 = stack1.jumpToIndex(2);
expect(stack2).not.toEqual(stack1);
expect(stack2.index).toEqual(2);
expect(stack2).not.toBe(stack1);
expect(stack2.index).toBe(2);
});
it('throws then jumping to index out of bound', () => {
@ -157,21 +199,20 @@ describe('NavigationRouteStack:', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b']);
var stack2 = stack1.replaceAtIndex(0, 'x');
expect(stack2).not.toEqual(stack1);
expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['x', 'b']);
expect(stack2.index).toEqual(1);
expect(stack2.index).toBe(1);
});
it('replaces route at negative index', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b']);
var stack2 = stack1.replaceAtIndex(-1, 'x');
expect(stack2).not.toEqual(stack1);
expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a', 'x']);
expect(stack2.index).toEqual(1);
expect(stack2.index).toBe(1);
});
it('throws when replacing empty route', () => {
expect(() => {
var stack = new NavigationRouteStack(1, ['a', 'b']);