codex-team / codex-team/editor.js
Testing editor.js with jest-dom
- Dominant language
- TypeScript
- Stars
- 31.9k
- Forks
- 2.2k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 1
Description
I am using editor.js in a React project and using [test-library](https://testing-library.com/) with jest-dom for tests.
I want to implement some basic test cases such as "load the editor then input some content and save" but I am not sure how to write this test.
I tried to list all the difficulties I faced and the workaround I used, if it can help !
### wait until the editor finishes loading (`isReady` promise)
This sounds trivial but I didn't find an easy to do this, I am currently using a ref for this purpose
```ts
export const editorRef: { current: Partial } = {
current: { isReady: new Promise(() => {}) },
};
jest.mock("@editorsjs/editorjs", () = (props: EditorConfig) => {
// an HTML element with id === props.holder needs to be present
// otherwise throws an error, so we need to create instance here
const instance = new EditorJS({ ...props, tunes: ["testWrapper"] });
// editorJS is not ready yet : { isReady: Promise { } }
// during each test, we need to wait until the isReady promise finishes
// so that other properties (blocks, save, ...) get populated
editorRef.current = instance;
return instance;
})
```
then in my test I can wait until the editor is ready
```ts
await waitFor(() => expect(editorRef.current.render).toBeDefined());
```
### retrieve a specific div inside editor.js
testing-library doesn't provide functions to search for elements with specific classnames, so I had to create a block tune to add a `data-testid` attribute to every block element through the wrap function.
```ts
class TestIdTune {
wrap(blockContent: HTMLDivElement) {
blockContent.setAttribute("data-testid", "block");
return blockContent;
}
save() {
return "";
}
render() {
return document.createElement("div");
}
static get isTune() {
return true;
}
}
```
This allowed me to retrieve a block through `screen.findByTestId("block")`
### click on an element to allow text input
Clicking on a block would throw the following error
> document.elementFromPoint is not a function
I have suspecting that it can't be helped due to jest-dom, but I am not knowledgeable enough and may have missed something.
I found that I could get rid of this error by updating my TestIdTune to also set `contenteditable=true`
```ts
blockContent.setAttribute("contenteditable", "true");
```
Then in my test I can successfully type some text inside the block :
```ts
const block = screen.getByTestId("block");
userEvent.type(block, "test");
```
### save() fails with the error "range(...).getBoundingClientRect is not a function"
It seems jest-dom doesn't have a proper implementation of the Range object, and I tried to mock the missing functions like this
```ts
document.createRange = () => {
const range = new Range();
range.getBoundingClientRect = jest.fn();
range.getClientRects = jest.fn(() => ({
item: () => null,
length: 0,
[Symbol.iterator]: jest.fn(),
}));
return range;
};
```
However I now get the following error
> TypeError: Cannot read properties of undefined (reading 'top')
which is thrown by the Caret class, specifically [this line](https://github.com/codex-team/editor.js/blob/9cdda110dac04c70cf137ef324085e5326c448ec/src/components/modules/caret.ts#L308)
---
At this point I am not sure whether I should dig deeper and create a very unstable testing environment, that's why I would like to know if there was a way to simulate a proper environment for editor.js to run with jest-dom. Thank you.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.