This repository has been archived by the owner on Feb 3, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Edgar
committed
Apr 10, 2019
1 parent
f297112
commit 313d1c8
Showing
10 changed files
with
8,682 additions
and
80 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
class Comparator { | ||
constructor(logger) { | ||
this._renderCount = 0; | ||
|
||
this._prevProps = null; | ||
this._prevState = null; | ||
|
||
this._logger = logger; | ||
} | ||
|
||
processChanges(nextProps, nextState) { | ||
const isFirstRender = !this._renderCount; | ||
if (isFirstRender) { | ||
this._logger.printInit(); | ||
} else { | ||
const propsChanges = this._shallowCompare(this._prevProps, nextProps); | ||
const stateChanges = this._shallowCompare(this._prevState, nextState); | ||
|
||
this._logger.printComparisonsResults(propsChanges, stateChanges); | ||
} | ||
|
||
this._renderCount += 1; | ||
this._prevState = nextState; | ||
this._prevProps = nextProps; | ||
} | ||
|
||
_shallowCompare(oldObj = {}, nextObj = {}) { | ||
if (!nextObj || !oldObj || oldObj === nextObj) { | ||
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; | ||
} | ||
} | ||
|
||
export default Comparator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import React from 'react'; | ||
|
||
class Input extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
} | ||
|
||
render() { | ||
const { value, onChange, title, description } = this.props; | ||
|
||
return ( | ||
<div> | ||
<input | ||
type="text" | ||
data-testid="text" | ||
value={value} | ||
onChange={onChange} | ||
/> | ||
<span data-testid="props-title">{title}</span> | ||
<span>{description}</span> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
export default Input; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,143 @@ | ||
import React from 'react'; | ||
import Enzyme, { shallow, mount } from 'enzyme'; | ||
import Adapter from 'enzyme-adapter-react-16'; | ||
|
||
Enzyme.configure({ adapter: new Adapter() }); | ||
import { render, fireEvent, cleanup } from 'react-testing-library' | ||
|
||
// React class component with state | ||
import Checkbox from './components/Checkbox'; | ||
// React class component without state | ||
import Input from './components/Input'; | ||
// React function component, with hooks | ||
import Counter from './components/Counter'; | ||
|
||
import Comparator from '../Comparator'; | ||
|
||
import patch from '../patch'; | ||
|
||
const noop = () => {}; | ||
const defaultProps = { | ||
title: "ping", | ||
description: "text", | ||
} | ||
|
||
beforeEach(() => { | ||
|
||
}); | ||
|
||
const fakeLogger = { | ||
log: noop, | ||
group: noop, | ||
groupCollapsed: noop, | ||
groupEnd: noop, | ||
}; | ||
afterEach(() => { | ||
cleanup(); | ||
}); | ||
|
||
it('patched checkbox working', () => { | ||
test('Checkbox, detect changed state', () => { | ||
// Arrange | ||
const PatchedCheckbox = patch(Checkbox, 'test-name', fakeLogger); | ||
const fakeLogger = { | ||
printInit: jest.fn(), | ||
printComparisonsResults: jest.fn(), | ||
}; | ||
const comparator = new Comparator(fakeLogger); | ||
const PatchedCheckbox = patch(Checkbox, comparator); | ||
|
||
// Act | ||
const { getByTestId } = render(<PatchedCheckbox {...defaultProps} />); | ||
|
||
const checkbox = shallow(<PatchedCheckbox label="ping" />); | ||
fireEvent.click(getByTestId('checkbox')); | ||
|
||
// Assert | ||
expect(fakeLogger.printInit.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls[0]).toEqual( | ||
[[], [{"key": "isChecked", "nextValue": true, "oldValue": false, "type": "boolean"}]] | ||
); | ||
expect(getByTestId('state-isChecked').textContent).toBe('1'); | ||
}); | ||
|
||
test('Checkbox, detect changed props', () => { | ||
// Arrange | ||
const fakeLogger = { | ||
printInit: jest.fn(), | ||
printComparisonsResults: jest.fn(), | ||
}; | ||
const comparator = new Comparator(fakeLogger); | ||
const PatchedCheckbox = patch(Checkbox, comparator); | ||
|
||
// Act | ||
checkbox.find('input').simulate('change'); | ||
checkbox.setProps({ label: 'pong' }); | ||
const { rerender, getByTestId } = render(<PatchedCheckbox {...defaultProps} />); | ||
|
||
rerender(<PatchedCheckbox {...defaultProps} title='pong' />); | ||
|
||
// Assert | ||
expect(checkbox.find('label').text()).toEqual('On'); | ||
expect(checkbox.find('span').text()).toEqual('pong'); | ||
expect(fakeLogger.printInit.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls[0]).toEqual( | ||
[[{"key":"title","type":"string","oldValue":"ping","nextValue":"pong"}],[]] | ||
); | ||
|
||
expect(getByTestId('props-title').textContent).toBe('pong'); | ||
}); | ||
|
||
it('patched counter working', () => { | ||
test('Counter, detect changed props re-render', () => { | ||
// Arrange | ||
// const PatchedCounter = patch(Counter, 'test-name', console); | ||
const fakeLogger = { | ||
printInit: jest.fn(), | ||
printComparisonsResults: jest.fn(), | ||
}; | ||
const comparator = new Comparator(fakeLogger); | ||
const PatchedCounter= patch(Counter, comparator); | ||
|
||
const counter = mount(<Counter label="ping" />); | ||
// Act | ||
const { rerender, getByTestId } = render(<PatchedCounter {...defaultProps} />); | ||
|
||
rerender(<PatchedCounter {...defaultProps} title='pong' />); | ||
|
||
// Assert | ||
expect(fakeLogger.printInit.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls[0]).toEqual( | ||
[[{"key":"title","type":"string","oldValue":"ping","nextValue":"pong"}],[]] | ||
); | ||
expect(getByTestId('props-title').textContent).toBe('pong'); | ||
}); | ||
|
||
test('Counter, used hooks', () => { | ||
// Arrange | ||
const fakeLogger = { | ||
printInit: jest.fn(), | ||
printComparisonsResults: jest.fn(), | ||
}; | ||
const comparator = new Comparator(fakeLogger); | ||
const PatchedCounter= patch(Counter, comparator); | ||
|
||
// Act | ||
counter.setProps({ label: 'pong' }); | ||
counter.find('button').simulate('click'); | ||
const { rerender, getByTestId } = render(<PatchedCounter {...defaultProps} />); | ||
|
||
fireEvent.click(getByTestId('button')); | ||
|
||
// Assert | ||
expect(counter.find('label').text()).toEqual('pong'); | ||
expect(counter.find('button').text()).toEqual('1'); | ||
expect(fakeLogger.printInit.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls.length).toBe(1); | ||
}); | ||
|
||
test('Input, detect changed props re-render', () => { | ||
// Arrange | ||
const fakeLogger = { | ||
printInit: jest.fn(), | ||
printComparisonsResults: jest.fn(), | ||
}; | ||
const comparator = new Comparator(fakeLogger); | ||
const PatchedInput= patch(Input, comparator); | ||
|
||
const inputDefaultProps = { | ||
...defaultProps, | ||
value: "", | ||
onChange: () => {}, | ||
} | ||
// Act | ||
const { rerender, getByTestId } = render(<PatchedInput {...inputDefaultProps} />); | ||
|
||
rerender(<PatchedInput {...inputDefaultProps} value='i type ...' />); | ||
|
||
// Assert | ||
expect(fakeLogger.printInit.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls.length).toBe(1); | ||
expect(fakeLogger.printComparisonsResults.mock.calls[0]).toEqual( | ||
[[{"key":"value","type":"string","oldValue":"","nextValue":"i type ..."}],[]] | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.