@tldraw/editor 3.16.0-internal.51e99e128bd4 → 3.16.0-internal.a478398270c6
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/index.d.ts +16 -217
- package/dist-cjs/index.js +1 -8
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +1 -3
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +5 -0
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/SVGContainer.js +1 -1
- package/dist-cjs/lib/components/SVGContainer.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +26 -4
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultBrush.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCursor.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultGrid.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultGrid.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultHandles.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultHandles.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +1 -9
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultSpinner.js +15 -27
- package/dist-cjs/lib/components/default-components/DefaultSpinner.js.map +3 -3
- package/dist-cjs/lib/config/TLUserPreferences.js +3 -15
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +67 -134
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +4 -14
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +1 -20
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js +2 -1
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +20 -24
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useEditor.js +4 -1
- package/dist-cjs/lib/hooks/useEditor.js.map +2 -2
- package/dist-cjs/lib/hooks/useEditorComponents.js +0 -2
- package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
- package/dist-cjs/lib/license/Watermark.js +8 -8
- package/dist-cjs/lib/license/Watermark.js.map +2 -2
- package/dist-cjs/lib/options.js +0 -7
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Arc2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +1 -3
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/geometry-constants.js +2 -2
- package/dist-cjs/lib/primitives/geometry/geometry-constants.js.map +2 -2
- package/dist-cjs/lib/primitives/intersect.js +4 -4
- package/dist-cjs/lib/primitives/intersect.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +0 -4
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +1 -0
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +16 -217
- package/dist-esm/index.mjs +2 -16
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +1 -3
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +5 -0
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/SVGContainer.mjs +1 -1
- package/dist-esm/lib/components/SVGContainer.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +26 -4
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultGrid.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultGrid.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -9
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultSpinner.mjs +15 -17
- package/dist-esm/lib/components/default-components/DefaultSpinner.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +3 -15
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +67 -134
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +4 -14
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +1 -20
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +21 -25
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditor.mjs +4 -1
- package/dist-esm/lib/hooks/useEditor.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditorComponents.mjs +0 -4
- package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
- package/dist-esm/lib/license/Watermark.mjs +8 -8
- package/dist-esm/lib/license/Watermark.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +0 -7
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +1 -3
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/geometry-constants.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/geometry-constants.mjs.map +2 -2
- package/dist-esm/lib/primitives/intersect.mjs +5 -5
- package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +0 -4
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +1 -0
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +313 -312
- package/package.json +38 -16
- package/src/index.ts +1 -15
- package/src/lib/TldrawEditor.tsx +5 -7
- package/src/lib/components/MenuClickCapture.tsx +8 -0
- package/src/lib/components/SVGContainer.tsx +1 -1
- package/src/lib/components/Shape.tsx +21 -6
- package/src/lib/components/default-components/DefaultBrush.tsx +1 -1
- package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +2 -2
- package/src/lib/components/default-components/DefaultCursor.tsx +1 -1
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/components/default-components/DefaultGrid.tsx +1 -1
- package/src/lib/components/default-components/DefaultHandles.tsx +1 -5
- package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +2 -6
- package/src/lib/components/default-components/DefaultSnapIndictor.tsx +1 -1
- package/src/lib/components/default-components/DefaultSpinner.tsx +12 -12
- package/src/lib/config/TLUserPreferences.ts +1 -15
- package/src/lib/editor/Editor.test.ts +8 -416
- package/src/lib/editor/Editor.ts +92 -177
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +14 -15
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +15 -16
- package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +48 -49
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +23 -24
- package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +6 -7
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +11 -12
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +50 -57
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +26 -51
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +13 -14
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +26 -55
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -14
- package/src/lib/editor/shapes/ShapeUtil.ts +0 -57
- package/src/lib/editor/tools/StateNode.ts +1 -27
- package/src/lib/editor/types/misc-types.ts +1 -73
- package/src/lib/exports/getSvgJsx.tsx +2 -2
- package/src/lib/hooks/useCanvasEvents.ts +32 -39
- package/src/lib/hooks/useEditor.tsx +5 -6
- package/src/lib/hooks/useEditorComponents.tsx +2 -8
- package/src/lib/license/LicenseManager.test.ts +1 -3
- package/src/lib/license/Watermark.test.tsx +1 -2
- package/src/lib/license/Watermark.tsx +8 -8
- package/src/lib/options.ts +0 -8
- package/src/lib/primitives/geometry/Arc2d.ts +2 -2
- package/src/lib/primitives/geometry/Circle2d.ts +2 -2
- package/src/lib/primitives/geometry/CubicBezier2d.ts +1 -4
- package/src/lib/primitives/geometry/Ellipse2d.ts +2 -2
- package/src/lib/primitives/geometry/geometry-constants.ts +1 -2
- package/src/lib/primitives/intersect.ts +5 -12
- package/src/lib/primitives/utils.ts +0 -11
- package/src/lib/test/currentToolIdMask.test.ts +49 -0
- package/src/lib/utils/sync/LocalIndexedDb.test.ts +1 -2
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
- package/src/lib/utils/sync/TLLocalSyncClient.ts +1 -0
- package/src/version.ts +3 -3
- package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js +0 -53
- package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js.map +0 -7
- package/dist-cjs/lib/hooks/useStateAttribute.js +0 -35
- package/dist-cjs/lib/hooks/useStateAttribute.js.map +0 -7
- package/dist-cjs/lib/utils/EditorAtom.js +0 -45
- package/dist-cjs/lib/utils/EditorAtom.js.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs +0 -23
- package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs.map +0 -7
- package/dist-esm/lib/hooks/useStateAttribute.mjs +0 -15
- package/dist-esm/lib/hooks/useStateAttribute.mjs.map +0 -7
- package/dist-esm/lib/utils/EditorAtom.mjs +0 -25
- package/dist-esm/lib/utils/EditorAtom.mjs.map +0 -7
- package/src/lib/components/default-components/DefaultShapeWrapper.tsx +0 -35
- package/src/lib/editor/tools/StateNode.test.ts +0 -285
- package/src/lib/hooks/useStateAttribute.ts +0 -15
- package/src/lib/primitives/intersect.test.ts +0 -946
- package/src/lib/utils/EditorAtom.ts +0 -37
|
@@ -1,59 +1,58 @@
|
|
|
1
|
-
import { Mock, Mocked, vi } from 'vitest'
|
|
2
1
|
import { Editor } from '../../Editor'
|
|
3
2
|
import { FocusManager } from './FocusManager'
|
|
4
3
|
|
|
5
4
|
// Mock the Editor class
|
|
6
|
-
|
|
5
|
+
jest.mock('../../Editor')
|
|
7
6
|
|
|
8
7
|
describe('FocusManager', () => {
|
|
9
|
-
let editor: Mocked<
|
|
8
|
+
let editor: jest.Mocked<
|
|
10
9
|
Editor & {
|
|
11
10
|
sideEffects: {
|
|
12
|
-
registerAfterChangeHandler: Mock
|
|
11
|
+
registerAfterChangeHandler: jest.Mock
|
|
13
12
|
}
|
|
14
|
-
getInstanceState: Mock
|
|
15
|
-
updateInstanceState: Mock
|
|
16
|
-
getContainer: Mock
|
|
17
|
-
isIn: Mock
|
|
18
|
-
getSelectedShapeIds: Mock
|
|
19
|
-
complete: Mock
|
|
13
|
+
getInstanceState: jest.Mock
|
|
14
|
+
updateInstanceState: jest.Mock
|
|
15
|
+
getContainer: jest.Mock
|
|
16
|
+
isIn: jest.Mock
|
|
17
|
+
getSelectedShapeIds: jest.Mock
|
|
18
|
+
complete: jest.Mock
|
|
20
19
|
}
|
|
21
20
|
>
|
|
22
21
|
let focusManager: FocusManager
|
|
23
22
|
let mockContainer: HTMLElement
|
|
24
|
-
let mockDispose: Mock
|
|
23
|
+
let mockDispose: jest.Mock
|
|
25
24
|
let originalAddEventListener: typeof document.body.addEventListener
|
|
26
25
|
let originalRemoveEventListener: typeof document.body.removeEventListener
|
|
27
26
|
|
|
28
27
|
beforeEach(() => {
|
|
29
28
|
// Create mock container element
|
|
30
29
|
mockContainer = document.createElement('div')
|
|
31
|
-
mockContainer.focus =
|
|
32
|
-
mockContainer.blur =
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
mockContainer.focus = jest.fn()
|
|
31
|
+
mockContainer.blur = jest.fn()
|
|
32
|
+
jest.spyOn(mockContainer.classList, 'add')
|
|
33
|
+
jest.spyOn(mockContainer.classList, 'remove')
|
|
35
34
|
|
|
36
35
|
// Create mock dispose function
|
|
37
|
-
mockDispose =
|
|
36
|
+
mockDispose = jest.fn()
|
|
38
37
|
|
|
39
38
|
// Mock editor
|
|
40
39
|
editor = {
|
|
41
40
|
sideEffects: {
|
|
42
|
-
registerAfterChangeHandler:
|
|
41
|
+
registerAfterChangeHandler: jest.fn(() => mockDispose),
|
|
43
42
|
},
|
|
44
|
-
getInstanceState:
|
|
45
|
-
updateInstanceState:
|
|
46
|
-
getContainer:
|
|
47
|
-
isIn:
|
|
48
|
-
getSelectedShapeIds:
|
|
49
|
-
complete:
|
|
43
|
+
getInstanceState: jest.fn(() => ({ isFocused: false })),
|
|
44
|
+
updateInstanceState: jest.fn(),
|
|
45
|
+
getContainer: jest.fn(() => mockContainer),
|
|
46
|
+
isIn: jest.fn(() => false),
|
|
47
|
+
getSelectedShapeIds: jest.fn(() => []),
|
|
48
|
+
complete: jest.fn(),
|
|
50
49
|
} as any
|
|
51
50
|
|
|
52
51
|
// Mock document.body event listeners
|
|
53
52
|
originalAddEventListener = document.body.addEventListener
|
|
54
53
|
originalRemoveEventListener = document.body.removeEventListener
|
|
55
|
-
document.body.addEventListener =
|
|
56
|
-
document.body.removeEventListener =
|
|
54
|
+
document.body.addEventListener = jest.fn()
|
|
55
|
+
document.body.removeEventListener = jest.fn()
|
|
57
56
|
})
|
|
58
57
|
|
|
59
58
|
afterEach(() => {
|
|
@@ -66,7 +65,7 @@ describe('FocusManager', () => {
|
|
|
66
65
|
focusManager.dispose()
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
jest.clearAllMocks()
|
|
70
69
|
})
|
|
71
70
|
|
|
72
71
|
describe('constructor', () => {
|
|
@@ -132,7 +131,7 @@ describe('FocusManager', () => {
|
|
|
132
131
|
const handler = handlerCall[1]
|
|
133
132
|
|
|
134
133
|
// Clear previous calls
|
|
135
|
-
|
|
134
|
+
jest.clearAllMocks()
|
|
136
135
|
|
|
137
136
|
// Simulate focus state change
|
|
138
137
|
const prev = { isFocused: false }
|
|
@@ -150,7 +149,7 @@ describe('FocusManager', () => {
|
|
|
150
149
|
const handlerCall = editor.sideEffects.registerAfterChangeHandler.mock.calls[0]
|
|
151
150
|
const handler = handlerCall[1]
|
|
152
151
|
|
|
153
|
-
|
|
152
|
+
jest.clearAllMocks()
|
|
154
153
|
|
|
155
154
|
// Simulate no focus state change
|
|
156
155
|
const prev = { isFocused: true }
|
|
@@ -171,7 +170,7 @@ describe('FocusManager', () => {
|
|
|
171
170
|
// Get the handler before clearing mocks
|
|
172
171
|
const handlerCall = editor.sideEffects.registerAfterChangeHandler.mock.calls[0]
|
|
173
172
|
handler = handlerCall[1]
|
|
174
|
-
|
|
173
|
+
jest.clearAllMocks()
|
|
175
174
|
})
|
|
176
175
|
|
|
177
176
|
it('should add focused class when editor is focused', () => {
|
|
@@ -206,11 +205,11 @@ describe('FocusManager', () => {
|
|
|
206
205
|
focusManager = new FocusManager(editor)
|
|
207
206
|
|
|
208
207
|
// Get the keydown handler that was registered
|
|
209
|
-
const addEventListenerCalls = (document.body.addEventListener as Mock).mock.calls
|
|
210
|
-
const keydownCall = addEventListenerCalls.find((call
|
|
211
|
-
keydownHandler = keydownCall
|
|
208
|
+
const addEventListenerCalls = (document.body.addEventListener as jest.Mock).mock.calls
|
|
209
|
+
const keydownCall = addEventListenerCalls.find((call) => call[0] === 'keydown')
|
|
210
|
+
keydownHandler = keydownCall[1]
|
|
212
211
|
|
|
213
|
-
|
|
212
|
+
jest.clearAllMocks()
|
|
214
213
|
})
|
|
215
214
|
|
|
216
215
|
it('should remove no-focus-ring class on Tab key', () => {
|
|
@@ -284,11 +283,11 @@ describe('FocusManager', () => {
|
|
|
284
283
|
focusManager = new FocusManager(editor)
|
|
285
284
|
|
|
286
285
|
// Get the mousedown handler that was registered
|
|
287
|
-
const addEventListenerCalls = (document.body.addEventListener as Mock).mock.calls
|
|
288
|
-
const mousedownCall = addEventListenerCalls.find((call
|
|
289
|
-
mousedownHandler = mousedownCall
|
|
286
|
+
const addEventListenerCalls = (document.body.addEventListener as jest.Mock).mock.calls
|
|
287
|
+
const mousedownCall = addEventListenerCalls.find((call) => call[0] === 'mousedown')
|
|
288
|
+
mousedownHandler = mousedownCall[1]
|
|
290
289
|
|
|
291
|
-
|
|
290
|
+
jest.clearAllMocks()
|
|
292
291
|
})
|
|
293
292
|
|
|
294
293
|
it('should add no-focus-ring class on mouse down', () => {
|
|
@@ -327,7 +326,7 @@ describe('FocusManager', () => {
|
|
|
327
326
|
it('should complete before bluring', () => {
|
|
328
327
|
const callOrder: string[] = []
|
|
329
328
|
editor.complete.mockImplementation(() => callOrder.push('complete'))
|
|
330
|
-
mockContainer.blur =
|
|
329
|
+
mockContainer.blur = jest.fn(() => callOrder.push('blur'))
|
|
331
330
|
|
|
332
331
|
focusManager.blur()
|
|
333
332
|
|
|
@@ -338,7 +337,7 @@ describe('FocusManager', () => {
|
|
|
338
337
|
describe('dispose', () => {
|
|
339
338
|
beforeEach(() => {
|
|
340
339
|
focusManager = new FocusManager(editor)
|
|
341
|
-
|
|
340
|
+
jest.clearAllMocks()
|
|
342
341
|
})
|
|
343
342
|
|
|
344
343
|
it('should remove keyboard event listener', () => {
|
|
@@ -377,7 +376,7 @@ describe('FocusManager', () => {
|
|
|
377
376
|
const handlerCall = editor.sideEffects.registerAfterChangeHandler.mock.calls[0]
|
|
378
377
|
const handler = handlerCall[1]
|
|
379
378
|
|
|
380
|
-
|
|
379
|
+
jest.clearAllMocks()
|
|
381
380
|
|
|
382
381
|
// Rapid focus changes
|
|
383
382
|
editor.getInstanceState.mockReturnValue({ isFocused: true })
|
|
@@ -395,9 +394,9 @@ describe('FocusManager', () => {
|
|
|
395
394
|
|
|
396
395
|
it('should handle keyboard navigation while editing', () => {
|
|
397
396
|
focusManager = new FocusManager(editor)
|
|
398
|
-
const addEventListenerCalls = (document.body.addEventListener as Mock).mock.calls
|
|
399
|
-
const keydownCall = addEventListenerCalls.find((call
|
|
400
|
-
const keydownHandler = keydownCall
|
|
397
|
+
const addEventListenerCalls = (document.body.addEventListener as jest.Mock).mock.calls
|
|
398
|
+
const keydownCall = addEventListenerCalls.find((call) => call[0] === 'keydown')
|
|
399
|
+
const keydownHandler = keydownCall[1]
|
|
401
400
|
|
|
402
401
|
editor.isIn.mockReturnValue(true) // Editing mode
|
|
403
402
|
|
|
@@ -410,15 +409,15 @@ describe('FocusManager', () => {
|
|
|
410
409
|
|
|
411
410
|
it('should handle mouse and keyboard interaction sequence', () => {
|
|
412
411
|
focusManager = new FocusManager(editor)
|
|
413
|
-
const addEventListenerCalls = (document.body.addEventListener as Mock).mock.calls
|
|
412
|
+
const addEventListenerCalls = (document.body.addEventListener as jest.Mock).mock.calls
|
|
414
413
|
|
|
415
|
-
const mousedownCall = addEventListenerCalls.find((call
|
|
416
|
-
const keydownCall = addEventListenerCalls.find((call
|
|
414
|
+
const mousedownCall = addEventListenerCalls.find((call) => call[0] === 'mousedown')
|
|
415
|
+
const keydownCall = addEventListenerCalls.find((call) => call[0] === 'keydown')
|
|
417
416
|
|
|
418
|
-
const mousedownHandler = mousedownCall
|
|
419
|
-
const keydownHandler = keydownCall
|
|
417
|
+
const mousedownHandler = mousedownCall[1]
|
|
418
|
+
const keydownHandler = keydownCall[1]
|
|
420
419
|
|
|
421
|
-
|
|
420
|
+
jest.clearAllMocks()
|
|
422
421
|
|
|
423
422
|
// Mouse down adds no-focus-ring
|
|
424
423
|
mousedownHandler()
|
|
@@ -1,31 +1,30 @@
|
|
|
1
1
|
import { TLShape, TLShapeId, createShapeId } from '@tldraw/tlschema'
|
|
2
|
-
import { Mock, Mocked, vi } from 'vitest'
|
|
3
2
|
import { Editor } from '../../Editor'
|
|
4
3
|
import { FontManager, TLFontFace } from './FontManager'
|
|
5
4
|
|
|
6
5
|
// Mock the Editor class
|
|
7
|
-
|
|
6
|
+
jest.mock('../../Editor')
|
|
8
7
|
|
|
9
8
|
// Mock globals
|
|
10
|
-
global.FontFace =
|
|
9
|
+
global.FontFace = jest.fn().mockImplementation((family, src, descriptors) => ({
|
|
11
10
|
family,
|
|
12
11
|
src,
|
|
13
12
|
...descriptors,
|
|
14
|
-
load:
|
|
13
|
+
load: jest.fn(() => Promise.resolve()),
|
|
15
14
|
}))
|
|
16
15
|
|
|
17
16
|
Object.defineProperty(global.document, 'fonts', {
|
|
18
17
|
value: {
|
|
19
|
-
add:
|
|
20
|
-
[Symbol.iterator]:
|
|
18
|
+
add: jest.fn(),
|
|
19
|
+
[Symbol.iterator]: jest.fn(() => [].values()),
|
|
21
20
|
},
|
|
22
21
|
configurable: true,
|
|
23
22
|
})
|
|
24
23
|
|
|
25
|
-
global.queueMicrotask =
|
|
24
|
+
global.queueMicrotask = jest.fn((fn) => Promise.resolve().then(fn))
|
|
26
25
|
|
|
27
26
|
describe('FontManager', () => {
|
|
28
|
-
let editor: Mocked<Editor>
|
|
27
|
+
let editor: jest.Mocked<Editor>
|
|
29
28
|
let fontManager: FontManager
|
|
30
29
|
let mockAssetUrls: { [key: string]: string }
|
|
31
30
|
|
|
@@ -51,30 +50,30 @@ describe('FontManager', () => {
|
|
|
51
50
|
})
|
|
52
51
|
|
|
53
52
|
beforeEach(() => {
|
|
54
|
-
|
|
53
|
+
jest.clearAllMocks()
|
|
55
54
|
|
|
56
55
|
mockAssetUrls = {
|
|
57
56
|
'test-font.woff2': 'https://example.com/fonts/test-font.woff2',
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
const mockShapeUtil = {
|
|
61
|
-
getFontFaces:
|
|
60
|
+
getFontFaces: jest.fn(() => []),
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
const mockStore = {
|
|
65
|
-
createComputedCache:
|
|
66
|
-
get:
|
|
64
|
+
createComputedCache: jest.fn(() => ({
|
|
65
|
+
get: jest.fn(() => []),
|
|
67
66
|
})),
|
|
68
|
-
createCache:
|
|
69
|
-
get:
|
|
67
|
+
createCache: jest.fn(() => ({
|
|
68
|
+
get: jest.fn(() => ({ get: jest.fn(() => []) })),
|
|
70
69
|
})),
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
editor = {
|
|
74
73
|
store: mockStore,
|
|
75
|
-
getShapeUtil:
|
|
76
|
-
getCurrentPageShapeIds:
|
|
77
|
-
getShape:
|
|
74
|
+
getShapeUtil: jest.fn(() => mockShapeUtil),
|
|
75
|
+
getCurrentPageShapeIds: jest.fn(() => new Set()),
|
|
76
|
+
getShape: jest.fn(),
|
|
78
77
|
isDisposed: false,
|
|
79
78
|
} as any
|
|
80
79
|
|
|
@@ -128,7 +127,7 @@ describe('FontManager', () => {
|
|
|
128
127
|
const shapes = shapeIds.map(createMockShape)
|
|
129
128
|
|
|
130
129
|
editor.getCurrentPageShapeIds.mockReturnValue(new Set(shapeIds))
|
|
131
|
-
editor.getShape.mockImplementation((id
|
|
130
|
+
editor.getShape.mockImplementation((id) => shapes.find((s) => s.id === id))
|
|
132
131
|
|
|
133
132
|
await expect(fontManager.loadRequiredFontsForCurrentPage(3)).resolves.toBeUndefined()
|
|
134
133
|
})
|
|
@@ -151,12 +150,12 @@ describe('FontManager', () => {
|
|
|
151
150
|
const font = createMockFont()
|
|
152
151
|
const error = new Error('Font load failed')
|
|
153
152
|
|
|
154
|
-
;(global.FontFace as Mock).mockReturnValue({
|
|
153
|
+
;(global.FontFace as jest.Mock).mockReturnValue({
|
|
155
154
|
family: font.family,
|
|
156
|
-
load:
|
|
155
|
+
load: jest.fn(() => Promise.reject(error)),
|
|
157
156
|
})
|
|
158
157
|
|
|
159
|
-
const consoleSpy =
|
|
158
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation()
|
|
160
159
|
|
|
161
160
|
await fontManager.ensureFontIsLoaded(font)
|
|
162
161
|
|
|
@@ -199,7 +198,7 @@ describe('FontManager', () => {
|
|
|
199
198
|
|
|
200
199
|
fontManager.requestFonts(fonts)
|
|
201
200
|
|
|
202
|
-
const callback = (queueMicrotask as Mock).mock.calls[0][0]
|
|
201
|
+
const callback = (queueMicrotask as jest.Mock).mock.calls[0][0]
|
|
203
202
|
expect(() => callback()).not.toThrow()
|
|
204
203
|
})
|
|
205
204
|
})
|
|
@@ -214,7 +213,7 @@ describe('FontManager', () => {
|
|
|
214
213
|
src: url("mock-data-url");
|
|
215
214
|
}`
|
|
216
215
|
|
|
217
|
-
|
|
216
|
+
jest.spyOn(fontManager, 'toEmbeddedCssDeclaration').mockResolvedValue(mockCssDeclaration)
|
|
218
217
|
|
|
219
218
|
const result = await fontManager.toEmbeddedCssDeclaration(font)
|
|
220
219
|
|
|
@@ -228,7 +227,7 @@ describe('FontManager', () => {
|
|
|
228
227
|
const font = createMockFont()
|
|
229
228
|
|
|
230
229
|
// Simple spy to verify the method is called
|
|
231
|
-
const spy =
|
|
230
|
+
const spy = jest.spyOn(fontManager, 'toEmbeddedCssDeclaration').mockResolvedValue('mock-css')
|
|
232
231
|
|
|
233
232
|
await fontManager.toEmbeddedCssDeclaration(font)
|
|
234
233
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { BaseRecord, RecordId, Store, StoreSchema, createRecordType } from '@tldraw/store'
|
|
2
|
-
import { vi } from 'vitest'
|
|
3
2
|
import { TLHistoryBatchOptions } from '../../types/history-types'
|
|
4
3
|
import { HistoryManager } from './HistoryManager'
|
|
5
4
|
|
|
@@ -490,7 +489,7 @@ describe('HistoryManager constructor and lifecycle', () => {
|
|
|
490
489
|
})
|
|
491
490
|
|
|
492
491
|
it('should initialize with optional annotateError callback', () => {
|
|
493
|
-
const mockAnnotateError =
|
|
492
|
+
const mockAnnotateError = jest.fn()
|
|
494
493
|
const manager = new HistoryManager({ store, annotateError: mockAnnotateError })
|
|
495
494
|
expect(manager).toBeDefined()
|
|
496
495
|
})
|
|
@@ -504,7 +503,7 @@ describe('HistoryManager constructor and lifecycle', () => {
|
|
|
504
503
|
})
|
|
505
504
|
|
|
506
505
|
it('should handle errors in batch operations with annotateError', () => {
|
|
507
|
-
const mockAnnotateError =
|
|
506
|
+
const mockAnnotateError = jest.fn()
|
|
508
507
|
const manager = new HistoryManager({ store, annotateError: mockAnnotateError })
|
|
509
508
|
|
|
510
509
|
const errorFn = () => {
|
|
@@ -516,7 +515,7 @@ describe('HistoryManager constructor and lifecycle', () => {
|
|
|
516
515
|
})
|
|
517
516
|
|
|
518
517
|
it('should handle nested batch error scenarios', () => {
|
|
519
|
-
const mockAnnotateError =
|
|
518
|
+
const mockAnnotateError = jest.fn()
|
|
520
519
|
const manager = new HistoryManager({ store, annotateError: mockAnnotateError })
|
|
521
520
|
|
|
522
521
|
const nestedErrorFn = () => {
|
|
@@ -696,7 +695,7 @@ describe('HistoryManager error scenarios and edge cases', () => {
|
|
|
696
695
|
describe('squashToMark error handling', () => {
|
|
697
696
|
it('should handle non-existent mark gracefully', () => {
|
|
698
697
|
store.update(ids.a, (s) => ({ ...s, value: 1 }))
|
|
699
|
-
const consoleSpy =
|
|
698
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation()
|
|
700
699
|
|
|
701
700
|
manager.squashToMark('non-existent-mark')
|
|
702
701
|
|
|
@@ -708,7 +707,7 @@ describe('HistoryManager error scenarios and edge cases', () => {
|
|
|
708
707
|
})
|
|
709
708
|
|
|
710
709
|
it('should handle empty stack when squashing', () => {
|
|
711
|
-
const consoleSpy =
|
|
710
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation()
|
|
712
711
|
|
|
713
712
|
manager.squashToMark('non-existent')
|
|
714
713
|
|
|
@@ -781,7 +780,7 @@ describe('HistoryManager error scenarios and edge cases', () => {
|
|
|
781
780
|
})
|
|
782
781
|
|
|
783
782
|
it('should maintain batch state correctly during errors', () => {
|
|
784
|
-
const mockAnnotateError =
|
|
783
|
+
const mockAnnotateError = jest.fn()
|
|
785
784
|
const errorManager = new HistoryManager({ store, annotateError: mockAnnotateError })
|
|
786
785
|
|
|
787
786
|
try {
|
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
import { TLScribble } from '@tldraw/tlschema'
|
|
2
|
-
import { Mock, Mocked, vi } from 'vitest'
|
|
3
2
|
import { Editor } from '../../Editor'
|
|
4
3
|
import { ScribbleItem, ScribbleManager } from './ScribbleManager'
|
|
5
4
|
|
|
6
5
|
// Mock the Editor class
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
uniqueId:
|
|
6
|
+
jest.mock('../../Editor')
|
|
7
|
+
jest.mock('@tldraw/utils', () => ({
|
|
8
|
+
uniqueId: jest.fn(() => 'test-id'),
|
|
10
9
|
}))
|
|
11
10
|
|
|
12
11
|
describe('ScribbleManager', () => {
|
|
13
|
-
let editor: Mocked<Editor>
|
|
12
|
+
let editor: jest.Mocked<Editor>
|
|
14
13
|
let scribbleManager: ScribbleManager
|
|
15
|
-
let mockUniqueId: Mock
|
|
14
|
+
let mockUniqueId: jest.Mock
|
|
16
15
|
|
|
17
|
-
beforeEach(
|
|
16
|
+
beforeEach(() => {
|
|
18
17
|
editor = {
|
|
19
|
-
updateInstanceState:
|
|
20
|
-
run:
|
|
18
|
+
updateInstanceState: jest.fn(),
|
|
19
|
+
run: jest.fn((fn) => fn()),
|
|
21
20
|
} as any
|
|
22
21
|
|
|
23
|
-
const { uniqueId } =
|
|
24
|
-
mockUniqueId = uniqueId
|
|
22
|
+
const { uniqueId } = jest.requireMock('@tldraw/utils')
|
|
23
|
+
mockUniqueId = uniqueId
|
|
25
24
|
mockUniqueId.mockReturnValue('test-id')
|
|
26
25
|
|
|
27
26
|
scribbleManager = new ScribbleManager(editor)
|
|
28
27
|
})
|
|
29
28
|
|
|
30
29
|
afterEach(() => {
|
|
31
|
-
|
|
30
|
+
jest.clearAllMocks()
|
|
32
31
|
})
|
|
33
32
|
|
|
34
33
|
describe('constructor and initialization', () => {
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TLFrameShape,
|
|
3
|
-
TLGroupShape,
|
|
4
|
-
TLPageId,
|
|
5
|
-
TLShape,
|
|
6
|
-
TLShapeId,
|
|
7
|
-
createShapeId,
|
|
8
|
-
} from '@tldraw/tlschema'
|
|
9
|
-
import { Mocked, vi } from 'vitest'
|
|
1
|
+
import { TLFrameShape, TLGroupShape, TLPageId, TLShapeId, createShapeId } from '@tldraw/tlschema'
|
|
10
2
|
import { Box } from '../../../primitives/Box'
|
|
11
3
|
import { Vec } from '../../../primitives/Vec'
|
|
12
4
|
import { Editor } from '../../Editor'
|
|
@@ -15,33 +7,32 @@ import { HandleSnaps } from './HandleSnaps'
|
|
|
15
7
|
import { GapsSnapIndicator, PointsSnapIndicator, SnapManager } from './SnapManager'
|
|
16
8
|
|
|
17
9
|
// Mock the Editor class
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
jest.mock('../../Editor')
|
|
11
|
+
jest.mock('./BoundsSnaps')
|
|
12
|
+
jest.mock('./HandleSnaps')
|
|
21
13
|
|
|
22
14
|
describe('SnapManager', () => {
|
|
23
|
-
let editor: Mocked<Editor>
|
|
15
|
+
let editor: jest.Mocked<Editor>
|
|
24
16
|
let snapManager: SnapManager
|
|
25
17
|
|
|
26
18
|
const createMockShape = (
|
|
27
19
|
id: TLShapeId,
|
|
28
20
|
type: string = 'geo',
|
|
29
21
|
parentId: TLShapeId | string = 'page:page'
|
|
30
|
-
) =>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}) as TLShape
|
|
22
|
+
) => ({
|
|
23
|
+
id,
|
|
24
|
+
type,
|
|
25
|
+
parentId,
|
|
26
|
+
x: 0,
|
|
27
|
+
y: 0,
|
|
28
|
+
rotation: 0,
|
|
29
|
+
index: 'a1' as const,
|
|
30
|
+
opacity: 1,
|
|
31
|
+
isLocked: false,
|
|
32
|
+
meta: {},
|
|
33
|
+
props: {},
|
|
34
|
+
typeName: 'shape' as const,
|
|
35
|
+
})
|
|
45
36
|
|
|
46
37
|
const createMockFrameShape = (id: TLShapeId): TLFrameShape =>
|
|
47
38
|
({
|
|
@@ -63,26 +54,26 @@ describe('SnapManager', () => {
|
|
|
63
54
|
|
|
64
55
|
beforeEach(() => {
|
|
65
56
|
editor = {
|
|
66
|
-
getZoomLevel:
|
|
67
|
-
getViewportPageBounds:
|
|
68
|
-
getSelectedShapeIds:
|
|
69
|
-
getSelectedShapes:
|
|
70
|
-
findCommonAncestor:
|
|
71
|
-
getCurrentPageId:
|
|
72
|
-
getSortedChildIdsForParent:
|
|
73
|
-
getShape:
|
|
74
|
-
getShapeUtil:
|
|
75
|
-
canSnap:
|
|
57
|
+
getZoomLevel: jest.fn(() => 1),
|
|
58
|
+
getViewportPageBounds: jest.fn(() => new Box(0, 0, 1000, 1000)),
|
|
59
|
+
getSelectedShapeIds: jest.fn(() => []),
|
|
60
|
+
getSelectedShapes: jest.fn(() => []),
|
|
61
|
+
findCommonAncestor: jest.fn(() => createShapeId('page')),
|
|
62
|
+
getCurrentPageId: jest.fn(() => 'page:page' as TLPageId),
|
|
63
|
+
getSortedChildIdsForParent: jest.fn(() => []),
|
|
64
|
+
getShape: jest.fn(),
|
|
65
|
+
getShapeUtil: jest.fn(() => ({
|
|
66
|
+
canSnap: jest.fn(() => true),
|
|
76
67
|
})),
|
|
77
|
-
getShapePageBounds:
|
|
78
|
-
isShapeOfType:
|
|
68
|
+
getShapePageBounds: jest.fn(),
|
|
69
|
+
isShapeOfType: jest.fn(),
|
|
79
70
|
} as any
|
|
80
71
|
|
|
81
72
|
snapManager = new SnapManager(editor)
|
|
82
73
|
})
|
|
83
74
|
|
|
84
75
|
afterEach(() => {
|
|
85
|
-
|
|
76
|
+
jest.clearAllMocks()
|
|
86
77
|
})
|
|
87
78
|
|
|
88
79
|
describe('constructor and initialization', () => {
|
|
@@ -313,7 +304,7 @@ describe('SnapManager', () => {
|
|
|
313
304
|
editor.getSortedChildIdsForParent.mockReturnValue([shapeId])
|
|
314
305
|
editor.getShape.mockReturnValue(shape as any)
|
|
315
306
|
editor.getShapeUtil.mockReturnValue({
|
|
316
|
-
canSnap:
|
|
307
|
+
canSnap: jest.fn(() => false),
|
|
317
308
|
} as any)
|
|
318
309
|
|
|
319
310
|
const result = snapManager.getSnappableShapes()
|
|
@@ -338,7 +329,7 @@ describe('SnapManager', () => {
|
|
|
338
329
|
const frameShape = createMockFrameShape(frameId)
|
|
339
330
|
|
|
340
331
|
editor.getSortedChildIdsForParent.mockReturnValue([frameId])
|
|
341
|
-
editor.getShape.mockReturnValue(frameShape)
|
|
332
|
+
editor.getShape.mockReturnValue(frameShape as any)
|
|
342
333
|
editor.isShapeOfType.mockImplementation((_shape, type) => type === 'frame')
|
|
343
334
|
editor.getShapePageBounds.mockReturnValue(new Box(10, 10, 50, 50))
|
|
344
335
|
|
|
@@ -357,12 +348,14 @@ describe('SnapManager', () => {
|
|
|
357
348
|
.mockReturnValueOnce([childId]) // Inside group
|
|
358
349
|
|
|
359
350
|
editor.getShape.mockImplementation((id) => {
|
|
360
|
-
if (id === groupId) return groupShape
|
|
361
|
-
if (id === childId) return childShape
|
|
351
|
+
if (id === groupId) return groupShape as any
|
|
352
|
+
if (id === childId) return childShape as any
|
|
362
353
|
return undefined
|
|
363
354
|
})
|
|
364
355
|
|
|
365
|
-
editor.isShapeOfType.mockImplementation(
|
|
356
|
+
editor.isShapeOfType.mockImplementation(
|
|
357
|
+
(shape, type) => shape && (shape as any).type === type
|
|
358
|
+
)
|
|
366
359
|
|
|
367
360
|
editor.getShapePageBounds.mockReturnValue(new Box(10, 10, 50, 50))
|
|
368
361
|
|
|
@@ -379,26 +372,26 @@ describe('SnapManager', () => {
|
|
|
379
372
|
|
|
380
373
|
// Override the getCurrentCommonAncestor mock for this specific test
|
|
381
374
|
const originalGetCurrentCommonAncestor = snapManager.getCurrentCommonAncestor
|
|
382
|
-
|
|
375
|
+
jest.spyOn(snapManager, 'getCurrentCommonAncestor').mockReturnValue(parentFrameId)
|
|
383
376
|
|
|
384
377
|
editor.getSortedChildIdsForParent.mockReturnValueOnce([childFrameId]) // Children of parent frame
|
|
385
378
|
|
|
386
|
-
editor.getShape.mockImplementation((id
|
|
379
|
+
editor.getShape.mockImplementation((id) => {
|
|
387
380
|
if (id === parentFrameId) return parentFrame as any
|
|
388
381
|
if (id === childFrameId) return childFrame as any
|
|
389
382
|
return undefined
|
|
390
383
|
})
|
|
391
384
|
|
|
392
|
-
editor.isShapeOfType.mockImplementation((shape
|
|
385
|
+
editor.isShapeOfType.mockImplementation((shape, type) => type === 'frame')
|
|
393
386
|
editor.getShapePageBounds.mockReturnValue(new Box(10, 10, 50, 50))
|
|
394
387
|
|
|
395
388
|
const result = snapManager.getSnappableShapes()
|
|
396
389
|
expect(result.has(childFrameId)).toBe(true)
|
|
397
390
|
|
|
398
391
|
// Restore original method
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
392
|
+
jest
|
|
393
|
+
.spyOn(snapManager, 'getCurrentCommonAncestor')
|
|
394
|
+
.mockImplementation(originalGetCurrentCommonAncestor)
|
|
402
395
|
})
|
|
403
396
|
|
|
404
397
|
it('should handle missing shape bounds gracefully', () => {
|
|
@@ -429,7 +422,7 @@ describe('SnapManager', () => {
|
|
|
429
422
|
|
|
430
423
|
// Override the getCurrentCommonAncestor mock for this specific test
|
|
431
424
|
const originalGetCurrentCommonAncestor = snapManager.getCurrentCommonAncestor
|
|
432
|
-
|
|
425
|
+
jest.spyOn(snapManager, 'getCurrentCommonAncestor').mockReturnValue(undefined)
|
|
433
426
|
|
|
434
427
|
editor.getCurrentPageId.mockReturnValue('page:current' as TLPageId)
|
|
435
428
|
editor.getSortedChildIdsForParent.mockReturnValue([shapeId])
|
|
@@ -440,9 +433,9 @@ describe('SnapManager', () => {
|
|
|
440
433
|
expect(editor.getSortedChildIdsForParent).toHaveBeenCalledWith('page:current')
|
|
441
434
|
|
|
442
435
|
// Restore original method
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
436
|
+
jest
|
|
437
|
+
.spyOn(snapManager, 'getCurrentCommonAncestor')
|
|
438
|
+
.mockImplementation(originalGetCurrentCommonAncestor)
|
|
446
439
|
})
|
|
447
440
|
})
|
|
448
441
|
|
|
@@ -477,7 +470,7 @@ describe('SnapManager', () => {
|
|
|
477
470
|
|
|
478
471
|
// Test with second set of shapes
|
|
479
472
|
editor.getSortedChildIdsForParent.mockReturnValue([shapeId1, shapeId2])
|
|
480
|
-
editor.getShape.mockImplementation((id
|
|
473
|
+
editor.getShape.mockImplementation((id) => {
|
|
481
474
|
if (id === shapeId1) return createMockShape(shapeId1) as any
|
|
482
475
|
if (id === shapeId2) return createMockShape(shapeId2) as any
|
|
483
476
|
return undefined
|