import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { RichTextEditor } from './rich-text-editor'; import { RICH_TEXT_EDITOR_CHANGE_EVENT, RICH_TEXT_EDITOR_COMMAND_EVENT, type RichTextEditorChangeEvent, type RichTextEditorCommandEvent, } from './rich-text-editor.types'; const MARKUP = `
Hi
' }); expect(editor.getHTML()).toBe('Hi
'); expect(content(root).hasAttribute('data-empty')).toBe(false); }); it('flags an empty editor with data-empty for the placeholder', () => { const root = setup(); new RichTextEditor(root); expect(content(root).hasAttribute('data-empty')).toBe(true); }); it('runs execCommand when a toolbar button is clicked', () => { const root = setup(); new RichTextEditor(root); button(root, 'bold').click(); expect(execSpy).toHaveBeenCalledWith('bold', false, undefined); }); it('prompts for a URL on createLink and passes it to execCommand', () => { const root = setup(); new RichTextEditor(root, { getLinkUrl: () => 'https://example.com' }); button(root, 'createLink').click(); expect(execSpy).toHaveBeenCalledWith('createLink', false, 'https://example.com'); }); it('cancels createLink when no URL is provided', () => { const root = setup(); new RichTextEditor(root, { getLinkUrl: () => null }); button(root, 'createLink').click(); expect(execSpy).not.toHaveBeenCalled(); }); it('reflects toggle command state on the buttons', () => { const root = setup(); stateSpy.mockImplementation((command: string) => command === 'bold'); const editor = new RichTextEditor(root); editor.format('bold'); expect(button(root, 'bold').getAttribute('aria-pressed')).toBe('true'); expect(button(root, 'bold').dataset.active).toBe('true'); expect(button(root, 'italic').getAttribute('aria-pressed')).toBe('false'); }); it('emits a command event then a change event on format()', () => { const root = setup(); const editor = new RichTextEditor(root); const onCommand = vi.fn(); const onChange = vi.fn(); editor.onnew
'); expect(editor.getHTML()).toBe('new
'); expect(onChange).toHaveBeenCalledOnce(); }); it('degrades gracefully when execCommand is unavailable', () => { const root = setup(); delete (document as unknown as { execCommand?: unknown }).execCommand; const editor = new RichTextEditor(root); expect(() => editor.format('bold')).not.toThrow(); }); it('removes listeners on destroy', () => { const root = setup(); const editor = new RichTextEditor(root); editor.destroy(); button(root, 'bold').click(); expect(execSpy).not.toHaveBeenCalled(); }); });