@pep/term-deck 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +356 -0
- package/bin/term-deck.ts +45 -0
- package/examples/slides/01-welcome.md +9 -0
- package/examples/slides/02-features.md +12 -0
- package/examples/slides/03-colors.md +17 -0
- package/examples/slides/04-ascii-art.md +11 -0
- package/examples/slides/05-gradients.md +14 -0
- package/examples/slides/06-themes.md +13 -0
- package/examples/slides/07-markdown.md +13 -0
- package/examples/slides/08-controls.md +13 -0
- package/examples/slides/09-thanks.md +11 -0
- package/examples/slides/deck.config.ts +13 -0
- package/examples/slides-hacker/01-welcome.md +9 -0
- package/examples/slides-hacker/02-features.md +12 -0
- package/examples/slides-hacker/03-colors.md +17 -0
- package/examples/slides-hacker/04-ascii-art.md +11 -0
- package/examples/slides-hacker/05-gradients.md +14 -0
- package/examples/slides-hacker/06-themes.md +13 -0
- package/examples/slides-hacker/07-markdown.md +13 -0
- package/examples/slides-hacker/08-controls.md +13 -0
- package/examples/slides-hacker/09-thanks.md +11 -0
- package/examples/slides-hacker/deck.config.ts +13 -0
- package/examples/slides-matrix/01-welcome.md +9 -0
- package/examples/slides-matrix/02-features.md +12 -0
- package/examples/slides-matrix/03-colors.md +17 -0
- package/examples/slides-matrix/04-ascii-art.md +11 -0
- package/examples/slides-matrix/05-gradients.md +14 -0
- package/examples/slides-matrix/06-themes.md +13 -0
- package/examples/slides-matrix/07-markdown.md +13 -0
- package/examples/slides-matrix/08-controls.md +13 -0
- package/examples/slides-matrix/09-thanks.md +11 -0
- package/examples/slides-matrix/deck.config.ts +13 -0
- package/examples/slides-minimal/01-welcome.md +9 -0
- package/examples/slides-minimal/02-features.md +12 -0
- package/examples/slides-minimal/03-colors.md +17 -0
- package/examples/slides-minimal/04-ascii-art.md +11 -0
- package/examples/slides-minimal/05-gradients.md +14 -0
- package/examples/slides-minimal/06-themes.md +13 -0
- package/examples/slides-minimal/07-markdown.md +13 -0
- package/examples/slides-minimal/08-controls.md +13 -0
- package/examples/slides-minimal/09-thanks.md +11 -0
- package/examples/slides-minimal/deck.config.ts +13 -0
- package/examples/slides-neon/01-welcome.md +9 -0
- package/examples/slides-neon/02-features.md +12 -0
- package/examples/slides-neon/03-colors.md +17 -0
- package/examples/slides-neon/04-ascii-art.md +11 -0
- package/examples/slides-neon/05-gradients.md +14 -0
- package/examples/slides-neon/06-themes.md +13 -0
- package/examples/slides-neon/07-markdown.md +13 -0
- package/examples/slides-neon/08-controls.md +13 -0
- package/examples/slides-neon/09-thanks.md +11 -0
- package/examples/slides-neon/deck.config.ts +13 -0
- package/examples/slides-retro/01-welcome.md +9 -0
- package/examples/slides-retro/02-features.md +12 -0
- package/examples/slides-retro/03-colors.md +17 -0
- package/examples/slides-retro/04-ascii-art.md +11 -0
- package/examples/slides-retro/05-gradients.md +14 -0
- package/examples/slides-retro/06-themes.md +13 -0
- package/examples/slides-retro/07-markdown.md +13 -0
- package/examples/slides-retro/08-controls.md +13 -0
- package/examples/slides-retro/09-thanks.md +11 -0
- package/examples/slides-retro/deck.config.ts +13 -0
- package/package.json +66 -0
- package/src/cli/__tests__/errors.test.ts +201 -0
- package/src/cli/__tests__/help.test.ts +157 -0
- package/src/cli/__tests__/init.test.ts +110 -0
- package/src/cli/commands/export.ts +33 -0
- package/src/cli/commands/init.ts +125 -0
- package/src/cli/commands/present.ts +29 -0
- package/src/cli/errors.ts +77 -0
- package/src/core/__tests__/slide.test.ts +1759 -0
- package/src/core/__tests__/theme.test.ts +1103 -0
- package/src/core/slide.ts +509 -0
- package/src/core/theme.ts +388 -0
- package/src/export/__tests__/recorder.test.ts +566 -0
- package/src/export/recorder.ts +639 -0
- package/src/index.ts +36 -0
- package/src/presenter/__tests__/main.test.ts +244 -0
- package/src/presenter/main.ts +658 -0
- package/src/renderer/__tests__/screen-extended.test.ts +801 -0
- package/src/renderer/__tests__/screen.test.ts +525 -0
- package/src/renderer/screen.ts +671 -0
- package/src/schemas/__tests__/config.test.ts +429 -0
- package/src/schemas/__tests__/slide.test.ts +349 -0
- package/src/schemas/__tests__/theme.test.ts +970 -0
- package/src/schemas/__tests__/validation.test.ts +256 -0
- package/src/schemas/config.ts +58 -0
- package/src/schemas/slide.ts +56 -0
- package/src/schemas/theme.ts +203 -0
- package/src/schemas/validation.ts +64 -0
- package/src/themes/matrix/index.ts +53 -0
- package/themes/hacker.ts +53 -0
- package/themes/minimal.ts +53 -0
- package/themes/neon.ts +53 -0
- package/themes/retro.ts +53 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { describe, it, expect } from 'bun:test'
|
|
2
|
+
import { DeckConfigSchema, SettingsSchema, ExportSettingsSchema } from '../config'
|
|
3
|
+
|
|
4
|
+
// Valid theme for testing
|
|
5
|
+
const validTheme = {
|
|
6
|
+
name: 'test-theme',
|
|
7
|
+
colors: {
|
|
8
|
+
primary: '#00cc66',
|
|
9
|
+
accent: '#ff6600',
|
|
10
|
+
background: '#0a0a0a',
|
|
11
|
+
text: '#ffffff',
|
|
12
|
+
muted: '#666666',
|
|
13
|
+
},
|
|
14
|
+
gradients: {
|
|
15
|
+
fire: ['#ff6600', '#ff3300', '#ff0066'],
|
|
16
|
+
},
|
|
17
|
+
glyphs: '0123456789abcdef',
|
|
18
|
+
animations: {},
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('SettingsSchema', () => {
|
|
22
|
+
describe('startSlide field', () => {
|
|
23
|
+
it('defaults to 0', () => {
|
|
24
|
+
const result = SettingsSchema.parse({})
|
|
25
|
+
expect(result.startSlide).toBe(0)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('accepts positive values', () => {
|
|
29
|
+
const result = SettingsSchema.parse({ startSlide: 5 })
|
|
30
|
+
expect(result.startSlide).toBe(5)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('accepts 0', () => {
|
|
34
|
+
const result = SettingsSchema.parse({ startSlide: 0 })
|
|
35
|
+
expect(result.startSlide).toBe(0)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('rejects negative values', () => {
|
|
39
|
+
expect(() => SettingsSchema.parse({ startSlide: -1 })).toThrow()
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('loop field', () => {
|
|
44
|
+
it('defaults to false', () => {
|
|
45
|
+
const result = SettingsSchema.parse({})
|
|
46
|
+
expect(result.loop).toBe(false)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('accepts true', () => {
|
|
50
|
+
const result = SettingsSchema.parse({ loop: true })
|
|
51
|
+
expect(result.loop).toBe(true)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('accepts false', () => {
|
|
55
|
+
const result = SettingsSchema.parse({ loop: false })
|
|
56
|
+
expect(result.loop).toBe(false)
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
describe('autoAdvance field', () => {
|
|
61
|
+
it('defaults to 0 (disabled)', () => {
|
|
62
|
+
const result = SettingsSchema.parse({})
|
|
63
|
+
expect(result.autoAdvance).toBe(0)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('accepts positive values (ms)', () => {
|
|
67
|
+
const result = SettingsSchema.parse({ autoAdvance: 5000 })
|
|
68
|
+
expect(result.autoAdvance).toBe(5000)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('accepts 0 (disabled)', () => {
|
|
72
|
+
const result = SettingsSchema.parse({ autoAdvance: 0 })
|
|
73
|
+
expect(result.autoAdvance).toBe(0)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('rejects negative values', () => {
|
|
77
|
+
expect(() => SettingsSchema.parse({ autoAdvance: -100 })).toThrow()
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
describe('showSlideNumbers field', () => {
|
|
82
|
+
it('defaults to false', () => {
|
|
83
|
+
const result = SettingsSchema.parse({})
|
|
84
|
+
expect(result.showSlideNumbers).toBe(false)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('accepts true', () => {
|
|
88
|
+
const result = SettingsSchema.parse({ showSlideNumbers: true })
|
|
89
|
+
expect(result.showSlideNumbers).toBe(true)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
describe('showProgress field', () => {
|
|
94
|
+
it('defaults to false', () => {
|
|
95
|
+
const result = SettingsSchema.parse({})
|
|
96
|
+
expect(result.showProgress).toBe(false)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('accepts true', () => {
|
|
100
|
+
const result = SettingsSchema.parse({ showProgress: true })
|
|
101
|
+
expect(result.showProgress).toBe(true)
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
describe('full settings object', () => {
|
|
106
|
+
it('accepts all fields', () => {
|
|
107
|
+
const settings = {
|
|
108
|
+
startSlide: 2,
|
|
109
|
+
loop: true,
|
|
110
|
+
autoAdvance: 3000,
|
|
111
|
+
showSlideNumbers: true,
|
|
112
|
+
showProgress: true,
|
|
113
|
+
}
|
|
114
|
+
const result = SettingsSchema.parse(settings)
|
|
115
|
+
expect(result).toEqual(settings)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('applies all defaults for empty object', () => {
|
|
119
|
+
const result = SettingsSchema.parse({})
|
|
120
|
+
expect(result).toEqual({
|
|
121
|
+
startSlide: 0,
|
|
122
|
+
loop: false,
|
|
123
|
+
autoAdvance: 0,
|
|
124
|
+
showSlideNumbers: false,
|
|
125
|
+
showProgress: false,
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
describe('ExportSettingsSchema', () => {
|
|
132
|
+
describe('width field', () => {
|
|
133
|
+
it('defaults to 120', () => {
|
|
134
|
+
const result = ExportSettingsSchema.parse({})
|
|
135
|
+
expect(result.width).toBe(120)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('accepts values at minimum (80)', () => {
|
|
139
|
+
const result = ExportSettingsSchema.parse({ width: 80 })
|
|
140
|
+
expect(result.width).toBe(80)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it('accepts values at maximum (400)', () => {
|
|
144
|
+
const result = ExportSettingsSchema.parse({ width: 400 })
|
|
145
|
+
expect(result.width).toBe(400)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('accepts values in range', () => {
|
|
149
|
+
const result = ExportSettingsSchema.parse({ width: 200 })
|
|
150
|
+
expect(result.width).toBe(200)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('rejects values below minimum', () => {
|
|
154
|
+
expect(() => ExportSettingsSchema.parse({ width: 79 })).toThrow()
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('rejects values above maximum', () => {
|
|
158
|
+
expect(() => ExportSettingsSchema.parse({ width: 401 })).toThrow()
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
describe('height field', () => {
|
|
163
|
+
it('defaults to 40', () => {
|
|
164
|
+
const result = ExportSettingsSchema.parse({})
|
|
165
|
+
expect(result.height).toBe(40)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
it('accepts values at minimum (24)', () => {
|
|
169
|
+
const result = ExportSettingsSchema.parse({ height: 24 })
|
|
170
|
+
expect(result.height).toBe(24)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
it('accepts values at maximum (100)', () => {
|
|
174
|
+
const result = ExportSettingsSchema.parse({ height: 100 })
|
|
175
|
+
expect(result.height).toBe(100)
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
it('accepts values in range', () => {
|
|
179
|
+
const result = ExportSettingsSchema.parse({ height: 50 })
|
|
180
|
+
expect(result.height).toBe(50)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
it('rejects values below minimum', () => {
|
|
184
|
+
expect(() => ExportSettingsSchema.parse({ height: 23 })).toThrow()
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('rejects values above maximum', () => {
|
|
188
|
+
expect(() => ExportSettingsSchema.parse({ height: 101 })).toThrow()
|
|
189
|
+
})
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
describe('fps field', () => {
|
|
193
|
+
it('defaults to 30', () => {
|
|
194
|
+
const result = ExportSettingsSchema.parse({})
|
|
195
|
+
expect(result.fps).toBe(30)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('accepts values at minimum (10)', () => {
|
|
199
|
+
const result = ExportSettingsSchema.parse({ fps: 10 })
|
|
200
|
+
expect(result.fps).toBe(10)
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
it('accepts values at maximum (60)', () => {
|
|
204
|
+
const result = ExportSettingsSchema.parse({ fps: 60 })
|
|
205
|
+
expect(result.fps).toBe(60)
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
it('accepts values in range', () => {
|
|
209
|
+
const result = ExportSettingsSchema.parse({ fps: 24 })
|
|
210
|
+
expect(result.fps).toBe(24)
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('rejects values below minimum', () => {
|
|
214
|
+
expect(() => ExportSettingsSchema.parse({ fps: 9 })).toThrow()
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it('rejects values above maximum', () => {
|
|
218
|
+
expect(() => ExportSettingsSchema.parse({ fps: 61 })).toThrow()
|
|
219
|
+
})
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
describe('full export settings object', () => {
|
|
223
|
+
it('accepts all fields', () => {
|
|
224
|
+
const exportSettings = {
|
|
225
|
+
width: 160,
|
|
226
|
+
height: 50,
|
|
227
|
+
fps: 24,
|
|
228
|
+
}
|
|
229
|
+
const result = ExportSettingsSchema.parse(exportSettings)
|
|
230
|
+
expect(result).toEqual(exportSettings)
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
it('applies all defaults for empty object', () => {
|
|
234
|
+
const result = ExportSettingsSchema.parse({})
|
|
235
|
+
expect(result).toEqual({
|
|
236
|
+
width: 120,
|
|
237
|
+
height: 40,
|
|
238
|
+
fps: 30,
|
|
239
|
+
})
|
|
240
|
+
})
|
|
241
|
+
})
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
describe('DeckConfigSchema', () => {
|
|
245
|
+
describe('metadata fields', () => {
|
|
246
|
+
it('accepts title', () => {
|
|
247
|
+
const config = { title: 'My Presentation', theme: validTheme }
|
|
248
|
+
const result = DeckConfigSchema.parse(config)
|
|
249
|
+
expect(result.title).toBe('My Presentation')
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
it('accepts author', () => {
|
|
253
|
+
const config = { author: 'John Doe', theme: validTheme }
|
|
254
|
+
const result = DeckConfigSchema.parse(config)
|
|
255
|
+
expect(result.author).toBe('John Doe')
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
it('accepts date', () => {
|
|
259
|
+
const config = { date: '2024-01-15', theme: validTheme }
|
|
260
|
+
const result = DeckConfigSchema.parse(config)
|
|
261
|
+
expect(result.date).toBe('2024-01-15')
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
it('accepts all metadata fields together', () => {
|
|
265
|
+
const config = {
|
|
266
|
+
title: 'My Presentation',
|
|
267
|
+
author: 'John Doe',
|
|
268
|
+
date: '2024-01-15',
|
|
269
|
+
theme: validTheme,
|
|
270
|
+
}
|
|
271
|
+
const result = DeckConfigSchema.parse(config)
|
|
272
|
+
expect(result.title).toBe('My Presentation')
|
|
273
|
+
expect(result.author).toBe('John Doe')
|
|
274
|
+
expect(result.date).toBe('2024-01-15')
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
it('all metadata fields are optional', () => {
|
|
278
|
+
const config = { theme: validTheme }
|
|
279
|
+
const result = DeckConfigSchema.parse(config)
|
|
280
|
+
expect(result.title).toBeUndefined()
|
|
281
|
+
expect(result.author).toBeUndefined()
|
|
282
|
+
expect(result.date).toBeUndefined()
|
|
283
|
+
})
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
describe('theme field', () => {
|
|
287
|
+
it('requires theme', () => {
|
|
288
|
+
const config = { title: 'My Presentation' }
|
|
289
|
+
expect(() => DeckConfigSchema.parse(config)).toThrow()
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
it('accepts valid theme', () => {
|
|
293
|
+
const config = { theme: validTheme }
|
|
294
|
+
const result = DeckConfigSchema.parse(config)
|
|
295
|
+
expect(result.theme.name).toBe('test-theme')
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
it('rejects invalid theme', () => {
|
|
299
|
+
const config = {
|
|
300
|
+
theme: {
|
|
301
|
+
name: 'invalid',
|
|
302
|
+
colors: { primary: 'not-a-hex' },
|
|
303
|
+
},
|
|
304
|
+
}
|
|
305
|
+
expect(() => DeckConfigSchema.parse(config)).toThrow()
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
it('applies theme defaults (animations)', () => {
|
|
309
|
+
const config = { theme: validTheme }
|
|
310
|
+
const result = DeckConfigSchema.parse(config)
|
|
311
|
+
expect(result.theme.animations.revealSpeed).toBe(1.0)
|
|
312
|
+
expect(result.theme.animations.matrixDensity).toBe(50)
|
|
313
|
+
expect(result.theme.animations.glitchIterations).toBe(5)
|
|
314
|
+
expect(result.theme.animations.lineDelay).toBe(30)
|
|
315
|
+
expect(result.theme.animations.matrixInterval).toBe(80)
|
|
316
|
+
})
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
describe('settings field', () => {
|
|
320
|
+
it('accepts settings object', () => {
|
|
321
|
+
const config = {
|
|
322
|
+
theme: validTheme,
|
|
323
|
+
settings: {
|
|
324
|
+
startSlide: 1,
|
|
325
|
+
loop: true,
|
|
326
|
+
},
|
|
327
|
+
}
|
|
328
|
+
const result = DeckConfigSchema.parse(config)
|
|
329
|
+
expect(result.settings?.startSlide).toBe(1)
|
|
330
|
+
expect(result.settings?.loop).toBe(true)
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
it('settings is optional', () => {
|
|
334
|
+
const config = { theme: validTheme }
|
|
335
|
+
const result = DeckConfigSchema.parse(config)
|
|
336
|
+
expect(result.settings).toBeUndefined()
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
it('applies settings defaults when settings provided', () => {
|
|
340
|
+
const config = {
|
|
341
|
+
theme: validTheme,
|
|
342
|
+
settings: { loop: true },
|
|
343
|
+
}
|
|
344
|
+
const result = DeckConfigSchema.parse(config)
|
|
345
|
+
expect(result.settings?.startSlide).toBe(0)
|
|
346
|
+
expect(result.settings?.loop).toBe(true)
|
|
347
|
+
expect(result.settings?.autoAdvance).toBe(0)
|
|
348
|
+
expect(result.settings?.showSlideNumbers).toBe(false)
|
|
349
|
+
expect(result.settings?.showProgress).toBe(false)
|
|
350
|
+
})
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
describe('export field', () => {
|
|
354
|
+
it('accepts export object', () => {
|
|
355
|
+
const config = {
|
|
356
|
+
theme: validTheme,
|
|
357
|
+
export: {
|
|
358
|
+
width: 160,
|
|
359
|
+
height: 50,
|
|
360
|
+
fps: 24,
|
|
361
|
+
},
|
|
362
|
+
}
|
|
363
|
+
const result = DeckConfigSchema.parse(config)
|
|
364
|
+
expect(result.export?.width).toBe(160)
|
|
365
|
+
expect(result.export?.height).toBe(50)
|
|
366
|
+
expect(result.export?.fps).toBe(24)
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
it('export is optional', () => {
|
|
370
|
+
const config = { theme: validTheme }
|
|
371
|
+
const result = DeckConfigSchema.parse(config)
|
|
372
|
+
expect(result.export).toBeUndefined()
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
it('applies export defaults when export provided', () => {
|
|
376
|
+
const config = {
|
|
377
|
+
theme: validTheme,
|
|
378
|
+
export: { fps: 24 },
|
|
379
|
+
}
|
|
380
|
+
const result = DeckConfigSchema.parse(config)
|
|
381
|
+
expect(result.export?.width).toBe(120)
|
|
382
|
+
expect(result.export?.height).toBe(40)
|
|
383
|
+
expect(result.export?.fps).toBe(24)
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('validates export constraints', () => {
|
|
387
|
+
const config = {
|
|
388
|
+
theme: validTheme,
|
|
389
|
+
export: { width: 50 }, // Below minimum of 80
|
|
390
|
+
}
|
|
391
|
+
expect(() => DeckConfigSchema.parse(config)).toThrow()
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
describe('full deck configuration', () => {
|
|
396
|
+
it('accepts minimal config (theme only)', () => {
|
|
397
|
+
const config = { theme: validTheme }
|
|
398
|
+
expect(() => DeckConfigSchema.parse(config)).not.toThrow()
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
it('accepts full config with all fields', () => {
|
|
402
|
+
const config = {
|
|
403
|
+
title: 'My Presentation',
|
|
404
|
+
author: 'John Doe',
|
|
405
|
+
date: '2024-01-15',
|
|
406
|
+
theme: validTheme,
|
|
407
|
+
settings: {
|
|
408
|
+
startSlide: 0,
|
|
409
|
+
loop: true,
|
|
410
|
+
autoAdvance: 5000,
|
|
411
|
+
showSlideNumbers: true,
|
|
412
|
+
showProgress: true,
|
|
413
|
+
},
|
|
414
|
+
export: {
|
|
415
|
+
width: 160,
|
|
416
|
+
height: 50,
|
|
417
|
+
fps: 24,
|
|
418
|
+
},
|
|
419
|
+
}
|
|
420
|
+
const result = DeckConfigSchema.parse(config)
|
|
421
|
+
expect(result.title).toBe('My Presentation')
|
|
422
|
+
expect(result.author).toBe('John Doe')
|
|
423
|
+
expect(result.date).toBe('2024-01-15')
|
|
424
|
+
expect(result.theme.name).toBe('test-theme')
|
|
425
|
+
expect(result.settings?.loop).toBe(true)
|
|
426
|
+
expect(result.export?.fps).toBe(24)
|
|
427
|
+
})
|
|
428
|
+
})
|
|
429
|
+
})
|