zenoamaro / react-quill

A Quill component for React.
https://zenoamaro.github.io/react-quill
MIT License
6.75k stars 920 forks source link

Full DOM rendering test fails at react-quill component. #434

Closed vldmrkl closed 4 years ago

vldmrkl commented 5 years ago

I'm using react-quill component in my app. Everything works fine except tests. I was writing some unit tests for my components. When I test my App component to simply render the app (using Enzyme's mount method), it fails rendering Quill component. Here is output:

    Error: Uncaught [ReferenceError: MutationObserver is not defined]
console.error node_modules/react-dom/cjs/react-dom.development.js:15123
    The above error occurred in the <Quill> component:
        in Quill (at board.js:64)
        in div (at board.js:63)
        in div (at board.js:62)
        in div (at board.js:49)
        in Board (created by WrappedBoard)
        in span (created by WrappedBoard)
        in div (created by WrappedBoard)
        in WrappedBoard (at app.js:19)
        in div (at app.js:17)
        in div (at app.js:16)
        in div (at app.js:14)

React-Quill version

1.3.2

To reproduce:

  1. Set up React app using create-react-app
  2. Add react-quill component
  3. Use react-quill component somewhere in your app
  4. Add enzyme to your app
  5. Write a unit test like this one:
import React from 'react';
import { mount } from 'enzyme';
import App from '../App';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

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

it('renders without crashing', () => {
  mount(<App />);
});
adambaialiev commented 5 years ago

Hi! I am using Jest and I have setupTests.js file where I put global mocks. This code helped me with the same problem...

global.MutationObserver = class {
  constructor(callback) {}
  disconnect() {}
  observe(element, initObject) {}
  takeRecords() {return []}
};
global.document.getSelection = function() {}
deskoh commented 5 years ago

Referencing Enzyme guide to mock DOM, the rendering failed due to the following line.

query instanceof HTMLElement

Update: Issue due to create-react-app already mocking DOM using jsdom. Getting this error now:

TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'.
aemc commented 5 years ago

I get this error with Jest + react-testing-library... not sure how to move forward

alexkrolick commented 5 years ago

You need a MutationObserver polyfill - Jest's JSDOM env is old to maintain Node 4 support.

You can install this or poyfill manually: https://github.com/ianschmitz/jest-environment-jsdom-fourteen

You may also need other polyfills depending on the environment - see the tests for this library itself: https://github.com/zenoamaro/react-quill/tree/master/test/polyfills

lyctw commented 5 years ago

Hi! I am using Jest and I have setupTests.js file where I put global mocks. This code helped me with the same problem...

global.MutationObserver = class {
  constructor(callback) {}
  disconnect() {}
  observe(element, initObject) {}
  takeRecords() {return []}
};
global.document.getSelection = function() {}

Thank you but it cause another error, anyone know how to solve it?

TypeError: Cannot read property 'classList' of null

I'm using custom html toolbar btw.

vineet-agrawal96 commented 5 years ago

@syokujinau , I'm also facing same issue. have you resolved it?

lyctw commented 5 years ago

@vineet-agrawal96 Not yet bro, im still trying.

guruusingh2033 commented 4 years ago

Same issue could anyone help me to resolve please

liamMellor commented 4 years ago

This fixed things for me

import MutationObserver from 'mutation-observer'

beforeAll(() => {
  window.MutationObserver = MutationObserver
  document.getSelection = () => {
    return {
      removeAllRanges: () => {},
      addRange: () => {},
      getRangeAt: () => {},
    }
  }
})
alexkrolick commented 4 years ago

Updating to Jest v25 (manually updating the JSDOM environment to JSDOM v14+) will include the necessary APIs by default

labkey-nicka commented 4 years ago

@lyctw I realize this was awhile ago but did you end up finding a solution for when you have a custom toolbar? I'm also receiving the error of the classList being null.

alita-moore commented 4 years ago

@labkey-nicka I fixed this today by installing jest npm install jest

labkey-nicka commented 4 years ago

@alita-moore Yes, I'm using jest as well but was unable to get it to work for a custom toolbar.

ericandrewscott commented 3 years ago

I get this error with Jest + react-testing-library... not sure how to move forward

@aemc Did you ever get this figured out? I'm having the same problem. I tried @adambaialiev 's solution of mocking MutationObserver, but now I get the following error:


  src/components/MessageInput/MessageInput.js
    ✕ Renders the textarea on the page (no tags) (65ms)

  ● src/components/MessageInput/MessageInput.js › Renders the textarea on the page (no tags)

    TypeError: Cannot convert undefined or null to object
        at Function.keys (<anonymous>)

      27 |
      28 | const customRender = (ui, {providerProps, ...renderOptions}) => {
    > 29 |     return render(
         |            ^
      30 |         <MessageContext.Provider value={providerProps}>
      31 |             {ui}
      32 |         </MessageContext.Provider>,

      at new Keyboard (node_modules/quill/dist/quill.js:4511:12)
      at SnowTheme.addModule (node_modules/quill/dist/quill.js:6130:28)
      at SnowTheme.addModule (node_modules/quill/dist/quill.js:6774:121)
      at new Quill (node_modules/quill/dist/quill.js:1160:32)
      at ReactQuill.Object.<anonymous>.ReactQuill.createEditor (node_modules/react-quill/src/index.tsx:330:20)
      at ReactQuill.Object.<anonymous>.ReactQuill.instantiateEditor (node_modules/react-quill/src/index.tsx:288:24)
      at ReactQuill.Object.<anonymous>.ReactQuill.componentDidMount (node_modules/react-quill/src/index.tsx:253:10)
      at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:19814:22)
      at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:22803:7)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:188:14)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:237:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:292:31)
      at commitRootImpl (node_modules/react-dom/cjs/react-dom.development.js:22541:9)
      at unstable_runWithPriority (node_modules/scheduler/cjs/scheduler.development.js:653:12)
      at runWithPriority$1 (node_modules/react-dom/cjs/react-dom.development.js:11039:10)
      at commitRoot (node_modules/react-dom/cjs/react-dom.development.js:22381:3)
      at finishSyncRender (node_modules/react-dom/cjs/react-dom.development.js:21807:3)
      at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:21793:7)
      at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:21188:7)
      at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:24373:3)
      at node_modules/react-dom/cjs/react-dom.development.js:24758:7
      at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:21903:12)
      at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:24757:5)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:24840:10)
      at node_modules/@testing-library/react/dist/pure.js:101:25
      at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:21856:12)
      at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:929:14)
      at render (node_modules/@testing-library/react/dist/pure.js:97:26)
      at customRender (src/components/MessageInput/test/MessageInput.test.js:29:12)
      at Object.<anonymous> (src/components/MessageInput/test/MessageInput.test.js:63:9)```
nappalm commented 1 year ago

Has anyone been able to solve it? I also have the following error:

Uncaught TypeError: Cannot read properties of null (reading 'innerHTML')

HQ1363 commented 1 year ago

Has anyone been able to solve it? I also have the following error:

Uncaught TypeError: Cannot read properties of null (reading 'innerHTML')

我也遇到了,但是我解决了,指定modules参数的时候,挂载container的id需要不一样的,否则会引起冲突