返回 oh-my-ppt
size-layout-skills.test.ts
根目录 / tests / unit / prompt / size-layout-skills.test.ts
1 import { readFileSync } from 'fs'
2 import path from 'path'
3 import { describe, expect, it } from 'vitest'
4
5 const projectRoot = process.cwd()
6
7 const readProjectFile = (filePath: string) =>
8 readFileSync(path.join(projectRoot, filePath), 'utf-8')
9
10 const sizeLayoutSkills = [
11 {
12 name: 'vertical-9-16-layout-skill',
13 dir: 'resources/skills/vertical-9-16-layout-skill',
14 patterns: ['hook-value-takeaway', 'vertical-step-story', 'data-takeaway']
15 },
16 {
17 name: 'standard-4-3-layout-skill',
18 dir: 'resources/skills/standard-4-3-layout-skill',
19 patterns: ['title-plus-two-zone', 'chart-insight-pair', 'matrix-2x2']
20 },
21 {
22 name: 'square-1-1-layout-skill',
23 dir: 'resources/skills/square-1-1-layout-skill',
24 patterns: ['center-hero-orbit', 'quadrant-card', 'square-data-card']
25 },
26 {
27 name: 'vertical-3-4-layout-skill',
28 dir: 'resources/skills/vertical-3-4-layout-skill',
29 patterns: ['poster-hero-proof', 'vertical-process', 'two-column-pocket']
30 },
31 {
32 name: 'red-layout-skill',
33 dir: 'resources/skills/red-layout-skill',
34 patterns: ['cover-hook', 'saveable-checklist', 'template-note']
35 }
36 ] as const
37
38 describe('size layout skills', () => {
39 it('use progressive disclosure with catalog and checklist references', () => {
40 for (const skill of sizeLayoutSkills) {
41 const source = readProjectFile(`${skill.dir}/SKILL.md`)
42 const catalog = readProjectFile(`${skill.dir}/references/catalog.md`)
43 const checklist = readProjectFile(`${skill.dir}/references/checklist.md`)
44
45 expect(source).toContain('references/catalog.md')
46 expect(source).toContain('references/checklist.md')
47 expect(source).toContain('Pattern Quick Lookup')
48 expect(source).not.toContain('## Structure Patterns')
49
50 expect(catalog).toContain('## Zone Skeletons')
51 expect(catalog).toContain('## Patterns')
52 expect(catalog).toContain('Structure recipe')
53 expect(catalog).toContain('Budget rule')
54 expect(catalog).toContain('Failure signs')
55 for (const pattern of skill.patterns) {
56 expect(catalog).toContain(pattern)
57 }
58
59 expect(checklist).toContain('P0 - Not Deliverable')
60 expect(checklist).toContain('P1 - Should Fix')
61 expect(checklist).toContain('P2 - Consider Optimizing')
62 }
63 })
64
65 it('keep each size skill focused on its own layout language', () => {
66 const skillNames = sizeLayoutSkills.map((skill) => skill.name)
67
68 for (const skill of sizeLayoutSkills) {
69 const combined = [
70 readProjectFile(`${skill.dir}/SKILL.md`),
71 readProjectFile(`${skill.dir}/references/catalog.md`),
72 readProjectFile(`${skill.dir}/references/checklist.md`)
73 ].join('\n')
74
75 for (const otherSkillName of skillNames.filter((name) => name !== skill.name)) {
76 expect(combined).not.toContain(otherSkillName)
77 }
78 expect(combined).not.toContain('When not to use')
79 expect(combined).not.toContain('Do not use')
80 }
81 })
82
83 it('low-density vertical/poster skills cap content capacity and prescribe overload priority', () => {
84 // These canvases are social/card formats, not compressed slides. They MUST
85 // declare a hard capacity ceiling and an overload priority so the page agent
86 // compresses content instead of shrinking fonts or overflowing.
87 const lowDensitySkills = [
88 'vertical-9-16-layout-skill',
89 'vertical-3-4-layout-skill',
90 'red-layout-skill'
91 ]
92
93 for (const name of lowDensitySkills) {
94 const source = readProjectFile(`resources/skills/${name}/SKILL.md`)
95
96 // Hard capacity ceiling is declared.
97 expect(source).toContain('Capacity ceiling (hard)')
98 // Vertical fill rule forces flex-1 / justify-between so the page never
99 // leaves an accidental bottom gap (LLMs cannot pixel-estimate accurately;
100 // CSS auto-distribution is the reliable fix).
101 expect(source).toContain('Vertical fill (hard)')
102 expect(source).toContain('flex-1')
103 expect(source).toContain('no accidental top-stack or bottom gap')
104 // Overload priority explicitly forbids going below font floors or
105 // exceeding canvas height as a way to fit more content.
106 expect(source).toContain('resolve overload in this priority')
107 expect(source).toContain('Never resolve overload by going below the font floors')
108 // Recognises the format as a low-density carrier, not a compressed slide.
109 expect(source).toContain('not a compressed slide')
110 }
111 })
112 })
113
113 lines TYPESCRIPT