@eclipse-glsp/client 2.8.0-next.8 → 2.8.0

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 (279) hide show
  1. package/README.md +1 -1
  2. package/css/grid.css +2 -1
  3. package/lib/base/action-dispatcher.js +1 -4
  4. package/lib/base/action-dispatcher.js.map +1 -1
  5. package/lib/base/auto-complete/auto-complete-widget.js +4 -8
  6. package/lib/base/auto-complete/auto-complete-widget.js.map +1 -1
  7. package/lib/base/auto-complete/base-autocomplete-palette.js +1 -2
  8. package/lib/base/auto-complete/base-autocomplete-palette.js.map +1 -1
  9. package/lib/base/editor-context-service.js +4 -7
  10. package/lib/base/editor-context-service.js.map +1 -1
  11. package/lib/base/feedback/css-feedback.js +1 -1
  12. package/lib/base/feedback/css-feedback.js.map +1 -1
  13. package/lib/base/feedback/feedback-action-dispatcher.js +4 -6
  14. package/lib/base/feedback/feedback-action-dispatcher.js.map +1 -1
  15. package/lib/base/feedback/feedback-command.js +1 -2
  16. package/lib/base/feedback/feedback-command.js.map +1 -1
  17. package/lib/base/feedback/feedback-emitter.js +1 -2
  18. package/lib/base/feedback/feedback-emitter.js.map +1 -1
  19. package/lib/base/feedback/set-model-command.js +1 -2
  20. package/lib/base/feedback/set-model-command.js.map +1 -1
  21. package/lib/base/feedback/update-model-command.js +1 -2
  22. package/lib/base/feedback/update-model-command.js.map +1 -1
  23. package/lib/base/model/diagram-loader.js +4 -6
  24. package/lib/base/model/diagram-loader.js.map +1 -1
  25. package/lib/base/model/glsp-model-source.d.ts +1 -1
  26. package/lib/base/model/glsp-model-source.d.ts.map +1 -1
  27. package/lib/base/model/glsp-model-source.js +3 -5
  28. package/lib/base/model/glsp-model-source.js.map +1 -1
  29. package/lib/base/model/model-registry.js +1 -2
  30. package/lib/base/model/model-registry.js.map +1 -1
  31. package/lib/base/selection-service.js +3 -3
  32. package/lib/base/selection-service.js.map +1 -1
  33. package/lib/base/shortcuts/available-shortcuts-extension.js +3 -2
  34. package/lib/base/shortcuts/available-shortcuts-extension.js.map +1 -1
  35. package/lib/base/shortcuts/available-shortcuts-tool.js +3 -2
  36. package/lib/base/shortcuts/available-shortcuts-tool.js.map +1 -1
  37. package/lib/base/tool-manager/tool-manager.js +1 -1
  38. package/lib/base/tool-manager/tool-manager.js.map +1 -1
  39. package/lib/base/ui-extension/ui-extension.js +4 -6
  40. package/lib/base/ui-extension/ui-extension.js.map +1 -1
  41. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-palette.js +12 -17
  42. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-palette.js.map +1 -1
  43. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-tool.js +3 -2
  44. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-tool.js.map +1 -1
  45. package/lib/features/accessibility/element-navigation/diagram-navigation-tool.js +11 -15
  46. package/lib/features/accessibility/element-navigation/diagram-navigation-tool.js.map +1 -1
  47. package/lib/features/accessibility/element-navigation/left-right-top-bottom-navigator.js +2 -3
  48. package/lib/features/accessibility/element-navigation/left-right-top-bottom-navigator.js.map +1 -1
  49. package/lib/features/accessibility/element-navigation/local-element-navigator.js +2 -3
  50. package/lib/features/accessibility/element-navigation/local-element-navigator.js.map +1 -1
  51. package/lib/features/accessibility/focus-tracker/focus-tracker-tool.js +5 -4
  52. package/lib/features/accessibility/focus-tracker/focus-tracker-tool.js.map +1 -1
  53. package/lib/features/accessibility/global-keylistener-tool.js +4 -3
  54. package/lib/features/accessibility/global-keylistener-tool.js.map +1 -1
  55. package/lib/features/accessibility/keyboard-grid/keyboard-grid-search-palette.js +3 -2
  56. package/lib/features/accessibility/keyboard-grid/keyboard-grid-search-palette.js.map +1 -1
  57. package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.js +5 -7
  58. package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.js.map +1 -1
  59. package/lib/features/accessibility/toast/toast-handler.js +2 -4
  60. package/lib/features/accessibility/toast/toast-handler.js.map +1 -1
  61. package/lib/features/accessibility/toast/toast-tool.js +3 -2
  62. package/lib/features/accessibility/toast/toast-tool.js.map +1 -1
  63. package/lib/features/accessibility/view-key-tools/deselect-key-tool.js +3 -2
  64. package/lib/features/accessibility/view-key-tools/deselect-key-tool.js.map +1 -1
  65. package/lib/features/accessibility/view-key-tools/grid-cell-zoom-key-tool.js +4 -3
  66. package/lib/features/accessibility/view-key-tools/grid-cell-zoom-key-tool.js.map +1 -1
  67. package/lib/features/bounds/freeform-layout.js +1 -1
  68. package/lib/features/bounds/freeform-layout.js.map +1 -1
  69. package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts +31 -1
  70. package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts.map +1 -1
  71. package/lib/features/bounds/glsp-hidden-bounds-updater.js +119 -58
  72. package/lib/features/bounds/glsp-hidden-bounds-updater.js.map +1 -1
  73. package/lib/features/bounds/hbox-layout.js +7 -10
  74. package/lib/features/bounds/hbox-layout.js.map +1 -1
  75. package/lib/features/bounds/layout-data.js +2 -4
  76. package/lib/features/bounds/layout-data.js.map +1 -1
  77. package/lib/features/bounds/local-bounds.js +3 -4
  78. package/lib/features/bounds/local-bounds.js.map +1 -1
  79. package/lib/features/bounds/set-bounds-feedback-command.js +2 -3
  80. package/lib/features/bounds/set-bounds-feedback-command.js.map +1 -1
  81. package/lib/features/bounds/vbox-layout.js +7 -10
  82. package/lib/features/bounds/vbox-layout.js.map +1 -1
  83. package/lib/features/change-bounds/model.js +1 -1
  84. package/lib/features/change-bounds/model.js.map +1 -1
  85. package/lib/features/change-bounds/move-element-handler.js +1 -2
  86. package/lib/features/change-bounds/move-element-handler.js.map +1 -1
  87. package/lib/features/change-bounds/movement-restrictor.js +1 -2
  88. package/lib/features/change-bounds/movement-restrictor.js.map +1 -1
  89. package/lib/features/change-bounds/point-position-updater.js +1 -1
  90. package/lib/features/change-bounds/point-position-updater.js.map +1 -1
  91. package/lib/features/change-bounds/resize/resize-default-tool.js +4 -3
  92. package/lib/features/change-bounds/resize/resize-default-tool.js.map +1 -1
  93. package/lib/features/change-bounds/resize/resize-handler.js +1 -2
  94. package/lib/features/change-bounds/resize/resize-handler.js.map +1 -1
  95. package/lib/features/change-bounds/resize/resize-tool.js +4 -3
  96. package/lib/features/change-bounds/resize/resize-tool.js.map +1 -1
  97. package/lib/features/change-bounds/tracker.js +1 -2
  98. package/lib/features/change-bounds/tracker.js.map +1 -1
  99. package/lib/features/command-palette/command-palette-tool.js +3 -2
  100. package/lib/features/command-palette/command-palette-tool.js.map +1 -1
  101. package/lib/features/command-palette/command-palette.js +2 -3
  102. package/lib/features/command-palette/command-palette.js.map +1 -1
  103. package/lib/features/context-menu/glsp-context-menu-mouse-listener.js +2 -3
  104. package/lib/features/context-menu/glsp-context-menu-mouse-listener.js.map +1 -1
  105. package/lib/features/copy-paste/copy-paste-handler.d.ts +1 -1
  106. package/lib/features/copy-paste/copy-paste-handler.d.ts.map +1 -1
  107. package/lib/features/copy-paste/copy-paste-handler.js +3 -5
  108. package/lib/features/copy-paste/copy-paste-handler.js.map +1 -1
  109. package/lib/features/copy-paste/copy-paste-standalone.js +6 -9
  110. package/lib/features/copy-paste/copy-paste-standalone.js.map +1 -1
  111. package/lib/features/debug/debug-bounds-decorator.js +9 -12
  112. package/lib/features/debug/debug-bounds-decorator.js.map +1 -1
  113. package/lib/features/debug/debug-model.js +1 -1
  114. package/lib/features/debug/debug-model.js.map +1 -1
  115. package/lib/features/decoration/decoration-placer.js +3 -2
  116. package/lib/features/decoration/decoration-placer.js.map +1 -1
  117. package/lib/features/element-template/add-template-element.d.ts +6 -1
  118. package/lib/features/element-template/add-template-element.d.ts.map +1 -1
  119. package/lib/features/element-template/add-template-element.js +17 -5
  120. package/lib/features/element-template/add-template-element.js.map +1 -1
  121. package/lib/features/element-template/mouse-tracking-element-position-listener.js +1 -1
  122. package/lib/features/element-template/mouse-tracking-element-position-listener.js.map +1 -1
  123. package/lib/features/element-template/remove-template-element.js +1 -1
  124. package/lib/features/element-template/remove-template-element.js.map +1 -1
  125. package/lib/features/export/default-png-diagram-exporter.js +4 -7
  126. package/lib/features/export/default-png-diagram-exporter.js.map +1 -1
  127. package/lib/features/export/diagram-export-postprocessor.js +1 -2
  128. package/lib/features/export/diagram-export-postprocessor.js.map +1 -1
  129. package/lib/features/export/glsp-svg-exporter.d.ts.map +1 -1
  130. package/lib/features/export/glsp-svg-exporter.js +5 -6
  131. package/lib/features/export/glsp-svg-exporter.js.map +1 -1
  132. package/lib/features/export/request-export-command.js +1 -1
  133. package/lib/features/export/request-export-command.js.map +1 -1
  134. package/lib/features/grid/grid-model.js +1 -1
  135. package/lib/features/grid/grid-model.js.map +1 -1
  136. package/lib/features/helper-lines/helper-line-feedback.js +7 -8
  137. package/lib/features/helper-lines/helper-line-feedback.js.map +1 -1
  138. package/lib/features/helper-lines/model.d.ts +1 -1
  139. package/lib/features/helper-lines/model.d.ts.map +1 -1
  140. package/lib/features/helper-lines/model.js +3 -4
  141. package/lib/features/helper-lines/model.js.map +1 -1
  142. package/lib/features/hints/type-hint-provider.js +3 -5
  143. package/lib/features/hints/type-hint-provider.js.map +1 -1
  144. package/lib/features/label-edit/edit-label-tool.js +3 -2
  145. package/lib/features/label-edit/edit-label-tool.js.map +1 -1
  146. package/lib/features/label-edit-ui/label-edit-ui.js +2 -3
  147. package/lib/features/label-edit-ui/label-edit-ui.js.map +1 -1
  148. package/lib/features/navigation/navigation-target-resolver.js +1 -1
  149. package/lib/features/navigation/navigation-target-resolver.js.map +1 -1
  150. package/lib/features/routing/sticky-manhattan-anchors.js +9 -6
  151. package/lib/features/routing/sticky-manhattan-anchors.js.map +1 -1
  152. package/lib/features/routing/sticky-manhattan-edge-router.js +10 -12
  153. package/lib/features/routing/sticky-manhattan-edge-router.js.map +1 -1
  154. package/lib/features/search-palette/search-palette.js +3 -2
  155. package/lib/features/search-palette/search-palette.js.map +1 -1
  156. package/lib/features/search-palette/suggestions/edge-element-suggestions.js +2 -3
  157. package/lib/features/search-palette/suggestions/edge-element-suggestions.js.map +1 -1
  158. package/lib/features/search-palette/suggestions/named-element-suggestions.js +8 -11
  159. package/lib/features/search-palette/suggestions/named-element-suggestions.js.map +1 -1
  160. package/lib/features/select/select-feedback-command.js +1 -1
  161. package/lib/features/select/select-feedback-command.js.map +1 -1
  162. package/lib/features/select/select-mouse-listener.js +1 -2
  163. package/lib/features/select/select-mouse-listener.js.map +1 -1
  164. package/lib/features/status/status-overlay.js +4 -4
  165. package/lib/features/status/status-overlay.js.map +1 -1
  166. package/lib/features/tool-palette/tool-palette.d.ts.map +1 -1
  167. package/lib/features/tool-palette/tool-palette.js +16 -23
  168. package/lib/features/tool-palette/tool-palette.js.map +1 -1
  169. package/lib/features/tools/change-bounds/change-bounds-manager.js +4 -6
  170. package/lib/features/tools/change-bounds/change-bounds-manager.js.map +1 -1
  171. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js +3 -4
  172. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js.map +1 -1
  173. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js +4 -8
  174. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js.map +1 -1
  175. package/lib/features/tools/change-bounds/change-bounds-tool.js +6 -6
  176. package/lib/features/tools/change-bounds/change-bounds-tool.js.map +1 -1
  177. package/lib/features/tools/change-bounds/change-bounds-tracker.js +7 -10
  178. package/lib/features/tools/change-bounds/change-bounds-tracker.js.map +1 -1
  179. package/lib/features/tools/deletion/delete-tool.js +6 -4
  180. package/lib/features/tools/deletion/delete-tool.js.map +1 -1
  181. package/lib/features/tools/edge-creation/dangling-edge-feedback.d.ts +1 -1
  182. package/lib/features/tools/edge-creation/dangling-edge-feedback.d.ts.map +1 -1
  183. package/lib/features/tools/edge-creation/dangling-edge-feedback.js +7 -5
  184. package/lib/features/tools/edge-creation/dangling-edge-feedback.js.map +1 -1
  185. package/lib/features/tools/edge-creation/edge-creation-tool.js +5 -6
  186. package/lib/features/tools/edge-creation/edge-creation-tool.js.map +1 -1
  187. package/lib/features/tools/edge-creation/view.js +1 -2
  188. package/lib/features/tools/edge-creation/view.js.map +1 -1
  189. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts +1 -1
  190. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts.map +1 -1
  191. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js +8 -5
  192. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js.map +1 -1
  193. package/lib/features/tools/edge-edit/edge-edit-tool.js +3 -2
  194. package/lib/features/tools/edge-edit/edge-edit-tool.js.map +1 -1
  195. package/lib/features/tools/marquee-selection/marquee-mouse-tool.js +3 -2
  196. package/lib/features/tools/marquee-selection/marquee-mouse-tool.js.map +1 -1
  197. package/lib/features/tools/marquee-selection/marquee-tool-feedback.js +2 -2
  198. package/lib/features/tools/marquee-selection/marquee-tool-feedback.js.map +1 -1
  199. package/lib/features/tools/marquee-selection/marquee-tool.js +3 -2
  200. package/lib/features/tools/marquee-selection/marquee-tool.js.map +1 -1
  201. package/lib/features/tools/marquee-selection/model.d.ts +1 -1
  202. package/lib/features/tools/marquee-selection/model.d.ts.map +1 -1
  203. package/lib/features/tools/marquee-selection/model.js +3 -2
  204. package/lib/features/tools/marquee-selection/model.js.map +1 -1
  205. package/lib/features/tools/node-creation/container-manager.js +3 -4
  206. package/lib/features/tools/node-creation/container-manager.js.map +1 -1
  207. package/lib/features/tools/node-creation/insert-indicator.d.ts +1 -1
  208. package/lib/features/tools/node-creation/insert-indicator.d.ts.map +1 -1
  209. package/lib/features/tools/node-creation/insert-indicator.js +5 -5
  210. package/lib/features/tools/node-creation/insert-indicator.js.map +1 -1
  211. package/lib/features/tools/node-creation/node-creation-tool.js +5 -6
  212. package/lib/features/tools/node-creation/node-creation-tool.js.map +1 -1
  213. package/lib/features/tools/node-creation/node-creation-views.js +1 -2
  214. package/lib/features/tools/node-creation/node-creation-views.js.map +1 -1
  215. package/lib/features/validation/issue-marker.d.ts +2 -2
  216. package/lib/features/validation/issue-marker.d.ts.map +1 -1
  217. package/lib/features/validation/issue-marker.js +7 -2
  218. package/lib/features/validation/issue-marker.js.map +1 -1
  219. package/lib/features/validation/marker-navigator.js +1 -1
  220. package/lib/features/validation/marker-navigator.js.map +1 -1
  221. package/lib/features/validation/validate.js +4 -6
  222. package/lib/features/validation/validate.js.map +1 -1
  223. package/lib/features/viewport/origin-viewport.js +1 -1
  224. package/lib/features/viewport/origin-viewport.js.map +1 -1
  225. package/lib/features/viewport/reposition.js +2 -3
  226. package/lib/features/viewport/reposition.js.map +1 -1
  227. package/lib/features/viewport/viewport-handler.js +2 -3
  228. package/lib/features/viewport/viewport-handler.js.map +1 -1
  229. package/lib/features/viewport/viewport-tool.js +4 -3
  230. package/lib/features/viewport/viewport-tool.js.map +1 -1
  231. package/lib/features/zorder/bring-to-front-command.js +1 -2
  232. package/lib/features/zorder/bring-to-front-command.js.map +1 -1
  233. package/lib/model.js +2 -2
  234. package/lib/model.js.map +1 -1
  235. package/lib/utils/argument-utils.js +5 -5
  236. package/lib/utils/argument-utils.js.map +1 -1
  237. package/lib/utils/gmodel-util.d.ts +13 -1
  238. package/lib/utils/gmodel-util.d.ts.map +1 -1
  239. package/lib/utils/gmodel-util.js +15 -7
  240. package/lib/utils/gmodel-util.js.map +1 -1
  241. package/lib/utils/layout-utils.js +1 -2
  242. package/lib/utils/layout-utils.js.map +1 -1
  243. package/lib/views/glsp-projection-view.js +1 -2
  244. package/lib/views/glsp-projection-view.js.map +1 -1
  245. package/package.json +18 -17
  246. package/src/base/feedback/feedback-command.ts +1 -1
  247. package/src/base/model/glsp-model-source.ts +1 -1
  248. package/src/features/accessibility/README.md +5 -5
  249. package/src/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.ts +1 -1
  250. package/src/features/bounds/glsp-hidden-bounds-updater.ts +133 -60
  251. package/src/features/copy-paste/copy-paste-handler.ts +3 -3
  252. package/src/features/element-template/add-template-element.ts +17 -2
  253. package/src/features/export/glsp-svg-exporter.ts +2 -2
  254. package/src/features/helper-lines/model.ts +4 -5
  255. package/src/features/tool-palette/tool-palette.ts +2 -4
  256. package/src/features/tools/edge-creation/dangling-edge-feedback.ts +4 -2
  257. package/src/features/tools/edge-edit/edge-edit-tool-feedback.ts +5 -3
  258. package/src/features/tools/marquee-selection/model.ts +3 -2
  259. package/src/features/tools/node-creation/insert-indicator.ts +5 -5
  260. package/src/features/validation/issue-marker.ts +7 -2
  261. package/src/utils/gmodel-util.ts +23 -1
  262. package/src/base/action-dispatcher.spec.ts +0 -366
  263. package/src/base/feedback/feedback-emitter.spec.ts +0 -176
  264. package/src/base/model/model-initialization-constraint.spec.ts +0 -95
  265. package/src/base/selection-service.spec.ts +0 -318
  266. package/src/default-modules.spec.ts +0 -56
  267. package/src/features/bounds/freeform-layout.spec.ts +0 -216
  268. package/src/features/bounds/hbox-layout.spec.ts +0 -170
  269. package/src/features/bounds/layouter-test-util.spec.ts +0 -127
  270. package/src/features/bounds/vbox-layout.spec.ts +0 -170
  271. package/src/features/change-bounds/point-position-updater.spec.ts +0 -81
  272. package/src/features/grid/grid-snapper.spec.ts +0 -30
  273. package/src/features/hints/type-hint-provider.spec.ts +0 -360
  274. package/src/features/layout/layout-elements-action.spec.ts +0 -426
  275. package/src/features/navigation/navigation-target-resolver.spec.ts +0 -56
  276. package/src/features/routing/sticky-manhattan-edge-router.spec.ts +0 -212
  277. package/src/features/tools/marquee-selection/marquee-behavior.spec.ts +0 -176
  278. package/src/features/validation/marker-navigator.spec.ts +0 -183
  279. package/src/utils/gmodel-util.spec.ts +0 -221
