fix(components): [mention] correct cursor position (#22070)

* fix(components): [mention] correct cursor position

* test: add test

* fix: use wrapper as a reference
This commit is contained in:
Zhong
2025-09-08 18:30:05 +08:00
committed by GitHub
parent 4a702344e9
commit 4845caab13
2 changed files with 73 additions and 3 deletions

View File

@@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils'
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
import Form from '@element-plus/components/form'
import Mention from '../src/mention.vue'
import * as helper from '../src/helper'
describe('Mention.vue', () => {
beforeEach(() => {
@@ -146,4 +147,73 @@ describe('Mention.vue', () => {
expect(option.attributes('aria-disabled')).toBe('true')
expect(option.classes()).toContain('is-disabled')
})
test('should ensure the cursor position is correct', async () => {
vi.spyOn(helper, 'getCursorPosition').mockReturnValue({
top: 7,
left: 14,
height: 21,
})
const wrapper = mount(Mention, {
attachTo: document.body,
props: { options, style: { marginTop: '100px', marginLeft: '100px' } },
})
const elInputEl = wrapper.find('.el-input').element
const inputEl = wrapper.find('input').element
const mockBoundingClientRect = (
el: Element,
rect: Partial<DOMRect> = {}
) => {
const defaultRect: DOMRect = {
x: 0,
y: 0,
width: 100,
height: 100,
top: 0,
left: 0,
bottom: 0,
right: 0,
toJSON: () => {},
}
return vi
.spyOn(el, 'getBoundingClientRect')
.mockReturnValue(Object.assign(defaultRect, rect))
}
// Actual information obtained on the browser
mockBoundingClientRect(elInputEl, {
width: 320,
height: 32,
left: 100,
x: 100,
top: 100,
y: 100,
})
mockBoundingClientRect(inputEl, {
width: 298,
height: 30,
left: 111,
x: 111,
top: 101,
y: 101,
})
inputEl.focus()
await wrapper.find('input').setValue('@')
vi.advanceTimersByTime(150)
await nextTick()
const cursorStyles = wrapper
.find('.el-tooltip__trigger')
.attributes('style')
expect(cursorStyles).toContain('left: 125px')
expect(cursorStyles).toContain('top: 108px')
vi.restoreAllMocks()
})
})

View File

@@ -259,14 +259,14 @@ const syncCursor = () => {
const caretPosition = getCursorPosition(inputEl)
const inputRect = inputEl.getBoundingClientRect()
const elInputRect = elInputRef.value!.$el.getBoundingClientRect()
const wrapperRect = wrapperRef.value!.getBoundingClientRect()
cursorStyle.value = {
position: 'absolute',
width: 0,
height: `${caretPosition.height}px`,
left: `${caretPosition.left + inputRect.left - elInputRect.left}px`,
top: `${caretPosition.top + inputRect.top - elInputRect.top}px`,
left: `${caretPosition.left + inputRect.left - wrapperRect.left}px`,
top: `${caretPosition.top + inputRect.top - wrapperRect.top}px`,
}
}