145 lines
4.2 KiB
JavaScript
145 lines
4.2 KiB
JavaScript
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)
|
|
})
|