Browse Source

add redux integration tests \#1649

Daniel Zlotin 6 years ago
parent
commit
f8e6d78145

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

@@ -0,0 +1,31 @@
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

@@ -0,0 +1,39 @@
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

@@ -0,0 +1,59 @@
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,7 +3,7 @@ const { Component } = require('react');
3 3
 
4 4
 const { Text } = require('react-native');
5 5
 const { connect } = require('remx');
6
-const store = require('./store');
6
+const store = require('./MyStore');
7 7
 
8 8
 class MyContainer extends Component {
9 9
   render() {

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

@@ -1,4 +1,3 @@
1
-const _ = require('lodash');
2 1
 const remx = require('remx');
3 2
 
4 3
 const state = remx.state({
@@ -19,11 +18,11 @@ const setters = remx.setters({
19 18
 
20 19
 const getters = remx.getters({
21 20
   getName() {
22
-    return _.get(state, ['person', 'name']);
21
+    return state.person.name;
23 22
   },
24 23
 
25 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,9 +7,8 @@ describe('remx support', () => {
7 7
   let store;
8 8
 
9 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 14
   it('renders normally', () => {

+ 49
- 3
package-lock.json View File

@@ -4561,9 +4561,9 @@
4561 4561
       "dev": true
4562 4562
     },
4563 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 4567
       "dev": true
4568 4568
     },
4569 4569
     "home-or-tmp": {
@@ -5754,6 +5754,12 @@
5754 5754
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
5755 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 5763
     "lodash._baseassign": {
5758 5764
       "version": "3.2.0",
5759 5765
       "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
@@ -6180,6 +6186,14 @@
6180 6186
       "dev": true,
6181 6187
       "requires": {
6182 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 6199
     "mocha": {
@@ -7541,6 +7555,20 @@
7541 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 7572
     "react-test-renderer": {
7545 7573
       "version": "16.0.0-alpha.6",
7546 7574
       "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.0.0-alpha.6.tgz",
@@ -7660,6 +7688,18 @@
7660 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 7703
     "regenerate": {
7664 7704
       "version": "1.3.2",
7665 7705
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz",
@@ -8466,6 +8506,12 @@
8466 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 8515
     "symbol-tree": {
8470 8516
       "version": "3.2.2",
8471 8517
       "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",

+ 2
- 0
package.json View File

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