Browse Source

add redux integration tests \#1649

Daniel Zlotin 7 years ago
parent
commit
f8e6d78145

+ 31
- 0
integration/redux/MyContainer.js View File

1
+const React = require('react');
2
+const { Component } = require('react');
3
+
4
+const { Text } = require('react-native');
5
+const { connect } = require('react-redux');
6
+const store = require('./MyStore');
7
+
8
+class MyContainer extends Component {
9
+  render() {
10
+    if (this.props.renderCountIncrement) {
11
+      this.props.renderCountIncrement();
12
+    }
13
+
14
+    return this.renderText(this.props.printAge ? this.props.age : this.props.name);
15
+  }
16
+
17
+  renderText(txt) {
18
+    return (
19
+      <Text>{txt}</Text>
20
+    );
21
+  }
22
+}
23
+
24
+function mapStateToProps(state) {
25
+  return {
26
+    name: store.selectors.getName(state),
27
+    age: store.selectors.getAge(state)
28
+  };
29
+}
30
+
31
+module.exports = connect(mapStateToProps)(MyContainer);

+ 39
- 0
integration/redux/MyStore.js View File

1
+const redux = require('redux');
2
+const _ = require('lodash');
3
+
4
+const initialState = {
5
+  person: {
6
+    name: 'no name'
7
+  }
8
+};
9
+
10
+const reducer = (state = initialState, action) => {
11
+  switch (action.type) {
12
+    case 'redux.MyStore.setName': {
13
+      return _.merge({}, state, { person: { name: action.name } });
14
+    }
15
+    case 'redux.MyStore.setAge': {
16
+      return _.merge({}, state, { person: { age: action.age } });
17
+    }
18
+    default: {
19
+      return state;
20
+    }
21
+  }
22
+};
23
+
24
+const selectors = {
25
+  getName(state) {
26
+    return _.get(state, 'person.name');
27
+  },
28
+
29
+  getAge(state) {
30
+    return state.person.age;
31
+  }
32
+};
33
+
34
+const reduxStore = redux.createStore(reducer);
35
+
36
+module.exports = {
37
+  reduxStore,
38
+  selectors
39
+};

+ 59
- 0
integration/redux/Redux.test.js View File

1
+const React = require('react');
2
+require('react-native');
3
+const renderer = require('react-test-renderer');
4
+const { Provider } = require('react-redux');
5
+
6
+describe('redux support', () => {
7
+  let MyConnectedContainer;
8
+  let store;
9
+
10
+  beforeEach(() => {
11
+    MyConnectedContainer = require('./MyContainer');
12
+    store = require('./MyStore');
13
+  });
14
+
15
+  it('renders normally', () => {
16
+    const tree = renderer.create(
17
+      <Provider store={store.reduxStore}>
18
+        <MyConnectedContainer />
19
+      </Provider>
20
+    );
21
+    expect(tree.toJSON().children).toEqual(['no name']);
22
+  });
23
+
24
+  it('rerenders as a result of an underlying state change (by selector)', () => {
25
+    const renderCountIncrement = jest.fn();
26
+    const tree = renderer.create(
27
+      <Provider store={store.reduxStore}>
28
+        <MyConnectedContainer renderCountIncrement={renderCountIncrement} />
29
+      </Provider>
30
+    );
31
+
32
+    expect(tree.toJSON().children).toEqual(['no name']);
33
+    expect(renderCountIncrement).toHaveBeenCalledTimes(1);
34
+
35
+    store.reduxStore.dispatch({ type: 'redux.MyStore.setName', name: 'Bob' });
36
+    expect(store.selectors.getName(store.reduxStore.getState())).toEqual('Bob');
37
+    expect(tree.toJSON().children).toEqual(['Bob']);
38
+
39
+    expect(renderCountIncrement).toHaveBeenCalledTimes(2);
40
+  });
41
+
42
+  it('rerenders as a result of an underlying state change with a new key', () => {
43
+    const renderCountIncrement = jest.fn();
44
+    const tree = renderer.create(
45
+      <Provider store={store.reduxStore}>
46
+        <MyConnectedContainer printAge={true} renderCountIncrement={renderCountIncrement} />
47
+      </Provider>
48
+    );
49
+
50
+    expect(tree.toJSON().children).toEqual(null);
51
+    expect(renderCountIncrement).toHaveBeenCalledTimes(1);
52
+
53
+    store.reduxStore.dispatch({ type: 'redux.MyStore.setAge', age: 30 });
54
+    expect(store.selectors.getAge(store.reduxStore.getState())).toEqual(30);
55
+    expect(tree.toJSON().children).toEqual(['30']);
56
+
57
+    expect(renderCountIncrement).toHaveBeenCalledTimes(2);
58
+  });
59
+});

integration/remx/component.js → integration/remx/MyContainer.js View File

3
 
3
 
4
 const { Text } = require('react-native');
4
 const { Text } = require('react-native');
5
 const { connect } = require('remx');
5
 const { connect } = require('remx');
6
-const store = require('./store');
6
+const store = require('./MyStore');
7
 
7
 
