공개 본문 라이브 선택 상태 분리
This commit is contained in:
115
tests/useContentMarkdownLiveSelection.test.js
Normal file
115
tests/useContentMarkdownLiveSelection.test.js
Normal file
@@ -0,0 +1,115 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
import { nextTick, ref } from 'vue'
|
||||
import { useContentMarkdownLiveSelection } from '../composables/useContentMarkdownLiveSelection.js'
|
||||
|
||||
/**
|
||||
* 테스트용 라이브 선택 상태를 만든다.
|
||||
* @param {Object} calls - 콜백 기록 객체
|
||||
* @returns {{ content: import('vue').Ref<string>, state: Object }} 상태
|
||||
*/
|
||||
const createLiveSelectionState = (calls = {}) => {
|
||||
const content = ref('첫 줄\n둘째 줄')
|
||||
const state = useContentMarkdownLiveSelection({
|
||||
content,
|
||||
interactive: ref(true),
|
||||
onLineFocus: (line) => {
|
||||
calls.focus = line
|
||||
},
|
||||
onLineBlur: () => {
|
||||
calls.blur = true
|
||||
},
|
||||
onContentReplace: (payload) => {
|
||||
calls.replace = payload
|
||||
},
|
||||
provideBridge: false
|
||||
})
|
||||
|
||||
return { content, state }
|
||||
}
|
||||
|
||||
test('라이브 선택 상태는 자식 편집기 포커스 요청과 원문 모드 표시를 관리한다', () => {
|
||||
const calls = {}
|
||||
const { state } = createLiveSelectionState(calls)
|
||||
|
||||
state.onEditorFocusLine({ line: 3, position: 'end', offset: 2 })
|
||||
|
||||
assert.equal(state.pendingFocusLine.value, 3)
|
||||
assert.equal(state.pendingFocusPosition.value, 'end')
|
||||
assert.equal(state.pendingFocusOffset.value, 2)
|
||||
|
||||
state.onInlineRawMode({ sourceLine: 7, active: true })
|
||||
assert.equal(state.rawEditingSourceLines.value.has(7), true)
|
||||
|
||||
state.onInlineRawMode({ sourceLine: 7, active: false })
|
||||
assert.equal(state.rawEditingSourceLines.value.has(7), false)
|
||||
|
||||
state.emitEditorFocusedLine(5)
|
||||
assert.equal(calls.focus, 5)
|
||||
})
|
||||
|
||||
test('라이브 선택 상태는 본문 변경 후 예약된 포커스 값을 초기화한다', async () => {
|
||||
const { content, state } = createLiveSelectionState()
|
||||
|
||||
state.onEditorFocusLine({ line: 1, position: 'start' })
|
||||
content.value = '바뀐 줄'
|
||||
await nextTick()
|
||||
|
||||
assert.equal(state.pendingFocusLine.value, null)
|
||||
assert.equal(state.pendingFocusPosition.value, 'auto')
|
||||
assert.equal(state.pendingFocusOffset.value, null)
|
||||
})
|
||||
|
||||
test('라이브 줄 포커스와 블러 이벤트를 상위 콜백으로 전달한다', () => {
|
||||
class FakeElement {
|
||||
/**
|
||||
* @param {number} line - 원본 줄 번호
|
||||
*/
|
||||
constructor(line) {
|
||||
this.line = line
|
||||
}
|
||||
|
||||
/**
|
||||
* 가장 가까운 데이터 줄 요소를 반환한다.
|
||||
* @returns {FakeElement} 자기 자신
|
||||
*/
|
||||
closest() {
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 속성 값을 반환한다.
|
||||
* @param {string} name - 속성명
|
||||
* @returns {string|null} 속성 값
|
||||
*/
|
||||
getAttribute(name) {
|
||||
return name === 'data-source-line' ? String(this.line) : null
|
||||
}
|
||||
}
|
||||
|
||||
const previousElement = globalThis.Element
|
||||
const previousNode = globalThis.Node
|
||||
globalThis.Element = FakeElement
|
||||
globalThis.Node = FakeElement
|
||||
|
||||
try {
|
||||
const calls = {}
|
||||
const { state } = createLiveSelectionState(calls)
|
||||
const target = new FakeElement(4)
|
||||
|
||||
state.emitLiveLineFocus({ target })
|
||||
assert.equal(calls.focus, 4)
|
||||
|
||||
state.rendererRootRef.value = {
|
||||
contains: (node) => node === target
|
||||
}
|
||||
state.emitLiveLineBlur({ relatedTarget: target })
|
||||
assert.equal(calls.blur, undefined)
|
||||
|
||||
state.emitLiveLineBlur({ relatedTarget: new FakeElement(9) })
|
||||
assert.equal(calls.blur, true)
|
||||
} finally {
|
||||
globalThis.Element = previousElement
|
||||
globalThis.Node = previousNode
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user