Files
sori.studio/tests/useContentMarkdownLiveSelection.test.js

116 lines
3.3 KiB
JavaScript

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
}
})