Skip to content
This repository was archived by the owner on Apr 9, 2019. It is now read-only.

Commit e22b728

Browse files
committed
Merge branch 'pop-to-root'
2 parents 7f90c5e + bdc8008 commit e22b728

File tree

4 files changed

+176
-20
lines changed

4 files changed

+176
-20
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,20 @@ Addtional options - see [pushView()](#push-options)
156156

157157
***
158158

159+
### `popToRootView([options])`
160+
161+
Pop the all the views off the stack except the first (root) view
162+
163+
**Arguments**
164+
165+
##### `options` `{object}`
166+
167+
Addtional options - see [pushView()](#push-options)
168+
169+
##### `options.transiton` `{number|function}` `default=Transition.type.PUSH_RIGHT`
170+
171+
***
172+
159173
### `setViews(views, [options])`
160174

161175
Replaces the views currently managed by the navigationController

karma.conf.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module.exports = function(config) {
1616
'spec/helpers.js',
1717
'node_modules/react/dist/react-with-addons.js',
1818
'node_modules/sinon/pkg/sinon.js',
19-
'spec/**/*.spec.{jsx,js}'
19+
'spec/**/*.spec.+(jsx|js)'
2020
],
2121

2222
// list of files to exclude
@@ -25,7 +25,7 @@ module.exports = function(config) {
2525
// preprocess matching files before serving them to the browser
2626
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
2727
preprocessors: {
28-
'spec/**/*.spec.{jsx,js}': ['webpack']
28+
'spec/**/*.spec.+(jsx|js)': ['webpack']
2929
},
3030

3131
// test results reporter to use

package.json

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-navigation-controller",
3-
"version": "1.0.2",
3+
"version": "1.0.3",
44
"description": "React view manager similar to UINavigationController",
55
"keywords": [
66
"react",
@@ -24,25 +24,27 @@
2424
"react": "^0.13.0"
2525
},
2626
"dependencies": {
27-
"classnames": "^1.2.0",
28-
"rebound": "0.0.12"
27+
"classnames": "^2.1.3",
28+
"rebound": "0.0.13"
2929
},
3030
"devDependencies": {
31-
"babel": "^4.7.16",
32-
"babel-loader": "^4.2.0",
33-
"chai": "^2.2.0",
34-
"karma": "^0.12.31",
31+
"babel": "^5.8.23",
32+
"babel-core": "^5.8.25",
33+
"babel-loader": "^5.3.2",
34+
"chai": "^3.3.0",
35+
"karma": "^0.13.10",
3536
"karma-chai": "^0.1.0",
36-
"karma-chrome-launcher": "^0.1.7",
37-
"karma-mocha": "^0.1.10",
38-
"karma-phantomjs-launcher": "^0.1.4",
39-
"karma-spec-reporter": "0.0.18",
40-
"karma-webpack": "^1.5.0",
41-
"minimist": "^1.1.1",
42-
"mocha": "^2.2.1",
43-
"react": "0.13.1",
44-
"sinon": "^1.14.1",
45-
"webpack": "^1.7.3",
46-
"webpack-dev-server": "^1.7.0"
37+
"karma-chrome-launcher": "^0.2.0",
38+
"karma-mocha": "^0.2.0",
39+
"karma-phantomjs-launcher": "^0.2.1",
40+
"karma-spec-reporter": "0.0.20",
41+
"karma-webpack": "^1.7.0",
42+
"minimist": "^1.2.0",
43+
"mocha": "^2.3.3",
44+
"phantomjs": "^1.9.18",
45+
"react": "0.13.3",
46+
"sinon": "^1.17.1",
47+
"webpack": "^1.12.2",
48+
"webpack-dev-server": "^1.12.0"
4749
}
4850
}

spec/navigation-controller.spec.jsx

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const transformPrefix = getVendorPrefix('transform');
2020
const View = require('../examples/src/view');
2121
class ViewA extends View { }
2222
class ViewB extends View { }
23+
class ViewC extends View { }
2324

2425
describe('NavigationController', () => {
2526
const views = [
@@ -597,6 +598,145 @@ describe('NavigationController', () => {
597598
});
598599
});
599600
});
601+
describe('#__popToRootView', () => {
602+
beforeEach(done => {
603+
controller = renderIntoDocument(
604+
<NavigationController views={[<ViewA />,<ViewB />,<ViewC />]} />
605+
);
606+
requestAnimationFrame(() => {
607+
done();
608+
});
609+
});
610+
it('throws an error if an only one view is in the stack', () => {
611+
controller.state.views = [<ViewA />];
612+
expect(() => {
613+
controller.__popToRootView()
614+
}).to.throw(/stack/);
615+
});
616+
it('returns early if the controller is already transitioning', () => {
617+
const spy = sinon.spy(controller, 'setState');
618+
controller.__isTransitioning = true;
619+
controller.__popToRootView();
620+
expect(spy.called).not.to.be.true;
621+
});
622+
it('shows the view wrappers', () => {
623+
const spy = sinon.spy(controller, '__displayViews');
624+
controller.__popToRootView();
625+
expect(spy.calledWith('block')).to.be.true;
626+
});
627+
it('removes all but the root view from state.views', (done) => {
628+
controller.__popToRootView({
629+
onComplete() {
630+
expect(controller.state.views).to.have.length(1);
631+
expect(controller.state.views[0].type).to.equal(ViewA);
632+
done();
633+
},
634+
transition: Transition.type.NONE
635+
});
636+
});
637+
it('sets state.transition', (done) => {
638+
controller.__popToRootView({
639+
transition: Transition.type.NONE,
640+
onComplete() {
641+
done();
642+
}
643+
});
644+
requestAnimationFrame(() => {
645+
expect(controller.state.transition).to.equal(Transition.type.NONE);
646+
});
647+
});
648+
it('sets state.mountedViews', (done) => {
649+
const [prev,next] = controller.__viewIndexes;
650+
controller.__popToRootView({
651+
transition: Transition.type.PUSH_RIGHT,
652+
onComplete() {
653+
done();
654+
}
655+
});
656+
requestAnimationFrame(() => {
657+
expect(controller.state.mountedViews[prev].type).to.equal(ViewC);
658+
expect(controller.state.mountedViews[next].type).to.equal(ViewA);
659+
});
660+
});
661+
it('transitions the views', (done) => {
662+
const spy = sinon.spy(controller, '__transitionViews');
663+
controller.__popToRootView({ transition: Transition.type.NONE });
664+
requestAnimationFrame(() => {
665+
expect(spy.calledOnce).to.be.true;
666+
done();
667+
});
668+
});
669+
it('sets __isTransitioning=true', () => {
670+
controller.__popToRootView({ transition: Transition.type.NONE });
671+
expect(controller.__isTransitioning).to.be.true;
672+
});
673+
it('calls the onComplete callback', (done) => {
674+
controller.__popToRootView({
675+
onComplete() {
676+
expect(true).to.be.true;
677+
done();
678+
}
679+
});
680+
});
681+
it('does not rehydrate the state', (done) => {
682+
controller = renderIntoDocument(
683+
<NavigationController views={[<ViewA />]} preserveState={false} />
684+
);
685+
requestAnimationFrame(() => {
686+
var rootView = controller.refs[`view-${controller.__viewIndexes[0]}`];
687+
rootView.setState({
688+
foo: 'bar'
689+
});
690+
controller.pushView(<ViewB />, {
691+
transition: Transition.type.NONE,
692+
onComplete() {
693+
controller.pushView(<ViewC />, {
694+
transition: Transition.type.NONE,
695+
onComplete() {
696+
controller.popToRootView({
697+
transition: Transition.type.NONE,
698+
onComplete() {
699+
rootView = controller.refs[`view-${controller.__viewIndexes[1]}`];
700+
expect(rootView.state)
701+
.not.to.have.property('foo');
702+
done();
703+
}
704+
});
705+
}
706+
})
707+
}
708+
});
709+
});
710+
});
711+
it('rehydrates the state', (done) => {
712+
controller = renderIntoDocument(
713+
<NavigationController views={[<ViewA />]} preserveState={true} />
714+
);
715+
requestAnimationFrame(() => {
716+
controller.refs[`view-${controller.__viewIndexes[0]}`].setState({
717+
foo: 'bar'
718+
});
719+
controller.pushView(<ViewB />, {
720+
transition: Transition.type.NONE,
721+
onComplete() {
722+
controller.pushView(<ViewC />, {
723+
transition: Transition.type.NONE,
724+
onComplete() {
725+
controller.popToRootView({
726+
transition: Transition.type.NONE,
727+
onComplete() {
728+
expect(controller.refs[`view-${controller.__viewIndexes[1]}`].state)
729+
.to.have.property('foo');
730+
done();
731+
}
732+
});
733+
}
734+
})
735+
}
736+
});
737+
});
738+
});
739+
});
600740
describe('#__setViews', () => {
601741
beforeEach(done => {
602742
requestAnimationFrame(() => {

0 commit comments

Comments
 (0)