diff --git a/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js b/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js index 91344e170..78fbfd157 100644 --- a/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js +++ b/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js @@ -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); } } diff --git a/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationRouteStack-test.js b/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationRouteStack-test.js index 3b750e054..a80bf8267 100644 --- a/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationRouteStack-test.js +++ b/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationRouteStack-test.js @@ -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']);