라이브 미리보기 포커스 실행 분리
This commit is contained in:
144
tests/useAdminMarkdownPreviewFocus.test.js
Normal file
144
tests/useAdminMarkdownPreviewFocus.test.js
Normal file
@@ -0,0 +1,144 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
import { ref } from 'vue'
|
||||
import { useAdminMarkdownPreviewFocus } from '../composables/useAdminMarkdownPreviewFocus.js'
|
||||
|
||||
/**
|
||||
* 테스트용 source line DOM 대역을 만든다.
|
||||
* @param {Object} options - 줄 옵션
|
||||
* @returns {Object} 줄 DOM 대역
|
||||
*/
|
||||
const createSourceLineStub = (options) => {
|
||||
return {
|
||||
line: options.line,
|
||||
rect: options.rect,
|
||||
closest: (selector) => selector === '[data-source-line]' ? options.closestResult ?? null : null,
|
||||
getAttribute: (name) => name === 'data-source-line' ? String(options.line) : null,
|
||||
getBoundingClientRect: () => options.rect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트용 미리보기 표면 상태를 만든다.
|
||||
* @param {Object} options - 테스트 옵션
|
||||
* @returns {Object} 테스트 상태
|
||||
*/
|
||||
const createPreviewFocusState = (options = {}) => {
|
||||
const calls = {
|
||||
focusEditableAtLine: [],
|
||||
selectAllLiveDocument: 0
|
||||
}
|
||||
const sourceLines = options.sourceLines ?? []
|
||||
const surface = {
|
||||
scrollTop: options.scrollTop ?? 80,
|
||||
contains: (element) => options.containedElements?.includes(element) ?? false,
|
||||
querySelectorAll: (selector) => selector === '[data-source-line]' ? sourceLines : [],
|
||||
getBoundingClientRect: () => options.surfaceRect ?? {
|
||||
top: 10,
|
||||
bottom: 600,
|
||||
height: 590
|
||||
}
|
||||
}
|
||||
const previewSurfaceRef = ref({
|
||||
getPreviewElement: () => surface,
|
||||
getSourceLineElement: (sourceLine) => sourceLines.find((line) => line.line === sourceLine) ?? null,
|
||||
focusEditableAtLine: (...args) => {
|
||||
calls.focusEditableAtLine.push(args)
|
||||
},
|
||||
selectAllLiveDocument: () => {
|
||||
calls.selectAllLiveDocument += 1
|
||||
}
|
||||
})
|
||||
const focusState = useAdminMarkdownPreviewFocus({
|
||||
previewSurfaceRef,
|
||||
isClient: true,
|
||||
getActiveElement: () => options.activeElement ?? null
|
||||
})
|
||||
|
||||
return {
|
||||
calls,
|
||||
focusState,
|
||||
previewSurfaceRef,
|
||||
sourceLines,
|
||||
surface
|
||||
}
|
||||
}
|
||||
|
||||
test('미리보기 표면 함수 호출을 표면 컴포넌트로 위임한다', () => {
|
||||
const line = createSourceLineStub({
|
||||
line: 3,
|
||||
rect: { top: 40, bottom: 70, height: 30 }
|
||||
})
|
||||
const state = createPreviewFocusState({
|
||||
sourceLines: [line]
|
||||
})
|
||||
|
||||
assert.equal(state.focusState.getPreviewSurfaceElement(), state.surface)
|
||||
assert.equal(state.focusState.getPreviewSourceLineElement(3), line)
|
||||
|
||||
state.focusState.focusPreviewEditableAtLine(3, 0, 'start')
|
||||
state.focusState.selectAllPreviewDocument()
|
||||
|
||||
assert.deepEqual(state.calls.focusEditableAtLine, [[3, 0, 'start']])
|
||||
assert.equal(state.calls.selectAllLiveDocument, 1)
|
||||
})
|
||||
|
||||
test('미리보기 상단 스크롤을 0으로 되돌린다', () => {
|
||||
const state = createPreviewFocusState()
|
||||
|
||||
state.focusState.scrollPreviewToTop()
|
||||
|
||||
assert.equal(state.surface.scrollTop, 0)
|
||||
})
|
||||
|
||||
test('현재 포커스가 미리보기 줄 안에 있으면 해당 source line을 반환한다', () => {
|
||||
const focusedLine = createSourceLineStub({
|
||||
line: 7,
|
||||
rect: { top: 240, bottom: 270, height: 30 }
|
||||
})
|
||||
const activeElement = {
|
||||
closest: (selector) => selector === '[data-source-line]' ? focusedLine : null
|
||||
}
|
||||
const state = createPreviewFocusState({
|
||||
activeElement,
|
||||
containedElements: [activeElement],
|
||||
sourceLines: [focusedLine]
|
||||
})
|
||||
|
||||
assert.equal(state.focusState.getCurrentPreviewSourceLine(), 7)
|
||||
})
|
||||
|
||||
test('포커스 줄이 없으면 화면 상단 기준으로 가까운 source line을 반환한다', () => {
|
||||
const firstLine = createSourceLineStub({
|
||||
line: 1,
|
||||
rect: { top: 4, bottom: 20, height: 16 }
|
||||
})
|
||||
const secondLine = createSourceLineStub({
|
||||
line: 2,
|
||||
rect: { top: 40, bottom: 70, height: 30 }
|
||||
})
|
||||
const thirdLine = createSourceLineStub({
|
||||
line: 3,
|
||||
rect: { top: 120, bottom: 150, height: 30 }
|
||||
})
|
||||
const state = createPreviewFocusState({
|
||||
sourceLines: [thirdLine, firstLine, secondLine],
|
||||
surfaceRect: {
|
||||
top: 10,
|
||||
bottom: 500,
|
||||
height: 490
|
||||
}
|
||||
})
|
||||
|
||||
assert.equal(state.focusState.getCurrentPreviewSourceLine(), 2)
|
||||
})
|
||||
|
||||
test('클라이언트가 아니거나 표면이 없으면 현재 줄을 반환하지 않는다', () => {
|
||||
const previewSurfaceRef = ref(null)
|
||||
const focusState = useAdminMarkdownPreviewFocus({
|
||||
previewSurfaceRef,
|
||||
isClient: false
|
||||
})
|
||||
|
||||
assert.equal(focusState.getCurrentPreviewSourceLine(), null)
|
||||
})
|
||||
Reference in New Issue
Block a user