codex-team / editor.js

A block-style editor with clean JSON output
https://editorjs.io
Apache License 2.0
28.73k stars 2.08k forks source link

Unable to test component having editor.js with react-test-renderer #1253

Open VShian opened 4 years ago

VShian commented 4 years ago

How to test the components that have the EditorJs component (imported from '@editorjs/editorjs') as a child.

I am getting the following error while running the tests: Editor.js is not ready because of Error: element with ID «editorjs» is missing. Pass correct holder's ID.

Custom Editor Component: CustomEditor.js

import React from 'react';
import EditorJS from '@editorjs/editorjs';
import Header from '@editorjs/header';
import List from '@editorjs/list';
import Paragraph from '@editorjs/paragraph';
import Quote from '@editorjs/quote';
import Table from '@editorjs/table';
import UppyUploader from './uppy.js';
import { useSelector } from 'react-redux';

function Editor({value, onChange}) {
  const editor_block = React.useRef(null);
  const space_slug = 'slug'

  React.useEffect(() => {
    new EditorJS({
      holder: editor_block.current,
      tools: {
        header: Header,
        list: List,
        paragraph: Paragraph,
        quote: Quote,
        table: Table,
        uppy: {
          class: UppyUploader,
          config: {
            space_slug: space_slug,
          },
        },
      },
      onChange: (value) =>
        value.saver.save().then((value) => {
          console.log(value);
          onChange(value);
        }),
      data: value,
    });
  }, []);

  return <div ref={editor_block}></div>;
}

Component: Component.js

import React from 'react';
import { Form, Input } from 'antd';
import EditorJS from './CustomEditor;

const Component = () => {
  return (
    <Form>
      <Form.Item> <EditorJs/> </Form.Item>
    </Form>
  );
}

Test code is as follows: Component.test.js

import renderer, { act } from 'react-test-renderer';
import Component from './Component'

describe('snapshot testing', () => {
  it('should render the component', () => {
      let component;
      act(() => {
        component = renderer.create(
          <Provider store={store}>
            <Component />
          </Provider>,
        );
      });
      const tree = component.toJSON();
      expect(tree).toMatchSnapshot();
    });
});
neSpecc commented 4 years ago

Can you log the editor_block.current variable? looks like it is a string, that means the id of a wrapper element. But the element with this id is not found.

VShian commented 4 years ago

@neSpecc, thanks for your reply. I've added the editor_block.current logged value.

  <ref *1> HTMLDivElement {
    '__reactInternalInstance$62qns47ogkd': <ref *2> FiberNode {
      tag: 5,
      key: null,
      elementType: 'div',
      type: 'div',
      stateNode: [Circular *1],
      return: FiberNode {
        tag: 0,
        key: null,
        elementType: [Function: Editor],
        type: [Function: Editor],
        stateNode: null,
        return: [FiberNode],
        child: [FiberNode],
        sibling: null,
        index: 0,
        ref: null,
        pendingProps: [Object],
        memoizedProps: [Object],
        updateQueue: null,
        memoizedState: [Object],
        dependencies: null,
        mode: 0,
        effectTag: 0,
        nextEffect: null,
        firstEffect: null,
        lastEffect: null,
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: [FiberNode],
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 14760,
        _debugIsCurrentlyTiming: false,
        _debugSource: [Object],
        _debugOwner: [FiberNode],
        _debugNeedsRemount: false,
        _debugHookTypes: [Array]
      },
      child: null,
      sibling: null,
      index: 0,
      ref: { current: [Circular *1] },
      pendingProps: {},
      memoizedProps: {},
      updateQueue: null,
      memoizedState: null,
      dependencies: null,
      mode: 0,
      effectTag: 128,
      nextEffect: null,
      firstEffect: null,
      lastEffect: null,
      expirationTime: 0,
      childExpirationTime: 0,
      alternate: FiberNode {
        tag: 5,
        key: null,
        elementType: 'div',
        type: 'div',
        stateNode: [Circular *1],
        return: [FiberNode],
        child: null,
        sibling: null,
        index: 0,
        ref: [Object],
        pendingProps: {},
        memoizedProps: {},
        updateQueue: null,
        memoizedState: null,
        dependencies: null,
        mode: 0,
        effectTag: 0,
        nextEffect: null,
        firstEffect: null,
        lastEffect: null,
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: [Circular *2],
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 14762,
        _debugIsCurrentlyTiming: false,
        _debugSource: [Object],
        _debugOwner: [FiberNode],
        _debugNeedsRemount: false,
        _debugHookTypes: null
      },
      actualDuration: 0,
      actualStartTime: -1,
      selfBaseDuration: 0,
      treeBaseDuration: 0,
      _debugID: 14762,
      _debugIsCurrentlyTiming: false,
      _debugSource: {
        fileName: '/Users/shreeharsha/project/factly/ecosystem/dega/dega-admin-portal/src/components/Editor/index.js',
        lineNumber: 45,
        columnNumber: 10
      },
      _debugOwner: FiberNode {
        tag: 0,
        key: null,
        elementType: [Function: Editor],
        type: [Function: Editor],
        stateNode: null,
        return: [FiberNode],
        child: [FiberNode],
        sibling: null,
        index: 0,
        ref: null,
        pendingProps: [Object],
        memoizedProps: [Object],
        updateQueue: null,
        memoizedState: [Object],
        dependencies: null,
        mode: 0,
        effectTag: 0,
        nextEffect: null,
        firstEffect: null,
        lastEffect: null,
        expirationTime: 0,
        childExpirationTime: 0,
        alternate: [FiberNode],
        actualDuration: 0,
        actualStartTime: -1,
        selfBaseDuration: 0,
        treeBaseDuration: 0,
        _debugID: 14760,
        _debugIsCurrentlyTiming: false,
        _debugSource: [Object],
        _debugOwner: [FiberNode],
        _debugNeedsRemount: false,
        _debugHookTypes: [Array]
      },
      _debugNeedsRemount: false,
      _debugHookTypes: null
    },
    '__reactEventHandlers$62qns47ogkd': {}
  }
sis-dk commented 4 years ago

I've never used react-test-renderer but looks like it doesn't really run an actual browser but just simulates the DOM. So the browser DOM APIs won't be available in your test. EditorJS relies on those APIs to insert the blocks. Don't think you'll be able to test EditorJS with react-test-renderer.

VShian commented 4 years ago

@sis-dk Is there any other way to test the component as in my case? In other words, may I know what testing libraries can I use to test the components that are using EditorJs?