Skip to content

Commit 07cf9c3

Browse files
committed
Renamed provide to provider and added some tests
1 parent 765663c commit 07cf9c3

File tree

9 files changed

+224
-37
lines changed

9 files changed

+224
-37
lines changed

examples/counter/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import {bind} from 'angular2/di';
33
import {createStore, applyMiddleware} from 'redux';
44
import thunk from 'redux-thunk';
55
import {App} from './containers/App';
6-
import {provide} from 'ng2-redux';
6+
import {provider} from 'ng2-redux';
77
import {rootReducer} from './reducers';
88

99
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
1010
const store = createStoreWithMiddleware(rootReducer);
1111

1212
bootstrap(
1313
App,
14-
[provide(store)]
14+
[provider(store)]
1515
);

examples/counter/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"homepage": "https://github.com/gaearon/redux#readme",
2929
"dependencies": {
3030
"angular2": "2.0.0-alpha.30",
31-
"ng2-redux": "0.0.1",
31+
"ng2-redux": "2.0.0-alpha",
3232
"react": "^0.13.3",
3333
"redux": "^1.0.0-rc",
3434
"reflect-metadata": "^0.1.0",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"babel-loader": "^5.3.2",
2828
"expect": "^1.8.0",
2929
"mocha": "^2.2.5",
30+
"sinon": "^1.16.1",
3031
"webpack": "^1.10.5"
3132
},
3233
"peerDependencies": {

src/connector.js renamed to src/components/connector.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import shallowEqual from './utils/shallowEqual';
2-
import wrapActionCreators from './utils/wrapActionCreators';
1+
import shallowEqual from '../utils/shallowEqual';
2+
import wrapActionCreators from '../utils/wrapActionCreators';
33
import invariant from 'invariant';
44
import _ from 'lodash';
55

src/components/provider.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import Connector from './connector';
2+
import {bind, Injector} from 'angular2/di';
3+
let redux = require('redux');
4+
5+
export function provider(store) {
6+
const _connector = new Connector(store);
7+
8+
return bind('ngRedux').toFactory(() => {
9+
return { connect: _connector.connect, ...store};
10+
});
11+
}
12+
13+
14+
/*
15+
const createStoreWithMiddleware = applyInjectableMiddleware(thunk, 'promise')(createStore);
16+
*/
17+
/*
18+
export function applyInjectableMiddleware(middlewares) {
19+
const injector = new Injector();
20+
let resolvedMiddlewares = [];
21+
_.forEach(middlewares, middleware => {
22+
_.isString(middleware)
23+
? resolvedMiddlewares.push(Injector.resolve(middleware))
24+
: resolvedMiddlewares.push(middleware)
25+
});
26+
27+
return redux.applyMiddleware(...resolvedMiddlewares);
28+
}
29+
*/
30+
31+
32+

src/index.js

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1 @@
1-
import Connector from './connector';
2-
import {bind, Injector} from 'angular2/di';
3-
let redux = require('redux');
4-
5-
export function provide(store) {
6-
const _connector = new Connector(store);
7-
8-
return bind('ngRedux').toFactory(() => {
9-
return { connect: _connector.connect, ...store};
10-
});
11-
}
12-
13-
14-
/*
15-
const createStoreWithMiddleware = applyInjectableMiddleware(thunk, 'promise')(createStore);
16-
*/
17-
/*
18-
export function applyInjectableMiddleware(middlewares) {
19-
const injector = new Injector();
20-
let resolvedMiddlewares = [];
21-
_.forEach(middlewares, middleware => {
22-
_.isString(middleware)
23-
? resolvedMiddlewares.push(Injector.resolve(middleware))
24-
: resolvedMiddlewares.push(middleware)
25-
});
26-
27-
return redux.applyMiddleware(...resolvedMiddlewares);
28-
}
29-
*/
30-
31-
32-
1+
export {provider} from './components/provider';

test/components/connector.spec.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import expect from 'expect';
2+
let sinon = require('sinon');
3+
import { createStore } from 'redux';
4+
import Connector from '../../src/components/connector';
5+
import _ from 'lodash';
6+
7+
describe('Connector', () => {
8+
let store;
9+
let connector;
10+
let targetObj;
11+
let defaultState;
12+
13+
beforeEach(() => {
14+
defaultState = {
15+
foo: 'bar',
16+
baz: -1
17+
};
18+
store = createStore((state = defaultState, action) => {
19+
return {...state, baz: action.payload};
20+
});
21+
targetObj = {};
22+
connector = new Connector(store);
23+
});
24+
25+
it('Should throw when target is not a Function or a plain object', () => {
26+
expect(connector.connect(() => ({})).bind(connector, 15)).toThrow();
27+
expect(connector.connect(() => ({})).bind(connector, undefined)).toThrow();
28+
expect(connector.connect(() => ({})).bind(connector, 'test')).toThrow();
29+
30+
expect(connector.connect(() => ({})).bind(connector, {})).toNotThrow();
31+
expect(connector.connect(() => ({})).bind(connector, () => {})).toNotThrow();
32+
33+
});
34+
35+
it('Should throw when selector does not return a plain object', () => {
36+
expect(connector.connect.bind(connector, state => state.foo)).toThrow();
37+
});
38+
39+
it('Should extend target (Object) with selected state once directly after creation', () => {
40+
connector.connect(
41+
() => ({
42+
vm: { test: 1 }
43+
}))(targetObj);
44+
45+
expect(targetObj.vm).toEqual({ test: 1 });
46+
});
47+
48+
it('Should update the target (Object) passed to connect when the store updates', () => {
49+
connector.connect(state => state)(targetObj);
50+
store.dispatch({ type: 'ACTION', payload: 0 });
51+
expect(targetObj.baz).toBe(0);
52+
store.dispatch({ type: 'ACTION', payload: 7 });
53+
expect(targetObj.baz).toBe(7);
54+
});
55+
56+
it('Should prevent unnecessary updates when state does not change (shallowly)', () => {
57+
connector.connect(state => state)(targetObj);
58+
store.dispatch({ type: 'ACTION', payload: 5 });
59+
60+
expect(targetObj.baz).toBe(5);
61+
62+
targetObj.baz = 0;
63+
64+
//this should not replace our mutation, since the state didn't change
65+
store.dispatch({ type: 'ACTION', payload: 5 });
66+
67+
expect(targetObj.baz).toBe(0);
68+
69+
});
70+
71+
it('Should extend target (object) with actionCreators', () => {
72+
connector.connect(() => ({}), { ac1: () => { }, ac2: () => { } })(targetObj);
73+
expect(_.isFunction(targetObj.ac1)).toBe(true);
74+
expect(_.isFunction(targetObj.ac2)).toBe(true);
75+
});
76+
77+
it('Should return an unsubscribing function', () => {
78+
const unsubscribe = connector.connect(state => state)(targetObj);
79+
store.dispatch({ type: 'ACTION', payload: 5 });
80+
81+
expect(targetObj.baz).toBe(5);
82+
83+
unsubscribe();
84+
85+
store.dispatch({ type: 'ACTION', payload: 7 });
86+
87+
expect(targetObj.baz).toBe(5);
88+
89+
});
90+
91+
it('Should provide dispatch to mapDispatchToTarget when receiving a Function', () => {
92+
let receivedDispatch;
93+
connector.connect(() => ({}), dispatch => { receivedDispatch = dispatch })(targetObj);
94+
expect(receivedDispatch).toBe(store.dispatch);
95+
});
96+
97+
});

test/utils/shallowEqual.spec.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import expect from 'expect';
2+
import shallowEqual from '../../src/utils/shallowEqual';
3+
4+
describe('Utils', () => {
5+
describe('shallowEqual', () => {
6+
it('should return true if arguments fields are equal', () => {
7+
expect(
8+
shallowEqual(
9+
{ a: 1, b: 2, c: undefined },
10+
{ a: 1, b: 2, c: undefined }
11+
)
12+
).toBe(true);
13+
14+
expect(
15+
shallowEqual(
16+
{ a: 1, b: 2, c: 3 },
17+
{ a: 1, b: 2, c: 3 }
18+
)
19+
).toBe(true);
20+
21+
const o = {};
22+
expect(
23+
shallowEqual(
24+
{ a: 1, b: 2, c: o },
25+
{ a: 1, b: 2, c: o }
26+
)
27+
).toBe(true);
28+
});
29+
30+
it('should return false if first argument has too many keys', () => {
31+
expect(
32+
shallowEqual(
33+
{ a: 1, b: 2, c: 3 },
34+
{ a: 1, b: 2 }
35+
)
36+
).toBe(false);
37+
});
38+
39+
it('should return false if second argument has too many keys', () => {
40+
expect(
41+
shallowEqual(
42+
{ a: 1, b: 2 },
43+
{ a: 1, b: 2, c: 3 }
44+
)
45+
).toBe(false);
46+
});
47+
48+
it('should return false if arguments have different keys', () => {
49+
expect(
50+
shallowEqual(
51+
{ a: 1, b: 2, c: undefined },
52+
{ a: 1, bb: 2, c: undefined }
53+
)
54+
).toBe(false);
55+
});
56+
});
57+
});

test/utils/wrapActionCreators.spec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import expect from 'expect';
2+
import wrapActionCreators from '../../src/utils/wrapActionCreators';
3+
4+
describe('Utils', () => {
5+
describe('wrapActionCreators', () => {
6+
it('should return a function that wraps argument in a call to bindActionCreators', () => {
7+
8+
function dispatch(action) {
9+
return {
10+
dispatched: action
11+
};
12+
}
13+
14+
const actionResult = {an: 'action'};
15+
16+
const actionCreators = {
17+
action: () => actionResult
18+
};
19+
20+
const wrapped = wrapActionCreators(actionCreators);
21+
expect(wrapped).toBeA(Function);
22+
expect(() => wrapped(dispatch)).toNotThrow();
23+
expect(() => wrapped().action()).toThrow();
24+
25+
const bound = wrapped(dispatch);
26+
expect(bound.action).toNotThrow();
27+
expect(bound.action().dispatched).toBe(actionResult);
28+
29+
});
30+
});
31+
});

0 commit comments

Comments
 (0)