@@ -1,426 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2019-2026 EclipseSource and others.
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * This Source Code may also be made available under the following Secondary
9
- * Licenses when the conditions for such availability set forth in the Eclipse
10
- * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- * with the GNU Classpath Exception which is available at
12
- * https://www.gnu.org/software/classpath/license.html.
13
- *
14
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
- ********************************************************************************/
16
-
17
- import {
18
- Action,
19
- AnimationFrameSyncer,
20
- Bounds,
21
- ChangeBoundsOperation,
22
- CommandExecutionContext,
23
- ConsoleLogger,
24
- ElementAndBounds,
25
- ElementMove,
26
- FeatureSet,
27
- GChildElement,
28
- GModelFactory,
29
- GModelRoot,
30
- GNode,
31
- GNodeSchema,
32
- IActionDispatcher,
33
- MoveAction,
34
- MoveCommand,
35
- RequestAction,
36
- ResponseAction,
37
- SetBoundsAction,
38
- SetBoundsCommand
39
- } from '@eclipse-glsp/sprotty';
40
- import { expect } from 'chai';
41
- import { Container } from 'inversify';
42
- import 'mocha';
43
- import 'reflect-metadata';
44
- import * as sinon from 'sinon';
45
- import { defaultModule } from '../../base/default.module';
46
- import { SelectionService } from '../../base/selection-service';
47
- import { GGraph } from '../../model';
48
- import { resizeFeature } from '../change-bounds/model';
49
- import {
50
- AlignElementsAction,
51
- AlignElementsActionHandler,
52
- Alignment,
53
- ResizeDimension,
54
- ResizeElementsAction,
55
- ResizeElementsActionHandler
56
- } from './layout-elements-action';
57
-
58
- class MockActionDispatcher implements IActionDispatcher {
59
- constructor(public dispatchedActions: Action[] = []) {}
60
- requestUntil<Res extends ResponseAction>(
61
- action: RequestAction<Res>,
62
- timeoutMs?: number | undefined,
63
- rejectOnTimeout?: boolean | undefined
64
- ): Promise<Res | undefined> {
65
- throw new Error('Method not implemented.');
66
- }
67
- dispatchOnceModelInitialized(...actions: Action[]): void {}
68
- onceModelInitialized(): Promise<void> {
69
- return Promise.resolve();
70
- }
71
- dispatchAfterNextUpdate(...actions: Action[]): void {}
72
- dispatch(action: Action): Promise<void> {
73
- this.dispatchedActions.push(action);
74
- return Promise.resolve();
75
- }
76
- dispatchAll(actions: Action[]): Promise<void> {
77
- actions.forEach(action => this.dispatchedActions.push(action));
78
- return Promise.resolve();
79
- }
80
- request<Res extends ResponseAction>(action: RequestAction<Res>): Promise<Res> {
81
- throw new Error('Method not implemented.');
82
- }
83
- }
84
-
85
- class MockSelectionService extends SelectionService {
86
- constructor(public modelRoot: GModelRoot) {
87
- super();
88
- }
89
- override getModelRoot(): Readonly<GModelRoot> {
90
- return this.modelRoot;
91
- }
92
- }
93
-
94
- // Generic Test setup
95
- const container = new Container();
96
- container.load(defaultModule);
97
-
98
- const actionDispatcher = new MockActionDispatcher();
99
-
100
- const node1 = {
101
- id: 'node1',
102
- type: 'node:circle',
103
- selected: true
104
- };
105
- const node2 = {
106
- id: 'node2',
107
- type: 'node:circle',
108
- selected: true
109
- };
110
- const node3 = {
111
- id: 'node3',
112
- type: 'node:circle',
113
- selected: true
114
- };
115
- const model = createModel();
116
-
117
- function createNode(schema: GNodeSchema): GNode {
118
- const node = new GNode();
119
- const features = new Set<symbol>(GNode.DEFAULT_FEATURES);
120
- node.features = features;
121
- Object.assign(node, schema);
122
- return node;
123
- }
124
-
125
- function createModel(): GModelRoot {
126
- const root = new GGraph();
127
- root.features = new Set<symbol>(GGraph.DEFAULT_FEATURES);
128
- root.add(createNode(node1));
129
- root.add(createNode(node2));
130
- root.add(createNode(node3));
131
-
132
- root.children.forEach(child => applyFeature(child, resizeFeature));
133
- return root;
134
- }
135
-
136
- function applyFeature(element: GChildElement, feature: symbol): void {
137
- (element.features as FeatureSet & Set<symbol>).add(feature);
138
- }
139
-
140
- const context: CommandExecutionContext = {
141
- root: model,
142
- modelFactory: sinon.createStubInstance(GModelFactory),
143
- duration: 0,
144
- modelChanged: undefined!,
145
- logger: new ConsoleLogger(),
146
- syncer: new AnimationFrameSyncer()
147
- };
148
-
149
- const defaultSize = { height: 10, width: 10 };
150
-
151
- describe('AlignElementsCommand', () => {
152
- let handler: AlignElementsActionHandler;
153
- const setModel = (newModel: GModelRoot): void => {
154
- handler['selectionService'] = new MockSelectionService(newModel);
155
- };
156
-
157
- beforeEach(() => {
158
- actionDispatcher.dispatchedActions = [];
159
-
160
- handler = new AlignElementsActionHandler();
161
- handler['actionDispatcher'] = actionDispatcher;
162
- });
163
- it('should align all elements left', () => {
164
- const newModel = initModel([
165
- { elementId: 'node1', newPosition: { x: 111, y: 111 }, newSize: defaultSize },
166
- { elementId: 'node2', newPosition: { x: 222, y: 222 }, newSize: defaultSize },
167
- { elementId: 'node3', newPosition: { x: 333, y: 333 }, newSize: defaultSize }
168
- ]);
169
- const action = AlignElementsAction.create({ elementIds: ['node1', 'node2', 'node3'], alignment: Alignment.Left });
170
- setModel(newModel);
171
- handler.handle(action);
172
-
173
- assertAllBounds(
174
- new Map([
175
- ['node1', { x: 111, y: 111, width: defaultSize.width, height: defaultSize.height }],
176
- ['node2', { x: 111, y: 222, width: defaultSize.width, height: defaultSize.height }],
177
- ['node3', { x: 111, y: 333, width: defaultSize.width, height: defaultSize.height }]
178
- ])
179
- );
180
- });
181
-
182
- it('should align all elements right', () => {
183
- const newModel = initModel([
184
- { elementId: 'node1', newPosition: { x: 111, y: 111 }, newSize: defaultSize },
185
- { elementId: 'node2', newPosition: { x: 222, y: 222 }, newSize: defaultSize },
186
- { elementId: 'node3', newPosition: { x: 333, y: 333 }, newSize: defaultSize }
187
- ]);
188
- const action = AlignElementsAction.create({ elementIds: ['node1', 'node2', 'node3'], alignment: Alignment.Right });
189
- setModel(newModel);
190
- handler.handle(action);
191
- assertAllBounds(
192
- new Map([
193
- ['node1', { x: 333, y: 111, width: defaultSize.width, height: defaultSize.height }],
194
- ['node2', { x: 333, y: 222, width: defaultSize.width, height: defaultSize.height }],
195
- ['node3', { x: 333, y: 333, width: defaultSize.width, height: defaultSize.height }]
196
- ])
197
- );
198
- });
199
-
200
- it('should align all elements center', () => {
201
- actionDispatcher.dispatchedActions = [];
202
- const newModel = initModel([
203
- { elementId: 'node1', newPosition: { x: 111, y: 111 }, newSize: defaultSize },
204
- { elementId: 'node2', newPosition: { x: 222, y: 222 }, newSize: defaultSize },
205
- { elementId: 'node3', newPosition: { x: 333, y: 333 }, newSize: defaultSize }
206
- ]);
207
- const action = AlignElementsAction.create({ elementIds: ['node1', 'node2', 'node3'], alignment: Alignment.Center });
208
- setModel(newModel);
209
- handler.handle(action);
210
-
211
- assertAllBounds(
212
- new Map([
213
- ['node1', { x: 222, y: 111, width: defaultSize.width, height: defaultSize.height }],
214
- ['node2', { x: 222, y: 222, width: defaultSize.width, height: defaultSize.height }],
215
- ['node3', { x: 222, y: 333, width: defaultSize.width, height: defaultSize.height }]
216
- ])
217
- );
218
- });
219
-
220
- it('should align all elements top', () => {
221
- const newModel = initModel([
222
- { elementId: 'node1', newPosition: { x: 111, y: 111 }, newSize: defaultSize },
223
- { elementId: 'node2', newPosition: { x: 222, y: 222 }, newSize: defaultSize },
224
- { elementId: 'node3', newPosition: { x: 333, y: 333 }, newSize: defaultSize }
225
- ]);
226
- const action = AlignElementsAction.create({ elementIds: ['node1', 'node2', 'node3'], alignment: Alignment.Top });
227
- setModel(newModel);
228
- handler.handle(action);
229
-
230
- assertAllBounds(
231
- new Map([
232
- ['node1', { x: 111, y: 111, width: defaultSize.width, height: defaultSize.height }],
233
- ['node2', { x: 222, y: 111, width: defaultSize.width, height: defaultSize.height }],
234
- ['node3', { x: 333, y: 111, width: defaultSize.width, height: defaultSize.height }]
235
- ])
236
- );
237
- });
238
-
239
- it('should align all elements bottom', () => {
240
- const newModel = initModel([
241
- { elementId: 'node1', newPosition: { x: 111, y: 111 }, newSize: defaultSize },
242
- { elementId: 'node2', newPosition: { x: 222, y: 222 }, newSize: defaultSize },
243
- { elementId: 'node3', newPosition: { x: 333, y: 333 }, newSize: defaultSize }
244
- ]);
245
- const action = AlignElementsAction.create({ elementIds: ['node1', 'node2', 'node3'], alignment: Alignment.Bottom });
246
- setModel(newModel);
247
- handler.handle(action);
248
-
249
- assertAllBounds(
250
- new Map([
251
- ['node1', { x: 111, y: 333, width: defaultSize.width, height: defaultSize.height }],
252
- ['node2', { x: 222, y: 333, width: defaultSize.width, height: defaultSize.height }],
253
- ['node3', { x: 333, y: 333, width: defaultSize.width, height: defaultSize.height }]
254
- ])
255
- );
256
- });
257
-
258
- it('should align all elements middle', () => {
259
- const newModel = initModel([
260
- { elementId: 'node1', newPosition: { x: 111, y: 111 }, newSize: defaultSize },
261
- { elementId: 'node2', newPosition: { x: 222, y: 222 }, newSize: defaultSize },
262
- { elementId: 'node3', newPosition: { x: 333, y: 333 }, newSize: defaultSize }
263
- ]);
264
- const action = AlignElementsAction.create({ elementIds: ['node1', 'node2', 'node3'], alignment: Alignment.Middle });
265
- setModel(newModel);
266
- handler.handle(action);
267
-
268
- assertAllBounds(
269
- new Map([
270
- ['node1', { x: 111, y: 222, width: defaultSize.width, height: defaultSize.height }],
271
- ['node2', { x: 222, y: 222, width: defaultSize.width, height: defaultSize.height }],
272
- ['node3', { x: 333, y: 222, width: defaultSize.width, height: defaultSize.height }]
273
- ])
274
- );
275
- });
276
- });
277
-
278
- describe('ResizeElementsCommand', () => {
279
- let handler: ResizeElementsActionHandler;
280
- const setModel = (newModel: GModelRoot): void => {
281
- handler['selectionService'] = new MockSelectionService(newModel);
282
- };
283
-
284
- beforeEach(() => {
285
- actionDispatcher.dispatchedActions = [];
286
-
287
- handler = new ResizeElementsActionHandler();
288
- handler['actionDispatcher'] = actionDispatcher;
289
- });
290
- it('should make same width as last', () => {
291
- const newModel = initModel([
292
- { elementId: 'node1', newPosition: { x: 100, y: 100 }, newSize: { height: 10, width: 10 } },
293
- { elementId: 'node2', newPosition: { x: 100, y: 200 }, newSize: { height: 20, width: 20 } },
294
- { elementId: 'node3', newPosition: { x: 100, y: 300 }, newSize: { height: 30, width: 30 } }
295
- ]);
296
- const action = ResizeElementsAction.create({
297
- elementIds: ['node1', 'node2', 'node3'],
298
- dimension: ResizeDimension.Width,
299
- reduceFunction: 'last'
300
- });
301
- setModel(newModel);
302
- handler.handle(action);
303
-
304
- // resize is keeping the center, so the X moves by diff / 2
305
- assertAllBoundsInChangeBounds(
306
- new Map([
307
- ['node1', { x: 90, y: 100, height: 10, width: 30 }],
308
- ['node2', { x: 95, y: 200, height: 20, width: 30 }],
309
- ['node3', { x: 100, y: 300, height: 30, width: 30 }]
310
- ])
311
- );
312
- });
313
-
314
- it('should make same height as last', () => {
315
- const newModel = initModel([
316
- { elementId: 'node1', newPosition: { x: 100, y: 100 }, newSize: { height: 10, width: 10 } },
317
- { elementId: 'node2', newPosition: { x: 100, y: 200 }, newSize: { height: 20, width: 20 } },
318
- { elementId: 'node3', newPosition: { x: 100, y: 300 }, newSize: { height: 30, width: 30 } }
319
- ]);
320
- const action = ResizeElementsAction.create({
321
- elementIds: ['node1', 'node2', 'node3'],
322
- dimension: ResizeDimension.Height,
323
- reduceFunction: 'last'
324
- });
325
- setModel(newModel);
326
- handler.handle(action);
327
-
328
- // resize is keeping the center, so the Y moves by diff / 2
329
- assertAllBoundsInChangeBounds(
330
- new Map([
331
- ['node1', { x: 100, y: 90, height: 30, width: 10 }],
332
- ['node2', { x: 100, y: 195, height: 30, width: 20 }],
333
- ['node3', { x: 100, y: 300, height: 30, width: 30 }]
334
- ])
335
- );
336
- });
337
-
338
- it('should make same width and height as last', () => {
339
- const newModel = initModel([
340
- { elementId: 'node1', newPosition: { x: 100, y: 100 }, newSize: { height: 10, width: 10 } },
341
- { elementId: 'node2', newPosition: { x: 100, y: 200 }, newSize: { height: 20, width: 20 } },
342
- { elementId: 'node3', newPosition: { x: 100, y: 300 }, newSize: { height: 30, width: 30 } }
343
- ]);
344
- const action = ResizeElementsAction.create({
345
- elementIds: ['node1', 'node2', 'node3'],
346
- dimension: ResizeDimension.Width_And_Height,
347
- reduceFunction: 'last'
348
- });
349
- setModel(newModel);
350
- handler.handle(action);
351
-
352
- // resize is keeping the center, so the Y moves by diff / 2
353
- assertAllBoundsInChangeBounds(
354
- new Map([
355
- ['node1', { x: 90, y: 90, height: 30, width: 30 }],
356
- ['node2', { x: 95, y: 195, height: 30, width: 30 }],
357
- ['node3', { x: 100, y: 300, height: 30, width: 30 }]
358
- ])
359
- );
360
- });
361
- });
362
-
363
- function initModel(elementAndBounds: ElementAndBounds[]): GModelRoot {
364
- const mySetBoundsAction = SetBoundsAction.create(elementAndBounds);
365
- const setBoundsCommand = new SetBoundsCommand(mySetBoundsAction);
366
- return setBoundsCommand.execute(context) as GModelRoot;
367
- }
368
-
369
- function assertAllBounds(allBounds: Map<string, Bounds>): void {
370
- allBounds.forEach((bounds, nodeId) => assertBounds(nodeId, bounds));
371
- }
372
-
373
- function assertAllBoundsInChangeBounds(allBounds: Map<string, Bounds>): void {
374
- allBounds.forEach((bounds, nodeId) => assertBoundsInChangeBoundsActions(nodeId, bounds));
375
- }
376
-
377
- function assertBounds(nodeId: string, bounds: Bounds): void {
378
- assertBoundsInMoves(nodeId, bounds);
379
- assertBoundsInChangeBoundsActions(nodeId, bounds);
380
- }
381
-
382
- function assertBoundsInMoves(nodeId: string, bounds: Bounds): void {
383
- const moves = dispatchedElementMoves();
384
- const move = getMoveById(nodeId, moves);
385
- expect(move.toPosition.x).to.be.equal(bounds.x);
386
- expect(move.toPosition.y).to.be.equal(bounds.y);
387
- }
388
-
389
- function assertBoundsInChangeBoundsActions(nodeId: string, bounds: Bounds): void {
390
- const allChangeBounds = dispatchedChangeBounds();
391
- const changeBounds = getElementAndBoundsById(nodeId, allChangeBounds);
392
- expect(changeBounds.newPosition!.x).to.be.equal(bounds.x);
393
- expect(changeBounds.newPosition!.y).to.be.equal(bounds.y);
394
- expect(changeBounds.newSize!.height).to.be.equal(bounds.height);
395
- expect(changeBounds.newSize!.width).to.be.equal(bounds.width);
396
- }
397
-
398
- function getMoveById(id: string, moves: ElementMove[]): ElementMove {
399
- return moves.filter(m => m.elementId === id)[0];
400
- }
401
-
402
- function getElementAndBoundsById(id: string, elementAndBounds: ElementAndBounds[]): ElementAndBounds {
403
- return elementAndBounds.filter(m => m.elementId === id)[0];
404
- }
405
-
406
- function dispatchedElementMoves(): ElementMove[] {
407
- return actionDispatcher.dispatchedActions
408
- .filter(isMoveAction)
409
- .map(a => a.moves)
410
- .reduce((acc, val) => acc.concat(val), []);
411
- }
412
-
413
- function dispatchedChangeBounds(): ElementAndBounds[] {
414
- return actionDispatcher.dispatchedActions
415
- .filter(isChangeBounds)
416
- .map(a => a.newBounds)
417
- .reduce((acc, val) => acc.concat(val), []);
418
- }
419
-
420
- function isMoveAction(action: Action): action is MoveAction {
421
- return action.kind === MoveCommand.KIND;
422
- }
423
-
424
- function isChangeBounds(action: Action): action is ChangeBoundsOperation {
425
- return action.kind === ChangeBoundsOperation.KIND;
426
- }
@@ -1,56 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2020-2023 EclipseSource and others.
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * This Source Code may also be made available under the following Secondary
9
- * Licenses when the conditions for such availability set forth in the Eclipse
10
- * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- * with the GNU Classpath Exception which is available at
12
- * https://www.gnu.org/software/classpath/license.html.
13
- *
14
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
- ********************************************************************************/
16
- import { expect } from 'chai';
17
- import 'mocha';
18
- import 'reflect-metadata';
19
- import { NavigationTarget } from '@eclipse-glsp/sprotty';
20
-
21
- describe('NavigationTarget', () => {
22
- it('should be able to set and get element IDs', () => {
23
- const navigationTarget: NavigationTarget = { uri: 'uri' };
24
- NavigationTarget.setElementIds(navigationTarget, 'id1', 'id2');
25
- expect(NavigationTarget.getElementIds(navigationTarget)).to.be.eql(['id1', 'id2']);
26
- });
27
-
28
- it('should be able to set and get textual positions', () => {
29
- const navigationTarget: NavigationTarget = { uri: 'uri' };
30
- NavigationTarget.setTextPosition(navigationTarget, { line: 1, character: 2 });
31
- expect(NavigationTarget.getTextPosition(navigationTarget)).to.be.eql({ line: 1, character: 2 });
32
- });
33
-
34
- it('should be able to set and get custom query arguments', () => {
35
- const navigationTarget: NavigationTarget = { uri: 'uri' };
36
- NavigationTarget.addArgument(navigationTarget, 'name', 'test');
37
- expect(navigationTarget.args!.name).to.be.eql('test');
38
- });
39
-
40
- it('should specify whether it has arguments', () => {
41
- let navigationTarget: NavigationTarget = { uri: 'uri' };
42
- expect(NavigationTarget.hasArguments(navigationTarget)).to.be.false;
43
- NavigationTarget.addArgument(navigationTarget, 'name', 'test');
44
- expect(NavigationTarget.hasArguments(navigationTarget)).to.be.true;
45
-
46
- navigationTarget = { uri: 'uri' };
47
- expect(NavigationTarget.hasArguments(navigationTarget)).to.be.false;
48
- NavigationTarget.setElementIds(navigationTarget, 'id1', 'id2');
49
- expect(NavigationTarget.hasArguments(navigationTarget)).to.be.true;
50
-
51
- navigationTarget = { uri: 'uri' };
52
- expect(NavigationTarget.hasArguments(navigationTarget)).to.be.false;
53
- NavigationTarget.setTextPosition(navigationTarget, { line: 1, character: 2 });
54
- expect(NavigationTarget.hasArguments(navigationTarget)).to.be.true;
55
- });
56
- });
@@ -1,212 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2026 EclipseSource and others.
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * This Source Code may also be made available under the following Secondary
9
- * Licenses when the conditions for such availability set forth in the Eclipse
10
- * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
- * with the GNU Classpath Exception which is available at
12
- * https://www.gnu.org/software/classpath/license.html.
13
- *
14
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
- ********************************************************************************/
16
- import { DefaultAnchors, EdgeRouterRegistry, GNode, GRoutableElement, Point, Side } from '@eclipse-glsp/sprotty';
17
- import { expect } from 'chai';
18
- import { Container } from 'inversify';
19
- import { GEdge, GGraph } from '../../model';
20
- import { routingModule } from './routing-module';
21
- import { GLSPStickyManhattanEdgeRouter, StickyManhattanRouterOptions } from './sticky-manhattan-edge-router';
22
-
23
- /** Exposes the protected helpers as public so the spec can exercise them directly. */
24
- class TestableStickyManhattanEdgeRouter extends GLSPStickyManhattanEdgeRouter {
25
- public override manhattanify(points: Point[], edge: GRoutableElement): void {
26
- super.manhattanify(points, edge);
27
- }
28
- public override getOptions(edge: GRoutableElement): StickyManhattanRouterOptions {
29
- return super.getOptions(edge);
30
- }
31
- public override getBestConnectionAnchors(
32
- sourceAnchors: DefaultAnchors,
33
- targetAnchors: DefaultAnchors,
34
- options: StickyManhattanRouterOptions
35
- ): { source: Side; target: Side } {
36
- return super.getBestConnectionAnchors(sourceAnchors, targetAnchors, options);
37
- }
38
- }
39
-
40
- function newNode(id: string, x: number, y: number, width = 40, height = 30): GNode {
41
- const node = new GNode();
42
- node.id = id;
43
- node.position = { x, y };
44
- node.size = { width, height };
45
- return node;
46
- }
47
-
48
- function setupEdge(opts: { sourcePos?: Point; targetPos?: Point; routingPoints?: Point[] }): {
49
- graph: GGraph;
50
- edge: GEdge;
51
- router: GLSPStickyManhattanEdgeRouter;
52
- } {
53
- const graph = new GGraph();
54
- const source = newNode('source', opts.sourcePos?.x ?? 0, opts.sourcePos?.y ?? 0);
55
- const target = newNode('target', opts.targetPos?.x ?? 200, opts.targetPos?.y ?? 100);
56
- graph.add(source);
57
- graph.add(target);
58
-
59
- const edge = new GEdge();
60
- edge.id = 'edge';
61
- edge.sourceId = 'source';
62
- edge.targetId = 'target';
63
- edge.routerKind = GLSPStickyManhattanEdgeRouter.KIND;
64
- if (opts.routingPoints) {
65
- edge.routingPoints = opts.routingPoints.slice();
66
- }
67
- graph.add(edge);
68
-
69
- const container = new Container();
70
- container.load(routingModule);
71
- const registry = container.get<EdgeRouterRegistry>(EdgeRouterRegistry);
72
- const router = registry.get(GLSPStickyManhattanEdgeRouter.KIND) as GLSPStickyManhattanEdgeRouter;
73
- return { graph, edge, router };
74
- }
75
-
76
- describe('GLSPStickyManhattanEdgeRouter', () => {
77
- describe('route()', () => {
78
- it('returns an empty route when the source node cannot be resolved', () => {
79
- const graph = new GGraph();
80
- const target = newNode('target', 200, 100);
81
- graph.add(target);
82
- const edge = new GEdge();
83
- edge.id = 'edge';
84
- edge.sourceId = 'missing';
85
- edge.targetId = 'target';
86
- edge.routerKind = GLSPStickyManhattanEdgeRouter.KIND;
87
- graph.add(edge);
88
-
89
- const container = new Container();
90
- container.load(routingModule);
91
- const router = container
92
- .get<EdgeRouterRegistry>(EdgeRouterRegistry)
93
- .get(GLSPStickyManhattanEdgeRouter.KIND) as GLSPStickyManhattanEdgeRouter;
94
- expect(router.route(edge)).to.deep.equal([]);
95
- });
96
-
97
- it('produces a source-first, target-last sequence with intermediate linear points', () => {
98
- const { edge, router } = setupEdge({});
99
- const route = router.route(edge);
100
- expect(route[0].kind).to.equal('source');
101
- expect(route[route.length - 1].kind).to.equal('target');
102
- expect(route.slice(1, -1).every(p => p.kind === 'linear')).to.equal(true);
103
- });
104
-
105
- it('computes a two-corner default route for horizontally separated nodes', () => {
106
- const { edge, router } = setupEdge({ sourcePos: { x: 0, y: 0 }, targetPos: { x: 200, y: 100 } });
107
- const route = router.route(edge);
108
- // source RIGHT -> target LEFT with different Y: two corners at midX.
109
- const interior = route.slice(1, -1);
110
- expect(interior).to.have.lengthOf(2);
111
- expect(interior[0].x).to.equal(interior[1].x);
112
- expect(interior[0].y).to.not.equal(interior[1].y);
113
- });
114
- });
115
-
116
- describe('sticky behavior', () => {
117
- it('preserves interior bend points when the source node moves vertically', () => {
118
- const { edge, router } = setupEdge({
119
- sourcePos: { x: 0, y: 0 },
120
- targetPos: { x: 300, y: 200 },
121
- routingPoints: [
122
- { x: 150, y: 15 },
123
- { x: 150, y: 215 }
124
- ]
125
- });
126
-
127
- // Prime the position snapshot.
128
- router.route(edge);
129
-
130
- // Move the source node down by 50px.
131
- edge.source!.position = { x: 0, y: 50 };
132
- const route = router.route(edge);
133
- const interior = route.slice(1, -1);
134
-
135
- // The shared x=150 spine must stay put — no recomputed midX.
136
- expect(interior.every(p => p.x === 150)).to.equal(true);
137
- // The target-side bend must not have moved.
138
- expect(interior[interior.length - 1].y).to.equal(215);
139
- });
140
- });
141
-
142
- describe('cleanupRoutingPoints()', () => {
143
- it('removes leading routing points that fall inside the source bounds', () => {
144
- const { edge, router } = setupEdge({
145
- sourcePos: { x: 0, y: 0 },
146
- targetPos: { x: 300, y: 100 },
147
- routingPoints: [
148
- { x: 10, y: 10 }, // inside source bounds (40x30 at origin)
149
- { x: 150, y: 20 },
150
- { x: 150, y: 110 }
151
- ]
152
- });
153
- const points = edge.routingPoints.slice();
154
- router.cleanupRoutingPoints(edge, points, false, false);
155
- expect(points).to.not.deep.include({ x: 10, y: 10 });
156
- expect(points[0]).to.deep.equal({ x: 150, y: 20 });
157
- });
158
-
159
- it('collapses degenerate segments shorter than minimalPointDistance', () => {
160
- const { edge, router } = setupEdge({ sourcePos: { x: 0, y: 0 }, targetPos: { x: 300, y: 100 } });
161
- const points: Point[] = [
162
- { x: 100, y: 20 },
163
- { x: 101, y: 21 }, // manhattan distance 2 < default minimal of 3
164
- { x: 250, y: 20 }
165
- ];
166
- router.cleanupRoutingPoints(edge, points, false, false);
167
- expect(points).to.have.lengthOf(1);
168
- expect(points[0]).to.deep.equal({ x: 250, y: 20 });
169
- });
170
- });
171
-
172
- describe('manhattanify()', () => {
173
- it('inserts an intermediate corner so every segment is strictly orthogonal', () => {
174
- const { edge, router } = setupEdge({});
175
- const testable = router as TestableStickyManhattanEdgeRouter;
176
- const points: Point[] = [
177
- { x: 0, y: 0 },
178
- { x: 50, y: 50 } // diagonal
179
- ];
180
- testable.manhattanify(points, edge);
181
- expect(points).to.deep.equal([
182
- { x: 0, y: 0 },
183
- { x: 0, y: 50 },
184
- { x: 50, y: 50 }
185
- ]);
186
- });
187
-
188
- it('leaves strictly orthogonal routes untouched', () => {
189
- const { edge, router } = setupEdge({});
190
- const testable = router as TestableStickyManhattanEdgeRouter;
191
- const points: Point[] = [
192
- { x: 0, y: 0 },
193
- { x: 50, y: 0 },
194
- { x: 50, y: 40 }
195
- ];
196
- const before = points.map(p => ({ ...p }));
197
- testable.manhattanify(points, edge);
198
- expect(points).to.deep.equal(before);
199
- });
200
- });
201
-
202
- describe('getBestConnectionAnchors()', () => {
203
- it('picks RIGHT/LEFT when source is clearly to the left of target', () => {
204
- const { edge } = setupEdge({ sourcePos: { x: 0, y: 0 }, targetPos: { x: 400, y: 0 } });
205
- const router = new TestableStickyManhattanEdgeRouter();
206
- const sourceAnchors = new DefaultAnchors(edge.source!, edge.parent, 'source');
207
- const targetAnchors = new DefaultAnchors(edge.target!, edge.parent, 'target');
208
- const result = router.getBestConnectionAnchors(sourceAnchors, targetAnchors, router.getOptions(edge));
209
- expect(result).to.deep.equal({ source: Side.RIGHT, target: Side.LEFT });
210
- });
211
- });
212
- });