106 lines
3.1 KiB
TypeScript
106 lines
3.1 KiB
TypeScript
import { flushPromises } from '@vue/test-utils'
|
|
import type { MediaItem } from '@/composables/useMedia'
|
|
import { imageOfItem, type MediaSummary } from '@/lib/mediaField'
|
|
import {
|
|
answerWrite,
|
|
entry42,
|
|
fieldWrapper,
|
|
lookupNames,
|
|
mountEditor,
|
|
text,
|
|
} from './entryEditorKit'
|
|
import { fieldLibrary } from './mediaFieldKit'
|
|
import { eventsWithThumbnail } from './schemaTestKit'
|
|
import type { EntryWrite, SchemaMount } from './schemaTestKit'
|
|
|
|
export const LIBRARY_COUNTS = { all: 48, unused: 2, duplicates: 2 }
|
|
|
|
export function libraryBody(items: MediaItem[] = fieldLibrary()) {
|
|
return { items, total: 48, page: 1, size: 25, counts: LIBRARY_COUNTS }
|
|
}
|
|
|
|
export function summaryOf(id: number): MediaSummary {
|
|
const item = fieldLibrary().find((candidate) => candidate.id === id)!
|
|
return imageOfItem(item)
|
|
}
|
|
|
|
export function entryWithThumbnail(thumbnail: number | null, media?: MediaSummary | 'none') {
|
|
const shown =
|
|
media === 'none' || thumbnail === null ? undefined : (media ?? summaryOf(thumbnail))
|
|
return {
|
|
...entry42,
|
|
data: { ...entry42.data, thumbnail },
|
|
...(shown ? { media: { thumbnail: shown } } : {}),
|
|
}
|
|
}
|
|
|
|
export function answerMediaWrite(write: EntryWrite) {
|
|
const answered = answerWrite(write)
|
|
const id = (write.body.data as Record<string, unknown>).thumbnail
|
|
return typeof id === 'number' ? { ...answered, media: { thumbnail: summaryOf(id) } } : answered
|
|
}
|
|
|
|
export function mountMedia(
|
|
path: string,
|
|
options: SchemaMount & {
|
|
required?: boolean
|
|
thumbnail?: number | null
|
|
media?: MediaSummary | 'none'
|
|
} = {},
|
|
) {
|
|
const { required, thumbnail = null, media, ...rest } = options
|
|
const type = eventsWithThumbnail({ required: required ?? false })
|
|
return mountEditor(path, {
|
|
type: () => type,
|
|
content: () => [type],
|
|
entry: () => entryWithThumbnail(thumbnail, media),
|
|
writeEntry: answerMediaWrite,
|
|
library: () => libraryBody(),
|
|
lookup: lookupNames,
|
|
...rest,
|
|
})
|
|
}
|
|
|
|
export function mediaControl() {
|
|
return fieldWrapper('thumbnail').querySelector<HTMLElement>('[data-testid="media-control"]')!
|
|
}
|
|
|
|
export function mediaState() {
|
|
const box = mediaControl()
|
|
if (box.querySelector('[data-testid="media-empty"]')) {
|
|
return 'empty'
|
|
}
|
|
return box.querySelector('[data-testid="media-filled"]') ? 'filled' : 'missing'
|
|
}
|
|
|
|
export function mediaText() {
|
|
return text(fieldWrapper('thumbnail'))
|
|
}
|
|
|
|
export function mediaButton(name: string) {
|
|
return [...fieldWrapper('thumbnail').querySelectorAll<HTMLButtonElement>('button')].find(
|
|
(button) => (button.getAttribute('aria-label') ?? text(button)) === name,
|
|
)
|
|
}
|
|
|
|
export function focusedName() {
|
|
const active = document.activeElement
|
|
return active?.getAttribute('aria-label') ?? text(active)
|
|
}
|
|
|
|
export async function pickFromLibrary(filename: string, opener = 'Change image') {
|
|
mediaButton(opener)!.click()
|
|
await flushPromises()
|
|
await flushPromises()
|
|
const tile = [...document.body.querySelectorAll<HTMLButtonElement>('[data-picker-tile]')].find(
|
|
(element) => element.getAttribute('aria-label')!.startsWith(`${filename},`),
|
|
)!
|
|
tile.click()
|
|
await flushPromises()
|
|
;[...document.body.querySelectorAll('button')]
|
|
.find((button) => text(button) === 'Use this image')!
|
|
.click()
|
|
await flushPromises()
|
|
await flushPromises()
|
|
}
|