Skip to content

Commit 9af5ca5

Browse files
committed
Merge branch 'develop'
2 parents 0320193 + 73f16bf commit 9af5ca5

38 files changed

+1923
-609
lines changed

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
# Topcoder React Utils Changelog
22

3+
### v0.6.0
4+
- A better way to build the library: both dev and prod builds are created; and
5+
the proper version is selected depending on `NODE_ENV` value at the buildtime
6+
(client-side) or runtime (server-side) of the host code.
7+
8+
**BREAKING CHANGE:** You should update the way you include style the global
9+
stylesheet into the host code, from:
10+
```jsx
11+
require('topcoder-react-utils/dist/style.css');
12+
```
13+
to
14+
```jsx
15+
/* eslint-disable global-require */
16+
if (process.env.NODE_ENV === 'production') {
17+
require('topcoder-react-utils/dist/prod/style.css');
18+
} else {
19+
require('topcoder-react-utils/dist/dev/style.css');
20+
}
21+
/* eslint-enable global-require */
22+
```
23+
This will include the proper version of compiled global styles into the host
24+
code.
25+
26+
- Also most of NPM dependencies updated to their latest versions, which might
27+
demand some fixes in your code.
28+
29+
- Adds optional `type` prop to [`<Button>`](docs/button.md)
30+
331
### v0.5.0
432
All dependencies are force-updated to their latest versions. It might introduce
533
breaking changes.

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,14 @@ $ npm install --save topcoder-react-utils
2626
$ ./node_modules/.bin/topcoder-lib-setup
2727
```
2828
Then import the global stylesheet into the root ReactJS component of your app:
29-
```js
30-
import 'topcoder-react-utils/dist/style.css';
29+
```jsx
30+
/* eslint-disable global-require */
31+
if (process.env.NODE_ENV === 'production') {
32+
require('topcoder-react-utils/dist/prod/style.css');
33+
} else {
34+
require('topcoder-react-utils/dist/dev/style.css');
35+
}
36+
/* eslint-enable global-require */
3137
```
3238

3339
To upgrade this library to the latest version just execute again

__tests__/server/renderer.jsx

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ const TEST_WEBPACK_CONFIG = {
4040
},
4141
};
4242

43-
const testBuildInfo =
44-
JSON.parse(fs.readFileSync(`${TEST_CONTEXT}/.build-info`));
43+
const testBuildInfo = JSON.parse(
44+
fs.readFileSync(`${TEST_CONTEXT}/.build-info`),
45+
);
4546

