@tldraw/tlschema 4.1.0-canary.e2133d922c9e → 4.1.0-canary.e259b517a450
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/dist-cjs/TLStore.js +3 -10
- package/dist-cjs/TLStore.js.map +2 -2
- package/dist-cjs/assets/TLBaseAsset.js.map +2 -2
- package/dist-cjs/assets/TLBookmarkAsset.js.map +2 -2
- package/dist-cjs/assets/TLImageAsset.js.map +2 -2
- package/dist-cjs/assets/TLVideoAsset.js.map +2 -2
- package/dist-cjs/bindings/TLArrowBinding.js.map +2 -2
- package/dist-cjs/bindings/TLBaseBinding.js.map +2 -2
- package/dist-cjs/createPresenceStateDerivation.js.map +2 -2
- package/dist-cjs/createTLSchema.js.map +2 -2
- package/dist-cjs/index.d.ts +4416 -223
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/misc/TLColor.js.map +2 -2
- package/dist-cjs/misc/TLCursor.js.map +2 -2
- package/dist-cjs/misc/TLHandle.js.map +2 -2
- package/dist-cjs/misc/TLOpacity.js.map +2 -2
- package/dist-cjs/misc/TLRichText.js.map +2 -2
- package/dist-cjs/misc/TLScribble.js.map +2 -2
- package/dist-cjs/misc/geometry-types.js.map +2 -2
- package/dist-cjs/misc/id-validator.js.map +2 -2
- package/dist-cjs/records/TLAsset.js.map +2 -2
- package/dist-cjs/records/TLBinding.js.map +2 -2
- package/dist-cjs/records/TLCamera.js.map +2 -2
- package/dist-cjs/records/TLDocument.js.map +2 -2
- package/dist-cjs/records/TLInstance.js.map +2 -2
- package/dist-cjs/records/TLPage.js.map +2 -2
- package/dist-cjs/records/TLPageState.js.map +2 -2
- package/dist-cjs/records/TLPointer.js.map +2 -2
- package/dist-cjs/records/TLPresence.js.map +2 -2
- package/dist-cjs/records/TLRecord.js.map +1 -1
- package/dist-cjs/records/TLShape.js.map +2 -2
- package/dist-cjs/recordsWithProps.js.map +2 -2
- package/dist-cjs/shapes/ShapeWithCrop.js.map +1 -1
- package/dist-cjs/shapes/TLArrowShape.js.map +2 -2
- package/dist-cjs/shapes/TLBaseShape.js.map +2 -2
- package/dist-cjs/shapes/TLBookmarkShape.js.map +2 -2
- package/dist-cjs/shapes/TLDrawShape.js.map +2 -2
- package/dist-cjs/shapes/TLEmbedShape.js.map +2 -2
- package/dist-cjs/shapes/TLFrameShape.js.map +2 -2
- package/dist-cjs/shapes/TLGeoShape.js.map +2 -2
- package/dist-cjs/shapes/TLGroupShape.js.map +2 -2
- package/dist-cjs/shapes/TLHighlightShape.js.map +2 -2
- package/dist-cjs/shapes/TLImageShape.js.map +2 -2
- package/dist-cjs/shapes/TLLineShape.js.map +2 -2
- package/dist-cjs/shapes/TLNoteShape.js.map +2 -2
- package/dist-cjs/shapes/TLTextShape.js.map +2 -2
- package/dist-cjs/shapes/TLVideoShape.js.map +2 -2
- package/dist-cjs/store-migrations.js.map +2 -2
- package/dist-cjs/styles/TLColorStyle.js.map +2 -2
- package/dist-cjs/styles/TLDashStyle.js.map +2 -2
- package/dist-cjs/styles/TLFillStyle.js.map +2 -2
- package/dist-cjs/styles/TLFontStyle.js.map +2 -2
- package/dist-cjs/styles/TLHorizontalAlignStyle.js.map +2 -2
- package/dist-cjs/styles/TLSizeStyle.js.map +2 -2
- package/dist-cjs/styles/TLTextAlignStyle.js.map +2 -2
- package/dist-cjs/styles/TLVerticalAlignStyle.js.map +2 -2
- package/dist-cjs/translations/translations.js +1 -1
- package/dist-cjs/translations/translations.js.map +2 -2
- package/dist-cjs/util-types.js.map +1 -1
- package/dist-esm/TLStore.mjs +3 -10
- package/dist-esm/TLStore.mjs.map +2 -2
- package/dist-esm/assets/TLBaseAsset.mjs.map +2 -2
- package/dist-esm/assets/TLBookmarkAsset.mjs.map +2 -2
- package/dist-esm/assets/TLImageAsset.mjs.map +2 -2
- package/dist-esm/assets/TLVideoAsset.mjs.map +2 -2
- package/dist-esm/bindings/TLArrowBinding.mjs.map +2 -2
- package/dist-esm/bindings/TLBaseBinding.mjs.map +2 -2
- package/dist-esm/createPresenceStateDerivation.mjs.map +2 -2
- package/dist-esm/createTLSchema.mjs.map +2 -2
- package/dist-esm/index.d.mts +4416 -223
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/misc/TLColor.mjs.map +2 -2
- package/dist-esm/misc/TLCursor.mjs.map +2 -2
- package/dist-esm/misc/TLHandle.mjs.map +2 -2
- package/dist-esm/misc/TLOpacity.mjs.map +2 -2
- package/dist-esm/misc/TLRichText.mjs.map +2 -2
- package/dist-esm/misc/TLScribble.mjs.map +2 -2
- package/dist-esm/misc/geometry-types.mjs.map +2 -2
- package/dist-esm/misc/id-validator.mjs.map +2 -2
- package/dist-esm/records/TLAsset.mjs.map +2 -2
- package/dist-esm/records/TLBinding.mjs.map +2 -2
- package/dist-esm/records/TLCamera.mjs.map +2 -2
- package/dist-esm/records/TLDocument.mjs.map +2 -2
- package/dist-esm/records/TLInstance.mjs.map +2 -2
- package/dist-esm/records/TLPage.mjs.map +2 -2
- package/dist-esm/records/TLPageState.mjs.map +2 -2
- package/dist-esm/records/TLPointer.mjs.map +2 -2
- package/dist-esm/records/TLPresence.mjs.map +2 -2
- package/dist-esm/records/TLShape.mjs.map +2 -2
- package/dist-esm/recordsWithProps.mjs.map +2 -2
- package/dist-esm/shapes/TLArrowShape.mjs.map +2 -2
- package/dist-esm/shapes/TLBaseShape.mjs.map +2 -2
- package/dist-esm/shapes/TLBookmarkShape.mjs.map +2 -2
- package/dist-esm/shapes/TLDrawShape.mjs.map +2 -2
- package/dist-esm/shapes/TLEmbedShape.mjs.map +2 -2
- package/dist-esm/shapes/TLFrameShape.mjs.map +2 -2
- package/dist-esm/shapes/TLGeoShape.mjs.map +2 -2
- package/dist-esm/shapes/TLGroupShape.mjs.map +2 -2
- package/dist-esm/shapes/TLHighlightShape.mjs.map +2 -2
- package/dist-esm/shapes/TLImageShape.mjs.map +2 -2
- package/dist-esm/shapes/TLLineShape.mjs.map +2 -2
- package/dist-esm/shapes/TLNoteShape.mjs.map +2 -2
- package/dist-esm/shapes/TLTextShape.mjs.map +2 -2
- package/dist-esm/shapes/TLVideoShape.mjs.map +2 -2
- package/dist-esm/store-migrations.mjs.map +2 -2
- package/dist-esm/styles/TLColorStyle.mjs.map +2 -2
- package/dist-esm/styles/TLDashStyle.mjs.map +2 -2
- package/dist-esm/styles/TLFillStyle.mjs.map +2 -2
- package/dist-esm/styles/TLFontStyle.mjs.map +2 -2
- package/dist-esm/styles/TLHorizontalAlignStyle.mjs.map +2 -2
- package/dist-esm/styles/TLSizeStyle.mjs.map +2 -2
- package/dist-esm/styles/TLTextAlignStyle.mjs.map +2 -2
- package/dist-esm/styles/TLVerticalAlignStyle.mjs.map +2 -2
- package/dist-esm/translations/translations.mjs +1 -1
- package/dist-esm/translations/translations.mjs.map +2 -2
- package/package.json +5 -5
- package/src/TLStore.test.ts +644 -0
- package/src/TLStore.ts +205 -20
- package/src/assets/TLBaseAsset.ts +90 -7
- package/src/assets/TLBookmarkAsset.test.ts +96 -0
- package/src/assets/TLBookmarkAsset.ts +52 -2
- package/src/assets/TLImageAsset.test.ts +213 -0
- package/src/assets/TLImageAsset.ts +60 -2
- package/src/assets/TLVideoAsset.test.ts +105 -0
- package/src/assets/TLVideoAsset.ts +93 -4
- package/src/bindings/TLArrowBinding.test.ts +55 -0
- package/src/bindings/TLArrowBinding.ts +132 -10
- package/src/bindings/TLBaseBinding.ts +140 -3
- package/src/createPresenceStateDerivation.test.ts +158 -0
- package/src/createPresenceStateDerivation.ts +71 -2
- package/src/createTLSchema.test.ts +181 -0
- package/src/createTLSchema.ts +164 -7
- package/src/index.ts +32 -0
- package/src/misc/TLColor.ts +50 -6
- package/src/misc/TLCursor.ts +110 -8
- package/src/misc/TLHandle.ts +86 -6
- package/src/misc/TLOpacity.ts +51 -2
- package/src/misc/TLRichText.ts +56 -3
- package/src/misc/TLScribble.ts +105 -5
- package/src/misc/geometry-types.ts +30 -2
- package/src/misc/id-validator.test.ts +50 -0
- package/src/misc/id-validator.ts +20 -1
- package/src/records/TLAsset.test.ts +234 -0
- package/src/records/TLAsset.ts +165 -8
- package/src/records/TLBinding.test.ts +22 -0
- package/src/records/TLBinding.ts +277 -11
- package/src/records/TLCamera.test.ts +19 -0
- package/src/records/TLCamera.ts +118 -7
- package/src/records/TLDocument.test.ts +35 -0
- package/src/records/TLDocument.ts +148 -8
- package/src/records/TLInstance.test.ts +201 -0
- package/src/records/TLInstance.ts +117 -9
- package/src/records/TLPage.test.ts +110 -0
- package/src/records/TLPage.ts +106 -8
- package/src/records/TLPageState.test.ts +228 -0
- package/src/records/TLPageState.ts +88 -7
- package/src/records/TLPointer.test.ts +63 -0
- package/src/records/TLPointer.ts +105 -7
- package/src/records/TLPresence.test.ts +190 -0
- package/src/records/TLPresence.ts +99 -5
- package/src/records/TLRecord.test.ts +70 -0
- package/src/records/TLRecord.ts +43 -1
- package/src/records/TLShape.test.ts +232 -0
- package/src/records/TLShape.ts +289 -12
- package/src/recordsWithProps.test.ts +188 -0
- package/src/recordsWithProps.ts +131 -2
- package/src/shapes/ShapeWithCrop.test.ts +18 -0
- package/src/shapes/ShapeWithCrop.ts +64 -2
- package/src/shapes/TLArrowShape.test.ts +505 -0
- package/src/shapes/TLArrowShape.ts +188 -10
- package/src/shapes/TLBaseShape.test.ts +142 -0
- package/src/shapes/TLBaseShape.ts +103 -4
- package/src/shapes/TLBookmarkShape.test.ts +122 -0
- package/src/shapes/TLBookmarkShape.ts +58 -4
- package/src/shapes/TLDrawShape.test.ts +177 -0
- package/src/shapes/TLDrawShape.ts +97 -6
- package/src/shapes/TLEmbedShape.test.ts +286 -0
- package/src/shapes/TLEmbedShape.ts +57 -4
- package/src/shapes/TLFrameShape.test.ts +71 -0
- package/src/shapes/TLFrameShape.ts +59 -4
- package/src/shapes/TLGeoShape.test.ts +247 -0
- package/src/shapes/TLGeoShape.ts +103 -7
- package/src/shapes/TLGroupShape.test.ts +59 -0
- package/src/shapes/TLGroupShape.ts +52 -4
- package/src/shapes/TLHighlightShape.test.ts +325 -0
- package/src/shapes/TLHighlightShape.ts +79 -4
- package/src/shapes/TLImageShape.test.ts +534 -0
- package/src/shapes/TLImageShape.ts +105 -5
- package/src/shapes/TLLineShape.test.ts +269 -0
- package/src/shapes/TLLineShape.ts +128 -8
- package/src/shapes/TLNoteShape.test.ts +1568 -0
- package/src/shapes/TLNoteShape.ts +97 -4
- package/src/shapes/TLTextShape.test.ts +407 -0
- package/src/shapes/TLTextShape.ts +94 -4
- package/src/shapes/TLVideoShape.test.ts +112 -0
- package/src/shapes/TLVideoShape.ts +99 -4
- package/src/store-migrations.test.ts +88 -0
- package/src/store-migrations.ts +47 -1
- package/src/styles/TLColorStyle.test.ts +439 -0
- package/src/styles/TLColorStyle.ts +228 -10
- package/src/styles/TLDashStyle.ts +54 -2
- package/src/styles/TLFillStyle.ts +54 -2
- package/src/styles/TLFontStyle.ts +72 -3
- package/src/styles/TLHorizontalAlignStyle.ts +55 -2
- package/src/styles/TLSizeStyle.ts +54 -2
- package/src/styles/TLTextAlignStyle.ts +52 -2
- package/src/styles/TLVerticalAlignStyle.ts +52 -2
- package/src/translations/translations.test.ts +378 -35
- package/src/translations/translations.ts +157 -10
- package/src/util-types.ts +51 -1
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
import { describe, expect, it, test } from 'vitest'
|
|
2
|
+
import { getTestMigration } from '../__tests__/migrationTestUtils'
|
|
3
|
+
import { arrowShapeMigrations, arrowShapeProps, arrowShapeVersions } from './TLArrowShape'
|
|
4
|
+
|
|
5
|
+
describe('TLArrowShape', () => {
|
|
6
|
+
describe('arrowShapeMigrations - AddLabelColor migration', () => {
|
|
7
|
+
const { up, down } = getTestMigration(arrowShapeVersions.AddLabelColor)
|
|
8
|
+
|
|
9
|
+
describe('AddLabelColor up migration', () => {
|
|
10
|
+
it('should add labelColor property with default value "black"', () => {
|
|
11
|
+
const oldRecord = {
|
|
12
|
+
id: 'shape:arrow1',
|
|
13
|
+
typeName: 'shape',
|
|
14
|
+
type: 'arrow',
|
|
15
|
+
x: 100,
|
|
16
|
+
y: 200,
|
|
17
|
+
rotation: 0,
|
|
18
|
+
index: 'a1',
|
|
19
|
+
parentId: 'page:main',
|
|
20
|
+
isLocked: false,
|
|
21
|
+
opacity: 1,
|
|
22
|
+
props: {
|
|
23
|
+
color: 'blue',
|
|
24
|
+
fill: 'none',
|
|
25
|
+
dash: 'solid',
|
|
26
|
+
size: 'm',
|
|
27
|
+
arrowheadStart: 'none',
|
|
28
|
+
arrowheadEnd: 'arrow',
|
|
29
|
+
font: 'draw',
|
|
30
|
+
start: { x: 0, y: 0 },
|
|
31
|
+
end: { x: 100, y: 100 },
|
|
32
|
+
},
|
|
33
|
+
meta: {},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const result = up(oldRecord)
|
|
37
|
+
expect(result.props.labelColor).toBe('black')
|
|
38
|
+
expect(result.props.color).toBe('blue') // Preserve other props
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should preserve all existing properties during migration', () => {
|
|
42
|
+
const oldRecord = {
|
|
43
|
+
id: 'shape:arrow2',
|
|
44
|
+
typeName: 'shape',
|
|
45
|
+
type: 'arrow',
|
|
46
|
+
x: 50,
|
|
47
|
+
y: 75,
|
|
48
|
+
rotation: 0.5,
|
|
49
|
+
index: 'b1',
|
|
50
|
+
parentId: 'page:test',
|
|
51
|
+
isLocked: true,
|
|
52
|
+
opacity: 0.8,
|
|
53
|
+
props: {
|
|
54
|
+
color: 'red',
|
|
55
|
+
fill: 'solid',
|
|
56
|
+
dash: 'dashed',
|
|
57
|
+
size: 'l',
|
|
58
|
+
arrowheadStart: 'triangle',
|
|
59
|
+
arrowheadEnd: 'diamond',
|
|
60
|
+
font: 'sans',
|
|
61
|
+
start: { x: 25, y: 50 },
|
|
62
|
+
end: { x: 200, y: 150 },
|
|
63
|
+
},
|
|
64
|
+
meta: { custom: 'data' },
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const result = up(oldRecord)
|
|
68
|
+
expect(result.props.labelColor).toBe('black')
|
|
69
|
+
expect(result.props.color).toBe('red')
|
|
70
|
+
expect(result.props.fill).toBe('solid')
|
|
71
|
+
expect(result.props.dash).toBe('dashed')
|
|
72
|
+
expect(result.props.size).toBe('l')
|
|
73
|
+
expect(result.props.arrowheadStart).toBe('triangle')
|
|
74
|
+
expect(result.props.arrowheadEnd).toBe('diamond')
|
|
75
|
+
expect(result.props.font).toBe('sans')
|
|
76
|
+
expect(result.props.start).toEqual({ x: 25, y: 50 })
|
|
77
|
+
expect(result.props.end).toEqual({ x: 200, y: 150 })
|
|
78
|
+
expect(result.meta).toEqual({ custom: 'data' })
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('should not modify labelColor if it already exists', () => {
|
|
82
|
+
const recordWithLabelColor = {
|
|
83
|
+
id: 'shape:arrow3',
|
|
84
|
+
typeName: 'shape',
|
|
85
|
+
type: 'arrow',
|
|
86
|
+
props: {
|
|
87
|
+
labelColor: 'red', // Already has labelColor
|
|
88
|
+
color: 'blue',
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const result = up(recordWithLabelColor)
|
|
93
|
+
expect(result.props.labelColor).toBe('black') // Migration sets default regardless
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
describe('AddLabelColor down migration', () => {
|
|
98
|
+
it('should be retired (no down migration)', () => {
|
|
99
|
+
// Based on the source code, the down migration is 'retired'
|
|
100
|
+
// The getTestMigration utility should throw when trying to access down migration
|
|
101
|
+
expect(() => {
|
|
102
|
+
// This should throw since the migration is retired
|
|
103
|
+
down({})
|
|
104
|
+
}).toThrow('Migration com.tldraw.shape.arrow/1 does not have a down function')
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
describe('arrowShapeMigrations - AddIsPrecise migration', () => {
|
|
110
|
+
const { up, down } = getTestMigration(arrowShapeVersions.AddIsPrecise)
|
|
111
|
+
|
|
112
|
+
describe('AddIsPrecise up migration', () => {
|
|
113
|
+
it('should add isPrecise property to binding start and end', () => {
|
|
114
|
+
const oldRecord = {
|
|
115
|
+
id: 'shape:arrow1',
|
|
116
|
+
props: {
|
|
117
|
+
start: {
|
|
118
|
+
type: 'binding',
|
|
119
|
+
boundShapeId: 'shape:rect1',
|
|
120
|
+
normalizedAnchor: { x: 0.5, y: 0.5 },
|
|
121
|
+
},
|
|
122
|
+
end: {
|
|
123
|
+
type: 'binding',
|
|
124
|
+
boundShapeId: 'shape:rect2',
|
|
125
|
+
normalizedAnchor: { x: 0.5, y: 0.5 },
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const result = up(oldRecord)
|
|
131
|
+
expect(result.props.start.isPrecise).toBe(false) // 0.5, 0.5 is not precise
|
|
132
|
+
expect(result.props.end.isPrecise).toBe(false)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('should set isPrecise to true for non-center anchors', () => {
|
|
136
|
+
const oldRecord = {
|
|
137
|
+
id: 'shape:arrow1',
|
|
138
|
+
props: {
|
|
139
|
+
start: {
|
|
140
|
+
type: 'binding',
|
|
141
|
+
boundShapeId: 'shape:rect1',
|
|
142
|
+
normalizedAnchor: { x: 0.25, y: 0.75 }, // Not center
|
|
143
|
+
},
|
|
144
|
+
end: {
|
|
145
|
+
type: 'binding',
|
|
146
|
+
boundShapeId: 'shape:rect2',
|
|
147
|
+
normalizedAnchor: { x: 1, y: 0 }, // Not center
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const result = up(oldRecord)
|
|
153
|
+
expect(result.props.start.isPrecise).toBe(true)
|
|
154
|
+
expect(result.props.end.isPrecise).toBe(true)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('should not modify non-binding terminals', () => {
|
|
158
|
+
const oldRecord = {
|
|
159
|
+
id: 'shape:arrow1',
|
|
160
|
+
props: {
|
|
161
|
+
start: { type: 'point', x: 0, y: 0 },
|
|
162
|
+
end: { type: 'point', x: 100, y: 100 },
|
|
163
|
+
},
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const result = up(oldRecord)
|
|
167
|
+
expect(result.props.start.isPrecise).toBeUndefined()
|
|
168
|
+
expect(result.props.end.isPrecise).toBeUndefined()
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
it('should handle mixed binding and point terminals', () => {
|
|
172
|
+
const oldRecord = {
|
|
173
|
+
id: 'shape:arrow1',
|
|
174
|
+
props: {
|
|
175
|
+
start: {
|
|
176
|
+
type: 'binding',
|
|
177
|
+
boundShapeId: 'shape:rect1',
|
|
178
|
+
normalizedAnchor: { x: 0, y: 0 }, // Precise
|
|
179
|
+
},
|
|
180
|
+
end: { type: 'point', x: 100, y: 100 },
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const result = up(oldRecord)
|
|
185
|
+
expect(result.props.start.isPrecise).toBe(true)
|
|
186
|
+
expect(result.props.end.isPrecise).toBeUndefined()
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
describe('AddIsPrecise down migration', () => {
|
|
191
|
+
it('should remove isPrecise property and adjust normalizedAnchor if not precise', () => {
|
|
192
|
+
const newRecord = {
|
|
193
|
+
id: 'shape:arrow1',
|
|
194
|
+
props: {
|
|
195
|
+
start: {
|
|
196
|
+
type: 'binding',
|
|
197
|
+
boundShapeId: 'shape:rect1',
|
|
198
|
+
normalizedAnchor: { x: 0.25, y: 0.75 },
|
|
199
|
+
isPrecise: false,
|
|
200
|
+
},
|
|
201
|
+
end: {
|
|
202
|
+
type: 'binding',
|
|
203
|
+
boundShapeId: 'shape:rect2',
|
|
204
|
+
normalizedAnchor: { x: 0.1, y: 0.9 },
|
|
205
|
+
isPrecise: true,
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const result = down(newRecord)
|
|
211
|
+
expect(result.props.start.isPrecise).toBeUndefined()
|
|
212
|
+
expect(result.props.start.normalizedAnchor).toEqual({ x: 0.5, y: 0.5 }) // Reset to center
|
|
213
|
+
expect(result.props.end.isPrecise).toBeUndefined()
|
|
214
|
+
expect(result.props.end.normalizedAnchor).toEqual({ x: 0.1, y: 0.9 }) // Keep precise anchor
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it('should not modify non-binding terminals', () => {
|
|
218
|
+
const newRecord = {
|
|
219
|
+
id: 'shape:arrow1',
|
|
220
|
+
props: {
|
|
221
|
+
start: { type: 'point', x: 0, y: 0 },
|
|
222
|
+
end: { type: 'point', x: 100, y: 100 },
|
|
223
|
+
},
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const result = down(newRecord)
|
|
227
|
+
expect(result.props.start).toEqual({ type: 'point', x: 0, y: 0 })
|
|
228
|
+
expect(result.props.end).toEqual({ type: 'point', x: 100, y: 100 })
|
|
229
|
+
})
|
|
230
|
+
})
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
describe('arrowShapeMigrations - AddLabelPosition migration', () => {
|
|
234
|
+
const { up, down } = getTestMigration(arrowShapeVersions.AddLabelPosition)
|
|
235
|
+
|
|
236
|
+
describe('AddLabelPosition up migration', () => {
|
|
237
|
+
it('should add labelPosition property with default value 0.5', () => {
|
|
238
|
+
const oldRecord = {
|
|
239
|
+
id: 'shape:arrow1',
|
|
240
|
+
props: {
|
|
241
|
+
color: 'blue',
|
|
242
|
+
start: { x: 0, y: 0 },
|
|
243
|
+
end: { x: 100, y: 100 },
|
|
244
|
+
},
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const result = up(oldRecord)
|
|
248
|
+
expect(result.props.labelPosition).toBe(0.5)
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('should preserve existing properties during migration', () => {
|
|
252
|
+
const oldRecord = {
|
|
253
|
+
id: 'shape:arrow1',
|
|
254
|
+
props: {
|
|
255
|
+
color: 'red',
|
|
256
|
+
fill: 'solid',
|
|
257
|
+
start: { x: 25, y: 50 },
|
|
258
|
+
end: { x: 200, y: 150 },
|
|
259
|
+
bend: 0.3,
|
|
260
|
+
},
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const result = up(oldRecord)
|
|
264
|
+
expect(result.props.labelPosition).toBe(0.5)
|
|
265
|
+
expect(result.props.color).toBe('red')
|
|
266
|
+
expect(result.props.fill).toBe('solid')
|
|
267
|
+
expect(result.props.start).toEqual({ x: 25, y: 50 })
|
|
268
|
+
expect(result.props.end).toEqual({ x: 200, y: 150 })
|
|
269
|
+
expect(result.props.bend).toBe(0.3)
|
|
270
|
+
})
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
describe('AddLabelPosition down migration', () => {
|
|
274
|
+
it('should remove labelPosition property', () => {
|
|
275
|
+
const newRecord = {
|
|
276
|
+
id: 'shape:arrow1',
|
|
277
|
+
props: {
|
|
278
|
+
color: 'blue',
|
|
279
|
+
start: { x: 0, y: 0 },
|
|
280
|
+
end: { x: 100, y: 100 },
|
|
281
|
+
labelPosition: 0.7,
|
|
282
|
+
},
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const result = down(newRecord)
|
|
286
|
+
expect(result.props.labelPosition).toBeUndefined()
|
|
287
|
+
expect(result.props.color).toBe('blue') // Preserve other props
|
|
288
|
+
})
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
describe('arrowShapeMigrations - ExtractBindings migration', () => {
|
|
293
|
+
const migration = arrowShapeMigrations.sequence.find(
|
|
294
|
+
(m) => 'id' in m && m.id === arrowShapeVersions.ExtractBindings
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
it('should be a store-scope migration', () => {
|
|
298
|
+
expect(migration).toBeDefined()
|
|
299
|
+
if (migration && 'scope' in migration) {
|
|
300
|
+
expect(migration.scope).toBe('store')
|
|
301
|
+
}
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it('should have up function for extracting bindings', () => {
|
|
305
|
+
if (migration && 'up' in migration) {
|
|
306
|
+
expect(migration.up).toBeDefined()
|
|
307
|
+
expect(typeof migration.up).toBe('function')
|
|
308
|
+
}
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
// Note: This migration is complex and modifies the entire store
|
|
312
|
+
// Testing the full migration would require setting up a mock store
|
|
313
|
+
// The migration extracts binding information from arrow terminals
|
|
314
|
+
// and creates separate binding records
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
describe('arrowShapeMigrations - AddScale migration', () => {
|
|
318
|
+
const { up, down } = getTestMigration(arrowShapeVersions.AddScale)
|
|
319
|
+
|
|
320
|
+
describe('AddScale up migration', () => {
|
|
321
|
+
it('should add scale property with default value 1', () => {
|
|
322
|
+
const oldRecord = {
|
|
323
|
+
id: 'shape:arrow1',
|
|
324
|
+
props: {
|
|
325
|
+
color: 'blue',
|
|
326
|
+
start: { x: 0, y: 0 },
|
|
327
|
+
end: { x: 100, y: 100 },
|
|
328
|
+
},
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const result = up(oldRecord)
|
|
332
|
+
expect(result.props.scale).toBe(1)
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
it('should preserve existing properties during migration', () => {
|
|
336
|
+
const oldRecord = {
|
|
337
|
+
id: 'shape:arrow1',
|
|
338
|
+
props: {
|
|
339
|
+
color: 'red',
|
|
340
|
+
labelPosition: 0.3,
|
|
341
|
+
start: { x: 10, y: 20 },
|
|
342
|
+
end: { x: 200, y: 150 },
|
|
343
|
+
},
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const result = up(oldRecord)
|
|
347
|
+
expect(result.props.scale).toBe(1)
|
|
348
|
+
expect(result.props.color).toBe('red')
|
|
349
|
+
expect(result.props.labelPosition).toBe(0.3)
|
|
350
|
+
})
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
describe('AddScale down migration', () => {
|
|
354
|
+
it('should remove scale property', () => {
|
|
355
|
+
const newRecord = {
|
|
356
|
+
id: 'shape:arrow1',
|
|
357
|
+
props: {
|
|
358
|
+
color: 'blue',
|
|
359
|
+
start: { x: 0, y: 0 },
|
|
360
|
+
end: { x: 100, y: 100 },
|
|
361
|
+
scale: 1.5,
|
|
362
|
+
},
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const result = down(newRecord)
|
|
366
|
+
expect(result.props.scale).toBeUndefined()
|
|
367
|
+
expect(result.props.color).toBe('blue') // Preserve other props
|
|
368
|
+
})
|
|
369
|
+
})
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
describe('arrowShapeMigrations - AddElbow migration', () => {
|
|
373
|
+
const { up, down } = getTestMigration(arrowShapeVersions.AddElbow)
|
|
374
|
+
|
|
375
|
+
describe('AddElbow up migration', () => {
|
|
376
|
+
it('should add kind and elbowMidPoint properties with default values', () => {
|
|
377
|
+
const oldRecord = {
|
|
378
|
+
id: 'shape:arrow1',
|
|
379
|
+
props: {
|
|
380
|
+
color: 'blue',
|
|
381
|
+
start: { x: 0, y: 0 },
|
|
382
|
+
end: { x: 100, y: 100 },
|
|
383
|
+
},
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const result = up(oldRecord)
|
|
387
|
+
expect(result.props.kind).toBe('arc')
|
|
388
|
+
expect(result.props.elbowMidPoint).toBe(0.5)
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
it('should preserve existing properties during migration', () => {
|
|
392
|
+
const oldRecord = {
|
|
393
|
+
id: 'shape:arrow1',
|
|
394
|
+
props: {
|
|
395
|
+
color: 'red',
|
|
396
|
+
scale: 1.2,
|
|
397
|
+
labelPosition: 0.7,
|
|
398
|
+
start: { x: 25, y: 50 },
|
|
399
|
+
end: { x: 200, y: 150 },
|
|
400
|
+
},
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const result = up(oldRecord)
|
|
404
|
+
expect(result.props.kind).toBe('arc')
|
|
405
|
+
expect(result.props.elbowMidPoint).toBe(0.5)
|
|
406
|
+
expect(result.props.color).toBe('red')
|
|
407
|
+
expect(result.props.scale).toBe(1.2)
|
|
408
|
+
expect(result.props.labelPosition).toBe(0.7)
|
|
409
|
+
})
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
describe('AddElbow down migration', () => {
|
|
413
|
+
it('should remove kind and elbowMidPoint properties', () => {
|
|
414
|
+
const newRecord = {
|
|
415
|
+
id: 'shape:arrow1',
|
|
416
|
+
props: {
|
|
417
|
+
kind: 'elbow',
|
|
418
|
+
elbowMidPoint: 0.3,
|
|
419
|
+
color: 'blue',
|
|
420
|
+
start: { x: 0, y: 0 },
|
|
421
|
+
end: { x: 100, y: 100 },
|
|
422
|
+
},
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const result = down(newRecord)
|
|
426
|
+
expect(result.props.kind).toBeUndefined()
|
|
427
|
+
expect(result.props.elbowMidPoint).toBeUndefined()
|
|
428
|
+
expect(result.props.color).toBe('blue') // Preserve other props
|
|
429
|
+
})
|
|
430
|
+
})
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
describe('arrowShapeMigrations - AddRichText migration', () => {
|
|
434
|
+
const { up } = getTestMigration(arrowShapeVersions.AddRichText)
|
|
435
|
+
|
|
436
|
+
describe('AddRichText up migration', () => {
|
|
437
|
+
it('should convert text property to richText', () => {
|
|
438
|
+
const oldRecord = {
|
|
439
|
+
id: 'shape:arrow1',
|
|
440
|
+
props: {
|
|
441
|
+
text: 'Simple text label',
|
|
442
|
+
color: 'blue',
|
|
443
|
+
start: { x: 0, y: 0 },
|
|
444
|
+
end: { x: 100, y: 100 },
|
|
445
|
+
},
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const result = up(oldRecord)
|
|
449
|
+
expect(result.props.richText).toBeDefined()
|
|
450
|
+
expect(result.props.text).toBeUndefined()
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
it('should handle empty text', () => {
|
|
454
|
+
const oldRecord = {
|
|
455
|
+
id: 'shape:arrow1',
|
|
456
|
+
props: {
|
|
457
|
+
text: '',
|
|
458
|
+
color: 'red',
|
|
459
|
+
start: { x: 10, y: 20 },
|
|
460
|
+
end: { x: 200, y: 150 },
|
|
461
|
+
},
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const result = up(oldRecord)
|
|
465
|
+
expect(result.props.richText).toBeDefined()
|
|
466
|
+
expect(result.props.text).toBeUndefined()
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
it('should preserve other properties during migration', () => {
|
|
470
|
+
const oldRecord = {
|
|
471
|
+
id: 'shape:arrow1',
|
|
472
|
+
props: {
|
|
473
|
+
text: 'Label text',
|
|
474
|
+
kind: 'elbow',
|
|
475
|
+
elbowMidPoint: 0.3,
|
|
476
|
+
color: 'green',
|
|
477
|
+
scale: 1.5,
|
|
478
|
+
},
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const result = up(oldRecord)
|
|
482
|
+
expect(result.props.richText).toBeDefined()
|
|
483
|
+
expect(result.props.text).toBeUndefined()
|
|
484
|
+
expect(result.props.kind).toBe('elbow')
|
|
485
|
+
expect(result.props.elbowMidPoint).toBe(0.3)
|
|
486
|
+
expect(result.props.color).toBe('green')
|
|
487
|
+
expect(result.props.scale).toBe(1.5)
|
|
488
|
+
})
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
// Note: The down migration is explicitly not defined (forced client update)
|
|
492
|
+
// so we don't test it
|
|
493
|
+
})
|
|
494
|
+
|
|
495
|
+
describe('edge cases and error handling', () => {
|
|
496
|
+
it('should handle zero scale validation correctly', () => {
|
|
497
|
+
// Zero should be invalid for scale (nonZeroNumber)
|
|
498
|
+
expect(() => arrowShapeProps.scale.validate(0)).toThrow()
|
|
499
|
+
|
|
500
|
+
// Very small positive numbers should be valid, but negative numbers should be invalid
|
|
501
|
+
expect(() => arrowShapeProps.scale.validate(0.0001)).not.toThrow()
|
|
502
|
+
expect(() => arrowShapeProps.scale.validate(-0.0001)).toThrow()
|
|
503
|
+
})
|
|
504
|
+
})
|
|
505
|
+
})
|