diff --git a/packages/basic-modules/__tests__/format-painter/format-painter-menu.test.ts b/packages/basic-modules/__tests__/format-painter/format-painter-menu.test.ts new file mode 100644 index 000000000..c960879d1 --- /dev/null +++ b/packages/basic-modules/__tests__/format-painter/format-painter-menu.test.ts @@ -0,0 +1,108 @@ +/** + * @description format painter menu test + * @author CodePencil + */ + +import { Editor } from 'slate' +import createEditor from '../../../../tests/utils/create-editor' +import FormatPainter from '../../src/modules/format-painter/menu/FormatPainter' + +describe('format painter menu', () => { + let editor: any + let menu: any + + beforeEach(() => { + editor = createEditor() + menu = new FormatPainter() + }) + + afterEach(() => { + editor = null + menu = null + FormatPainter.attrs.isSelect = false + FormatPainter.attrs.formatStyle = null + }) + + it('get value', () => { + expect(menu.getValue(editor)).toBe('') + }) + + it('is active', () => { + expect(menu.isActive(editor)).toBe(FormatPainter.attrs.isSelect) + }) + + it('is disabled', () => { + expect(menu.isDisabled(editor)).toBeFalsy() + }) + + it('set format html', () => { + editor.focus() + editor.insertText('Hello World') + + // 选中文本 + editor.select({ + anchor: { path: [0, 0], offset: 0 }, + focus: { path: [0, 0], offset: 5 }, + }) + + editor.addMark('bold', true) + editor.addMark('italic', true) + + // 选中有样式的文本后启用格式刷 + menu.exec(editor) + expect(FormatPainter.attrs.isSelect).toBeTruthy() + + // 启用了格式刷但是未选中文本 + editor.deselect() + menu.setFormatHtml(editor) + expect(FormatPainter.attrs.isSelect).toBeTruthy() + expect(FormatPainter.attrs.formatStyle).toEqual({ bold: true, italic: true }) + + // 启用了格式刷并选中文本 + editor.select({ + anchor: { path: [0, 0], offset: 0 }, + focus: { path: [0, 0], offset: 5 }, + }) + menu.setFormatHtml(editor) + expect(Editor.marks(editor)).toEqual({ bold: true, italic: true }) + expect(FormatPainter.attrs.isSelect).toBeFalsy() + expect(FormatPainter.attrs.formatStyle).toBeNull() + }) + + it('exec', () => { + editor.focus() + + editor.insertText('Hello World') + + // 取消选中文本 + editor.deselect() + menu.exec(editor) + expect(FormatPainter.attrs.isSelect).toBeFalsy() + expect(FormatPainter.attrs.formatStyle).toBeNull() + + // 选中文本 + editor.select({ + anchor: { path: [0, 0], offset: 0 }, + focus: { path: [0, 0], offset: 5 }, + }) + + menu.exec(editor) // 启用格式刷 + expect(FormatPainter.attrs.isSelect).toBeTruthy() + + menu.exec(editor) // 取消格式刷 + expect(FormatPainter.attrs.isSelect).toBeFalsy() + + // 选中文本 + editor.select({ + anchor: { path: [0, 0], offset: 0 }, + focus: { path: [0, 0], offset: 5 }, + }) + + // 选中有样式的文本后启用格式刷 + editor.addMark('bold', true) + editor.addMark('italic', true) + + menu.exec(editor) + expect(FormatPainter.attrs.formatStyle).toEqual({ bold: true, italic: true }) + }) +}) diff --git a/packages/basic-modules/__tests__/format-painter/helper.test.ts b/packages/basic-modules/__tests__/format-painter/helper.test.ts new file mode 100644 index 000000000..1d2bb3652 --- /dev/null +++ b/packages/basic-modules/__tests__/format-painter/helper.test.ts @@ -0,0 +1,36 @@ +/** + * @description format painter helper test + * @author CodePencil + */ + +import { Editor } from 'slate' +import createEditor from '../../../../tests/utils/create-editor' +import { clearAllMarks } from '../../src/modules/format-painter/helper' + +describe('format painter helper', () => { + let editor: any + let startLocation: any + + beforeEach(() => { + editor = createEditor() + startLocation = Editor.start(editor, []) + }) + + afterEach(() => { + editor = null + startLocation = null + }) + + it('clear all marks ', () => { + editor.select(startLocation) + + editor.addMark('bold', true) + editor.addMark('italic', true) + + expect(Editor.marks(editor)).toEqual({ bold: true, italic: true }) + + clearAllMarks(editor) + + expect(Editor.marks(editor)).toEqual({}) + }) +}) diff --git a/packages/basic-modules/__tests__/format-painter/plugin.test.ts b/packages/basic-modules/__tests__/format-painter/plugin.test.ts new file mode 100644 index 000000000..57968491b --- /dev/null +++ b/packages/basic-modules/__tests__/format-painter/plugin.test.ts @@ -0,0 +1,53 @@ +import createEditor from '../../../../tests/utils/create-editor' +import withFormatPainter from '../../src/modules/format-painter/plugin' +import FormatPainter from '../../src/modules/format-painter/menu/FormatPainter' + +describe('format painter plugin', () => { + let editor: any + + beforeEach(() => { + editor = withFormatPainter(createEditor()) + + jest.spyOn(document, 'addEventListener') + jest.spyOn(document, 'removeEventListener') + + editor.focus() + editor.insertText('Hello World') + editor.select({ + anchor: { path: [0, 0], offset: 0 }, + focus: { path: [0, 0], offset: 5 }, + }) + }) + + afterEach(() => { + jest.clearAllMocks() + }) + + it('format painter change', () => { + // 模拟 FormatPainter 处于活动状态 + FormatPainter.attrs.isSelect = true + + // 监控静态方法 setFormatHtml + const setFormatHtmlSpy = jest.spyOn(FormatPainter.prototype, 'setFormatHtml') + + // 模拟 onChange 的调用 + editor.onChange() + + // 检查是否绑定了 mouseup 事件 + expect(document.addEventListener).toHaveBeenCalledWith('mouseup', expect.any(Function)) + + // 创建并触发 mouseup 事件 + const mouseUpEvent = new MouseEvent('mouseup', { + bubbles: true, + cancelable: true, + }) + + document.dispatchEvent(mouseUpEvent) + + // 验证 setFormatHtml 是否被调用 + expect(setFormatHtmlSpy).toHaveBeenCalledWith(editor) + + // 检查是否解绑了 mouseup 事件 + expect(document.removeEventListener).toHaveBeenCalledWith('mouseup', expect.any(Function)) + }) +}) diff --git a/packages/basic-modules/src/modules/format-painter/menu/FormatPainter.ts b/packages/basic-modules/src/modules/format-painter/menu/FormatPainter.ts index 041820876..ace40193c 100644 --- a/packages/basic-modules/src/modules/format-painter/menu/FormatPainter.ts +++ b/packages/basic-modules/src/modules/format-painter/menu/FormatPainter.ts @@ -35,24 +35,27 @@ class FormatPainter implements IButtonMenu { } setFormatHtml(editor: IDomEditor) { - if (!editor.getSelectionText().length) return + const selectionText = editor.getSelectionText() + if (!selectionText.length) return if (FormatPainter.attrs.formatStyle) { clearAllMarks(editor) for (const [key, value] of Object.entries(FormatPainter.attrs.formatStyle)) { editor.addMark(key, value) } } - FormatPainter.attrs.formatStyle = {} + FormatPainter.attrs.formatStyle = null FormatPainter.attrs.isSelect = false } - exec(editor: IDomEditor, value: string | boolean) { + exec(editor: IDomEditor) { // 如果已经选中了格式刷则取消选中,反之保存已经选中文本的样式 if (FormatPainter.attrs.isSelect) { FormatPainter.attrs.isSelect = false + FormatPainter.attrs.formatStyle = null } else { + const selectionText = editor.getSelectionText() // 判断是否选中文本 - if (editor.getSelectionText().length) { + if (selectionText.length) { FormatPainter.attrs.formatStyle = Editor.marks(editor) FormatPainter.attrs.isSelect = true }