4647
beforeAll(() => {
4748
Helmet.canUseDOM = false;
@@ -84,11 +85,11 @@ async function coreTest(webpackConfig, options) {
8485
}
8586
}
8687

87-
test('Base rendering of HTML template', () =>
88-
coreTest(TEST_WEBPACK_CONFIG, {}));
88+
test('Base rendering of HTML template',
89+
() => coreTest(TEST_WEBPACK_CONFIG, {}));
8990

90-
test('Config overriding for injection', () =>
91-
coreTest(TEST_WEBPACK_CONFIG, {
91+
test('Config overriding for injection',
92+
() => coreTest(TEST_WEBPACK_CONFIG, {
9293
beforeRender: async (res, sanitizedConfig) => {
9394
expect(res).toEqual(TEST_HTTP_REQUEST);
9495
expect(sanitizedConfig).toBeInstanceOf(Object);
@@ -102,22 +103,28 @@ test('Config overriding for injection', () =>
102103
},
103104
}));
104105

105-
test('Hemlet integration works', () =>
106-
coreTest(TEST_WEBPACK_CONFIG, {
106+
test('Hemlet integration works',
107+
() => coreTest(TEST_WEBPACK_CONFIG, {
107108
Application: () => (
108109
<div>
109-
<p>Hello World!</p>
110+
<p>
111+
Hello World!
112+
</p>
110113
<Helmet>
111-
<title>Test Page Title</title>
114+
<title>
115+
Test Page Title
116+
</title>
112117
<meta property="description" content="Test Page Description" />
113118
</Helmet>
114-
<p>Goodbye World!</p>
119+
<p>
120+
Goodbye World!
121+
</p>
115122
</div>
116123
),
117124
}));
118125

119-
test('Injection of additional JS scripts', () =>
120-
coreTest(TEST_WEBPACK_CONFIG, {
126+
test('Injection of additional JS scripts',
127+
() => coreTest(TEST_WEBPACK_CONFIG, {
121128
beforeRender: async () => ({
122129
extraScripts: [
123130
'<script>Dummy JS Sript</script>',
@@ -126,14 +133,18 @@ test('Injection of additional JS scripts', () =>
126133
}),
127134
}));
128135

129-
test('Server-side rendering (SSR); injection of CSS chunks & Redux state', () =>
130-
coreTest(TEST_WEBPACK_CONFIG, {
136+
test('Server-side rendering (SSR); injection of CSS chunks & Redux state',
137+
() => coreTest(TEST_WEBPACK_CONFIG, {
131138
Application: () => (
132139
<Route
133140
component={({ staticContext }) => {
134141
staticContext.chunks.push('test-chunk-a');
135142
staticContext.chunks.push('test-chunk-b');
136-
return <div>Hello Wold!</div>;
143+
return (
144+
<div>
145+
Hello Wold!
146+
</div>
147+
);
137148
}}
138149
/>
139150
),
@@ -148,7 +159,11 @@ test('Setting of response HTTP status the server-side rendering', () => {
148159
<Route
149160
component={({ staticContext }) => {
150161
staticContext.status = 404; // eslint-disable-line no-param-reassign
151-
return <div>404 Error Test</div>;
162+
return (
163+
<div>
164+
404 Error Test
165+
</div>
166+
);
152167
}}
153168
/>
154169
),

__tests__/server/server.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ jest.mock('webpack', () => {
1313
return mock;
1414
});
1515

16-
jest.mock('webpack-hot-middleware', () =>
17-
jest.fn(() => (req, res, next) => next()));
16+
jest.mock('webpack-hot-middleware',
17+
() => jest.fn(() => (req, res, next) => next()));
1818

1919
const TEST_CONTEXT = `${__dirname}/test_data`;
2020

__tests__/shared/actions/collection.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ afterAll(() => MockDate.reset());
1313

1414
test('Exports expected actions', () => expect(actions).toMatchSnapshot());
1515

16-
test('`addItems` payload creator', () =>
17-
expect(a.addItems({ id1: 'Item 1', id2: 'Item 2' })).toMatchSnapshot());
16+
test('`addItems` payload creator',
17+
() => expect(a.addItems({ id1: 'Item 1', id2: 'Item 2' })).toMatchSnapshot());
1818

1919
test('`bookItems` payload creator', () => {
2020
expect(a.bookItems('id1')).toMatchSnapshot();
@@ -33,8 +33,9 @@ test('`freeItems` payload creator', () => {
3333
expect(a.freeItems(['id1', 'id2', 'id3'])).toMatchSnapshot();
3434
});
3535

36-
test('`loadItemInit` payload creator', () =>
37-
expect(a.loadItemInit('operation-id', 'item-id')).toMatchSnapshot());
36+
test('`loadItemInit` payload creator',
37+
() => expect(a.loadItemInit('operation-id', 'item-id')).toMatchSnapshot());
3838

39-
test('`loadItemDone` payload creator', () =>
40-
expect(a.loadItemDone('operation-id', 'item-id', 'item')).toMatchSnapshot());
39+
test('`loadItemDone` payload creator', () => {
40+
expect(a.loadItemDone('operation-id', 'item-id', 'item')).toMatchSnapshot();
41+
});

__tests__/shared/actions/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
import actions from 'actions';
66

7-
test('Exports expected actions', () =>
8-
expect(actions).toMatchSnapshot());
7+
test('Exports expected actions',
8+
() => expect(actions).toMatchSnapshot());

__tests__/shared/components/Button.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,3 @@ describe('Matches snapshots', () => {
7676
));
7777
});
7878
});
79-

__tests__/shared/components/GenericLink.jsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@
33
import GenericLink from 'components/GenericLink';
44
import PT from 'prop-types';
55
import React from 'react';
6-
import { findInDomByClass, renderDom, simulate, snapshot } from 'utils/jest';
6+
import {
7+
findInDomByClass,
8+
renderDom,
9+
simulate,
10+
snapshot,
11+
} from 'utils/jest';
712

813
function Link(props) {
14+
const { className, onClick } = props;
915
return (
1016
<button
11-
onClick={props.onClick}
12-
className={props.className}
17+
onClick={onClick}
18+
className={className}
19+
type="button"
1320
>
1421
{JSON.stringify(props)}
1522
</button>

__tests__/shared/components/ScalableRect.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import React from 'react';
33
import { snapshot } from 'utils/jest';
44

55
test('Snapshots match', () => {
6-
snapshot(<ScalableRect>CONTENT</ScalableRect>);
6+
snapshot((
7+
<ScalableRect>
8+
CONTENT
9+
</ScalableRect>
10+
));
711
snapshot((
812
<ScalableRect
913
className="CLASS_NAME"

__tests__/shared/components/__snapshots__/Button.jsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ exports[`Matches snapshots when active 1`] = `
55
className="BUTTON_CLASS ACTIVE_CLASS REGULAR_CLASS"
66
onClick={[Function]}
77
onMouseDown={null}
8+
type="button"
89
>
910
BUTTON
1011
</button>
@@ -15,6 +16,7 @@ exports[`Matches snapshots when active 2`] = `
1516
className="BUTTON_CLASS ACTIVE_CLASS"
1617
onClick={[Function]}
1718
onMouseDown={null}
19+
type="button"
1820
>
1921
BUTTON
2022
</button>

__tests__/shared/components/__snapshots__/GenericLink.jsx.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ exports[`Matches snapshots in a minimalistic example 1`] = `
44
<button
55
className={null}
66
onClick={[Function]}
7+
type="button"
78
>
89
{"to":"SOME/TEST/URL","className":null,"onMouseDown":null,"replace":false,"children":"LINK"}
910
</button>

__tests__/shared/utils/isomorphy.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ afterEach(() => {
99
delete window.TRU_BUILD_INFO;
1010
delete window.TRU_FRONT_END;
1111
delete process.env.BABEL_ENV;
12+
process.env.NODE_ENV = 'test';
1213
});
1314

1415
beforeEach(() => jest.resetModules());
@@ -25,27 +26,27 @@ test('Server-side detection', () => {
2526
});
2627

2728
test('Dev mode detection - client side', () => {
28-
window.TRU_BUILD_INFO = { mode: 'development' };
29+
process.env.NODE_ENV = 'development';
2930
window.TRU_FRONT_END = true;
3031
expect(m().isDevBuild()).toBe(true);
3132
expect(m().isProdBuild()).toBe(false);
3233
});
3334

3435
test('Dev mode detection - server side', () => {
35-
global.TRU_BUILD_INFO = { mode: 'development' };
36+
process.env.NODE_ENV = 'development';
3637
expect(m().isDevBuild()).toBe(true);
3738
expect(m().isProdBuild()).toBe(false);
3839
});
3940

4041
test('Prod mode - client side', () => {
41-
window.TRU_BUILD_INFO = { mode: 'production' };
42+
process.env.NODE_ENV = 'production';
4243
window.TRU_FRONT_END = true;
4344
expect(m().isDevBuild()).toBe(false);
4445
expect(m().isProdBuild()).toBe(true);
4546
});
4647

4748
test('Prod mode - server side', () => {
48-
global.TRU_BUILD_INFO = { mode: 'production' };
49+
process.env.NODE_ENV = 'production';
4950
expect(m().isDevBuild()).toBe(false);
5051
expect(m().isProdBuild()).toBe(true);
5152
});

config/babel/node-ssr.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ config.plugins = config.plugins.concat([
1717
['css-modules-transform', cssModulesTransformPluginOps],
1818
]);
1919

20-
const moduleResolverPluginOps
21-
= config.plugins.find(x => x[0] === 'module-resolver')[1];
20+
const moduleResolverPluginOps = config.plugins.find(
21+
x => x[0] === 'module-resolver',
22+
)[1];
2223

2324
moduleResolverPluginOps.transformFunctions = [
2425
'resolveWeak',
@@ -41,7 +42,7 @@ switch (process.env.BABEL_ENV) {
4142

4243
module.exports = (apt, ops = {}) => {
4344
const baseAssetsOutputPath = ops.baseAssetsOutputPath || '';
44-
transformAssetsPluginOptions.name
45-
= `${baseAssetsOutputPath}/images/[hash].[ext]`;
45+
transformAssetsPluginOptions.name = `${
46+
baseAssetsOutputPath}/images/[hash].[ext]`;
4647
return config;
4748
};

config/webpack/app-base.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ module.exports = function configFactory(ops) {
6767
/* A random 32-bit key, that can be used for encryption. */
6868
key: forge.random.getBytesSync(32),
6969

70-
/* This will be equal to "development" or "production" */
71-
mode: ops.babelEnv,
72-
7370
/* Build timestamp. */
7471
timestamp: now.utc().toISOString(),
7572
};
@@ -83,10 +80,10 @@ module.exports = function configFactory(ops) {
8380
else if (!_.isArray(entry.polyfills)) {
8481
entry.polyfills = [entry.polyfills];
8582
}
83+
8684
entry.polyfills = _.union(entry.polyfills, [
8785
'babel-polyfill',
8886
'nodelist-foreach-polyfill',
89-
'topcoder-react-utils/dist/client/init',
9087
]);
9188

9289
return {

config/webpack/app-development.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
*/
44

55
const _ = require('lodash');
6-
const baseFactory = require('./app-base');
76
const webpack = require('webpack');
87
const webpackMerge = require('webpack-merge');
8+
const baseFactory = require('./app-base');
99

1010
/**
1111
* Creates a new development Webpack config, and performs some auxiliary
@@ -53,5 +53,6 @@ module.exports = function configFactory(ops) {
5353
'react-hot-loader/patch',
5454
'webpack-hot-middleware/client?reload=true',
5555
].concat(res.entry.main);
56+
res.entry.polyfills.push('topcoder-react-utils/dist/dev/client/init');
5657
return res;
5758
};

config/webpack/app-production.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
* Production Webpack configuration for ReactJS applications.
33
*/
44

5-
const baseFactory = require('./app-base');
65
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
76
const webpack = require('webpack');
87
const webpackMerge = require('webpack-merge');
8+
const baseFactory = require('./app-base');
99

1010
/**
1111
* Creates a new production Webpack config, and performs some auxiliary
@@ -28,7 +28,7 @@ const webpackMerge = require('webpack-merge');
2828
* @param {String} ops.publicPath Base URL for the output of the build assets.
2929
*/
3030
module.exports = function configFactory(ops) {
31-
return webpackMerge.smart(baseFactory({
31+
const res = webpackMerge.smart(baseFactory({
3232
...ops,
3333
babelEnv: 'production',
3434
mode: 'production',
@@ -52,4 +52,6 @@ module.exports = function configFactory(ops) {
5252
}),
5353
],
5454
});
55+
res.entry.polyfills.push('topcoder-react-utils/dist/prod/client/init');
56+
return res;
5557
};

0 commit comments

Comments
 (0)