Skip to content

Commit 3798a2d

Browse files
committedAug 13, 2019
initial commit
0 parents  commit 3798a2d

29 files changed

+12565
-0
lines changed
 

‎.eslintrc.js

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
const prettierOptions = JSON.parse(
5+
fs.readFileSync(path.resolve(__dirname, '.prettierrc'), 'utf8'),
6+
);
7+
8+
module.exports = {
9+
parser: 'babel-eslint',
10+
extends: ['airbnb', 'prettier', 'prettier/react'],
11+
plugins: ['prettier', 'redux-saga', 'react', 'react-hooks', 'jsx-a11y'],
12+
env: {
13+
jest: true,
14+
browser: true,
15+
node: true,
16+
es6: true,
17+
},
18+
parserOptions: {
19+
ecmaVersion: 6,
20+
sourceType: 'module',
21+
ecmaFeatures: {
22+
jsx: true,
23+
},
24+
},
25+
rules: {
26+
'prettier/prettier': ['error', prettierOptions],
27+
'arrow-body-style': [2, 'as-needed'],
28+
'class-methods-use-this': 0,
29+
'import/imports-first': 0,
30+
'import/newline-after-import': 0,
31+
'import/no-dynamic-require': 0,
32+
'import/no-extraneous-dependencies': 0,
33+
'import/no-named-as-default': 0,
34+
'import/no-unresolved': 2,
35+
'import/no-webpack-loader-syntax': 0,
36+
'import/prefer-default-export': 0,
37+
indent: [
38+
2,
39+
2,
40+
{
41+
SwitchCase: 1,
42+
},
43+
],
44+
'jsx-a11y/aria-props': 2,
45+
'jsx-a11y/heading-has-content': 0,
46+
'jsx-a11y/label-has-associated-control': [
47+
2,
48+
{
49+
// NOTE: If this error triggers, either disable it or add
50+
// your custom components, labels and attributes via these options
51+
// See https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-associated-control.md
52+
controlComponents: ['Input'],
53+
},
54+
],
55+
'jsx-a11y/label-has-for': 0,
56+
'jsx-a11y/mouse-events-have-key-events': 2,
57+
'jsx-a11y/role-has-required-aria-props': 2,
58+
'jsx-a11y/role-supports-aria-props': 2,
59+
'max-len': 0,
60+
'newline-per-chained-call': 0,
61+
'no-confusing-arrow': 0,
62+
'no-console': 1,
63+
'no-unused-vars': 2,
64+
'no-use-before-define': 0,
65+
'prefer-template': 2,
66+
'react/destructuring-assignment': 0,
67+
'react-hooks/rules-of-hooks': 'error',
68+
'react/jsx-closing-tag-location': 0,
69+
'react/forbid-prop-types': 0,
70+
'react/jsx-first-prop-new-line': [2, 'multiline'],
71+
'react/jsx-filename-extension': 0,
72+
'react/jsx-no-target-blank': 0,
73+
'react/jsx-uses-vars': 2,
74+
'react/require-default-props': 0,
75+
'react/require-extension': 0,
76+
'react/self-closing-comp': 0,
77+
'react/sort-comp': 0,
78+
'redux-saga/no-yield-in-race': 2,
79+
'redux-saga/yield-effects': 2,
80+
'require-yield': 0,
81+
},
82+
settings: {
83+
'import/resolver': {
84+
webpack: {
85+
config: './internals/webpack/webpack.prod.babel.js',
86+
},
87+
},
88+
},
89+
};

‎.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Don't check auto-generated stuff into git
2+
coverage
3+
build
4+
node_modules
5+
stats.json
6+
7+
# Cruft
8+
.DS_Store
9+
npm-debug.log
10+
.idea

‎.nvmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lts/dubnium

‎.prettierignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
build/
2+
node_modules/
3+
internals/generators/
4+
internals/scripts/
5+
package-lock.json
6+
yarn.lock
7+
package.json

‎.stylelintrc

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"processors": ["stylelint-processor-styled-components"],
3+
"extends": [
4+
"stylelint-config-recommended",
5+
"stylelint-config-styled-components"
6+
]
7+
}

