Skip to content

Commit 7effaf1

Browse files
authored
Add reducer testing (piotrwitek#50)
* added jest test configuration and setup instructions added example reducer tests * added better reducer example with tests
1 parent e5cfe69 commit 7effaf1

22 files changed

+1913
-367
lines changed

README.md

+244-121
Large diffs are not rendered by default.

docs/markdown/2_redux.md

+11-4
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,24 @@ state.counterPairs[0].immutableCounter1 = 1; // Error, cannot be mutated
6868
state.counterPairs[0].immutableCounter2 = 1; // Error, cannot be mutated
6969
```
7070

71-
> _There are some experiments in the community to make a `ReadonlyRecursive` mapped type. I'll update this section of the guide as soon as they are stable_
71+
> _There is a new (work in progress) feature called **Conditional Types**, that will allow `ReadonlyRecursive` mapped type_
7272
7373
[⇧ back to top](#table-of-contents)
7474

75-
### Reducer Example
76-
> using `getType` helper and [Discriminated Union types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
75+
### Typing reducer
76+
> using type inference with [Discriminated Union types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
7777
78-
::example='../../playground/src/redux/counters/reducer.ts'::
78+
::example='../../playground/src/redux/todos/reducer.ts'::
7979

8080
[⇧ back to top](#table-of-contents)
8181

82+
### Testing reducer
83+
84+
::example='../../playground/src/redux/todos/reducer.spec.ts'::
85+
86+
[⇧ back to top](#table-of-contents)
87+
88+
8289
---
8390

8491
## Store Configuration

docs/markdown/3_tools.md

+143
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,134 @@
11
# Tools
22

3+
## TSLint
4+
5+
> Installation
6+
`npm i -D jest ts-jest @types/jest`
7+
8+
#### tslint.json
9+
- Recommended setup is to extend build-in preset `tslint:recommended` (use `tslint:all` to enable all rules)
10+
- Add additional `react` specific rules: `npm i -D tslint-react` https://github.com/palantir/tslint-react
11+
- Overwritten some defaults for more flexibility
12+
13+
```js
14+
{
15+
"extends": ["tslint:recommended", "tslint-react"],
16+
"rules": {
17+
"arrow-parens": false,
18+
"arrow-return-shorthand": [false],
19+
"comment-format": [true, "check-space"],
20+
"import-blacklist": [true, "rxjs"],
21+
"interface-over-type-literal": false,
22+
"interface-name": false,
23+
"max-line-length": [true, 120],
24+
"member-access": false,
25+
"member-ordering": [true, { "order": "fields-first" }],
26+
"newline-before-return": false,
27+
"no-any": false,
28+
"no-empty-interface": false,
29+
"no-import-side-effect": [true],
30+
"no-inferrable-types": [true, "ignore-params", "ignore-properties"],
31+
"no-invalid-this": [true, "check-function-in-method"],
32+
"no-null-keyword": false,
33+
"no-require-imports": false,
34+
"no-submodule-imports": [true, "@src", "rxjs"],
35+
"no-this-assignment": [true, { "allow-destructuring": true }],
36+
"no-trailing-whitespace": true,
37+
"no-unused-variable": [true, "react"],
38+
"object-literal-sort-keys": false,
39+
"object-literal-shorthand": false,
40+
"one-variable-per-declaration": [false],
41+
"only-arrow-functions": [true, "allow-declarations"],
42+
"ordered-imports": [false],
43+
"prefer-method-signature": false,
44+
"prefer-template": [true, "allow-single-concat"],
45+
"quotemark": [true, "single", "jsx-double"],
46+
"semicolon": [true, "always"],
47+
"trailing-comma": [true, {
48+
"singleline": "never",
49+
"multiline": {
50+
"objects": "always",
51+
"arrays": "always",
52+
"functions": "never",
53+
"typeLiterals": "ignore"
54+
},
55+
"esSpecCompliant": true
56+
}],
57+
"triple-equals": [true, "allow-null-check"],
58+
"type-literal-delimiter": true,
59+
"typedef": [true,"parameter", "property-declaration"],
60+
"variable-name": [true, "ban-keywords", "check-format", "allow-pascal-case", "allow-leading-underscore"],
61+
// tslint-react
62+
"jsx-no-lambda": false
63+
}
64+
}
65+
```
66+
67+
[⇧ back to top](#table-of-contents)
68+
69+
## Jest
70+
71+
> Installation
72+
`npm i -D jest ts-jest @types/jest`
73+
74+
#### jest.config.json
75+
```json
76+
{
77+
"verbose": true,
78+
"transform": {
79+
".(ts|tsx)": "./node_modules/ts-jest/preprocessor.js"
80+
},
81+
"testRegex": "(/spec/.*|\\.(test|spec))\\.(ts|tsx|js)$",
82+
"moduleFileExtensions": ["ts", "tsx", "js"],
83+
"moduleNameMapper": {
84+
"^Components/(.*)": "./src/components/$1"
85+
},
86+
"globals": {
87+
"window": {},
88+
"ts-jest": {
89+
"tsConfigFile": "./tsconfig.json"
90+
}
91+
},
92+
"setupFiles": [
93+
"./jest.stubs.js"
94+
],
95+
"setupTestFrameworkScriptFile": "./jest.tests.js"
96+
}
97+
```
98+
99+
#### jest.stubs.js
100+
```js
101+
// Global/Window object Stubs for Jest
102+
window.requestAnimationFrame = function (callback) {
103+
setTimeout(callback);
104+
};
105+
106+
window.localStorage = {
107+
getItem: function () { },
108+
setItem: function () { },
109+
};
110+
111+
Object.values = () => [];
112+
```
113+
114+
115+
[⇧ back to top](#table-of-contents)
116+
117+
## Enzyme
118+
119+
> Installation
120+
`npm i -D enzyme enzyme-adapter-react-16 @types/enzyme`
121+
122+
#### jest.tests.js
123+
```js
124+
import { configure } from 'enzyme';
125+
import Adapter from 'enzyme-adapter-react-16';
126+
127+
configure({ adapter: new Adapter() });
128+
```
129+
130+
[⇧ back to top](#table-of-contents)
131+
3132
## Living Style Guide
4133
### ["react-styleguidist"](https://github.com/styleguidist/react-styleguidist)
5134

@@ -8,3 +137,17 @@
8137
[⟩⟩⟩ demo](https://piotrwitek.github.io/react-redux-typescript-guide/)
9138

10139
[⇧ back to top](#table-of-contents)
140+
141+
## Common Npm Scripts
142+
> Common TS-related npm scripts shared across projects
143+
```
144+
"lint": "tslint -p ./",
145+
"tsc": "tsc -p ./ --noEmit",
146+
"tsc:watch": "tsc -p ./ --noEmit -w",
147+
"pretest": "npm run lint & npm run tsc",
148+
"test": "jest --config jest.config.json",
149+
"test:watch": "jest --config jest.config.json --watch",
150+
"test:update": "jest --config jest.config.json -u",
151+
```
152+
153+
[⇧ back to top](#table-of-contents)

docs/markdown/4_extras.md

+3-108
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Extras
22

33
### tsconfig.json
4-
> - Recommended setup for best benefits from type-checking, with support for JSX and ES2016 features
5-
> - Add [`tslib`](https://www.npmjs.com/package/tslib) to minimize bundle size: `npm i tslib` - this will externalize helper functions generated by transpiler and otherwise inlined in your modules
6-
> - Include absolute imports config working with Webpack
4+
- Recommended setup for best benefits from type-checking, with support for JSX and ES2016 features
5+
- Add [`tslib`](https://www.npmjs.com/package/tslib) to minimize bundle size: `npm i tslib` - this will externalize helper functions generated by transpiler and otherwise inlined in your modules
6+
- Include absolute imports config working with Webpack
77

88
```js
99
{
@@ -55,98 +55,6 @@
5555

5656
[⇧ back to top](#table-of-contents)
5757

58-
### tslint.json
59-
> - Recommended setup is to extend build-in preset `tslint:recommended` (for all rules use `tslint:all`)
60-
> - Add tslint react rules: `npm i -D tslint-react` https://github.com/palantir/tslint-react
61-
> - Amended some extended defaults for more flexibility
62-
63-
```json
64-
{
65-
"extends": ["tslint:recommended", "tslint-react"],
66-
"rules": {
67-
"arrow-parens": false,
68-
"arrow-return-shorthand": [false],
69-
"comment-format": [true, "check-space"],
70-
"import-blacklist": [true, "rxjs"],
71-
"interface-over-type-literal": false,
72-
"interface-name": false,
73-
"max-line-length": [true, 120],
74-
"member-access": false,
75-
"member-ordering": [true, { "order": "fields-first" }],
76-
"newline-before-return": false,
77-
"no-any": false,
78-
"no-empty-interface": false,
79-
"no-import-side-effect": [true],
80-
"no-inferrable-types": [true, "ignore-params", "ignore-properties"],
81-
"no-invalid-this": [true, "check-function-in-method"],
82-
"no-null-keyword": false,
83-
"no-require-imports": false,
84-
"no-submodule-imports": [true, "@src", "rxjs"],
85-
"no-this-assignment": [true, { "allow-destructuring": true }],
86-
"no-trailing-whitespace": true,
87-
"no-unused-variable": [true, "react"],
88-
"object-literal-sort-keys": false,
89-
"object-literal-shorthand": false,
90-
"one-variable-per-declaration": [false],
91-
"only-arrow-functions": [true, "allow-declarations"],
92-
"ordered-imports": [false],
93-
"prefer-method-signature": false,
94-
"prefer-template": [true, "allow-single-concat"],
95-
"quotemark": [true, "single", "jsx-double"],
96-
"semicolon": [true, "always"],
97-
"trailing-comma": [true, {
98-
"singleline": "never",
99-
"multiline": {
100-
"objects": "always",
101-
"arrays": "always",
102-
"functions": "never",
103-
"typeLiterals": "ignore"
104-
},
105-
"esSpecCompliant": true
106-
}],
107-
"triple-equals": [true, "allow-null-check"],
108-
"type-literal-delimiter": true,
109-
"typedef": [true,"parameter", "property-declaration"],
110-
"variable-name": [true, "ban-keywords", "check-format", "allow-pascal-case", "allow-leading-underscore"],
111-
// tslint-react
112-
"jsx-no-lambda": false
113-
}
114-
}
115-
```
116-
117-
[⇧ back to top](#table-of-contents)
118-
119-
### jest.config.json
120-
> - Recommended setup for Jest with TypeScript
121-
> - Install with `npm i -D jest-cli ts-jest @types/jest`
122-
123-
```json
124-
{
125-
"verbose": true,
126-
"transform": {
127-
".(ts|tsx)": "./node_modules/ts-jest/preprocessor.js"
128-
},
129-
"testRegex": "(/spec/.*|\\.(test|spec))\\.(ts|tsx|js)$",
130-
"moduleFileExtensions": [
131-
"ts",
132-
"tsx",
133-
"js"
134-
],
135-
"globals": {
136-
"window": {},
137-
"ts-jest": {
138-
"tsConfigFile": "./tsconfig.json"
139-
}
140-
},
141-
"setupFiles": [
142-
"./jest.stubs.js",
143-
"./src/rxjs-imports.tsx"
144-
]
145-
}
146-
```
147-
148-
[⇧ back to top](#table-of-contents)
149-
15058
### Default and Named Module Exports
15159
> Most flexible solution is to use module folder pattern, because you can leverage both named and default import when you see fit.
15260
Using this solution you'll achieve better encapsulation for internal structure/naming refactoring without breaking your consumer code:
@@ -212,16 +120,3 @@ declare module 'rxjs/Subject' {
212120
> More advanced scenarios for working with vendor module declarations can be found here [Official TypeScript Docs](https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Modules.md#working-with-other-javascript-libraries)
213121
214122
[⇧ back to top](#table-of-contents)
215-
216-
### Npm Scripts
217-
> Common TS-related npm scripts shared across projects
218-
```
219-
"check": "npm run lint & npm run tsc",
220-
"lint": "tslint --project './tsconfig.json'",
221-
"tsc": "tsc -p . --noEmit",
222-
"tsc:watch": "tsc -p . --noEmit -w",
223-
"test": "jest --config jest.config.json",
224-
"test:watch": "jest --config jest.config.json --watch",
225-
```
226-
227-
[⇧ back to top](#table-of-contents)

docs/markdown/_toc.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,21 @@
1111
- [Action Creators](#action-creators) 📝 __UPDATED__
1212
- [Reducers](#reducers) 📝 __UPDATED__
1313
- [State with Type-level Immutability](#state-with-type-level-immutability)
14-
- [Reducer Example](#reducer-example)
14+
- [Typing reducer](#typing-reducer)
15+
- [Testing reducer](#testing-reducer)
1516
- [Store Configuration](#store-configuration) 📝 __UPDATED__
1617
- [Async Flow](#async-flow) 📝 __UPDATED__
1718
- [Selectors](#selectors)
1819
- [Tools](#tools)
20+
- [TSLint](#tslint)
21+
- [Jest](#jest)
22+
- [Enzyme](#enzyme)
1923
- [Living Style Guide](#living-style-guide) 🌟 __NEW__
24+
- [Common Npm Scripts](#common-npm-scripts)
2025
- [Extras](#extras)
2126
- [tsconfig.json](#tsconfigjson)
22-
- [tslint.json](#tslintjson)
23-
- [jest.config.json](#jestconfigjson)
24-
- [Default and Named Module Exports](#default-and-named-module-exports)
2527
- [Vendor Types Augmentation](#vendor-types-augmentation)
26-
- [Npm Scripts](#npm-scripts)
28+
- [Default and Named Module Exports](#default-and-named-module-exports)
2729
- [FAQ](#faq)
2830
- [Roadmap](#roadmap)
2931
- [Contribution Guide](#contribution-guide)

playground/jest.config.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"verbose": true,
3+
"transform": {
4+
".(ts|tsx)": "./node_modules/ts-jest/preprocessor.js"
5+
},
6+
"testRegex": "(/spec/.*|\\.(test|spec))\\.(ts|tsx|js)$",
7+
"moduleFileExtensions": ["ts", "tsx", "js"],
8+
"moduleNameMapper": {
9+
"^Components/(.*)": "./src/components/$1"
10+
},
11+
"globals": {
12+
"window": {},
13+
"ts-jest": {
14+
"tsConfigFile": "./tsconfig.json"
15+
}
16+
},
17+
"setupFiles": [
18+
"./jest.stubs.js"
19+
],
20+
"setupTestFrameworkScriptFile": "./jest.tests.js"
21+
}

playground/jest.stubs.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Global/Window object Stubs for Jest
2+
window.matchMedia = window.matchMedia || function () {
3+
return {
4+
matches: false,
5+
addListener: function () { },
6+
removeListener: function () { },
7+
};
8+
};
9+
10+
window.requestAnimationFrame = function (callback) {
11+
setTimeout(callback);
12+
};
13+
14+
window.localStorage = {
15+
getItem: function () { },
16+
setItem: function () { },
17+
};
18+
19+
Object.values = () => [];

playground/jest.tests.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { configure } from 'enzyme';
2+
import Adapter from 'enzyme-adapter-react-16';
3+
4+
configure({ adapter: new Adapter() });

0 commit comments

Comments
 (0)