We are using the CKEditor 5 React component in a project and having issues running unit tests.
Take this super paired back component
import { CKEditor } from '@ckeditor/ckeditor5-react'
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
const TextEditor = ({ message, onReady, onChange, onBlur, onFocus }) => {
return (
<div style={{ width: '98vw' }}>
<CKEditor
editor={ClassicEditor}
data={message}
onReady={onReady}
onChange={onChange}
onBlur={onBlur}
onFocus={onFocus}
/>
</div>
)
}
and Jest test
import { render } from '@testing-library/react'
import TextEditor from '.'
describe('components > TextEditor', () => {
const message = 'message'
const onChange = jest.fn()
const onFocus = jest.fn()
const onReady = jest.fn()
const onBlur = jest.fn()
let component
beforeAll(() => {
component = render(
<TextEditor
message={message}
onChange={onChange}
onFocus={onFocus}
onReady={onReady}
onBlur={onBlur}
/>
)
})
it('rendered without crashing', () => {
expect(component.asFragment()).toMatchSnapshot()
})
})
The test passes okay but something within the editor throws an error so we see this in the logs
(node:38593) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'destroy' of null
It's not a show-stopper, and we don't see the issue when actually running our app, but I'd love to know how to properly test the editor in a way that doesn't generate this warning.
It looks like in some cases, the watchdog instance tries to destroy itself before its created and assigned properly.
cc: @ma2ciek
Got the same error on a different scenario, where we load CKEditor the second time via NextJS' dynamic import
It works fine with V2.1.0.
I am getting the same error. Please help fix it and it will be much appreciated.
same here.
Same here.
I was able to resolve this by making sure that the component had fully rendered before continuing on in my test. This leads me to believe that the real issue is that the CKEditor is trying to do something after unmount (probably the code that @pomek mentioned above).
I was having the same problem, in my case, I was using a "map" and using the index as the map key, causing the error when erase any index that not the last, I changed the key for a unique code and the problem was resolved.
@davesag, @deniapps, @evertonsmenezes, the issue has been fixed and released as https://github.com/ckeditor/ckeditor5-react/releases/tag/v3.0.2.
Could I ask you to check once again whether the problem occurs?
@davesag, @deniapps, @evertonsmenezes, the issue has been fixed and released as https://github.com/ckeditor/ckeditor5-react/releases/tag/v3.0.2.
Could I ask you to check once again whether the problem occurs?
Yes. It works for me. Thank you for fixing this!
Just a reminder that starting from v3, we have to use named import (i.e., enclose "CKEditor" in curly braces), like this:
import { CKEditor } from "@ckeditor/ckeditor5-react";
My demo page is running on v3.02 now: https://deniapps.com/playground/ckeditor
I've upgraded
"@ckeditor/ckeditor5-build-classic": "^26.0.0",
"@ckeditor/ckeditor5-react": "^3.0.2",
but when I run my tests I am still seeing
(node:8446) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'destroy' of null
in my test output.
My component is as follows
import { bool, func, string } from 'prop-types'
import { CKEditor } from '@ckeditor/ckeditor5-react'
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
// ref https://github.com/ckeditor/ckeditor5-react
const TextEditor = ({ hidden, message, onReady, onChange, onBlur, onFocus, ...props }) =>
hidden ? (
<div {...props} />
) : (
<div {...props}>
<CKEditor
editor={ClassicEditor}
data={message}
onReady={onReady}
onChange={onChange}
onBlur={onBlur}
onFocus={onFocus}
/>
</div>
)
TextEditor.propTypes = {
hidden: bool,
message: string,
onReady: func,
onChange: func,
onBlur: func,
onFocus: func
}
TextEditor.defaultProps = {
hidden: false,
message: '',
onReady: undefined, // editor => {}
onBlur: undefined, // (event, editor) => { data = editor.getData() }
onFocus: undefined, // (event, editor) => { data = editor.getData() }
onChange: undefined // (event, editor) => { data = editor.getData() }
}
export default TextEditor
and my test is as follows
import { render } from '@testing-library/react'
import TextEditor from '.'
describe('components > TextEditor > TextEditor', () => {
const message = 'message'
const onChange = jest.fn()
const onFocus = jest.fn()
const onReady = jest.fn()
const onBlur = jest.fn()
let component
beforeAll(() => {
component = render(
<TextEditor
message={message}
onChange={onChange}
onFocus={onFocus}
onReady={onReady}
onBlur={onBlur}
/>
)
})
it('rendered without crashing', () => {
expect(component.asFragment()).toMatchSnapshot()
})
})
@davesag, I've tried to reproduce the issue using the code you provided but unfortunately, wick no luck. I assumed it passed for me because I use Karma+Webpack as the test runner. Do you use Jest? We already have a few issues that Jest does not work properly with our editor.
I'd like to ask about preparing a minimal part of the application that allows reproducing the issue. It will help us understand what tools are needed to get the error.
Yep I am using Jest. It's a standard CRA app which uses CRAco to override some of the standard CRA config.
I'll put a very basic example repo together tomorrow morning.
The issue about support running tests in Jest – https://github.com/ckeditor/ckeditor5-react/issues/225.
@davesag, @deniapps, @evertonsmenezes, the issue has been fixed and released as https://github.com/ckeditor/ckeditor5-react/releases/tag/v3.0.2.
Could I ask you to check once again whether the problem occurs?Yes. It works for me. Thank you for fixing this!
Just a reminder that starting from v3, we have to use named import (i.e., enclose "CKEditor" in curly braces), like this:
import { CKEditor } from "@ckeditor/ckeditor5-react";My demo page is running on v3.02 now: https://deniapps.com/playground/ckeditor
Actually, this is still an issue for me. Not on the demo page that I listed above, but in my application. I have CKEditor dynamically loaded in a component and looks like the error is thrown after unmounted/re-mounted.

