172 lines
4.6 KiB
JavaScript
172 lines
4.6 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
import { nextTick, ref } from 'vue'
|
|
import { useAdminMarkdownPreviewActions } from '../composables/useAdminMarkdownPreviewActions.js'
|
|
|
|
/**
|
|
* 테스트용 미리보기 액션 상태를 만든다.
|
|
* @param {Object} options - 테스트 옵션
|
|
* @returns {Object} 테스트 상태
|
|
*/
|
|
const createPreviewActionsState = (options = {}) => {
|
|
const calls = {
|
|
focusPreview: [],
|
|
resetBlockPanel: 0,
|
|
replacedRanges: []
|
|
}
|
|
const value = ref(options.value ?? [
|
|
':::gallery',
|
|
'',
|
|
'',
|
|
':::',
|
|
'아래'
|
|
].join('\n'))
|
|
const activeLogicalLineIndex = ref(options.activeLogicalLineIndex ?? 0)
|
|
const liveSlashInsertLine = ref(options.liveSlashInsertLine ?? null)
|
|
const actions = useAdminMarkdownPreviewActions({
|
|
value,
|
|
activeLogicalLineIndex,
|
|
liveSlashInsertLine,
|
|
replaceLineRange: (startLine, endLine, replacementLines, focusEditor = false) => {
|
|
calls.replacedRanges.push({ startLine, endLine, replacementLines, focusEditor })
|
|
const lines = String(value.value || '').split('\n')
|
|
lines.splice(startLine, endLine - startLine + 1, ...replacementLines)
|
|
value.value = lines.join('\n')
|
|
},
|
|
resolveCurrentFencedBlockEndLine: (startLine, fallbackEndLine) => {
|
|
return options.resolveCurrentFencedBlockEndLine?.(startLine, fallbackEndLine) ?? fallbackEndLine
|
|
},
|
|
resetBlockPanelContext: () => {
|
|
calls.resetBlockPanel += 1
|
|
},
|
|
focusPreviewEditableAtLine: (...args) => {
|
|
calls.focusPreview.push(args)
|
|
}
|
|
})
|
|
|
|
return {
|
|
actions,
|
|
activeLogicalLineIndex,
|
|
calls,
|
|
liveSlashInsertLine,
|
|
value
|
|
}
|
|
}
|
|
|
|
test('갤러리 순서 변경 payload를 Markdown 값에 반영한다', () => {
|
|
const state = createPreviewActionsState()
|
|
|
|
state.actions.onPreviewGalleryReorder({
|
|
startLine: 0,
|
|
endLine: 3,
|
|
images: [
|
|
{ url: '/b.png' },
|
|
{ url: '/a.png' }
|
|
]
|
|
})
|
|
|
|
assert.equal(state.value.value, [
|
|
':::gallery',
|
|
'',
|
|
'',
|
|
':::',
|
|
'아래'
|
|
].join('\n'))
|
|
})
|
|
|
|
test('갤러리 이미지 삭제 후 활성 줄을 삭제 결과 기준으로 갱신한다', () => {
|
|
const state = createPreviewActionsState()
|
|
|
|
state.actions.onPreviewRemoveGalleryImage({
|
|
startLine: 0,
|
|
endLine: 3,
|
|
imageIndex: 1
|
|
})
|
|
|
|
assert.equal(state.value.value, [
|
|
'',
|
|
'아래'
|
|
].join('\n'))
|
|
assert.equal(state.activeLogicalLineIndex.value, 0)
|
|
})
|
|
|
|
test('미디어 슬래시 삽입 대기 줄의 지연 commit은 무시한다', () => {
|
|
const state = createPreviewActionsState({
|
|
value: '',
|
|
liveSlashInsertLine: 2
|
|
})
|
|
|
|
state.actions.onPreviewBlockContentChange({
|
|
startLine: 2,
|
|
endLine: 2,
|
|
replacementLines: ['/image']
|
|
})
|
|
|
|
assert.equal(state.value.value, '')
|
|
assert.deepEqual(state.calls.replacedRanges, [])
|
|
})
|
|
|
|
test('미리보기 블록 본문 변경은 fenced 닫는 줄 보정 후 줄 범위를 교체한다', () => {
|
|
const state = createPreviewActionsState({
|
|
value: [
|
|
':::callout',
|
|
'기존',
|
|
':::',
|
|
'아래'
|
|
].join('\n'),
|
|
resolveCurrentFencedBlockEndLine: () => 2
|
|
})
|
|
|
|
state.actions.onPreviewBlockContentChange({
|
|
startLine: 0,
|
|
endLine: 0,
|
|
replacementLines: [':::callout title=수정', '변경', ':::']
|
|
})
|
|
|
|
assert.equal(state.value.value, [
|
|
':::callout title=수정',
|
|
'변경',
|
|
':::',
|
|
'아래'
|
|
].join('\n'))
|
|
assert.deepEqual(state.calls.replacedRanges, [{
|
|
startLine: 0,
|
|
endLine: 2,
|
|
replacementLines: [':::callout title=수정', '변경', ':::'],
|
|
focusEditor: false
|
|
}])
|
|
})
|
|
|
|
test('지정 줄 삽입 후 블록 패널 컨텍스트를 초기화하고 미리보기 포커스를 예약한다', async () => {
|
|
const state = createPreviewActionsState({
|
|
value: '첫 줄'
|
|
})
|
|
|
|
state.actions.onPreviewInsertAfterLine({
|
|
afterLine: 0,
|
|
lines: ['둘째 줄'],
|
|
focusLine: 1
|
|
})
|
|
await nextTick()
|
|
|
|
assert.equal(state.value.value, '첫 줄\n둘째 줄')
|
|
assert.equal(state.activeLogicalLineIndex.value, 1)
|
|
assert.equal(state.calls.resetBlockPanel, 1)
|
|
assert.deepEqual(state.calls.focusPreview, [[1, 0, 'start']])
|
|
})
|
|
|
|
test('줄 삭제와 이전 줄 병합 결과를 본문에 반영한다', () => {
|
|
const state = createPreviewActionsState({
|
|
value: ['첫 줄', '둘째 줄', '셋째 줄'].join('\n')
|
|
})
|
|
|
|
state.actions.onPreviewDeleteLine(1)
|
|
assert.equal(state.value.value, '첫 줄\n셋째 줄')
|
|
|
|
state.actions.onPreviewMergeWithPreviousLine({
|
|
lineIndex: 1,
|
|
mergedLine: '첫 줄셋째 줄'
|
|
})
|
|
assert.equal(state.value.value, '첫 줄셋째 줄')
|
|
})
|