8
 class MyContainer extends Component {
8
 class MyContainer extends Component {
9
   render() {
9
   render() {

integration/remx/store.js → integration/remx/MyStore.js View File

1
-const _ = require('lodash');
2
 const remx = require('remx');
1
 const remx = require('remx');
3
 
2
 
4
 const state = remx.state({
3
 const state = remx.state({
19
 
18
 
20
 const getters = remx.getters({
19
 const getters = remx.getters({
21
   getName() {
20
   getName() {
22
-    return _.get(state, ['person', 'name']);
21
+    return state.person.name;
23
   },
22
   },
24
 
23
 
25
   getAge() {
24
   getAge() {
26
-    return _(state).get('person.age');
25
+    return state.person.age;
27
   }
26
   }
28
 });
27
 });
29
 
28
 

+ 2
- 3
integration/remx/remx.test.js View File

7
   let store;
7
   let store;
8
 
8
 
9
   beforeEach(() => {
9
   beforeEach(() => {
10
-    jest.resetModules();
11
-    MyConnectedContainer = require('./component');
12
-    store = require('./store');
10
+    MyConnectedContainer = require('./MyContainer');
11
+    store = require('./MyStore');
13
   });
12
   });
14
 
13
 
15
   it('renders normally', () => {
14
   it('renders normally', () => {

+ 49
- 3
package-lock.json View File

4561
       "dev": true
4561
       "dev": true
4562
     },
4562
     },
4563
     "hoist-non-react-statics": {
4563
     "hoist-non-react-statics": {
4564
-      "version": "1.2.0",
4565
-      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz",
4566
-      "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=",
4564
+      "version": "2.3.1",
4565
+      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz",
4566
+      "integrity": "sha1-ND24TGAYxlB3iJgkATWhQg7iLOA=",
4567
       "dev": true
4567
       "dev": true
4568
     },
4568
     },
4569
     "home-or-tmp": {
4569
     "home-or-tmp": {
5754
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
5754
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
5755
       "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
5755
       "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
5756
     },
5756
     },
5757
+    "lodash-es": {
5758
+      "version": "4.17.4",
5759
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz",
5760
+      "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=",
5761
+      "dev": true
5762
+    },
5757
     "lodash._baseassign": {
5763
     "lodash._baseassign": {
5758
       "version": "3.2.0",
5764
       "version": "3.2.0",
5759
       "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
5765
       "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
6180
       "dev": true,
6186
       "dev": true,
6181
       "requires": {
6187
       "requires": {
6182
         "hoist-non-react-statics": "1.2.0"
6188
         "hoist-non-react-statics": "1.2.0"
6189
+      },
6190
+      "dependencies": {
6191
+        "hoist-non-react-statics": {
6192
+          "version": "1.2.0",
6193
+          "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz",
6194
+          "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=",
6195
+          "dev": true
6196
+        }
6183
       }
6197
       }
6184
     },
6198
     },
6185
     "mocha": {
6199
     "mocha": {
7541
         "react-deep-force-update": "1.1.1"
7555
         "react-deep-force-update": "1.1.1"
7542
       }
7556
       }
7543
     },
7557
     },
7558
+    "react-redux": {
7559
+      "version": "5.0.6",
7560
+      "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.6.tgz",
7561
+      "integrity": "sha512-8taaaGu+J7PMJQDJrk/xiWEYQmdo3mkXw6wPr3K3LxvXis3Fymiq7c13S+Tpls/AyNUAsoONkU81AP0RA6y6Vw==",
7562
+      "dev": true,
7563
+      "requires": {
7564
+        "hoist-non-react-statics": "2.3.1",
7565
+        "invariant": "2.2.2",
7566
+        "lodash": "4.17.4",
7567
+        "lodash-es": "4.17.4",
7568
+        "loose-envify": "1.3.1",
7569
+        "prop-types": "15.5.10"
7570
+      }
7571
+    },
7544
     "react-test-renderer": {
7572
     "react-test-renderer": {
7545
       "version": "16.0.0-alpha.6",
7573
       "version": "16.0.0-alpha.6",
7546
       "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.0.0-alpha.6.tgz",
7574
       "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.0.0-alpha.6.tgz",
7660
         "strip-indent": "1.0.1"
7688
         "strip-indent": "1.0.1"
7661
       }
7689
       }
7662
     },
7690
     },
7691
+    "redux": {
7692
+      "version": "3.7.2",
7693
+      "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz",
7694
+      "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==",
7695
+      "dev": true,
7696
+      "requires": {
7697
+        "lodash": "4.17.4",
7698
+        "lodash-es": "4.17.4",
7699
+        "loose-envify": "1.3.1",
7700
+        "symbol-observable": "1.0.4"
7701
+      }
7702
+    },
7663
     "regenerate": {
7703
     "regenerate": {
7664
       "version": "1.3.2",
7704
       "version": "1.3.2",
7665
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz",
7705
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz",
8466
         "has-flag": "2.0.0"
8506
         "has-flag": "2.0.0"
8467
       }
8507
       }
8468
     },
8508
     },
8509
+    "symbol-observable": {
8510
+      "version": "1.0.4",
8511
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz",
8512
+      "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=",
8513
+      "dev": true
8514
+    },
8469
     "symbol-tree": {
8515
     "symbol-tree": {
8470
       "version": "3.2.2",
8516
       "version": "3.2.2",
8471
       "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
8517
       "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",

+ 2
- 0
package.json View File

59
     "react-native": "0.44.0",
59
     "react-native": "0.44.0",
60
     "react-test-renderer": "16.0.0-alpha.6",
60
     "react-test-renderer": "16.0.0-alpha.6",
61
     "remx": "2.x.x",
61
     "remx": "2.x.x",
62
+    "redux": "3.x.x",
63
+    "react-redux": "5.x.x",
62
     "semver": "5.x.x",
64
     "semver": "5.x.x",
63
     "shell-utils": "1.x.x"
65
     "shell-utils": "1.x.x"
64
   },
66
   },