diff --git a/docs/plans/2026-03-19-fix-source-cursor-offset.md b/docs/plans/2026-03-19-fix-source-cursor-offset.md index a81730bd..a35faeb5 100644 --- a/docs/plans/2026-03-19-fix-source-cursor-offset.md +++ b/docs/plans/2026-03-19-fix-source-cursor-offset.md @@ -480,10 +480,10 @@ Append to the end of `src/editor/__tests__/FormattingToolbar.test.tsx` (after li * Element-type selections occur when cursor is at structural boundaries (empty lines, etc). */ function InsertMultilineAndSelectElement({ - children, + structure, elementOffset }: { - children: Array<{ type: 'text'; content: string } | { type: 'linebreak' }> + structure: Array<{ type: 'text'; content: string } | { type: 'linebreak' }> elementOffset: number // Child index for element-type selection }) { const [editor] = useLexicalComposerContext() @@ -493,9 +493,9 @@ function InsertMultilineAndSelectElement({ root.clear() const codeNode = $createCodeNode('markdown') - for (const child of children) { - if (child.type === 'text') { - codeNode.append($createTextNode(child.content)) + for (const node of structure) { + if (node.type === 'text') { + codeNode.append($createTextNode(node.content)) } else { codeNode.append($createLineBreakNode()) } @@ -508,18 +508,18 @@ function InsertMultilineAndSelectElement({ selection.focus.set(codeNode.getKey(), elementOffset, 'element') $setSelection(selection) }) - }, [editor, children, elementOffset]) + }, [editor, structure, elementOffset]) return null } interface TestElementSelectionEditorProps { - children: Array<{ type: 'text'; content: string } | { type: 'linebreak' }> + structure: Array<{ type: 'text'; content: string } | { type: 'linebreak' }> elementOffset: number onEditorReady?: (editor: LexicalEditor) => void } function TestElementSelectionEditor({ - children, + structure, elementOffset, onEditorReady }: TestElementSelectionEditorProps) { @@ -540,7 +540,7 @@ function TestElementSelectionEditor({ @@ -554,16 +554,17 @@ describe('FormattingToolbar element-type selection bug fix', () => { cleanup() }) - it('inserts bold at element-type selection on empty line', async () => { + it('inserts bold at element-type selection at start of line after empty line', async () => { const user = userEvent.setup() let testEditor: LexicalEditor | null = null - // Structure: "line1\n\nline3" with element selection at empty line position + // Structure: "line1\n\nline3" // Children: [text:"line1"(5), lb(1), lb(1), text:"line3"(5)] - // Element offset 3 = after children[0..2] = 5+1+1 = position 7 (start of empty line visually) + // Element offset 3 = after children[0..2] = 5+1+1 = position 7 (start of line3) + // This is the position where cursor lands after pressing down-arrow from line1 render( { }) }) + it('inserts bold at element-type selection ON empty line', async () => { + const user = userEvent.setup() + let testEditor: LexicalEditor | null = null + + // Structure: "line1\n\nline3" + // Children: [text:"line1"(5), lb(1), lb(1), text:"line3"(5)] + // Element offset 2 = after children[0..1] = 5+1 = position 6 (on the empty line) + // This is the position where cursor lands when clicking on the empty line + render( + { testEditor = e }} + /> + ) + + await user.click(screen.getByRole('button', { name: 'Bold' })) + + await vi.waitFor(() => { + testEditor?.getEditorState().read(() => { + const root = $getRoot() + const text = root.getTextContent() + // Bold markers should be at position 6 (on empty line) + expect(text).toBe('line1\n****\nline3') + }) + }) + }) + it('inserts bold at element-type selection at document start', async () => { const user = userEvent.setup() let testEditor: LexicalEditor | null = null @@ -593,7 +627,7 @@ describe('FormattingToolbar element-type selection bug fix', () => { // Element selection at offset 0 (before first child) render( { // Element selection at offset 1 (after first/only child) = position 5 render( { // Element selection at offset 2 = after lb, before "line2" = position 6 render( { }) }) - it('inserts link at element-type selection on empty line', async () => { + it('inserts link at element-type selection between lines', async () => { const user = userEvent.setup() let testEditor: LexicalEditor | null = null - // Structure: "line1\n\nline3" with element selection at empty line position + // Structure: "line1\n\nline3" with element selection at start of line3 // Children: [text:"line1"(5), lb(1), lb(1), text:"line3"(5)] // Element offset 3 = after children[0..2] = 5+1+1 = position 7 render(