It works fine with the initial load. Here is how I use CKEditor component:
const RichTextEditor = dynamic(() => import("./CKEditor"), { ssr: false });
{props.type === "editor" && (
<RichTextEditor
value={props.value}
onChange={handleEditorChange}
onUpload={handleUpload}
/>
)}
FYI: My repos is here
@deniapps, are you sure that you use the latest version of the react integration package?
@deniapps, are you sure that you use the latest version of the react integration package?
Yes. I did. But because V3 causes the issue, I rolled back to V2. When I get a chance, I will create a branch to demo the issue.
@deniapps, did you get any resolution for this? I'm also facing the same issue with a NextJS app. I'm using V3 (3.0.2).
@deniapps, did you get any resolution for this? I'm also facing the same issue with a NextJS app. I'm using V3 (3.0.2).
Yes. I fixed this a few days ago. In my case, it's due to some unnecessary page renders. Basically, the form (with CKEditor) was supposed to be rendered when the data is ready, but it was rendered regardless. So it's fixed by something like:
async componentDidMount() {
// ... get data
// NOTE: I set pageReady here!!!
this.setState({ allOptions: newAllOptions, pageReady: true });
}
// In the page render
render() {
if (!this.state.pageReady) {
return <p>Loading</p>;
}
return (
<Form data={this.state.data} /> // the CKEditor is in the Form component
)
}
Here is the commit for the fixes in my project: https://github.com/deniapps/nextfeathers/commit/23fd112b483e015be59b566c564ec5f76a9b7b23
I'm having the same issue with the latest @ckeditor/ckeditor5-react package (3.0.3 to date) and I'm using Jest too.
With node 14, I would get many warnings in the console, but the test would pass. With node 16, it fails with:
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "TypeError: Cannot read properties of null (reading 'destroy')".] {
code: 'ERR_UNHANDLED_REJECTION'
}
Most helpful comment
I am getting the same error. Please help fix it and it will be much appreciated.