Skip to content

Commit 68e7a32

Browse files
author
vinogradov
committed
1) add Jest+Webpack infrastructure, 2) refactor eslint: migrate to airbnb config, add special eslint config for tests
1 parent 53a8d52 commit 68e7a32

22 files changed

+731
-739
lines changed

.babelrc

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
{
2-
"presets": [
3-
[
4-
"es2015",
5-
{
6-
"modules": false
7-
}
8-
],
9-
"es2016",
10-
"es2017",
11-
"react"
2+
"presets": [
3+
[
4+
"es2015", {"modules": false}
125
],
13-
"plugins": [
14-
"transform-object-rest-spread"
15-
]
16-
}
6+
"es2016",
7+
"es2017",
8+
"react"
9+
],
10+
"plugins": [
11+
"transform-object-rest-spread"
12+
],
13+
"env": {
14+
"test": {
15+
"plugins": ["transform-es2015-modules-commonjs"]
16+
}
17+
}
18+
}

.editorconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[*]
22
end_of_line = lf
3-
insert_final_newline = false
3+
insert_final_newline = true
44
indent_style = space
5-
indent_size = 4
5+
indent_size = 2

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist
2+
__tests__

.eslintrc-test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = {
2+
extends: [
3+
'./.eslintrc.js',
4+
'plugin:jest/recommended'
5+
],
6+
plugins: [
7+
'jest'
8+
],
9+
env: {
10+
jest: true
11+
},
12+
rules: {
13+
'no-magic-numbers': ['off']
14+
}
15+
};

.eslintrc.js

