155 lines
4.1 KiB
JavaScript
155 lines
4.1 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
import { effectScope, nextTick, ref } from 'vue'
|
|
import { useAdminMarkdownBlockPanel } from '../composables/useAdminMarkdownBlockPanel.js'
|
|
|
|
globalThis.window ??= {
|
|
setTimeout,
|
|
clearTimeout
|
|
}
|
|
|
|
/**
|
|
* 테스트용 블록 패널 상태를 만든다.
|
|
* @param {Object} options - 테스트 옵션
|
|
* @returns {Object} 테스트 상태
|
|
*/
|
|
const createBlockPanelState = (options = {}) => {
|
|
const scope = effectScope()
|
|
const activeMode = ref(options.activeMode ?? 'write')
|
|
const value = ref(options.value ?? '')
|
|
const writeModeContextValue = ref(null)
|
|
const activeLogicalLineIndex = ref(options.activeLogicalLineIndex ?? 0)
|
|
const isMediaPickerOpen = ref(false)
|
|
const currentBlock = ref(options.block ?? {
|
|
kind: 'image',
|
|
startLine: 0,
|
|
endLine: 0
|
|
})
|
|
const inlineContext = ref(null)
|
|
const emitted = []
|
|
let panel
|
|
|
|
scope.run(() => {
|
|
panel = useAdminMarkdownBlockPanel({
|
|
activeMode,
|
|
value,
|
|
writeModeContextValue,
|
|
activeLogicalLineIndex,
|
|
isMediaPickerOpen,
|
|
resolveBlockContext: () => currentBlock.value,
|
|
getInlineColorSelectionContext: () => inlineContext.value,
|
|
emitBlockPanel: (payload) => {
|
|
emitted.push(payload)
|
|
}
|
|
})
|
|
})
|
|
|
|
return {
|
|
activeLogicalLineIndex,
|
|
currentBlock,
|
|
emitted,
|
|
inlineContext,
|
|
isMediaPickerOpen,
|
|
panel,
|
|
stop: () => scope.stop()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 패널 watch와 내부 nextTick을 비운다.
|
|
* @returns {Promise<void>}
|
|
*/
|
|
const flushBlockPanelTicks = async () => {
|
|
await nextTick()
|
|
await nextTick()
|
|
}
|
|
|
|
test('textarea 포커스가 있으면 활성 블록 패널을 연다', () => {
|
|
const state = createBlockPanelState()
|
|
|
|
state.panel.handleTextareaFocusIn()
|
|
state.panel.syncBlockPanelState()
|
|
|
|
assert.equal(state.panel.isBlockPanelVisible.value, true)
|
|
assert.deepEqual(state.emitted.at(-1), {
|
|
open: true,
|
|
panel: {
|
|
kind: 'image',
|
|
startLine: 0,
|
|
endLine: 0
|
|
}
|
|
})
|
|
state.stop()
|
|
})
|
|
|
|
test('인라인 색상 선택 컨텍스트는 일반 블록보다 우선 표시된다', () => {
|
|
const state = createBlockPanelState()
|
|
|
|
state.inlineContext.value = {
|
|
kind: 'inline-color',
|
|
mode: 'source',
|
|
start: 0,
|
|
end: 2,
|
|
text: '색상'
|
|
}
|
|
state.panel.syncInlineColorSelectionContext()
|
|
state.panel.syncBlockPanelState()
|
|
|
|
assert.equal(state.panel.isBlockPanelEngaged.value, true)
|
|
assert.equal(state.panel.activePanelContext.value.kind, 'inline-color')
|
|
assert.deepEqual(state.emitted.at(-1).panel, state.inlineContext.value)
|
|
state.stop()
|
|
})
|
|
|
|
test('IME 조합 중 활성 블록이 잠시 비어도 직전 블록 패널을 유지한다', async () => {
|
|
const state = createBlockPanelState()
|
|
|
|
state.panel.handleTextareaFocusIn()
|
|
state.panel.handleTextareaCompositionStart()
|
|
state.currentBlock.value = null
|
|
state.activeLogicalLineIndex.value = 0
|
|
await flushBlockPanelTicks()
|
|
|
|
assert.equal(state.panel.activePanelContext.value.kind, 'image')
|
|
state.stop()
|
|
})
|
|
|
|
test('라이브 줄 포커스는 해당 줄 블록 패널을 편집 중 상태로 연다', async () => {
|
|
const state = createBlockPanelState({
|
|
activeMode: 'preview',
|
|
block: {
|
|
kind: 'callout',
|
|
startLine: 2,
|
|
endLine: 4
|
|
}
|
|
})
|
|
|
|
await state.panel.handleLiveLineFocus(3)
|
|
await flushBlockPanelTicks()
|
|
|
|
assert.equal(state.activeLogicalLineIndex.value, 3)
|
|
assert.equal(state.panel.isBlockPanelEngaged.value, true)
|
|
assert.equal(state.panel.activePanelContext.value.kind, 'callout')
|
|
assert.equal(state.emitted.at(-1).open, true)
|
|
state.stop()
|
|
})
|
|
|
|
test('패널 닫기는 편집 상태와 인라인 색상 컨텍스트를 초기화한다', () => {
|
|
const state = createBlockPanelState()
|
|
|
|
state.inlineContext.value = {
|
|
kind: 'inline-color',
|
|
mode: 'source',
|
|
start: 0,
|
|
end: 2,
|
|
text: '색상'
|
|
}
|
|
state.panel.syncInlineColorSelectionContext()
|
|
state.panel.closeBlockPanel()
|
|
|
|
assert.equal(state.panel.isBlockPanelEngaged.value, false)
|
|
assert.equal(state.panel.inlineColorSelectionContext.value, null)
|
|
assert.equal(state.emitted.at(-1).open, false)
|
|
state.stop()
|
|
})
|