codex-team / codex-team/editor.js

Testing editor.js with jest-dom

Open
#1,957 1 comment 6 reactions 0 assignees View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.