Skip to content
This repository has been archived by the owner on Feb 3, 2021. It is now read-only.

Commit

Permalink
Revert "Revert "add tests infrastructure and simple test""
Browse files Browse the repository at this point in the history
This reverts commit 48d3e16.
  • Loading branch information
Edgar committed Feb 26, 2019
1 parent 48d3e16 commit 2561b9e
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 139 deletions.
14 changes: 0 additions & 14 deletions .babelrc

This file was deleted.

3 changes: 3 additions & 0 deletions .babelrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
};
21 changes: 17 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,27 @@
"render"
],
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-plugin-transform-es2015-modules-umd": "6.24.1",
"babel-preset-es2015": "^6.24.1"
"@babel/core": "*",
"@babel/preset-env": "*",
"@babel/preset-react": "*",
"babel-jest": "*",
"enzyme": "*",
"enzyme-adapter-react-16": "*",
"jest": "*",
"react": "^16.4.0",
"react-dom": "^16.4.0"
},
"main": "build/index.js",
"scripts": {
"build": "babel src/index.js --no-babelrc --presets es2015 --out-file build/index.js",
"build-umd": "babel src/index.js --out-file build/umd/index.js"
"build-umd": "babel src/index.js --out-file build/umd/index.js",
"test": "jest",
"format": "prettier --single-quote --trailing-comma es5 --write \"src/**/*.js\""
},
"jest": {
"testPathIgnorePatterns": [
"<rootDir>/src/__tests__/components/"
]
},
"repository": {
"type": "git",
Expand Down
27 changes: 27 additions & 0 deletions src/__tests__/components/SimpleComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';

export default class SimpleComponent extends React.Component {
constructor(props) {
super(props);
this.state = { isChecked: false };

this.onChange = this.onChange.bind(this);
}

onChange() {
this.setState({ isChecked: !this.state.isChecked });
}

render() {
return (
<label>
<input
type="checkbox"
checked={this.state.isChecked}
onChange={this.onChange}
/>
{this.state.isChecked ? this.props.labelOn : this.props.labelOff}
</label>
);
}
}
24 changes: 24 additions & 0 deletions src/__tests__/patch.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

import SimpleComponent from './components/SimpleComponent';
import patch from '../patch';

it('changed state', () => {
const PatchedSimpleComponent = patch(SimpleComponent, 'test-name', console);

const checkbox = shallow(
<PatchedSimpleComponent labelOn="On" labelOff="Off" />
);

expect(checkbox.text()).toEqual('Off');

checkbox.find('input').simulate('change');

expect(checkbox.text()).toEqual('On');

checkbox.setProps({ labelOn: 'Off' });
});
134 changes: 13 additions & 121 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,118 +1,6 @@
class Logger {
constructor(componentName) {
this._componentName = componentName;
this._propsChanges = [];
this._stateChanges = [];
this._renderCount = 0;
}

init() {
console.log('%c[clear-render] init for', 'color: #848d95;', this._componentName);
console.log('%c[clear-render] render', 'color: #848d95;', this._componentName);
}

_printChange(change) {
if (typeof change === 'object') {
console.groupCollapsed(`${change.key} %c [${change.type}]`, 'color: #848d95; font-style: italic;');
console.log('%c old ', 'background: #ff6347; color: #fff', change.oldValue);
console.log('%c new ', 'background: #5fba7d; color: #fff', change.nextValue);
console.groupEnd();
} else {
console.log(change);
}
}

printComparisonsResults() {
console.group(`%c[clear-render] re-render #${this._renderCount}`, 'color: #848d95;', this._componentName);
this._printComparisonResult('props', this._propsChanges);
this._printComparisonResult('state', this._stateChanges);
console.groupEnd();
}

_printComparisonResult(title, changes = []) {
if (changes.length === 0) {
return;
}
console.group(title);
changes.forEach(this._printChange);
console.groupEnd();
}

_differenceBetweenObjects(oldObj = {}, nextObj = {}) {
if (!nextObj || !oldObj) {
return [];
}
let difference = [];
Object.keys(nextObj).forEach(key => {
if (nextObj[key] !== oldObj[key]) {
const type = typeof nextObj[key];
difference.push({
key,
type,
oldValue: oldObj[key],
nextValue: nextObj[key],
});
}
});
return difference;
}

shallowCompareProps(prevProps, nextProps) {
this._propsChanges = this._differenceBetweenObjects(prevProps, nextProps);
}

shallowCompareState(prevState, nextState) {
this._stateChanges = this._differenceBetweenObjects(prevState, nextState);
}

get isFirstRender() {
return !this._renderCount;
}
import patch from './patch';

incrementRenderCount() {
this._renderCount++;
}
};

const wrap = (ComponentClass, forcedDisplayedName) => {
const componentClassName = ComponentClass.name;

const logger = new Logger(forcedDisplayedName || componentClassName);

const originalRender = ComponentClass.prototype.render;
ComponentClass.prototype.render = function () {
if (logger.isFirstRender) {
logger.init();
}

logger.incrementRenderCount();

if (originalRender) {
return originalRender.call(this);
} else {
return null;
}
}

const originalСomponentDidUpdate = ComponentClass.prototype.componentDidUpdate;
ComponentClass.prototype.componentDidUpdate = function (...args) {
const [prevProps, prevState] = args;
const nextProps = this.props;
const nextState = this.state;

logger.shallowCompareState(prevState, nextState);
logger.shallowCompareProps(prevProps, nextProps);
logger.printComparisonsResults();

if (originalСomponentDidUpdate) {
return originalСomponentDidUpdate.call(this, ...args);
}
}

return ComponentClass;
};

module.exports = function (...args) {
export default (...args) => {
if (args.length > 2) {
console.error('[clear-render] Error: Too many arguments');
return null;
Expand All @@ -131,13 +19,15 @@ module.exports = function (...args) {

switch (type) {
case 'symbol':
case 'string': {
forcedDisplayedName = arg;
}
case 'string':
{
forcedDisplayedName = arg;
}
break;
default: {
ComponentClass = arg;
}
default:
{
ComponentClass = arg;
}
break;
}
});
Expand All @@ -147,5 +37,7 @@ module.exports = function (...args) {
return null;
}

return wrap(ComponentClass, forcedDisplayedName);
const name = forcedDisplayedName || ComponentClass.name;

return patch(ComponentClass, name, console);
};
116 changes: 116 additions & 0 deletions src/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
class Logger {
constructor(componentName, log) {
this._componentName = componentName;
this._propsChanges = [];
this._stateChanges = [];
this._renderCount = 0;

this._log = log;
}

init() {
if (this._isFirstRender) {
this._printInit();
}

this._incrementRenderCount();
}

processChanges(stateChange, propsChange) {
this._shallowCompareState(...stateChange);
this._shallowCompareProps(...propsChange);
this._printComparisonsResults();
}

_printInit() {
this._log.log(
'%c[clear-render] init for',
'color: #848d95;',
this._componentName
);
this._log.log(
'%c[clear-render] render',
'color: #848d95;',
this._componentName
);
}

_printChange(change) {
if (typeof change === 'object') {
this._log.groupCollapsed(
`${change.key} %c [${change.type}]`,
'color: #848d95; font-style: italic;'
);
this._log.log(
'%c old ',
'background: #ff6347; color: #fff',
change.oldValue
);
this._log.log(
'%c new ',
'background: #5fba7d; color: #fff',
change.nextValue
);
this._log.groupEnd();
} else {
this._log.log(change);
}
}

_printComparisonsResults() {
this._log.group(
`%c[clear-render] re-render #${this._renderCount}`,
'color: #848d95;',
this._componentName
);
this._printComparisonResult('props', this._propsChanges);
this._printComparisonResult('state', this._stateChanges);
this._log.groupEnd();
}

_printComparisonResult(title, changes = []) {
if (changes.length === 0) {
return;
}
this._log.group(title);
changes.forEach(this._printChange.bind(this));
this._log.groupEnd();
}

_differenceBetweenObjects(oldObj = {}, nextObj = {}) {
if (!nextObj || !oldObj) {
return [];
}
let difference = [];
Object.keys(nextObj).forEach(key => {
if (nextObj[key] !== oldObj[key]) {
const type = typeof nextObj[key];
difference.push({
key,
type,
oldValue: oldObj[key],
nextValue: nextObj[key],
});
}
});
return difference;
}

_shallowCompareProps(prevProps, nextProps) {
this._propsChanges = this._differenceBetweenObjects(prevProps, nextProps);
}

_shallowCompareState(prevState, nextState) {
this._stateChanges = this._differenceBetweenObjects(prevState, nextState);
}

get _isFirstRender() {
return !this._renderCount;
}

_incrementRenderCount() {
this._renderCount++;
}
}

export default Logger;
Loading

0 comments on commit 2561b9e

Please sign in to comment.