Lines changed: 11 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -1,179 +1,12 @@
11
module.exports = {
2-
'parserOptions': {
3-
'ecmaVersion': 8,
4-
'sourceType': 'module',
5-
'ecmaFeatures': {
6-
'jsx': true,
7-
'experimentalObjectRestSpread': true
8-
}
9-
},
10-
'rules': {
11-
// Possible Errors (http://eslint.org/docs/rules/#possible-errors):
12-
'valid-jsdoc': ['warn', {
13-
'prefer': {
14-
'return': 'returns'
15-
}
16-
}],
17-
18-
19-
// Best Practices (http://eslint.org/docs/rules/#best-practices):
20-
'consistent-return': ['warn'],
21-
'curly': ['warn'],
22-
'dot-location': ['warn', 'property'],
23-
'dot-notation': ['warn'],
24-
'eqeqeq': ['warn'],
25-
'no-alert': ['warn'],
26-
'no-caller': ['warn'],
27-
'no-else-return': ['warn'],
28-
'no-empty-function': ['warn'],
29-
'no-empty-pattern': ['warn'],
30-
'no-eq-null': ['warn'],
31-
'no-eval': ['warn'],
32-
'no-extend-native': ['warn'],
33-
'no-extra-bind': ['warn'],
34-
'no-extra-label': ['warn'],
35-
'no-fallthrough': ['warn'],
36-
'no-floating-decimal': ['warn'],
37-
'no-implicit-coercion': ['warn', {
38-
'boolean': false
39-
}],
40-
'no-implicit-globals': ['warn'],
41-
'no-implied-eval': ['warn'],
42-
'no-invalid-this': ['warn'],
43-
'no-iterator': ['warn'],
44-
'no-labels': ['warn'],
45-
'no-lone-blocks': ['warn'],
46-
'no-loop-func': ['warn'],
47-
'no-magic-numbers': ['warn'],
48-
'no-multi-spaces': ['warn'],
49-
'no-native-reassign': ['warn'],
50-
'no-new-func': ['warn'],
51-
'no-new-wrappers': ['warn'],
52-
'no-proto': ['warn'],
53-
'no-redeclare': ['warn'],
54-
'no-return-assign': ['warn'],
55-
'no-script-url': ['warn'],
56-
'no-self-assign': ['warn'],
57-
'no-self-compare': ['warn'],
58-
'no-sequences': ['warn'],
59-
'no-unmodified-loop-condition': ['warn'],
60-
'no-unused-expressions': ['warn'],
61-
'no-unused-labels': ['warn'],
62-
'no-useless-call': ['warn'],
63-
'no-useless-concat': ['warn'],
64-
'no-useless-escape': ['warn'],
65-
'no-with': ['warn'],
66-
'require-await': ['warn'],
67-
'wrap-iife': ['warn'],
68-
'yoda': ['warn'],
69-
70-
71-
// Strict Mode (http://eslint.org/docs/rules/#strict-mode):
72-
'strict': ['warn'],
73-
74-
75-
// Variables (http://eslint.org/docs/rules/#variables):
76-
'no-catch-shadow': ['warn'],
77-
'no-delete-var': ['warn'],
78-
'no-label-var': ['warn'],
79-
'no-shadow': ['warn'],
80-
'no-shadow-restricted-names': ['warn'],
81-
'no-undef-init': ['warn'],
82-
'no-use-before-define': ['warn'],
83-
84-
85-
// Node.js and CommonJS (http://eslint.org/docs/rules/#nodejs-and-commonjs):
86-
'global-require': ['warn'],
87-
'no-mixed-requires': ['warn'],
88-
'no-path-concat': ['warn'],
89-
'no-sync': ['warn'],
90-
91-
92-
// Stylistic Issues (http://eslint.org/docs/rules/#stylistic-issues):
93-
'array-bracket-spacing': ['warn'],
94-
'block-spacing': ['warn'],
95-
'brace-style': ['warn', '1tbs', {'allowSingleLine': true}],
96-
'camelcase': ['warn', {'properties': 'never'}],
97-
'comma-dangle': ['warn', 'never'],
98-
'comma-spacing': ['warn', {'before': false, 'after': true}],
99-
'comma-style': ['warn', 'last'],
100-
'computed-property-spacing': ['warn', 'never'],
101-
'consistent-this': ['warn', 'that'],
102-
'func-style': ['warn', 'declaration'],
103-
'indent': ['warn', 4, {'SwitchCase': 1}],
104-
'key-spacing': ['warn'],
105-
'keyword-spacing': ['warn'],
106-
'linebreak-style': ['warn', 'unix'],
107-
'max-depth': ['warn', 10],
108-
'max-len': ['warn', {'code': 140, 'ignoreUrls': true}],
109-
'max-nested-callbacks': ['warn', 5],
110-
'max-params': ['warn', 5],
111-
'max-statements-per-line': ['warn', {'max': 10}],
112-
'new-cap': ['warn'],
113-
'new-parens': ['warn'],
114-
'no-lonely-if': ['warn'],
115-
'no-mixed-spaces-and-tabs': ['warn'],
116-
'no-nested-ternary': ['warn'],
117-
'no-new-object': ['warn'],
118-
'no-spaced-func': ['warn'],
119-
'no-trailing-spaces': ['warn'],
120-
'no-underscore-dangle': ['warn', {'allowAfterThis': true}],
121-
'no-unneeded-ternary': ['warn'],
122-
'no-whitespace-before-property': ['warn'],
123-
'object-curly-spacing': ['warn', 'never'],
124-
'one-var-declaration-per-line': ['warn'],
125-
'operator-assignment': ['warn'],
126-
'operator-linebreak': ['warn', 'after'],
127-
'padded-blocks': ['warn', {'blocks': 'never', 'switches': 'never', 'classes': 'never'}],
128-
'quote-props': ['warn', 'as-needed'],
129-
'quotes': ['warn', 'single'],
130-
'semi': ['warn', 'always'],
131-
'semi-spacing': ['warn', {'before': false, 'after': true}],
132-
'space-before-blocks': ['warn'],
133-
'space-before-function-paren': ['warn', 'never'],
134-
'space-in-parens': ['warn', 'never'],
135-
'space-infix-ops': ['warn'],
136-
'space-unary-ops': ['warn', {'words': true, 'nonwords': false}],
137-
'spaced-comment': ['warn', 'always'],
138-
139-
140-
// ECMAScript2015 (http://eslint.org/docs/rules/#ecmascript-6):
141-
'arrow-body-style': ['warn', 'as-needed'],
142-
'arrow-parens': ['warn'],
143-
'arrow-spacing': ['warn', {'before': true, 'after': true}],
144-
'constructor-super': ['warn'],
145-
146-
'generator-star-spacing': ['warn', {'before': true, 'after': true}],
147-
'yield-star-spacing': ['warn', {'before': true, 'after': true}],
148-
149-
'no-class-assign': ['warn'],
150-
'no-confusing-arrow': ['warn', {'allowParens': true}],
151-
'no-const-assign': ['warn'],
152-
'no-dupe-class-members': ['warn'],
153-
'no-duplicate-imports': ['warn'],
154-
'no-new-symbol': ['warn'],
155-
'no-this-before-super': ['warn'],
156-
'no-useless-constructor': ['warn'],
157-
'no-var': ['warn'],
158-
'object-shorthand': ['warn', 'always'],
159-
'prefer-arrow-callback': ['warn'],
160-
'prefer-const': ['warn'],
161-
'prefer-reflect': ['warn'],
162-
'prefer-rest-params': ['warn'],
163-
'prefer-spread': ['warn'],
164-
'prefer-template': ['warn'],
165-
'require-yield': ['warn'],
166-
'template-curly-spacing': ['warn', 'never']
167-
},
168-
'env': {
169-
'browser': true,
170-
'commonjs': true
171-
},
172-
'extends': [
173-
'eslint:recommended',
174-
'plugin:react/recommended'
175-
],
176-
'plugins': [
177-
'react'
178-
]
179-
};
2+
rules: {
3+
'object-curly-spacing': ['warn', 'never'],
4+
'comma-dangle': ['warn', 'never'],
5+
'max-len': ['warn', 120],
6+
'react/jsx-filename-extension': ['off']
7+
},
8+
env: {
9+
browser: true
10+
},
11+
extends: 'airbnb'
12+
};

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
Includes only the latest and greatest web technologies. Use it for your next heroic SPA project because you can't go wrong with it. Contains minimal viable "hello, world" code just to proof it works. Remove hello world and write your own great project.
22

