[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); 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, * Returns a new stack with the provided route appended,
* starting at this stack size. * starting at this stack size.
@ -71,7 +81,7 @@ class RouteStack {
list.slice(0, this._index + 1).push(route); 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. // When popping, removes the rest of the routes past the current index.
var routes = this._routes.slice(0, this._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 { jumpToIndex(index: number): RouteStack {
@ -92,11 +102,7 @@ class RouteStack {
'index out of bound' 'index out of bound'
); );
if (index === this._index) { return this._update(index, this._routes);
return this;
}
return new RouteStack(index, this._routes);
} }
/** /**
@ -129,7 +135,14 @@ class RouteStack {
); );
var routes = this._routes.set(index, route); 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 // Basic
it('gets index', () => { it('gets index', () => {
var stack = new NavigationRouteStack(1, ['a', 'b', 'c']); var stack = new NavigationRouteStack(1, ['a', 'b', 'c']);
expect(stack.index).toEqual(1); expect(stack.index).toBe(1);
}); });
it('gets size', () => { it('gets size', () => {
var stack = new NavigationRouteStack(1, ['a', 'b', 'c']); var stack = new NavigationRouteStack(1, ['a', 'b', 'c']);
expect(stack.size).toEqual(3); expect(stack.size).toBe(3);
}); });
it('gets route', () => { it('gets route', () => {
var stack = new NavigationRouteStack(0, ['a', 'b', 'c']); 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', () => { it('converts to an array', () => {
@ -57,7 +57,7 @@ describe('NavigationRouteStack:', () => {
it('creates a new stack after mutation', () => { it('creates a new stack after mutation', () => {
var stack1 = new NavigationRouteStack(0, ['a', 'b']); var stack1 = new NavigationRouteStack(0, ['a', 'b']);
var stack2 = stack1.push('c'); var stack2 = stack1.push('c');
expect(stack1).not.toEqual(stack2); expect(stack1).not.toBe(stack2);
}); });
it('throws at index out of bound', () => { it('throws at index out of bound', () => {
@ -70,15 +70,57 @@ describe('NavigationRouteStack:', () => {
}).toThrow(); }).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 // Push
it('pushes route', () => { it('pushes route', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b']); var stack1 = new NavigationRouteStack(1, ['a', 'b']);
var stack2 = stack1.push('c'); var stack2 = stack1.push('c');
expect(stack2).not.toEqual(stack1); expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a', 'b', 'c']); expect(stack2.toArray()).toEqual(['a', 'b', 'c']);
expect(stack2.index).toEqual(2); expect(stack2.index).toBe(2);
expect(stack2.size).toEqual(3); expect(stack2.size).toBe(3);
}); });
it('throws when pushing empty route', () => { it('throws when pushing empty route', () => {
@ -101,27 +143,27 @@ describe('NavigationRouteStack:', () => {
it('replaces routes on push', () => { it('replaces routes on push', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c']); var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c']);
var stack2 = stack1.push('d'); var stack2 = stack1.push('d');
expect(stack2).not.toEqual(stack1); expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a', 'b', 'd']); expect(stack2.toArray()).toEqual(['a', 'b', 'd']);
expect(stack2.index).toEqual(2); expect(stack2.index).toBe(2);
}); });
// Pop // Pop
it('pops route', () => { it('pops route', () => {
var stack1 = new NavigationRouteStack(2, ['a', 'b', 'c']); var stack1 = new NavigationRouteStack(2, ['a', 'b', 'c']);
var stack2 = stack1.pop(); var stack2 = stack1.pop();
expect(stack2).not.toEqual(stack1); expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a', 'b']); expect(stack2.toArray()).toEqual(['a', 'b']);
expect(stack2.index).toEqual(1); expect(stack2.index).toBe(1);
expect(stack2.size).toEqual(2); expect(stack2.size).toBe(2);
}); });
it('replaces routes on pop', () => { it('replaces routes on pop', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c']); var stack1 = new NavigationRouteStack(1, ['a', 'b', 'c']);
var stack2 = stack1.pop(); var stack2 = stack1.pop();
expect(stack2).not.toEqual(stack1); expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a']); expect(stack2.toArray()).toEqual(['a']);
expect(stack2.index).toEqual(0); expect(stack2.index).toBe(0);
}); });
it('throws when popping to empty stack', () => { it('throws when popping to empty stack', () => {
@ -136,8 +178,8 @@ describe('NavigationRouteStack:', () => {
var stack1 = new NavigationRouteStack(0, ['a', 'b', 'c']); var stack1 = new NavigationRouteStack(0, ['a', 'b', 'c']);
var stack2 = stack1.jumpToIndex(2); var stack2 = stack1.jumpToIndex(2);
expect(stack2).not.toEqual(stack1); expect(stack2).not.toBe(stack1);
expect(stack2.index).toEqual(2); expect(stack2.index).toBe(2);
}); });
it('throws then jumping to index out of bound', () => { it('throws then jumping to index out of bound', () => {
@ -157,21 +199,20 @@ describe('NavigationRouteStack:', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b']); var stack1 = new NavigationRouteStack(1, ['a', 'b']);
var stack2 = stack1.replaceAtIndex(0, 'x'); var stack2 = stack1.replaceAtIndex(0, 'x');
expect(stack2).not.toEqual(stack1); expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['x', 'b']); expect(stack2.toArray()).toEqual(['x', 'b']);
expect(stack2.index).toEqual(1); expect(stack2.index).toBe(1);
}); });
it('replaces route at negative index', () => { it('replaces route at negative index', () => {
var stack1 = new NavigationRouteStack(1, ['a', 'b']); var stack1 = new NavigationRouteStack(1, ['a', 'b']);
var stack2 = stack1.replaceAtIndex(-1, 'x'); var stack2 = stack1.replaceAtIndex(-1, 'x');
expect(stack2).not.toEqual(stack1); expect(stack2).not.toBe(stack1);
expect(stack2.toArray()).toEqual(['a', 'x']); expect(stack2.toArray()).toEqual(['a', 'x']);
expect(stack2.index).toEqual(1); expect(stack2.index).toBe(1);
}); });
it('throws when replacing empty route', () => { it('throws when replacing empty route', () => {
expect(() => { expect(() => {
var stack = new NavigationRouteStack(1, ['a', 'b']); var stack = new NavigationRouteStack(1, ['a', 'b']);