-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix issue with ReactEditor.focus + tests (#5527)
* Fix issue with slate-react static ReactEditor.focus method This will make sure we don't try to focus the editor while it's in the midst of applying operations. If this is the case, retry setting focus in the next tick. * Replace react-test-renderer with @testing-library/react We need to be able to test against window features, like the DOM selection. @testing-library/react has a very similar API, but have also these features, which react-test-renderer is missing. * Rewrite tests for @testing-library/react This will rewrite the existing tests for Editable and move them into a own file. * Add tests for ReactEditor.focus * Add changeset
- Loading branch information
1 parent
f9cca97
commit fc08181
Showing
7 changed files
with
540 additions
and
251 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
'slate-react': minor | ||
--- | ||
|
||
Fixes a bug with `ReactEditor.focus` where it would throw an error if the editor was in the middle of applying pending operations. | ||
With this change, setting focus will be retried until the editor no longer has any pending operations. | ||
Calling `ReactEditor.focus` on a editor without a current selection, will now make a selection in the top of the document. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
import React, { useEffect } from 'react' | ||
import { createEditor, Text, Transforms } from 'slate' | ||
import { act, render } from '@testing-library/react' | ||
import { Slate, withReact, Editable } from '../src' | ||
|
||
describe('slate-react', () => { | ||
describe('Editable', () => { | ||
describe('NODE_TO_KEY logic', () => { | ||
test('should not unmount the node that gets split on a split_node operation', async () => { | ||
const editor = withReact(createEditor()) | ||
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }] | ||
const mounts = jest.fn() | ||
|
||
act(() => { | ||
render( | ||
<Slate | ||
editor={editor} | ||
initialValue={initialValue} | ||
onChange={() => {}} | ||
> | ||
<Editable | ||
renderElement={({ children }) => { | ||
useEffect(() => mounts(), []) | ||
|
||
return children | ||
}} | ||
/> | ||
</Slate> | ||
) | ||
}) | ||
|
||
// slate updates at next tick, so we need this to be async | ||
await act(async () => | ||
Transforms.splitNodes(editor, { at: { path: [0, 0], offset: 2 } }) | ||
) | ||
|
||
// 2 renders, one for the main element and one for the split element | ||
expect(mounts).toHaveBeenCalledTimes(2) | ||
}) | ||
|
||
test('should not unmount the node that gets merged into on a merge_node operation', async () => { | ||
const editor = withReact(createEditor()) | ||
const initialValue = [ | ||
{ type: 'block', children: [{ text: 'te' }] }, | ||
{ type: 'block', children: [{ text: 'st' }] }, | ||
] | ||
const mounts = jest.fn() | ||
|
||
act(() => { | ||
render( | ||
<Slate | ||
editor={editor} | ||
initialValue={initialValue} | ||
onChange={() => {}} | ||
> | ||
<Editable | ||
renderElement={({ children }) => { | ||
useEffect(() => mounts(), []) | ||
|
||
return children | ||
}} | ||
/> | ||
</Slate> | ||
) | ||
}) | ||
|
||
// slate updates at next tick, so we need this to be async | ||
await act(async () => | ||
Transforms.mergeNodes(editor, { at: { path: [0, 0], offset: 0 } }) | ||
) | ||
|
||
// only 2 renders for the initial render | ||
expect(mounts).toHaveBeenCalledTimes(2) | ||
}) | ||
}) | ||
test('calls onSelectionChange when editor select change', async () => { | ||
const editor = withReact(createEditor()) | ||
const initialValue = [ | ||
{ type: 'block', children: [{ text: 'te' }] }, | ||
{ type: 'block', children: [{ text: 'st' }] }, | ||
] | ||
const onChange = jest.fn() | ||
const onValueChange = jest.fn() | ||
const onSelectionChange = jest.fn() | ||
|
||
act(() => { | ||
render( | ||
<Slate | ||
editor={editor} | ||
initialValue={initialValue} | ||
onChange={onChange} | ||
onValueChange={onValueChange} | ||
onSelectionChange={onSelectionChange} | ||
> | ||
<Editable /> | ||
</Slate> | ||
) | ||
}) | ||
|
||
await act(async () => | ||
Transforms.select(editor, { path: [0, 0], offset: 2 }) | ||
) | ||
|
||
expect(onSelectionChange).toHaveBeenCalled() | ||
expect(onChange).toHaveBeenCalled() | ||
expect(onValueChange).not.toHaveBeenCalled() | ||
}) | ||
|
||
test('calls onValueChange when editor children change', async () => { | ||
const editor = withReact(createEditor()) | ||
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }] | ||
const onChange = jest.fn() | ||
const onValueChange = jest.fn() | ||
const onSelectionChange = jest.fn() | ||
|
||
act(() => { | ||
render( | ||
<Slate | ||
editor={editor} | ||
initialValue={initialValue} | ||
onChange={onChange} | ||
onValueChange={onValueChange} | ||
onSelectionChange={onSelectionChange} | ||
> | ||
<Editable /> | ||
</Slate> | ||
) | ||
}) | ||
|
||
await act(async () => Transforms.insertText(editor, 'Hello word!')) | ||
|
||
expect(onValueChange).toHaveBeenCalled() | ||
expect(onChange).toHaveBeenCalled() | ||
expect(onSelectionChange).not.toHaveBeenCalled() | ||
}) | ||
|
||
test('calls onValueChange when editor setNodes', async () => { | ||
const editor = withReact(createEditor()) | ||
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }] | ||
const onChange = jest.fn() | ||
const onValueChange = jest.fn() | ||
const onSelectionChange = jest.fn() | ||
|
||
act(() => { | ||
render( | ||
<Slate | ||
editor={editor} | ||
initialValue={initialValue} | ||
onChange={onChange} | ||
onValueChange={onValueChange} | ||
onSelectionChange={onSelectionChange} | ||
> | ||
<Editable /> | ||
</Slate> | ||
) | ||
}) | ||
|
||
await act(async () => | ||
Transforms.setNodes( | ||
editor, | ||
// @ts-ignore | ||
{ bold: true }, | ||
{ | ||
at: { path: [0, 0], offset: 2 }, | ||
match: Text.isText, | ||
split: true, | ||
} | ||
) | ||
) | ||
|
||
expect(onChange).toHaveBeenCalled() | ||
expect(onValueChange).toHaveBeenCalled() | ||
expect(onSelectionChange).not.toHaveBeenCalled() | ||
}) | ||
|
||
test('calls onValueChange when editor children change', async () => { | ||
const editor = withReact(createEditor()) | ||
const initialValue = [{ type: 'block', children: [{ text: 'test' }] }] | ||
const onChange = jest.fn() | ||
const onValueChange = jest.fn() | ||
const onSelectionChange = jest.fn() | ||
|
||
act(() => { | ||
render( | ||
<Slate | ||
editor={editor} | ||
initialValue={initialValue} | ||
onChange={onChange} | ||
onValueChange={onValueChange} | ||
onSelectionChange={onSelectionChange} | ||
> | ||
<Editable /> | ||
</Slate> | ||
) | ||
}) | ||
|
||
await act(async () => Transforms.insertText(editor, 'Hello word!')) | ||
|
||
expect(onValueChange).toHaveBeenCalled() | ||
expect(onChange).toHaveBeenCalled() | ||
expect(onSelectionChange).not.toHaveBeenCalled() | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.