‎babel.config.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module.exports = {
2+
presets: [
3+
[
4+
'@babel/preset-env',
5+
{
6+
modules: false,
7+
},
8+
],
9+
'@babel/preset-react',
10+
],
11+
plugins: [
12+
'styled-components',
13+
'@babel/plugin-proposal-class-properties',
14+
'@babel/plugin-syntax-dynamic-import',
15+
],
16+
env: {
17+
production: {
18+
only: ['app'],
19+
plugins: [
20+
'lodash',
21+
'transform-react-remove-prop-types',
22+
'@babel/plugin-transform-react-inline-elements',
23+
'@babel/plugin-transform-react-constant-elements',
24+
],
25+
},
26+
test: {
27+
plugins: [
28+
'@babel/plugin-transform-modules-commonjs',
29+
'dynamic-import-node',
30+
],
31+
},
32+
},
33+
};

‎generators/component/index.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Component Generator
3+
*/
4+
5+
/* eslint strict: ["off"] */
6+
7+
'use strict';
8+
9+
module.exports = {
10+
description: 'Add tests for an existing component',
11+
prompts: [
12+
{
13+
type: 'input',
14+
name: 'name',
15+
message: 'What is the name of the component you want to add tests for?',
16+
default: 'Button',
17+
},
18+
],
19+
actions: () => {
20+
// index.test.js
21+
const actions = [
22+
{
23+
type: 'add',
24+
path: '../app/components/{{properCase name}}/tests/index.test.js',
25+
templateFile: './component/test.js.hbs',
26+
abortOnFail: true,
27+
},
28+
];
29+
actions.push({
30+
type: 'prettify',
31+
path: '/components/',
32+
});
33+
return actions;
34+
},
35+
};

