diff --git a/package.json b/package.json
index 548f7a8bb0f..b4240af03f4 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
"jest": "^23.6.0",
"lerna": "~2.9.1",
"lolex": "~2.3.2",
+ "mutationobserver-shim": "^0.3.3",
"prettier": "~1.16.4",
"raf": "~3.4.0",
"ts-jest": "^23.10.5",
diff --git a/packages/ra-input-rich-text/src/index.js b/packages/ra-input-rich-text/src/index.js
index 1ae88488912..b2c5337a9d0 100644
--- a/packages/ra-input-rich-text/src/index.js
+++ b/packages/ra-input-rich-text/src/index.js
@@ -10,6 +10,8 @@ import { withStyles } from '@material-ui/core/styles';
import styles from './styles';
export class RichTextInput extends Component {
+ lastValueChange = null;
+
static propTypes = {
addLabel: PropTypes.bool.isRequired,
classes: PropTypes.object,
@@ -56,6 +58,10 @@ export class RichTextInput extends Component {
this.quill.on('text-change', debounce(this.onTextChange, 500));
}
+ shouldComponentUpdate(nextProps) {
+ return nextProps.input.value !== this.lastValueChange;
+ }
+
componentDidUpdate(prevProps) {
if (prevProps.input.value !== this.props.input.value) {
const selection = this.quill.getSelection();
@@ -76,6 +82,7 @@ export class RichTextInput extends Component {
onTextChange = () => {
const value =
this.editor.innerHTML == '
' ? '' : this.editor.innerHTML;
+ this.lastValueChange = value;
this.props.input.onChange(value);
};
@@ -91,7 +98,7 @@ export class RichTextInput extends Component {
fullWidth={this.props.fullWidth}
className="ra-rich-text-input"
>
-
+
{error && {error}}
{helperText && {helperText}}
diff --git a/packages/ra-input-rich-text/src/index.spec.js b/packages/ra-input-rich-text/src/index.spec.js
new file mode 100644
index 00000000000..e9e7feafa64
--- /dev/null
+++ b/packages/ra-input-rich-text/src/index.spec.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import debounce from 'lodash/debounce';
+import {render, fireEvent, waitForElement, cleanup, getByTestId} from 'react-testing-library'
+
+import { RichTextInput } from './index';
+
+let container;
+
+jest.mock('lodash/debounce');
+describe('RichTextInput', () => {
+ beforeEach(() => {
+ container = document.createElement('div');
+ document.body.appendChild(container);
+ // required as quilljs uses getSelection api
+ document.getSelection = () => {
+ return {
+ removeAllRanges: () => {},
+ getRangeAt: function() {},
+ };
+ };
+ });
+
+ afterEach(() => {
+ document.body.removeChild(container);
+ container = null;
+ });
+
+ it('should call handleChange only once when editing', async () => {
+ jest.useFakeTimers();
+ const handleChange = jest.fn();
+ debounce.mockImplementation(fn => fn);
+ const { getByTestId, rerender } = render(
+ test',
+ onChange: handleChange
+ }}
+ meta={{error: null}} />);
+ const quillNode = await waitForElement(() => {
+ return getByTestId('quill')
+ });
+ const node = quillNode.querySelector('.ql-editor');
+ fireEvent.input(node, {
+ target: { innerHTML: 'test1
' }
+ });
+
+ // ensuring the first 'text-change' event had been handled
+ jest.runOnlyPendingTimers();
+
+ rerender(
+ test1',
+ onChange: handleChange
+ }}
+ meta={{error: null}} />)
+
+ expect(handleChange).toHaveBeenCalledTimes(1);
+ });
+})
diff --git a/test-setup.js b/test-setup.js
index 46e3b690fe7..a552cd44b6d 100644
--- a/test-setup.js
+++ b/test-setup.js
@@ -1,4 +1,9 @@
require('raf/polyfill');
+/**
+ * As jsDom do not support mutationobserver and
+ * quill requires mutationobserver, thus a shim is needed
+ * */
+require('mutationobserver-shim');
var enzyme = require('enzyme');
var Adapter = require('enzyme-adapter-react-16');
diff --git a/yarn.lock b/yarn.lock
index 62fed4b7ff7..685cf6b9acf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10181,6 +10181,11 @@ multimatch@^2.0.0:
arrify "^1.0.0"
minimatch "^3.0.0"
+mutationobserver-shim@^0.3.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz#65869630bc89d7bf8c9cd9cb82188cd955aacd2b"
+ integrity sha512-gciOLNN8Vsf7YzcqRjKzlAJ6y7e+B86u7i3KXes0xfxx/nfLmozlW1Vn+Sc9x3tPIePFgc1AeIFhtRgkqTjzDQ==
+
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"