@tldraw/tlschema 4.2.1 → 4.2.2

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.
Files changed (117) hide show
  1. package/dist-cjs/bindings/TLBaseBinding.js.map +2 -2
  2. package/dist-cjs/createTLSchema.js.map +2 -2
  3. package/dist-cjs/index.d.ts +242 -71
  4. package/dist-cjs/index.js +4 -1
  5. package/dist-cjs/index.js.map +2 -2
  6. package/dist-cjs/misc/TLOpacity.js +1 -5
  7. package/dist-cjs/misc/TLOpacity.js.map +2 -2
  8. package/dist-cjs/misc/TLRichText.js +5 -1
  9. package/dist-cjs/misc/TLRichText.js.map +2 -2
  10. package/dist-cjs/misc/b64Vecs.js +224 -0
  11. package/dist-cjs/misc/b64Vecs.js.map +7 -0
  12. package/dist-cjs/records/TLAsset.js.map +1 -1
  13. package/dist-cjs/records/TLBinding.js.map +2 -2
  14. package/dist-cjs/records/TLShape.js.map +2 -2
  15. package/dist-cjs/shapes/ShapeWithCrop.js.map +1 -1
  16. package/dist-cjs/shapes/TLArrowShape.js +26 -13
  17. package/dist-cjs/shapes/TLArrowShape.js.map +2 -2
  18. package/dist-cjs/shapes/TLBaseShape.js.map +2 -2
  19. package/dist-cjs/shapes/TLDrawShape.js +37 -4
  20. package/dist-cjs/shapes/TLDrawShape.js.map +2 -2
  21. package/dist-cjs/shapes/TLEmbedShape.js +17 -0
  22. package/dist-cjs/shapes/TLEmbedShape.js.map +2 -2
  23. package/dist-cjs/shapes/TLGeoShape.js +12 -1
  24. package/dist-cjs/shapes/TLGeoShape.js.map +2 -2
  25. package/dist-cjs/shapes/TLHighlightShape.js +29 -2
  26. package/dist-cjs/shapes/TLHighlightShape.js.map +2 -2
  27. package/dist-cjs/shapes/TLNoteShape.js +12 -1
  28. package/dist-cjs/shapes/TLNoteShape.js.map +2 -2
  29. package/dist-cjs/shapes/TLTextShape.js +12 -1
  30. package/dist-cjs/shapes/TLTextShape.js.map +2 -2
  31. package/dist-cjs/store-migrations.js +15 -15
  32. package/dist-cjs/store-migrations.js.map +2 -2
  33. package/dist-esm/bindings/TLBaseBinding.mjs.map +2 -2
  34. package/dist-esm/createTLSchema.mjs.map +2 -2
  35. package/dist-esm/index.d.mts +242 -71
  36. package/dist-esm/index.mjs +5 -1
  37. package/dist-esm/index.mjs.map +2 -2
  38. package/dist-esm/misc/TLOpacity.mjs +1 -5
  39. package/dist-esm/misc/TLOpacity.mjs.map +2 -2
  40. package/dist-esm/misc/TLRichText.mjs +5 -1
  41. package/dist-esm/misc/TLRichText.mjs.map +2 -2
  42. package/dist-esm/misc/b64Vecs.mjs +204 -0
  43. package/dist-esm/misc/b64Vecs.mjs.map +7 -0
  44. package/dist-esm/records/TLAsset.mjs.map +1 -1
  45. package/dist-esm/records/TLBinding.mjs.map +2 -2
  46. package/dist-esm/records/TLShape.mjs.map +2 -2
  47. package/dist-esm/shapes/TLArrowShape.mjs +26 -13
  48. package/dist-esm/shapes/TLArrowShape.mjs.map +2 -2
  49. package/dist-esm/shapes/TLBaseShape.mjs.map +2 -2
  50. package/dist-esm/shapes/TLDrawShape.mjs +37 -4
  51. package/dist-esm/shapes/TLDrawShape.mjs.map +2 -2
  52. package/dist-esm/shapes/TLEmbedShape.mjs +17 -0
  53. package/dist-esm/shapes/TLEmbedShape.mjs.map +2 -2
  54. package/dist-esm/shapes/TLGeoShape.mjs +12 -1
  55. package/dist-esm/shapes/TLGeoShape.mjs.map +2 -2
  56. package/dist-esm/shapes/TLHighlightShape.mjs +29 -2
  57. package/dist-esm/shapes/TLHighlightShape.mjs.map +2 -2
  58. package/dist-esm/shapes/TLNoteShape.mjs +12 -1
  59. package/dist-esm/shapes/TLNoteShape.mjs.map +2 -2
  60. package/dist-esm/shapes/TLTextShape.mjs +12 -1
  61. package/dist-esm/shapes/TLTextShape.mjs.map +2 -2
  62. package/dist-esm/store-migrations.mjs +15 -15
  63. package/dist-esm/store-migrations.mjs.map +2 -2
  64. package/package.json +8 -8
  65. package/src/__tests__/migrationTestUtils.ts +9 -3
  66. package/src/bindings/TLBaseBinding.ts +25 -14
  67. package/src/createTLSchema.ts +8 -2
  68. package/src/index.ts +9 -0
  69. package/src/migrations.test.ts +149 -1
  70. package/src/misc/TLOpacity.ts +1 -5
  71. package/src/misc/TLRichText.ts +6 -1
  72. package/src/misc/b64Vecs.ts +308 -0
  73. package/src/records/TLAsset.ts +2 -2
  74. package/src/records/TLBinding.ts +65 -23
  75. package/src/records/TLShape.ts +100 -5
  76. package/src/shapes/ShapeWithCrop.ts +2 -2
  77. package/src/shapes/TLArrowShape.ts +28 -14
  78. package/src/shapes/TLBaseShape.ts +34 -10
  79. package/src/shapes/TLDrawShape.ts +59 -12
  80. package/src/shapes/TLEmbedShape.ts +17 -0
  81. package/src/shapes/TLGeoShape.ts +14 -1
  82. package/src/shapes/TLHighlightShape.ts +37 -0
  83. package/src/shapes/TLNoteShape.ts +15 -1
  84. package/src/shapes/TLTextShape.ts +16 -2
  85. package/src/store-migrations.ts +17 -16
  86. package/src/assets/TLBookmarkAsset.test.ts +0 -96
  87. package/src/assets/TLImageAsset.test.ts +0 -213
  88. package/src/assets/TLVideoAsset.test.ts +0 -105
  89. package/src/bindings/TLArrowBinding.test.ts +0 -55
  90. package/src/misc/id-validator.test.ts +0 -50
  91. package/src/records/TLAsset.test.ts +0 -234
  92. package/src/records/TLBinding.test.ts +0 -22
  93. package/src/records/TLCamera.test.ts +0 -19
  94. package/src/records/TLDocument.test.ts +0 -35
  95. package/src/records/TLInstance.test.ts +0 -201
  96. package/src/records/TLPage.test.ts +0 -110
  97. package/src/records/TLPageState.test.ts +0 -228
  98. package/src/records/TLPointer.test.ts +0 -63
  99. package/src/records/TLPresence.test.ts +0 -190
  100. package/src/records/TLRecord.test.ts +0 -70
  101. package/src/records/TLShape.test.ts +0 -232
  102. package/src/shapes/ShapeWithCrop.test.ts +0 -18
  103. package/src/shapes/TLArrowShape.test.ts +0 -505
  104. package/src/shapes/TLBaseShape.test.ts +0 -142
  105. package/src/shapes/TLBookmarkShape.test.ts +0 -122
  106. package/src/shapes/TLDrawShape.test.ts +0 -177
  107. package/src/shapes/TLEmbedShape.test.ts +0 -286
  108. package/src/shapes/TLFrameShape.test.ts +0 -71
  109. package/src/shapes/TLGeoShape.test.ts +0 -247
  110. package/src/shapes/TLGroupShape.test.ts +0 -59
  111. package/src/shapes/TLHighlightShape.test.ts +0 -325
  112. package/src/shapes/TLImageShape.test.ts +0 -534
  113. package/src/shapes/TLLineShape.test.ts +0 -269
  114. package/src/shapes/TLNoteShape.test.ts +0 -1568
  115. package/src/shapes/TLTextShape.test.ts +0 -407
  116. package/src/shapes/TLVideoShape.test.ts +0 -112
  117. package/src/styles/TLColorStyle.test.ts +0 -439