‎generators/component/index.js.hbs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
*
3+
* {{ properCase name }}
4+
*
5+
*/
6+
7+
{{#if memo}}
8+
import React, { memo } from 'react';
9+
{{else}}
10+
import React from 'react';
11+
{{/if}}
12+
// import PropTypes from 'prop-types';
13+
// import styled from 'styled-components';
14+
15+
{{#if wantMessages}}
16+
import { FormattedMessage } from 'react-intl';
17+
import messages from './messages';
18+
{{/if}}
19+
20+
function {{ properCase name }}() {
21+
return (
22+
<div>
23+
{{#if wantMessages}}
24+
<FormattedMessage {...messages.header} />
25+
{{/if}}
26+
</div>
27+
);
28+
}
29+
30+
{{ properCase name }}.propTypes = {};
31+
32+
{{#if memo}}
33+
export default memo({{ properCase name }});
34+
{{else}}
35+
export default {{ properCase name }};
36+
{{/if}}

‎generators/component/loadable.js.hbs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
*
3+
* Asynchronously loads the component for {{ properCase name }}
4+
*
5+
*/
6+
7+
import loadable from 'utils/loadable';
8+
9+
export default loadable(() => import('./index'));

‎generators/component/messages.js.hbs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* {{ properCase name }} Messages
3+
*
4+
* This contains all the text for the {{ properCase name }} component.
5+
*/
6+
7+
import { defineMessages } from 'react-intl';
8+
9+
export const scope = 'app.components.{{ properCase name }}';
10+
11+
export default defineMessages({
12+
header: {
13+
id: `${scope}.header`,
14+
defaultMessage: 'This is the {{ properCase name }} component!',
15+
},
16+
});

‎generators/component/test.js.hbs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
*
3+
* Tests for {{ properCase name }}
4+
*
5+
* @see https://github.com/react-boilerplate/react-boilerplate/tree/master/docs/testing
6+
*
7+
*/
8+
9+
import React from 'react';
10+
import Enzyme, { shallow } from 'enzyme';
11+
import Adapter from 'enzyme-adapter-react-16'
12+
{{#if wantMessages}}
13+
import { IntlProvider } from 'react-intl';
14+
{{/if}}
15+
// import 'jest-dom/extend-expect'; // add some helpful assertions
16+
17+
import {{ properCase name }} from '../index';
18+
{{#if wantMessages}}
19+
import { DEFAULT_LOCALE } from '../../../i18n';
20+
{{/if}}
21+
22+
Enzyme.configure({ adapter: new Adapter() })
23+
24+
describe('<{{ properCase name }} />', () => {
25+
26+
it('Should render and match the snapshot', () => {
27+
{{#if wantMessages}}
28+
const component = render(<IntlProvider locale={DEFAULT_LOCALE}>
29+
<{{ properCase name }} />
30+
</IntlProvider>,
31+
);
32+
{{else}}
33+
const component = shallow(<{{ properCase name }} />);
34+
{{/if}}
35+
expect(component).toMatchSnapshot();
36+
});
37+
});

‎generators/container/actions.js.hbs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
*
3+
* {{ properCase name }} actions
4+
*
5+
*/
6+
7+
import { DEFAULT_ACTION } from './constants';
8+
9+
export function defaultAction() {
10+
return {
11+
type: DEFAULT_ACTION,
12+
};
13+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { defaultAction } from '../actions';
2+
import { DEFAULT_ACTION } from '../constants';
3+
4+
describe('{{ properCase name }} actions', () => {
5+
describe('Default Action', () => {
6+
it('has a type of DEFAULT_ACTION', () => {
7+
const expected = {
8+
type: DEFAULT_ACTION,
9+
};
10+
expect(defaultAction()).toEqual(expected);
11+
});
12+
});
13+
});

‎generators/container/constants.js.hbs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
*
3+
* {{ properCase name }} constants
4+
*
5+
*/
6+
7+
export const DEFAULT_ACTION = 'app/{{ properCase name }}/DEFAULT_ACTION';

‎generators/container/index.js

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* Container Generator
3+
*/
4+
5+
module.exports = {
6+
description: 'Add test for an existing container component',
7+
prompts: [
8+
{
9+
type: 'input',
10+
name: 'name',
11+
message: 'Which container do you want to add tests for?',
12+
default: 'Form',
13+
},
14+
{
15+
type: 'confirm',
16+
name: 'wantActionsAndReducer',
17+
default: true,
18+
message:
19+
'Do you want add tests for actions, selectors & reducer tuple for this container?',
20+
},
21+
{
22+
type: 'confirm',
23+
name: 'wantSaga',
24+
default: true,
25+
message: 'Do you want to add tests for sagas?',
26+
},
27+
],
28+
actions: data => {
29+
// Generate index.js and index.test.js
30+
const actions = [
31+
{
32+
type: 'add',
33+
path: '../app/containers/{{properCase name}}/tests/index.test.js',
34+
templateFile: './container/test.js.hbs',
35+
abortOnFail: true,
36+
},
37+
];
38+
39+
// If component wants messages
40+
if (data.wantMessages) {
41+
actions.push({
42+
type: 'add',
43+
path: '../app/containers/{{properCase name}}/messages.js',
44+
templateFile: './container/messages.js.hbs',
45+
abortOnFail: true,
46+
});
47+
}
48+
49+
// If they want actions and a reducer, generate actions.js, constants.js,
50+
// reducer.js and the corresponding tests for actions and the reducer
51+
if (data.wantActionsAndReducer) {
52+
// Actions
53+
actions.push({
54+
type: 'add',
55+
path: '../app/containers/{{properCase name}}/tests/actions.test.js',
56+
templateFile: './container/actions.test.js.hbs',
57+
abortOnFail: true,
58+
});
59+
60+
// Selectors
61+
actions.push({
62+
type: 'add',
63+
path: '../app/containers/{{properCase name}}/tests/selectors.test.js',
64+
templateFile: './container/selectors.test.js.hbs',
65+
abortOnFail: true,
66+
});
67+
68+
// Reducer
69+
actions.push({
70+
type: 'add',
71+
path: '../app/containers/{{properCase name}}/tests/reducer.test.js',
72+
templateFile: './container/reducer.test.js.hbs',
73+
abortOnFail: true,
74+
});
75+
}
76+
77+
// Sagas
78+
if (data.wantSaga) {
79+
actions.push({
80+
type: 'add',
81+
path: '../app/containers/{{properCase name}}/tests/saga.test.js',
82+
templateFile: './container/saga.test.js.hbs',
83+
abortOnFail: true,
84+
});
85+
}
86+
87+
actions.push({
88+
type: 'prettify',
89+
path: '/containers/',
90+
});
91+
92+
return actions;
93+
},
94+
};

‎generators/container/index.js.hbs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
*
3+
* {{properCase name }}
4+
*
5+
*/
6+
7+
{{#if memo}}
8+
import React, { memo } from 'react';
9+
{{else}}
10+
import React from 'react';
11+
{{/if}}
12+
import PropTypes from 'prop-types';
13+
import { connect } from 'react-redux';
14+
{{#if wantHeaders}}
15+
import { Helmet } from 'react-helmet';
16+
{{/if}}
17+
{{#if wantMessages}}
18+
import { FormattedMessage } from 'react-intl';
19+
{{/if}}
20+
{{#if wantActionsAndReducer}}
21+
import { createStructuredSelector } from 'reselect';
22+
{{/if}}
23+
import { compose } from 'redux';
24+
25+
{{#if wantSaga}}
26+
import { useInjectSaga } from 'utils/injectSaga';
27+
{{/if}}
28+
{{#if wantActionsAndReducer}}
29+
import { useInjectReducer } from 'utils/injectReducer';
30+
import makeSelect{{properCase name}} from './selectors';
31+
import reducer from './reducer';
32+
{{/if}}
33+
{{#if wantSaga}}
34+
import saga from './saga';
35+
{{/if}}
36+
{{#if wantMessages}}
37+
import messages from './messages';
38+
{{/if}}
39+
40+
export function {{ properCase name }}() {
41+
{{#if wantActionsAndReducer}}
42+
useInjectReducer({ key: '{{ camelCase name }}', reducer });
43+
{{/if}}
44+
{{#if wantSaga}}
45+
useInjectSaga({ key: '{{ camelCase name }}', saga });
46+
{{/if}}
47+
48+
return (
49+
<div>
50+
{{#if wantHeaders}}
51+
<Helmet>
52+
<title>{{properCase name}}</title>
53+
<meta name="description" content="Description of {{properCase name}}" />
54+
</Helmet>
55+
{{/if}}
56+
{{#if wantMessages}}
57+
<FormattedMessage {...messages.header} />
58+
{{/if}}
59+
</div>
60+
);
61+
}
62+
63+
{{ properCase name }}.propTypes = {
64+
dispatch: PropTypes.func.isRequired,
65+
};
66+
67+
{{#if wantActionsAndReducer}}
68+
const mapStateToProps = createStructuredSelector({
69+
{{ camelCase name }}: makeSelect{{properCase name}}(),
70+
});
71+
{{/if}}
72+
73+
function mapDispatchToProps(dispatch) {
74+
return {
75+
dispatch,
76+
};
77+
}
78+
79+
{{#if wantActionsAndReducer}}
80+
const withConnect = connect(mapStateToProps, mapDispatchToProps);
81+
{{else}}
82+
const withConnect = connect(null, mapDispatchToProps);
83+
{{/if}}
84+
85+
export default compose(
86+
withConnect,
87+
{{#if memo}}
88+
memo,
89+
{{/if}}
90+
)({{ properCase name }});

‎generators/container/messages.js.hbs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* {{ properCase name }} Messages
3+
*
4+
* This contains all the text for the {{ properCase name }} container.
5+
*/
6+
7+
import { defineMessages } from 'react-intl';
8+
9+
export const scope = 'app.containers.{{ properCase name }}';
10+
11+
export default defineMessages({
12+
header: {
13+
id: `${scope}.header`,
14+
defaultMessage: 'This is the {{ properCase name }} container!',
15+
},
16+
});

‎generators/container/reducer.js.hbs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
*
3+
* {{ properCase name }} reducer
4+
*
5+
*/
6+
import produce from 'immer';
7+
import { DEFAULT_ACTION } from './constants';
8+
9+
export const initialState = {};
10+
11+
/* eslint-disable default-case, no-param-reassign */
12+
const {{ camelCase name }}Reducer = (state = initialState, action) =>
13+
produce(state, (/* draft */) => {
14+
switch (action.type) {
15+
case DEFAULT_ACTION:
16+
break;
17+
}
18+
});
19+
20+
export default {{ camelCase name }}Reducer;
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// import produce from 'immer';
2+
import {{ camelCase name }}Reducer from '../reducer';
3+
// import { someAction } from '../actions';
4+
5+
/* eslint-disable default-case, no-param-reassign */
6+
describe('{{ camelCase name }}Reducer', () => {
7+
let state;
8+
beforeEach(() => {
9+
state = {
10+
// default state params here
11+
};
12+
});
13+
14+
it('returns the initial state', () => {
15+
const expectedResult = state;
16+
expect({{ camelCase name }}Reducer(undefined, {})).toEqual(expectedResult);
17+
});
18+
19+
/**
20+
* Example state change comparison
21+
*
22+
* it('should handle the someAction action correctly', () => {
23+
* const expectedResult = produce(state, draft => {
24+
* draft.loading = true;
25+
* draft.error = false;
26+
* draft.userData.nested = false;
27+
* });
28+
*
29+
* expect(appReducer(state, someAction())).toEqual(expectedResult);
30+
* });
31+
*/
32+
});

‎generators/container/saga.js.hbs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// import { take, call, put, select } from 'redux-saga/effects';
2+
3+
// Individual exports for testing
4+
export default function* {{ camelCase name }}Saga() {
5+
// See example in containers/HomePage/saga.js
6+
}

‎generators/container/saga.test.js.hbs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Test sagas
3+
*/
4+
5+
/* eslint-disable redux-saga/yield-effects */
6+
// import { take, call, put, select } from 'redux-saga/effects';
7+
// import {{ camelCase name }}Saga from '../saga';
8+
9+
// const generator = {{ camelCase name }}Saga();
10+
11+
describe('{{ camelCase name }}Saga Saga', () => {
12+
it('Expect to have unit tests specified', () => {
13+
expect(true).toEqual(false);
14+
});
15+
});

‎generators/container/selectors.js.hbs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { createSelector } from 'reselect';
2+
import { initialState } from './reducer';
3+
4+
/**
5+
* Direct selector to the {{ camelCase name }} state domain
6+
*/
7+
8+
const select{{ properCase name }}Domain = state => state.{{ camelCase name }} || initialState;
9+
10+
/**
11+
* Other specific selectors
12+
*/
13+
14+
/**
15+
* Default selector used by {{ properCase name }}
16+
*/
17+
18+
const makeSelect{{ properCase name }} = () =>
19+
createSelector(select{{ properCase name }}Domain, substate => substate);
20+
21+
export default makeSelect{{ properCase name }};
22+
export { select{{ properCase name }}Domain };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// import { select{{ properCase name }}Domain } from '../selectors';
2+
3+
describe('select{{ properCase name }}Domain', () => {
4+
it('Expect to have unit tests specified', () => {
5+
expect(true).toEqual(false);
6+
});
7+
});

‎generators/container/test.js.hbs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
*
3+
* Tests for {{ properCase name }}
4+
*
5+
* @see https://github.com/react-boilerplate/react-boilerplate/tree/master/docs/testing
6+
*
7+
*/
8+
9+
import React from 'react';
10+
import Enzyme, { shallow } from 'enzyme';
11+
import Adapter from 'enzyme-adapter-react-16'
12+
{{#if wantMessages}}
13+
import { IntlProvider } from 'react-intl';
14+
{{/if}}
15+
// import 'jest-dom/extend-expect'; // add some helpful assertions
16+
17+
import { {{ properCase name }} } from '../index';
18+
{{#if wantMessages}}
19+
import { DEFAULT_LOCALE } from '../../../i18n';
20+
{{/if}}
21+
22+
Enzyme.configure({ adapter: new Adapter() })
23+
24+
describe('<{{ properCase name }} />', () => {
25+
26+
it('Should render and match the snapshot', () => {
27+
{{#if wantMessages}}
28+
const component = shallow(
29+
<IntlProvider locale={DEFAULT_LOCALE}>
30+
<{{ properCase name }} />
31+
</IntlProvider>,
32+
);
33+
{{else}}
34+
const component = shallow(<{{ properCase name }} />);
35+
{{/if}}
36+
expect(component).toMatchSnapshot();
37+
});
38+
});

‎generators/index.js

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* generator/index.js
3+
*
4+
* Exports the generators so plop knows them
5+
*/
6+
7+
const fs = require('fs');
8+
const path = require('path');
9+
const { execSync } = require('child_process');
10+
const componentGenerator = require('./component/index.js');
11+
const containerGenerator = require('./container/index.js');
12+
13+
/**
14+
* Every generated backup file gets this extension
15+
* @type {string}
16+
*/
17+
const BACKUPFILE_EXTENSION = 'rbgen';
18+
19+
module.exports = plop => {
20+
plop.setGenerator('component', componentGenerator);
21+
plop.setGenerator('container', containerGenerator);
22+
plop.addHelper('directory', comp => {
23+
try {
24+
fs.accessSync(
25+
path.join(__dirname, `../../app/containers/${comp}`),
26+
fs.F_OK,
27+
);
28+
return `containers/${comp}`;
29+
} catch (e) {
30+
return `components/${comp}`;
31+
}
32+
});
33+
plop.addHelper('curly', (object, open) => (open ? '{' : '}'));
34+
plop.setActionType('prettify', (answers, config) => {
35+
const folderPath = `${path.join(
36+
__dirname,
37+
'/../../app/',
38+
config.path,
39+
plop.getHelper('properCase')(answers.name),
40+
'**',
41+
'**.js',
42+
)}`;
43+
44+
try {
45+
execSync(`npm run prettify -- "${folderPath}"`);
46+
return folderPath;
47+
} catch (err) {
48+
throw err;
49+
}
50+
});
51+
plop.setActionType('backup', (answers, config) => {
52+
try {
53+
fs.copyFileSync(
54+
path.join(__dirname, config.path, config.file),
55+
path.join(
56+
__dirname,
57+
config.path,
58+
`${config.file}.${BACKUPFILE_EXTENSION}`,
59+
),
60+
'utf8',
61+
);
62+
return path.join(
63+
__dirname,
64+
config.path,
65+
`${config.file}.${BACKUPFILE_EXTENSION}`,
66+
);
67+
} catch (err) {
68+
throw err;
69+
}
70+
});
71+
};
72+
73+
module.exports.BACKUPFILE_EXTENSION = BACKUPFILE_EXTENSION;

‎jest.config.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module.exports = {
2+
collectCoverageFrom: [
3+
'app/**/*.{js,jsx}',
4+
'!app/**/*.test.{js,jsx}',
5+
'!app/*/RbGenerated*/*.{js,jsx}',
6+
'!app/app.js',
7+
'!app/global-styles.js',
8+
'!app/*/*/Loadable.{js,jsx}',
9+
],
10+
coverageThreshold: {
11+
global: {
12+
statements: 98,
13+
branches: 91,
14+
functions: 98,
15+
lines: 98,
16+
},
17+
},
18+
moduleDirectories: ['node_modules', 'app'],
19+
moduleNameMapper: {
20+
'.*\\.(css|less|styl|scss|sass)$': '<rootDir>/internals/mocks/cssModule.js',
21+
'.*\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
22+
'<rootDir>/internals/mocks/image.js',
23+
},
24+
setupFilesAfterEnv: [
25+
'<rootDir>/testing/test-bundler.js',
26+
'react-testing-library/cleanup-after-each',
27+
],
28+
setupFiles: ['raf/polyfill'],
29+
testRegex: 'tests/.*\\.test\\.js$',
30+
snapshotSerializers: [],
31+
};

‎package.json

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
{
2+
"name": "test-generator",
3+
"version": "1.0.0",
4+
"description": "A Test generation library",
5+
"repository": {
6+
"type": "git",
7+
"url": "git://github.com/wednesday-solutions/test-generator.git"
8+
},
9+
"engines": {
10+
"npm": ">=5",
11+
"node": ">=8.15.1"
12+
},
13+
"author": "Wednesday Solutions",
14+
"license": "MIT",
15+
"scripts": {
16+
"analyze:clean": "rimraf stats.json",
17+
"preanalyze": "npm run analyze:clean",
18+
"analyze": "node ./internals/scripts/analyze.js",
19+
"extract-intl": "node ./internals/scripts/extract-intl.js",
20+
"prebuild": "npm run build:clean",
21+
"build": "cross-env NODE_ENV=production webpack --config internals/webpack/webpack.prod.babel.js --color -p --progress --hide-modules --display-optimization-bailout",
22+
"build:clean": "rimraf ./build",
23+
"start": "cross-env NODE_ENV=development node server",
24+
"start:tunnel": "cross-env NODE_ENV=development ENABLE_TUNNEL=true node server",
25+
"start:production": "npm run test && npm run build && npm run start:prod",
26+
"start:prod": "cross-env NODE_ENV=production node server",
27+
"presetup": "npm i chalk shelljs",
28+
"setup": "node ./internals/scripts/setup.js",
29+
"clean": "shjs ./internals/scripts/clean.js",
30+
"clean:all": "npm run analyze:clean && npm run test:clean && npm run build:clean",
31+
"gentest": "plop --plopfile generators/index.js -f",
32+
"lint": "npm run lint:js && npm run lint:css",
33+
"lint:css": "stylelint app/**/*.js",
34+
"lint:eslint": "eslint --ignore-path .gitignore --ignore-pattern internals/scripts",
35+
"lint:eslint:fix": "eslint --ignore-path .gitignore --ignore-pattern internals/scripts --fix",
36+
"lint:js": "npm run lint:eslint -- . ",
37+
"lint:staged": "lint-staged",
38+
"pretest": "#npm run test:clean && npm run lint",
39+
"test:clean": "rimraf ./coverage",
40+
"test": "cross-env NODE_ENV=test jest",
41+
"test:watch": "cross-env NODE_ENV=test jest --watchAll",
42+
"coveralls": "cat ./coverage/lcov.info | coveralls",
43+
"prettify": "prettier --write"
44+
},
45+
"lint-staged": {
46+
"*.js": [
47+
"npm run lint:eslint:fix",
48+
"git add --force"
49+
],
50+
"*.json": [
51+
"prettier --write",
52+
"git add --force"
53+
]
54+
},
55+
"pre-commit": "lint:staged",
56+
"resolutions": {
57+
"babel-core": "7.0.0-bridge.0"
58+
},
59+
"dependencies": {
60+
"@babel/polyfill": "7.4.3",
61+
"chalk": "^2.4.2",
62+
"compression": "1.7.4",
63+
"connected-react-router": "6.4.0",
64+
"cross-env": "5.2.0",
65+
"enzyme": "^3.10.0",
66+
"enzyme-adapter-react-16": "^1.14.0",
67+
"express": "4.16.4",
68+
"fontfaceobserver": "2.1.0",
69+
"history": "4.9.0",
70+
"hoist-non-react-statics": "3.3.0",
71+
"immer": "3.0.0",
72+
"intl": "1.2.5",
73+
"invariant": "2.2.4",
74+
"ip": "1.1.5",
75+
"lodash": "4.17.11",
76+
"minimist": "1.2.0",
77+
"prop-types": "15.7.2",
78+
"react": "16.8.6",
79+
"react-dom": "16.8.6",
80+
"react-helmet": "6.0.0-beta",
81+
"react-intl": "2.8.0",
82+
"react-redux": "7.0.2",
83+
"react-router-dom": "5.0.0",
84+
"redux": "4.0.1",
85+
"redux-saga": "1.0.2",
86+
"reselect": "4.0.0",
87+
"sanitize.css": "8.0.0",
88+
"styled-components": "4.2.0"
89+
},
90+
"devDependencies": {
91+
"@babel/cli": "7.4.3",
92+
"@babel/core": "7.4.3",
93+
"@babel/plugin-proposal-class-properties": "7.4.0",
94+
"@babel/plugin-syntax-dynamic-import": "7.2.0",
95+
"@babel/plugin-transform-modules-commonjs": "7.4.3",
96+
"@babel/plugin-transform-react-constant-elements": "7.2.0",
97+
"@babel/plugin-transform-react-inline-elements": "7.2.0",
98+
"@babel/preset-env": "7.4.3",
99+
"@babel/preset-react": "7.0.0",
100+
"@babel/register": "7.4.0",
101+
"add-asset-html-webpack-plugin": "3.1.3",
102+
"babel-core": "7.0.0-bridge.0",
103+
"babel-eslint": "10.0.1",
104+
"babel-loader": "8.0.5",
105+
"babel-plugin-dynamic-import-node": "2.2.0",
106+
"babel-plugin-lodash": "3.3.4",
107+
"babel-plugin-react-intl": "3.0.1",
108+
"babel-plugin-styled-components": "1.10.0",
109+
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
110+
"circular-dependency-plugin": "5.0.2",
111+
"compare-versions": "3.4.0",
112+
"compression-webpack-plugin": "2.0.0",
113+
"coveralls": "3.0.3",
114+
"css-loader": "2.1.1",
115+
"eslint": "5.16.0",
116+
"eslint-config-airbnb": "17.1.0",
117+
"eslint-config-airbnb-base": "13.1.0",
118+
"eslint-config-prettier": "4.1.0",
119+
"eslint-import-resolver-webpack": "0.11.1",
120+
"eslint-plugin-import": "2.17.2",
121+
"eslint-plugin-jsx-a11y": "6.2.1",
122+
"eslint-plugin-prettier": "3.0.1",
123+
"eslint-plugin-react": "7.12.4",
124+
"eslint-plugin-react-hooks": "1.6.0",
125+
"eslint-plugin-redux-saga": "1.0.0",
126+
"file-loader": "3.0.1",
127+
"html-loader": "0.5.5",
128+
"html-webpack-plugin": "3.2.0",
129+
"image-webpack-loader": "4.6.0",
130+
"imports-loader": "0.8.0",
131+
"jest-cli": "24.7.1",
132+
"jest-dom": "3.1.3",
133+
"jest-styled-components": "6.3.1",
134+
"lint-staged": "8.1.5",
135+
"ngrok": "3.1.1",
136+
"node-plop": "0.18.0",
137+
"null-loader": "0.1.1",
138+
"offline-plugin": "5.0.6",
139+
"plop": "2.3.0",
140+
"pre-commit": "1.2.2",
141+
"prettier": "1.17.0",
142+
"react-app-polyfill": "0.2.2",
143+
"react-test-renderer": "16.8.6",
144+
"react-testing-library": "6.1.2",
145+
"rimraf": "2.6.3",
146+
"shelljs": "^0.8.3",
147+
"style-loader": "0.23.1",
148+
"stylelint": "10.0.1",
149+
"stylelint-config-recommended": "2.2.0",
150+
"stylelint-config-styled-components": "0.1.1",
151+
"stylelint-processor-styled-components": "1.6.0",
152+
"svg-url-loader": "2.3.2",
153+
"terser-webpack-plugin": "1.2.3",
154+
"url-loader": "1.1.2",
155+
"webpack": "4.30.0",
156+
"webpack-cli": "3.3.0",
157+
"webpack-dev-middleware": "3.6.2",
158+
"webpack-hot-middleware": "2.24.3",
159+
"webpack-pwa-manifest": "4.0.0",
160+
"whatwg-fetch": "3.0.0"
161+
}
162+
}

‎testing/test-bundler.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// needed for regenerator-runtime
2+
// (ES7 generator support is required by redux-saga)
3+
import '@babel/polyfill';

‎yarn.lock

+11,643
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.