Browse Source
Merge pull request #220 from wangeditor-team/test-editor
Merge pull request #220 from wangeditor-team/test-editor
test: editor API configfix-react18

committed by
GitHub

No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 545 additions and 2 deletions
-
30packages/editor/__tests__/API/config-api.test.ts
-
156packages/editor/__tests__/API/content-api.test.ts
-
65packages/editor/__tests__/API/dom-api.test.ts
-
55packages/editor/__tests__/API/node-api.test.ts
-
41packages/editor/__tests__/API/selection.test.ts
-
120packages/editor/__tests__/config/editor-config.test.ts
-
25packages/editor/__tests__/config/menu-config.test.ts
-
52packages/editor/__tests__/config/toolbar-config.test.ts
-
3tests/utils/create-editor.ts
@ -0,0 +1,30 @@ |
|||
/** |
|||
* @description config API test |
|||
* @author wangfupeng |
|||
*/ |
|||
|
|||
import createEditor from '../../../../tests/utils/create-editor' |
|||
|
|||
describe('editor config API', () => { |
|||
it('get config', () => { |
|||
const editor = createEditor() |
|||
const defaultConfig = editor.getConfig() |
|||
expect(defaultConfig).not.toBeNull() |
|||
expect(defaultConfig.autoFocus).toBeTruthy() |
|||
expect(defaultConfig.readOnly).toBeFalsy() |
|||
// 其他 props 不一一写了
|
|||
}) |
|||
|
|||
it('get menu config', () => { |
|||
const editor = createEditor() |
|||
const insertLinkConfig = editor.getMenuConfig('insertLink') |
|||
expect(insertLinkConfig).not.toBeNull() |
|||
}) |
|||
|
|||
it('get all menus', () => { |
|||
const editor = createEditor() |
|||
const menuKeys = editor.getAllMenuKeys() |
|||
expect(Array.isArray(menuKeys)).toBeTruthy() |
|||
expect(menuKeys.length).toBeGreaterThan(50) // 内置了 50+ 菜单
|
|||
}) |
|||
}) |
@ -0,0 +1,156 @@ |
|||
/** |
|||
* @description content API test |
|||
* @author wangfupeng |
|||
*/ |
|||
|
|||
import { Editor, Transforms, Node } from 'slate' |
|||
import createEditor from '../../../../tests/utils/create-editor' |
|||
|
|||
describe('editor content API', () => { |
|||
function getStartLocation(editor) { |
|||
return Editor.start(editor, []) |
|||
} |
|||
|
|||
it('handleTab', () => { |
|||
const editor = createEditor() |
|||
editor.select(getStartLocation(editor)) |
|||
editor.handleTab() |
|||
expect(editor.getText().length).toBe(4) // 默认 tab 键,输入 4 空格
|
|||
}) |
|||
|
|||
it('getHtml', () => { |
|||
const editor = createEditor({ |
|||
content: [{ type: 'paragraph', children: [{ text: 'hello' }] }], |
|||
}) |
|||
|
|||
const html1 = editor.getHtml() |
|||
expect(html1).toBe('<div class="w-e-content-container">\r\n <p>hello</p>\r\n</div>') // 格式化 html
|
|||
|
|||
const html2 = editor.getHtml({ withFormat: false, containerClassName: 'my-container' }) |
|||
expect(html2).toBe('<div class="my-container"><p>hello</p></div>') // 非格式化 + 自定义 class
|
|||
}) |
|||
|
|||
it('getText', () => { |
|||
const editor = createEditor({ |
|||
content: [ |
|||
{ type: 'paragraph', children: [{ text: 'hello' }] }, |
|||
{ type: 'paragraph', children: [{ text: 'world' }] }, |
|||
], |
|||
}) |
|||
const text = editor.getText() |
|||
expect(text).toBe('hello\nworld') |
|||
}) |
|||
|
|||
it('isEmpty', () => { |
|||
const editor1 = createEditor() |
|||
expect(editor1.isEmpty()).toBeTruthy() |
|||
|
|||
const editor2 = createEditor({ |
|||
content: [{ type: 'paragraph', children: [{ text: 'hello' }] }], |
|||
}) |
|||
expect(editor2.isEmpty()).toBeFalsy() |
|||
}) |
|||
|
|||
it('getSelectionText', () => { |
|||
const editor = createEditor({ |
|||
content: [{ type: 'paragraph', children: [{ text: 'hello' }] }], |
|||
}) |
|||
editor.select(getStartLocation(editor)) // 光标在开始位置
|
|||
expect(editor.getSelectionText()).toBe('') |
|||
|
|||
editor.select([]) // 全选
|
|||
expect(editor.getSelectionText()).toBe('hello') |
|||
}) |
|||
|
|||
it('getElemsByTypePrefix', () => { |
|||
const editor = createEditor({ |
|||
content: [ |
|||
{ type: 'header1', children: [{ text: 'a' }] }, |
|||
{ type: 'header2', children: [{ text: 'b' }] }, |
|||
{ type: 'paragraph', children: [{ text: 'c' }] }, |
|||
], |
|||
}) |
|||
const headers = editor.getElemsByTypePrefix('header') |
|||
expect(headers.length).toBe(2) |
|||
const pList = editor.getElemsByTypePrefix('paragraph') |
|||
expect(pList.length).toBe(1) |
|||
const images = editor.getElemsByTypePrefix('image') |
|||
expect(images.length).toBe(0) |
|||
}) |
|||
|
|||
it('deleteBackward and deleteForward', () => { |
|||
const editor = createEditor({ |
|||
content: [{ type: 'paragraph', children: [{ text: 'hello' }] }], |
|||
}) |
|||
editor.select(getStartLocation(editor)) // 光标在开始位置
|
|||
Transforms.move(editor, { distance: 2, unit: 'character' }) // 光标移动 3 个字符
|
|||
|
|||
editor.deleteBackward('character') // 向后删除
|
|||
expect(editor.getText()).toBe('hllo') |
|||
|
|||
editor.deleteForward('character') // 向前删除
|
|||
expect(editor.getText()).toBe('hlo') |
|||
}) |
|||
|
|||
it('getFragment and deleteFragment', () => { |
|||
const editor = createEditor({ |
|||
content: [{ type: 'paragraph', children: [{ text: 'hello' }] }], |
|||
}) |
|||
// 选中 'hel'lo
|
|||
editor.select({ |
|||
anchor: { |
|||
path: [0, 0], |
|||
offset: 0, |
|||
}, |
|||
focus: { |
|||
path: [0, 0], |
|||
offset: 3, |
|||
}, |
|||
}) |
|||
|
|||
const fragment = editor.getFragment() // 获取选中内容
|
|||
expect(Node.string(fragment[0])).toBe('hel') |
|||
|
|||
editor.deleteFragment() // 删除选中内容
|
|||
expect(editor.getText()).toBe('lo') |
|||
}) |
|||
|
|||
it('insertBreak', () => { |
|||
const editor = createEditor() |
|||
editor.select(getStartLocation(editor)) // 光标在开始位置
|
|||
|
|||
editor.insertBreak() |
|||
const pList = editor.getElemsByTypePrefix('paragraph') |
|||
expect(pList.length).toBe(2) |
|||
}) |
|||
|
|||
it('insertText', () => { |
|||
const editor = createEditor() |
|||
editor.select(getStartLocation(editor)) // 光标在开始位置
|
|||
editor.insertText('xxx') |
|||
expect(editor.getText()).toBe('xxx') |
|||
}) |
|||
|
|||
it('clear', () => { |
|||
const editor = createEditor({ |
|||
content: [{ type: 'paragraph', children: [{ text: 'hello' }] }], |
|||
}) |
|||
editor.clear() |
|||
expect(editor.getText()).toBe('') |
|||
}) |
|||
|
|||
it('undo and redo', () => { |
|||
const editor = createEditor() |
|||
editor.select(getStartLocation(editor)) // 光标在开始位置
|
|||
|
|||
editor.insertText('hello') |
|||
|
|||
// @ts-ignore
|
|||
editor.undo() |
|||
expect(editor.getText()).toBe('') |
|||
|
|||
// @ts-ignore
|
|||
editor.redo() |
|||
expect(editor.getText()).toBe('hello') |
|||
}) |
|||
}) |
@ -0,0 +1,65 @@ |
|||
/** |
|||
* @description editor DOM API test |
|||
* @author wangfupeng |
|||
*/ |
|||
|
|||
import { Editor } from 'slate' |
|||
import createEditor from '../../../../tests/utils/create-editor' |
|||
|
|||
describe('editor DOM API', () => { |
|||
function getStartLocation(editor) { |
|||
return Editor.start(editor, []) |
|||
} |
|||
|
|||
it('editor id', () => { |
|||
const editor = createEditor() |
|||
expect(editor.id).not.toBeNull() |
|||
}) |
|||
|
|||
it('isFullScreen fullScreen unFullScreen', done => { |
|||
const editor = createEditor() |
|||
|
|||
expect(editor.isFullScreen).toBeFalsy() |
|||
|
|||
editor.fullScreen() |
|||
expect(editor.isFullScreen).toBeTruthy() |
|||
|
|||
editor.unFullScreen() |
|||
setTimeout(() => { |
|||
expect(editor.isFullScreen).toBeFalsy() |
|||
done() |
|||
}, 1000) |
|||
}) |
|||
|
|||
// TODO focus blur isFocused 用 jest 测试异常,以及 editor-config.test.ts 中的 `onFocus` `onBlur`
|
|||
|
|||
it('disable isDisabled enable', () => { |
|||
const editor = createEditor() |
|||
editor.select(getStartLocation(editor)) |
|||
|
|||
expect(editor.isDisabled()).toBeFalsy() |
|||
editor.insertText('123') |
|||
expect(editor.getText().length).toBe(3) |
|||
|
|||
editor.disable() |
|||
expect(editor.isDisabled()).toBeTruthy() |
|||
editor.insertText('123') // disabled ,不会插入
|
|||
expect(editor.getText().length).toBe(3) |
|||
|
|||
editor.enable() |
|||
expect(editor.isDisabled()).toBeFalsy() |
|||
editor.insertText('123') // enable ,可以插入
|
|||
expect(editor.getText().length).toBe(6) |
|||
}) |
|||
|
|||
it('destroy', done => { |
|||
const editor = createEditor() |
|||
expect(editor.isDestroyed).toBeFalsy() |
|||
|
|||
setTimeout(() => { |
|||
editor.destroy() |
|||
expect(editor.isDestroyed).toBeTruthy() |
|||
done() |
|||
}) |
|||
}) |
|||
}) |
@ -0,0 +1,55 @@ |
|||
/** |
|||
* @description node API test |
|||
* @author wangfupeng |
|||
*/ |
|||
|
|||
import { Editor } from 'slate' |
|||
import createEditor from '../../../../tests/utils/create-editor' |
|||
|
|||
describe('editor node API', () => { |
|||
function getStartLocation(editor) { |
|||
return Editor.start(editor, []) |
|||
} |
|||
|
|||
it('insertNode', () => { |
|||
const editor = createEditor() |
|||
editor.select(getStartLocation(editor)) |
|||
|
|||
const p = { type: 'paragraph', children: [{ text: 'hello' }] } |
|||
editor.insertNode(p) |
|||
|
|||
const pList = editor.getElemsByTypePrefix('paragraph') |
|||
expect(pList.length).toBe(2) |
|||
}) |
|||
|
|||
// insertNodes removeNodes Editor.nodes setNodes 是 slate Transforms API ,不用测试
|
|||
|
|||
it('getParentNode', () => { |
|||
const textNode = { text: 'hello' } |
|||
const p = { type: 'paragraph', children: [textNode] } |
|||
const editor = createEditor({ |
|||
content: [p], |
|||
}) |
|||
|
|||
const parentNode = editor.getParentNode(textNode) |
|||
expect(parentNode).not.toBeNull() |
|||
expect(parentNode.type).toBe('paragraph') |
|||
}) |
|||
|
|||
it('toDOMNode', done => { |
|||
const p = { type: 'paragraph', children: [{ text: 'hello' }] } |
|||
const editor = createEditor({ |
|||
content: [p], |
|||
}) |
|||
|
|||
setTimeout(() => { |
|||
const domNode = editor.toDOMNode(p) |
|||
expect(domNode.tagName).toBe('P') |
|||
done() |
|||
}) |
|||
}) |
|||
|
|||
// isInline isVoid addMark removeMark 是 slate editor 自带 API ,不用测试
|
|||
|
|||
// isText isElement marks 是 slate 提供的 API ,不用测试
|
|||
}) |
@ -0,0 +1,41 @@ |
|||
/** |
|||
* @description selection API test |
|||
* @author wangfupeng |
|||
*/ |
|||
|
|||
import { Editor } from 'slate' |
|||
import createEditor from '../../../../tests/utils/create-editor' |
|||
|
|||
describe('editor selection API', () => { |
|||
function getStartLocation(editor) { |
|||
return Editor.start(editor, []) |
|||
} |
|||
|
|||
// selection select deselect 是 slate 自带 API 或属性,不测试
|
|||
|
|||
// // TODO 运行报错,看源码有使用 focus ,可能和这个相关???
|
|||
// it('restoreSelection', () => {
|
|||
// const editor = createEditor()
|
|||
// editor.select(getStartLocation(editor))
|
|||
|
|||
// editor.deselect()
|
|||
// expect(editor.selection).toBeNull()
|
|||
|
|||
// editor.restoreSelection()
|
|||
// expect(editor.selection).not.toBeNull()
|
|||
// // console.log(111, JSON.stringify(editor.selection))
|
|||
// })
|
|||
|
|||
it('isSelectedAll', () => { |
|||
const p = { type: 'paragraph', children: [{ text: 'hello' }] } |
|||
|
|||
const editor = createEditor({ content: [p] }) |
|||
expect(editor.isSelectedAll()).toBeFalsy() |
|||
|
|||
editor.select(getStartLocation(editor)) |
|||
expect(editor.isSelectedAll()).toBeFalsy() |
|||
|
|||
editor.select([]) |
|||
expect(editor.isSelectedAll()).toBeTruthy() |
|||
}) |
|||
}) |
@ -0,0 +1,120 @@ |
|||
/** |
|||
* @description editor config test |
|||
* @author wangfupeng |
|||
*/ |
|||
|
|||
import { Editor } from 'slate' |
|||
import createEditor from '../../../../tests/utils/create-editor' |
|||
|
|||
describe('editor config', () => { |
|||
function getStartLocation(editor) { |
|||
return Editor.start(editor, []) |
|||
} |
|||
|
|||
it('readOnly', () => { |
|||
const editor = createEditor({ |
|||
config: { |
|||
readOnly: true, |
|||
}, |
|||
}) |
|||
expect(editor.isDisabled()).toBeTruthy() |
|||
|
|||
editor.select(getStartLocation(editor)) |
|||
editor.insertText('xxx') // readOnly 时无法插入文本
|
|||
expect(editor.getText()).toBe('') |
|||
}) |
|||
|
|||
it('autoFocus', () => { |
|||
createEditor({ |
|||
config: { |
|||
autoFocus: false, |
|||
}, |
|||
}) |
|||
// @ts-ignore
|
|||
expect(document.activeElement.tagName).toBe('BODY') |
|||
}) |
|||
|
|||
it('maxLength', done => { |
|||
const editor = createEditor({ |
|||
config: { |
|||
maxLength: 10, |
|||
onMaxLength: () => { |
|||
done() // 触发回调,才能完成该测试
|
|||
}, |
|||
}, |
|||
}) |
|||
editor.select(getStartLocation(editor)) |
|||
|
|||
// 插入 10 个字符,正好等于 maxLength
|
|||
editor.insertText('1234567890') |
|||
expect(editor.getText()).toBe('1234567890') |
|||
|
|||
// 再插入字符,则不会插入成功
|
|||
editor.insertText('xx') |
|||
expect(editor.getText()).toBe('1234567890') |
|||
}) |
|||
|
|||
it('onCreated', done => { |
|||
createEditor({ |
|||
config: { |
|||
onCreated: () => { |
|||
done() // 触发回调,才能完成该测试
|
|||
}, |
|||
}, |
|||
}) |
|||
}) |
|||
|
|||
it('onChange', done => { |
|||
const editor = createEditor({ |
|||
config: { |
|||
onChange: () => { |
|||
done() // 触发回调,才能完成该测试
|
|||
}, |
|||
}, |
|||
}) |
|||
setTimeout(() => { |
|||
editor.select(getStartLocation(editor)) // 选区变化,触发 onchange
|
|||
}) |
|||
}) |
|||
|
|||
it('onDestroyed', done => { |
|||
const editor = createEditor({ |
|||
config: { |
|||
onDestroyed: () => { |
|||
done() // 触发回调,才能完成该测试
|
|||
}, |
|||
}, |
|||
}) |
|||
setTimeout(() => { |
|||
editor.destroy() |
|||
}) |
|||
}) |
|||
|
|||
// it('onFocus', done => {
|
|||
// const editor = createEditor({
|
|||
// config: {
|
|||
// autoFocus: false,
|
|||
// onFocus: () => {
|
|||
// done() // 触发回调,才能完成该测试
|
|||
// },
|
|||
// },
|
|||
// })
|
|||
// setTimeout(() => {
|
|||
// editor.focus()
|
|||
// }, 500)
|
|||
// })
|
|||
|
|||
// it('onBlur', done => {
|
|||
// const editor = createEditor({
|
|||
// config: {
|
|||
// onBlur: () => {
|
|||
// done() // 触发回调,才能完成该测试
|
|||
// },
|
|||
// },
|
|||
// })
|
|||
// setTimeout(() => {
|
|||
// console.log(111, document.activeElement)
|
|||
// editor.blur()
|
|||
// })
|
|||
// })
|
|||
}) |
@ -0,0 +1,25 @@ |
|||
/** |
|||
* @description menu config test |
|||
* @author wangfupeng |
|||
*/ |
|||
|
|||
import createEditor from '../../../../tests/utils/create-editor' |
|||
|
|||
describe('menu config', () => { |
|||
it('set and get', () => { |
|||
const menuKey = 'bold' // 必须是一个存在的 menu key
|
|||
const menuConfig = { |
|||
x: 100, |
|||
} |
|||
|
|||
const editor = createEditor({ |
|||
config: { |
|||
MENU_CONF: { |
|||
[menuKey]: menuConfig, |
|||
}, |
|||
}, |
|||
}) |
|||
|
|||
expect(editor.getMenuConfig(menuKey)).toEqual(menuConfig) |
|||
}) |
|||
}) |
@ -0,0 +1,52 @@ |
|||
/** |
|||
* @description toolbar config test |
|||
* @author wangfupeng |
|||
*/ |
|||
|
|||
import createEditor from '../../../../tests/utils/create-editor' |
|||
import createToolbar from '../../../../tests/utils/create-toolbar' |
|||
|
|||
describe('toolbar config', () => { |
|||
const editor = createEditor() |
|||
|
|||
it('default config', () => { |
|||
const toolbar = createToolbar(editor) |
|||
const defaultConfig = toolbar.getConfig() |
|||
const { excludeKeys = [], toolbarKeys = [] } = defaultConfig |
|||
expect(excludeKeys.length).toBe(0) |
|||
expect(toolbarKeys.length).toBeGreaterThan(0) |
|||
}) |
|||
|
|||
it('toolbarKeys', () => { |
|||
const keys = [ |
|||
'headerSelect', |
|||
'|', |
|||
'bold', |
|||
'color', |
|||
'insertImage', |
|||
'|', |
|||
{ |
|||
key: 'group-more-style', // 必填,要以 group 开头
|
|||
title: '更多样式', // 必填
|
|||
iconSvg: '<svg>....</svg>', // 可选
|
|||
menuKeys: ['through', 'code', 'clearStyle'], // 下级菜单 key ,必填
|
|||
}, |
|||
] |
|||
|
|||
const toolbar = createToolbar(editor, { |
|||
toolbarKeys: keys, |
|||
}) |
|||
|
|||
const { toolbarKeys = [] } = toolbar.getConfig() |
|||
expect(toolbarKeys).toEqual(keys) |
|||
}) |
|||
|
|||
it('excludeKeys', () => { |
|||
const keys = ['headerSelect', 'italic'] |
|||
const toolbar = createToolbar(editor, { |
|||
excludeKeys: keys, |
|||
}) |
|||
const { excludeKeys = [] } = toolbar.getConfig() |
|||
expect(excludeKeys).toEqual(keys) |
|||
}) |
|||
}) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue