| 123456789101112131415161718192021222324252627282930313233343536373839 |
- import { createServer } from 'vite'
- import assert from 'node:assert/strict'
- import { writeFileSync } from 'node:fs'
- import { slideDesignFixture } from './fixtures/aiPptSlideDesign.mjs'
- const vite = await createServer({ server: { middlewareMode: true }, appType: 'custom', logLevel: 'error' })
- try {
- const { aiCoursewareToSlides } = await vite.ssrLoadModule('/src/utils/aiCoursewareToSlides.ts')
- const { modelSlideDesignIssues } = await vite.ssrLoadModule('/src/utils/aiPptModelSlideDesign.ts')
- const { getAiPptImageAspectRatios, buildAiPptSlidePreviews } = await vite.ssrLoadModule('/src/utils/aiPptTemplateEngine.ts')
- const fixture = slideDesignFixture(), before = structuredClone(fixture)
- const result = aiCoursewareToSlides(fixture)
- assert.deepEqual(fixture, before, '渲染不得改写输入内容')
- assert.equal(result.slides[1].elements.find(e => e.name === '模型教学色块').left, 130 * 1.2)
- assert.equal(result.slides[1].elements.find(e => e.name === '模型教学色块').fill, '#FCE4CE')
- assert(result.slides[0].elements.find(e => e.type === 'text').content.includes('67.2px'), '模型字号按画布比例转换,不由前端重新选择')
- assert(result.slides.every(s => s.background.color === '#FFFDF5'))
- assert.equal(getAiPptImageAspectRatios('blank').model_design_v7, 1)
- for (const [name, mutate, reason] of [
- ['overflow', p => p.pageDesign.elements[3].height = 10, /实际高度|投屏安全区/],
- ['missing', p => p.pageDesign.elements.pop(), /遗漏/],
- ['contrast', p => p.pageDesign.elements[3].color = '#D9EDF3', /对比度/],
- ['unknown reference', p => p.pageDesign.elements[3].textRef = 'interaction.answer', /引用/],
- ['required image', p => p.visualPlan.visualMode = 'reference_image', /槽位/],
- ['unknown element', p => p.pageDesign.elements[0].kind = 'script', /无效/]
- ]) {
- const broken = structuredClone(fixture); mutate(broken.pages[0])
- assert.throws(() => aiCoursewareToSlides(broken), reason, name)
- const previews = buildAiPptSlidePreviews(broken)
- assert(previews[0].error && previews[1].slide, `${name}不能清空其他页`)
- }
- assert.deepEqual(modelSlideDesignIssues(fixture.pages[0]), [])
- const textOnly = structuredClone(fixture)
- textOnly.pages.forEach(page => { page.pageDesign.elements = page.pageDesign.elements.filter(e => e.kind === 'text') })
- const textOnlySlides = aiCoursewareToSlides(textOnly).slides
- assert(textOnlySlides.every(slide => slide.elements.every(element => element.type === 'text')), '纯文字设计可通过,不得自动添加色块或分隔线')
- writeFileSync('artifacts/ai-ppt-tests/model-slide-design-fixture.json', JSON.stringify(fixture, null, 2))
- writeFileSync('artifacts/ai-ppt-tests/model-slide-design-render.json', JSON.stringify(result, null, 2))
- console.log('PASS: 模型坐标/颜色/字号忠实执行;内容不变;溢出、遗漏、低对比、未知引用、缺图片槽位和未知元素均阻断;单页错误保留其他预览。此测试使用协议夹具。')
- } finally { await vite.close() }
|