3+
# Principles
4+
1. Use plain ES2015/16/17. Minimize use of experimental Stage-* Javascript features
5+
1. Use tests (by [jest](https://github.com/facebook/jest))
6+
1. Use linting (by [airbnb eslint config](https://github.com/airbnb/javascript))
7+
38
Suitable for:
49
1. Education
5-
2. Small pet projects/protorypes
6-
3. Production
10+
1. Small pet projects/protorypes
11+
1. Production
712

813
# 🎁 What’s Inside?
914

@@ -43,4 +48,4 @@ If you have problems with running it please [file an issue](https://github.com/v
4348
# Examples
4449

4550
1. [examples/react](https://github.com/vinogradov/react-starter-kit/tree/master/src/examples/react) - trivial hello world using React
46-
1. [examples/redux](https://github.com/vinogradov/react-starter-kit/tree/master/src/examples/redux) - counter example with `redux` and `redux-saga`
51+
1. [examples/redux](https://github.com/vinogradov/react-starter-kit/tree/master/src/examples/redux) - counter example with `redux` and `redux-saga`

__mocks__/fileMock.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = 'path-to-file';

__mocks__/styleMock.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

package.json

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
"scripts": {
77
"start": "webpack-dev-server",
88
"dist": "webpack --display-error-details --env.dist",
9-
"test": "echo \"Error: no test specified\" && exit 1"
9+
"test": "jest src",
10+
"lint": "eslint .; eslint --no-ignore --config .eslintrc.js --config .eslintrc-test.js --ext test.js ."
1011
},
1112
"license": "MIT",
1213
"dependencies": {
1314
"babel-core": "6.24.1",
14-
"babel-jest": "19.0.0",
15+
"babel-jest": "20.0.1",
1516
"babel-loader": "7.0.0",
1617
"babel-plugin-transform-object-rest-spread": "6.23.0",
1718
"babel-preset-es2015": "6.24.1",
@@ -21,31 +22,42 @@
2122
"clean-webpack-plugin": "0.1.16",
2223
"css-loader": "0.28.1",
2324
"eslint": "3.19.0",
25+
"eslint-config-airbnb": "14.1.0",
2426
"eslint-loader": "1.7.1",
25-
"eslint-plugin-react": "6.10.3",
27+
"eslint-plugin-import": "2.2.0",
28+
"eslint-plugin-jest": "20.0.1",
29+
"eslint-plugin-jsx-a11y": "4.0.0",
30+
"eslint-plugin-react": "7.0.1",
2631
"extract-text-webpack-plugin": "2.1.0",
2732
"file-loader": "0.11.1",
2833
"html-webpack-plugin": "2.28.0",
2934
"isomorphic-fetch": "2.2.1",
30-
"jest": "19.0.2",
35+
"jest": "20.0.1",
3136
"node-sass": "4.5.2",
32-
"prop-types": "15.5.8",
37+
"prop-types": "15.5.10",
3338
"react": "15.5.4",
3439
"react-dom": "15.5.4",
3540
"react-redux": "5.0.4",
3641
"react-router-dom": "4.1.1",
42+
"react-test-renderer": "15.5.4",
3743
"redux": "3.6.0",
3844
"redux-logger": "3.0.1",
39-
"redux-saga": "0.15.1",
45+
"redux-saga": "0.15.3",
4046
"redux-thunk": "2.2.0",
41-
"sass-loader": "6.0.3",
47+
"sass-loader": "6.0.5",
4248
"style-loader": "0.17.0",
43-
"webpack": "2.5.0"
49+
"webpack": "2.5.1"
4450
},
4551
"devDependencies": {
4652
"webpack-dev-server": "2.4.5"
4753
},
4854
"engines": {
4955
"node": ">=7.5.0"
56+
},
57+
"jest": {
58+
"moduleNameMapper": {
59+
"\\.(scss)$": "<rootDir>/__mocks__/styleMock.js",
60+
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|ico)$": "<rootDir>/__mocks__/fileMock.js"
61+
}
5062
}
5163
}

src/entry.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
/* eslint-disable */
12
import 'file-loader?name=[name].[ext]!./favicon.ico';
3+
/* eslint-enable */
24

3-
import './examples/react';
4-
// import './examples/redux';
5-
5+
// import './examples/react/index';
6+
import './examples/redux';
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`renders correctly 1`] = `
4+
<div
5+
className="hello-message"
6+
>
7+
<div>
8+
Hello
9+
<span
10+
className="name"
11+
>
12+
John
13+
</span>
14+
</div>
15+
<button
16+
onClick={[Function]}
17+
>
18+
toggle:
19+
ON
20+
</button>
21+
</div>
22+
`;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as React from 'react';
2+
import renderer from 'react-test-renderer';
3+
import Hello from '../hello';
4+
5+
test('renders correctly', () => {
6+
const tree = renderer.create(
7+
<Hello name="John" />
8+
).toJSON();
9+
10+
expect(tree).toMatchSnapshot();
11+
});

0 commit comments

Comments
 (0)