@@ -1,407 +0,0 @@
1
- import { T } from '@tldraw/validate'
2
- import { describe, expect, it } from 'vitest'
3
- import { getTestMigration } from '../__tests__/migrationTestUtils'
4
- import { TLRichText, toRichText } from '../misc/TLRichText'
5
- import { DefaultColorStyle } from '../styles/TLColorStyle'
6
- import { DefaultFontStyle } from '../styles/TLFontStyle'
7
- import { DefaultSizeStyle } from '../styles/TLSizeStyle'
8
- import { DefaultTextAlignStyle } from '../styles/TLTextAlignStyle'
9
- import { textShapeMigrations, textShapeProps, textShapeVersions } from './TLTextShape'
10
-
11
- describe('TLTextShape', () => {
12
- describe('textShapeProps validation schema', () => {
13
- it('should validate using comprehensive object validator', () => {
14
- const fullValidator = T.object(textShapeProps)
15
-
16
- const validPropsObject = {
17
- color: 'red' as const,
18
- size: 's' as const,
19
- font: 'mono' as const,
20
- textAlign: 'end' as const,
21
- w: 250,
22
- richText: toRichText('Complete validation test') as TLRichText,
23
- scale: 0.8,
24
- autoSize: true,
25
- }
26
-
27
- expect(() => fullValidator.validate(validPropsObject)).not.toThrow()
28
- const result = fullValidator.validate(validPropsObject)
29
- expect(result).toEqual(validPropsObject)
30
- })
31
-
32
- it('should validate width as nonZeroNumber', () => {
33
- // Valid non-zero positive numbers
34
- const validWidths = [0.1, 1, 50, 100, 1000, 0.001]
35
-
36
- validWidths.forEach((w) => {
37
- expect(() => textShapeProps.w.validate(w)).not.toThrow()
38
- })
39
-
40
- // Invalid widths (zero, negative numbers, and non-numbers)
41
- const invalidWidths = [0, -1, -0.1, 'not-number', null, undefined, {}, [], true, false]
42
-
43
- invalidWidths.forEach((w) => {
44
- expect(() => textShapeProps.w.validate(w)).toThrow()
45
- })
46
- })
47
-
48
- it('should validate scale as nonZeroNumber', () => {
49
- // Valid non-zero positive numbers
50
- const validScales = [0.1, 0.5, 1, 1.5, 2, 10]
51
-
52
- validScales.forEach((scale) => {
53
- expect(() => textShapeProps.scale.validate(scale)).not.toThrow()
54
- })
55
-
56
- // Invalid scales (zero, negative numbers, and non-numbers)
57
- const invalidScales = [0, -0.5, -1, -2, 'not-number', null, undefined, {}, [], true, false]
58
-
59
- invalidScales.forEach((scale) => {
60
- expect(() => textShapeProps.scale.validate(scale)).toThrow()
61
- })
62
- })
63
-
64
- it('should use correct default style validators', () => {
65
- // Verify that the props schema uses the expected style validators
66
- expect(textShapeProps.color).toBe(DefaultColorStyle)
67
- expect(textShapeProps.size).toBe(DefaultSizeStyle)
68
- expect(textShapeProps.font).toBe(DefaultFontStyle)
69
- expect(textShapeProps.textAlign).toBe(DefaultTextAlignStyle)
70
- })
71
-
72
- it('should use correct primitive validators', () => {
73
- // Check that non-style properties use correct T validators
74
- expect(textShapeProps.w).toBe(T.nonZeroNumber)
75
- expect(textShapeProps.scale).toBe(T.nonZeroNumber)
76
- expect(textShapeProps.autoSize).toBe(T.boolean)
77
- })
78
- })
79
-
80
- describe('textShapeVersions', () => {
81
- it('should have all expected migration versions', () => {
82
- const expectedVersions: Array<keyof typeof textShapeVersions> = [
83
- 'RemoveJustify',
84
- 'AddTextAlign',
85
- 'AddRichText',
86
- ]
87
-
88
- expectedVersions.forEach((version) => {
89
- expect(textShapeVersions[version]).toBeDefined()
90
- expect(typeof textShapeVersions[version]).toBe('string')
91
- })
92
- })
93
- })
94
-
95
- describe('textShapeMigrations', () => {
96
- it('should have migrations for all version IDs', () => {
97
- const migrationIds = textShapeMigrations.sequence
98
- .filter((migration) => 'id' in migration)
99
- .map((migration) => ('id' in migration ? migration.id : null))
100
- .filter(Boolean)
101
-
102
- const versionIds = Object.values(textShapeVersions)
103
-
104
- versionIds.forEach((versionId) => {
105
- expect(migrationIds).toContain(versionId)
106
- })
107
- })
108
- })
109
-
110
- describe('textShapeMigrations - RemoveJustify migration', () => {
111
- const { up, down } = getTestMigration(textShapeVersions.RemoveJustify)
112
-
113
- describe('RemoveJustify up migration', () => {
114
- it('should convert justify alignment to start', () => {
115
- const oldRecord = {
116
- id: 'shape:text1',
117
- props: {
118
- color: 'black',
119
- font: 'draw',
120
- size: 'm',
121
- align: 'justify',
122
- w: 200,
123
- text: 'Test text',
124
- scale: 1,
125
- autoSize: true,
126
- },
127
- }
128
-
129
- const result = up(oldRecord)
130
- expect(result.props.align).toBe('start')
131
- expect(result.props.color).toBe('black') // Preserve other props
132
- expect(result.props.text).toBe('Test text')
133
- })
134
-
135
- it('should preserve non-justify alignments', () => {
136
- const alignments = ['start', 'middle', 'end']
137
-
138
- alignments.forEach((align) => {
139
- const oldRecord = {
140
- id: 'shape:text1',
141
- props: {
142
- color: 'red',
143
- font: 'sans',
144
- size: 'l',
145
- align,
146
- w: 300,
147
- text: 'Aligned text',
148
- scale: 1,
149
- autoSize: false,
150
- },
151
- }
152
-
153
- const result = up(oldRecord)
154
- expect(result.props.align).toBe(align)
155
- })
156
- })
157
-
158
- it('should preserve all other properties during migration', () => {
159
- const oldRecord = {
160
- id: 'shape:text1',
161
- props: {
162
- color: 'blue',
163
- font: 'serif',
164
- size: 'xl',
165
- align: 'justify',
166
- w: 400,
167
- text: 'Justified text becomes start aligned',
168
- scale: 1.5,
169
- autoSize: false,
170
- },
171
- }
172
-
173
- const result = up(oldRecord)
174
- expect(result.props.align).toBe('start')
175
- expect(result.props.color).toBe('blue')
176
- expect(result.props.font).toBe('serif')
177
- expect(result.props.size).toBe('xl')
178
- expect(result.props.w).toBe(400)
179
- expect(result.props.text).toBe('Justified text becomes start aligned')
180
- expect(result.props.scale).toBe(1.5)
181
- expect(result.props.autoSize).toBe(false)
182
- })
183
- })
184
-
185
- describe('RemoveJustify down migration', () => {
186
- it('should be retired (no down migration)', () => {
187
- expect(() => {
188
- down({})
189
- }).toThrow('Migration com.tldraw.shape.text/1 does not have a down function')
190
- })
191
- })
192
- })
193
-
194
- describe('textShapeMigrations - AddTextAlign migration', () => {
195
- const { up, down } = getTestMigration(textShapeVersions.AddTextAlign)
196
-
197
- describe('AddTextAlign up migration', () => {
198
- it('should migrate align to textAlign', () => {
199
- const oldRecord = {
200
- id: 'shape:text1',
201
- props: {
202
- color: 'black',
203
- font: 'draw',
204
- size: 'm',
205
- align: 'start',
206
- w: 200,
207
- text: 'Test text',
208
- scale: 1,
209
- autoSize: true,
210
- },
211
- }
212
-
213
- const result = up(oldRecord)
214
- expect(result.props.textAlign).toBe('start')
215
- expect(result.props.align).toBeUndefined()
216
- expect(result.props.color).toBe('black') // Preserve other props
217
- })
218
-
219
- it('should handle all alignment values', () => {
220
- const alignments = ['start', 'middle', 'end']
221
-
222
- alignments.forEach((align) => {
223
- const oldRecord = {
224
- id: 'shape:text1',
225
- props: {
226
- color: 'red',
227
- align,
228
- w: 200,
229
- text: 'Test',
230
- },
231
- }
232
-
233
- const result = up(oldRecord)
234
- expect(result.props.textAlign).toBe(align)
235
- expect(result.props.align).toBeUndefined()
236
- })
237
- })
238
-
239
- it('should preserve all other properties during migration', () => {
240
- const oldRecord = {
241
- id: 'shape:text1',
242
- props: {
243
- color: 'green',
244
- font: 'mono',
245
- size: 's',
246
- align: 'middle',
247
- w: 150,
248
- text: 'Migration test',
249
- scale: 2,
250
- autoSize: false,
251
- },
252
- }
253
-
254
- const result = up(oldRecord)
255
- expect(result.props.textAlign).toBe('middle')
256
- expect(result.props.align).toBeUndefined()
257
- expect(result.props.color).toBe('green')
258
- expect(result.props.font).toBe('mono')
259
- expect(result.props.size).toBe('s')
260
- expect(result.props.w).toBe(150)
261
- expect(result.props.text).toBe('Migration test')
262
- expect(result.props.scale).toBe(2)
263
- expect(result.props.autoSize).toBe(false)
264
- })
265
- })
266
-
267
- describe('AddTextAlign down migration', () => {
268
- it('should migrate textAlign back to align', () => {
269
- const newRecord = {
270
- id: 'shape:text1',
271
- props: {
272
- color: 'black',
273
- font: 'draw',
274
- size: 'm',
275
- textAlign: 'start',
276
- w: 200,
277
- text: 'Test text',
278
- scale: 1,
279
- autoSize: true,
280
- },
281
- }
282
-
283
- const result = down(newRecord)
284
- expect(result.props.align).toBe('start')
285
- expect(result.props.textAlign).toBeUndefined()
286
- expect(result.props.color).toBe('black') // Preserve other props
287
- })
288
-
289
- it('should handle all textAlign values during down migration', () => {
290
- const alignments = ['start', 'middle', 'end']
291
-
292
- alignments.forEach((textAlign) => {
293
- const newRecord = {
294
- id: 'shape:text1',
295
- props: {
296
- color: 'blue',
297
- textAlign,
298
- w: 200,
299
- text: 'Test',
300
- },
301
- }
302
-
303
- const result = down(newRecord)
304
- expect(result.props.align).toBe(textAlign)
305
- expect(result.props.textAlign).toBeUndefined()
306
- })
307
- })
308
- })
309
- })
310
-
311
- describe('textShapeMigrations - AddRichText migration', () => {
312
- const { up } = getTestMigration(textShapeVersions.AddRichText)
313
-
314
- describe('AddRichText up migration', () => {
315
- it('should convert text property to richText', () => {
316
- const oldRecord = {
317
- id: 'shape:text1',
318
- props: {
319
- color: 'black',
320
- font: 'draw',
321
- size: 'm',
322
- textAlign: 'start',
323
- w: 200,
324
- text: 'Simple text content',
325
- scale: 1,
326
- autoSize: true,
327
- },
328
- }
329
-
330
- const result = up(oldRecord)
331
- expect(result.props.richText).toBeDefined()
332
- expect(result.props.text).toBeUndefined()
333
- expect(result.props.color).toBe('black') // Preserve other props
334
- })
335
-
336
- it('should handle empty text', () => {
337
- const oldRecord = {
338
- id: 'shape:text1',
339
- props: {
340
- color: 'red',
341
- font: 'sans',
342
- size: 'l',
343
- textAlign: 'middle',
344
- w: 300,
345
- text: '',
346
- scale: 1,
347
- autoSize: false,
348
- },
349
- }
350
-
351
- const result = up(oldRecord)
352
- expect(result.props.richText).toBeDefined()
353
- expect(result.props.text).toBeUndefined()
354
- })
355
-
356
- it('should handle multi-line text', () => {
357
- const oldRecord = {
358
- id: 'shape:text1',
359
- props: {
360
- color: 'blue',
361
- font: 'serif',
362
- size: 'xl',
363
- textAlign: 'end',
364
- w: 400,
365
- text: 'Line 1\nLine 2\nLine 3',
366
- scale: 1.2,
367
- autoSize: true,
368
- },
369
- }
370
-
371
- const result = up(oldRecord)
372
- expect(result.props.richText).toBeDefined()
373
- expect(result.props.text).toBeUndefined()
374
- })
375
-
376
- it('should preserve all other properties during migration', () => {
377
- const oldRecord = {
378
- id: 'shape:text1',
379
- props: {
380
- color: 'green',
381
- font: 'mono',
382
- size: 's',
383
- textAlign: 'start',
384
- w: 250,
385
- text: 'Rich text migration test',
386
- scale: 0.8,
387
- autoSize: false,
388
- },
389
- }
390
-
391
- const result = up(oldRecord)
392
- expect(result.props.richText).toBeDefined()
393
- expect(result.props.text).toBeUndefined()
394
- expect(result.props.color).toBe('green')
395
- expect(result.props.font).toBe('mono')
396
- expect(result.props.size).toBe('s')
397
- expect(result.props.textAlign).toBe('start')
398
- expect(result.props.w).toBe(250)
399
- expect(result.props.scale).toBe(0.8)
400
- expect(result.props.autoSize).toBe(false)
401
- })
402
- })
403
-
404
- // Note: The down migration is explicitly not defined (forced client update)
405
- // so we don't test it
406
- })
407
- })
@@ -1,112 +0,0 @@
1
- import { T } from '@tldraw/validate'
2
- import { describe, expect, it } from 'vitest'
3
- import { getTestMigration } from '../__tests__/migrationTestUtils'
4
- import { TLAssetId } from '../records/TLAsset'
5
- import { videoShapeMigrations, videoShapeProps, videoShapeVersions } from './TLVideoShape'
6
-
7
- describe('TLVideoShape', () => {
8
- describe('videoShapeProps validation', () => {
9
- it('should validate dimensions as nonZeroNumber', () => {
10
- expect(() => videoShapeProps.w.validate(1)).not.toThrow()
11
- expect(() => videoShapeProps.h.validate(100)).not.toThrow()
12
- expect(() => videoShapeProps.w.validate(0)).toThrow()
13
- expect(() => videoShapeProps.h.validate(-1)).toThrow()
14
- })
15
-
16
- it('should validate time as number including negatives', () => {
17
- expect(() => videoShapeProps.time.validate(0)).not.toThrow()
18
- expect(() => videoShapeProps.time.validate(-5)).not.toThrow()
19
- expect(() => videoShapeProps.time.validate(30.5)).not.toThrow()
20
- expect(() => videoShapeProps.time.validate('not-number')).toThrow()
21
- })
22
-
23
- it('should validate boolean properties', () => {
24
- expect(() => videoShapeProps.playing.validate(true)).not.toThrow()
25
- expect(() => videoShapeProps.autoplay.validate(false)).not.toThrow()
26
- expect(() => videoShapeProps.playing.validate('true')).toThrow()
27
- })
28
-
29
- it('should validate URLs and assetIds', () => {
30
- expect(() => videoShapeProps.url.validate('')).not.toThrow()
31
- expect(() => videoShapeProps.url.validate('https://example.com/video.mp4')).not.toThrow()
32
- expect(() => videoShapeProps.assetId.validate(null)).not.toThrow()
33
- expect(() => videoShapeProps.assetId.validate('asset:video123' as TLAssetId)).not.toThrow()
34
- expect(() => videoShapeProps.altText.validate('Alt text')).not.toThrow()
35
- })
36
-
37
- it('should validate complete props object', () => {
38
- const validator = T.object(videoShapeProps)
39
- const validProps = {
40
- w: 640,
41
- h: 480,
42
- time: 0,
43
- playing: false,
44
- autoplay: true,
45
- url: 'https://example.com/video.mp4',
46
- assetId: 'asset:video123' as TLAssetId,
47
- altText: 'Test video',
48
- }
49
- expect(() => validator.validate(validProps)).not.toThrow()
50
- })
51
- })
52
-
53
- describe('videoShapeVersions', () => {
54
- it('should have expected migration versions', () => {
55
- expect(videoShapeVersions.AddUrlProp).toBeDefined()
56
- expect(videoShapeVersions.MakeUrlsValid).toBeDefined()
57
- expect(videoShapeVersions.AddAltText).toBeDefined()
58
- expect(videoShapeVersions.AddAutoplay).toBeDefined()
59
- })
60
- })
61
-
62
- describe('videoShapeMigrations', () => {
63
- it('should add url property in AddUrlProp migration', () => {
64
- const { up } = getTestMigration(videoShapeVersions.AddUrlProp)
65
- const oldRecord = {
66
- props: { w: 640, h: 480, time: 30, playing: true, assetId: 'asset:video123' },
67
- }
68
- const result = up(oldRecord)
69
- expect(result.props.url).toBe('')
70
- expect(result.props.w).toBe(640)
71
- })
72
-
73
- it('should clear invalid URLs in MakeUrlsValid migration', () => {
74
- const { up } = getTestMigration(videoShapeVersions.MakeUrlsValid)
75
- const oldRecord = {
76
- props: { url: 'invalid-url', w: 400, h: 300 },
77
- }
78
- const result = up(oldRecord)
79
- expect(result.props.url).toBe('')
80
- })
81
-
82
- it('should add altText in AddAltText migration', () => {
83
- const { up, down } = getTestMigration(videoShapeVersions.AddAltText)
84
- const oldRecord = { props: { w: 800, h: 600 } }
85
- const result = up(oldRecord)
86
- expect(result.props.altText).toBe('')
87
-
88
- // Test down migration removes altText
89
- const newRecord = { props: { w: 640, h: 480, altText: 'Test' } }
90
- const downResult = down(newRecord)
91
- expect(downResult.props.altText).toBeUndefined()
92
- })
93
-
94
- it('should add autoplay in AddAutoplay migration', () => {
95
- const { up, down } = getTestMigration(videoShapeVersions.AddAutoplay)
96
- const oldRecord = { props: { w: 480, h: 270 } }
97
- const result = up(oldRecord)
98
- expect(result.props.autoplay).toBe(true)
99
-
100
- // Test down migration removes autoplay
101
- const newRecord = { props: { w: 800, h: 450, autoplay: false } }
102
- const downResult = down(newRecord)
103
- expect(downResult.props.autoplay).toBeUndefined()
104
- })
105
-
106
- it('should have migrations for all versions', () => {
107
- expect(videoShapeMigrations.sequence).toBeDefined()
108
- expect(Array.isArray(videoShapeMigrations.sequence)).toBe(true)
109
- expect(videoShapeMigrations.sequence.length).toBeGreaterThanOrEqual(4)
110
- })
111
- })
112
- })