166 lines
5.4 KiB
JavaScript
166 lines
5.4 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { describe, it } from 'node:test'
|
|
import { ref } from 'vue'
|
|
import { useAdminMarkdownMediaActions } from '../composables/useAdminMarkdownMediaActions.js'
|
|
|
|
/**
|
|
* 미디어 액션 테스트 상태를 만든다.
|
|
* @param {Object} [overrides] - 상태 재정의
|
|
* @returns {Object} 테스트 상태
|
|
*/
|
|
const createMediaActionHarness = (overrides = {}) => {
|
|
const value = ref(overrides.value ?? '본문')
|
|
const mediaPickerTarget = ref(overrides.target ?? 'image')
|
|
const liveSlashInsertLine = ref(overrides.liveSlashLine ?? null)
|
|
const isUploading = ref(overrides.isUploading ?? false)
|
|
const isMediaPickerOpen = ref(overrides.isMediaPickerOpen ?? false)
|
|
const activeMediaPickerTab = ref(overrides.activeMediaPickerTab ?? 'upload')
|
|
const calls = {
|
|
insertedBlocks: [],
|
|
activeGalleryImages: [],
|
|
closed: 0,
|
|
fetched: 0,
|
|
toasts: []
|
|
}
|
|
const selectedItems = ref(overrides.selectedItems ?? [])
|
|
const uploadedItems = ref(overrides.uploadedItems ?? [])
|
|
const modalUploadedItems = ref(overrides.modalUploadedItems ?? [])
|
|
|
|
const actions = useAdminMarkdownMediaActions({
|
|
value,
|
|
mediaPickerTarget,
|
|
liveSlashInsertLine,
|
|
isUploading,
|
|
isMediaPickerOpen,
|
|
activeMediaPickerTab,
|
|
resolveCurrentSelectedMediaItems: () => selectedItems.value,
|
|
uploadMediaFilesWithState: async () => uploadedItems.value,
|
|
uploadFilesIntoMediaPicker: async () => modalUploadedItems.value,
|
|
fetchMediaItems: async () => {
|
|
calls.fetched += 1
|
|
},
|
|
closeMediaPicker: () => {
|
|
calls.closed += 1
|
|
},
|
|
insertBlockSnippet: (snippet) => {
|
|
calls.insertedBlocks.push(snippet)
|
|
value.value = `${value.value}\n${snippet}`
|
|
},
|
|
appendImagesToActiveGallery: (images) => {
|
|
calls.activeGalleryImages.push(images)
|
|
},
|
|
showToast: (type, message) => {
|
|
calls.toasts.push({ type, message })
|
|
},
|
|
resolveUploadFetchErrorMessage: (error) => `업로드 오류: ${error.message}`
|
|
})
|
|
|
|
return {
|
|
value,
|
|
mediaPickerTarget,
|
|
liveSlashInsertLine,
|
|
isUploading,
|
|
isMediaPickerOpen,
|
|
activeMediaPickerTab,
|
|
selectedItems,
|
|
uploadedItems,
|
|
modalUploadedItems,
|
|
calls,
|
|
actions
|
|
}
|
|
}
|
|
|
|
describe('useAdminMarkdownMediaActions', () => {
|
|
it('일반 이미지와 갤러리를 블록 조각으로 삽입한다', () => {
|
|
const imageHarness = createMediaActionHarness({
|
|
selectedItems: [{ url: '/uploads/a.png' }]
|
|
})
|
|
|
|
imageHarness.actions.applyMediaSelection()
|
|
|
|
assert.deepEqual(imageHarness.calls.insertedBlocks, [''])
|
|
assert.equal(imageHarness.calls.closed, 1)
|
|
|
|
const galleryHarness = createMediaActionHarness({
|
|
target: 'gallery',
|
|
selectedItems: [{ url: '/uploads/a.png' }, { url: '/uploads/b.png' }]
|
|
})
|
|
|
|
galleryHarness.actions.applyMediaSelection()
|
|
|
|
assert.deepEqual(galleryHarness.calls.insertedBlocks, [
|
|
[':::gallery', '', '', ':::'].join('\n')
|
|
])
|
|
})
|
|
|
|
it('활성 갤러리 대상은 블록 삽입 대신 갤러리 추가 콜백을 호출한다', () => {
|
|
const harness = createMediaActionHarness({
|
|
target: 'active-gallery',
|
|
selectedItems: [{ url: '/uploads/a.png' }, { url: '/uploads/b.png' }]
|
|
})
|
|
|
|
harness.actions.applyMediaSelection()
|
|
|
|
assert.equal(harness.calls.insertedBlocks.length, 0)
|
|
assert.deepEqual(harness.calls.activeGalleryImages, [[
|
|
{ url: '/uploads/a.png', useAlt: false, caption: '' },
|
|
{ url: '/uploads/b.png', useAlt: false, caption: '' }
|
|
]])
|
|
})
|
|
|
|
it('슬래시 미디어 대기 줄에는 해당 줄 위치로 삽입하고 대기 상태를 초기화한다', () => {
|
|
const harness = createMediaActionHarness({
|
|
value: '첫 줄\n/image\n마지막 줄',
|
|
target: 'image',
|
|
liveSlashLine: 1,
|
|
selectedItems: [{ url: '/uploads/a.png' }]
|
|
})
|
|
|
|
harness.actions.applyMediaSelection()
|
|
|
|
assert.equal(harness.value.value, '첫 줄\n\n마지막 줄')
|
|
assert.equal(harness.liveSlashInsertLine.value, null)
|
|
})
|
|
|
|
it('커서 업로드 삽입 후 라이브러리 탭이 열려 있으면 목록을 갱신한다', async () => {
|
|
const harness = createMediaActionHarness({
|
|
target: 'image',
|
|
uploadedItems: [{ url: '/uploads/a.png' }],
|
|
isMediaPickerOpen: true,
|
|
activeMediaPickerTab: 'library'
|
|
})
|
|
|
|
await harness.actions.uploadAndInsert([{ name: 'a.png' }], 'image')
|
|
|
|
assert.deepEqual(harness.calls.insertedBlocks, [''])
|
|
assert.equal(harness.calls.fetched, 1)
|
|
})
|
|
|
|
it('업로드 중이면 삽입과 모달 업로드를 실행하지 않는다', async () => {
|
|
const harness = createMediaActionHarness({
|
|
isUploading: true,
|
|
uploadedItems: [{ url: '/uploads/a.png' }],
|
|
modalUploadedItems: [{ url: '/uploads/b.png' }]
|
|
})
|
|
|
|
await harness.actions.uploadAndInsert([{ name: 'a.png' }], 'image')
|
|
await harness.actions.uploadFromMediaModal([{ name: 'b.png' }])
|
|
|
|
assert.equal(harness.calls.insertedBlocks.length, 0)
|
|
assert.equal(harness.calls.toasts.length, 0)
|
|
})
|
|
|
|
it('미디어 모달 업로드 성공 시 완료 토스트를 표시한다', async () => {
|
|
const harness = createMediaActionHarness({
|
|
modalUploadedItems: [{ url: '/uploads/a.png' }]
|
|
})
|
|
|
|
await harness.actions.uploadFromMediaModal([{ name: 'a.png' }])
|
|
|
|
assert.deepEqual(harness.calls.toasts, [{
|
|
type: 'success',
|
|
message: '업로드가 완료되어 파일이 선택되었습니다.'
|
|
}])
|
|
})
|
|
})
|