import { App, createApp, h, nextTick } from 'vue' import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest' vi.mock('../../../components/infoCron/light/light.css', () => ({}), { virtual: true }) vi.mock('../../../components/infoCron/core/index.ts', () => { const { defineComponent, h } = require('vue') return { default: defineComponent({ name: 'cron-light', props: { modelValue: { type: String, default: '' } }, emits: ['update:modelValue', 'error'], setup (props: { modelValue: string }, { emit }: { emit: (event: string, value: string) => void }) { return () => h('div', { class: 'cron-light-stub' }, [ h('span', { class: 'cron-light-value' }, props.modelValue), h('button', { class: 'cron-light-update', onClick: () => emit('update:modelValue', '0 0 12 * * ?') }, 'update'), h('button', { class: 'cron-light-error', onClick: () => emit('error', 'invalid cron') }, 'error') ]) } }) } }, { virtual: true }) let InfoCron: any interface RenderResult { app: App el: HTMLDivElement } const renderedApps: RenderResult[] = [] beforeAll(async () => { InfoCron = (await import('../../../components/infoCron/index.vue')).default }) const renderCron = async (): Promise => { const el = document.createElement('div') document.body.appendChild(el) const app = createApp({ render () { return h(InfoCron) } }) app.config.globalProperties.$t = (key: string) => key app.mount(el) await nextTick() const result = { app, el } renderedApps.push(result) return result } const getRoot = () => document.body const click = async (selector: string) => { const target = getRoot().querySelector(selector) as HTMLElement | null expect(target).not.toBeNull() target!.click() await nextTick() } afterEach(() => { while (renderedApps.length) { const current = renderedApps.pop()! current.app.unmount() current.el.remove() } document.body.innerHTML = '' }) describe('components/infoCron', () => { it('渲染默认 cron 表达式', async () => { await renderCron() expect(getRoot().querySelector('.cron-light-stub')).not.toBeNull() expect(getRoot().textContent).toContain('cron: * * * * *') expect(getRoot().querySelector('.cron-light-value')?.textContent).toBe('* * * * *') }) it('在 cron-light 更新值后同步展示内容', async () => { await renderCron() await click('.cron-light-update') expect(getRoot().textContent).toContain('cron: 0 0 12 * * ?') expect(getRoot().querySelector('.cron-light-value')?.textContent).toBe('0 0 12 * * ?') }) it('接收 error 事件后仍可继续更新值', async () => { await renderCron() await click('.cron-light-error') await click('.cron-light-update') expect(getRoot().querySelector('.cron-light-stub')).not.toBeNull() expect(getRoot().querySelector('.cron-light-value')?.textContent).toBe('0 0 12 * * ?') }) })