@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.
- package/README.md +1 -1
- package/css/grid.css +2 -1
- package/lib/base/action-dispatcher.js +1 -4
- package/lib/base/action-dispatcher.js.map +1 -1
- package/lib/base/auto-complete/auto-complete-widget.js +4 -8
- package/lib/base/auto-complete/auto-complete-widget.js.map +1 -1
- package/lib/base/auto-complete/base-autocomplete-palette.js +1 -2
- package/lib/base/auto-complete/base-autocomplete-palette.js.map +1 -1
- package/lib/base/editor-context-service.js +4 -7
- package/lib/base/editor-context-service.js.map +1 -1
- package/lib/base/feedback/css-feedback.js +1 -1
- package/lib/base/feedback/css-feedback.js.map +1 -1
- package/lib/base/feedback/feedback-action-dispatcher.js +4 -6
- package/lib/base/feedback/feedback-action-dispatcher.js.map +1 -1
- package/lib/base/feedback/feedback-command.js +1 -2
- package/lib/base/feedback/feedback-command.js.map +1 -1
- package/lib/base/feedback/feedback-emitter.js +1 -2
- package/lib/base/feedback/feedback-emitter.js.map +1 -1
- package/lib/base/feedback/set-model-command.js +1 -2
- package/lib/base/feedback/set-model-command.js.map +1 -1
- package/lib/base/feedback/update-model-command.js +1 -2
- package/lib/base/feedback/update-model-command.js.map +1 -1
- package/lib/base/model/diagram-loader.js +4 -6
- package/lib/base/model/diagram-loader.js.map +1 -1
- package/lib/base/model/glsp-model-source.d.ts +1 -1
- package/lib/base/model/glsp-model-source.d.ts.map +1 -1
- package/lib/base/model/glsp-model-source.js +3 -5
- package/lib/base/model/glsp-model-source.js.map +1 -1
- package/lib/base/model/model-registry.js +1 -2
- package/lib/base/model/model-registry.js.map +1 -1
- package/lib/base/selection-service.js +3 -3
- package/lib/base/selection-service.js.map +1 -1
- package/lib/base/shortcuts/available-shortcuts-extension.js +3 -2
- package/lib/base/shortcuts/available-shortcuts-extension.js.map +1 -1
- package/lib/base/shortcuts/available-shortcuts-tool.js +3 -2
- package/lib/base/shortcuts/available-shortcuts-tool.js.map +1 -1
- package/lib/base/tool-manager/tool-manager.js +1 -1
- package/lib/base/tool-manager/tool-manager.js.map +1 -1
- package/lib/base/ui-extension/ui-extension.js +4 -6
- package/lib/base/ui-extension/ui-extension.js.map +1 -1
- package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-palette.js +12 -17
- package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-palette.js.map +1 -1
- package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-tool.js +3 -2
- package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-tool.js.map +1 -1
- package/lib/features/accessibility/element-navigation/diagram-navigation-tool.js +11 -15
- package/lib/features/accessibility/element-navigation/diagram-navigation-tool.js.map +1 -1
- package/lib/features/accessibility/element-navigation/left-right-top-bottom-navigator.js +2 -3
- package/lib/features/accessibility/element-navigation/left-right-top-bottom-navigator.js.map +1 -1
- package/lib/features/accessibility/element-navigation/local-element-navigator.js +2 -3
- package/lib/features/accessibility/element-navigation/local-element-navigator.js.map +1 -1
- package/lib/features/accessibility/focus-tracker/focus-tracker-tool.js +5 -4
- package/lib/features/accessibility/focus-tracker/focus-tracker-tool.js.map +1 -1
- package/lib/features/accessibility/global-keylistener-tool.js +4 -3
- package/lib/features/accessibility/global-keylistener-tool.js.map +1 -1
- package/lib/features/accessibility/keyboard-grid/keyboard-grid-search-palette.js +3 -2
- package/lib/features/accessibility/keyboard-grid/keyboard-grid-search-palette.js.map +1 -1
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.js +5 -7
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.js.map +1 -1
- package/lib/features/accessibility/toast/toast-handler.js +2 -4
- package/lib/features/accessibility/toast/toast-handler.js.map +1 -1
- package/lib/features/accessibility/toast/toast-tool.js +3 -2
- package/lib/features/accessibility/toast/toast-tool.js.map +1 -1
- package/lib/features/accessibility/view-key-tools/deselect-key-tool.js +3 -2
- package/lib/features/accessibility/view-key-tools/deselect-key-tool.js.map +1 -1
- package/lib/features/accessibility/view-key-tools/grid-cell-zoom-key-tool.js +4 -3
- package/lib/features/accessibility/view-key-tools/grid-cell-zoom-key-tool.js.map +1 -1
- package/lib/features/bounds/freeform-layout.js +1 -1
- package/lib/features/bounds/freeform-layout.js.map +1 -1
- package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts +31 -1
- package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts.map +1 -1
- package/lib/features/bounds/glsp-hidden-bounds-updater.js +119 -58
- package/lib/features/bounds/glsp-hidden-bounds-updater.js.map +1 -1
- package/lib/features/bounds/hbox-layout.js +7 -10
- package/lib/features/bounds/hbox-layout.js.map +1 -1
- package/lib/features/bounds/layout-data.js +2 -4
- package/lib/features/bounds/layout-data.js.map +1 -1
- package/lib/features/bounds/local-bounds.js +3 -4
- package/lib/features/bounds/local-bounds.js.map +1 -1
- package/lib/features/bounds/set-bounds-feedback-command.js +2 -3
- package/lib/features/bounds/set-bounds-feedback-command.js.map +1 -1
- package/lib/features/bounds/vbox-layout.js +7 -10
- package/lib/features/bounds/vbox-layout.js.map +1 -1
- package/lib/features/change-bounds/model.js +1 -1
- package/lib/features/change-bounds/model.js.map +1 -1
- package/lib/features/change-bounds/move-element-handler.js +1 -2
- package/lib/features/change-bounds/move-element-handler.js.map +1 -1
- package/lib/features/change-bounds/movement-restrictor.js +1 -2
- package/lib/features/change-bounds/movement-restrictor.js.map +1 -1
- package/lib/features/change-bounds/point-position-updater.js +1 -1
- package/lib/features/change-bounds/point-position-updater.js.map +1 -1
- package/lib/features/change-bounds/resize/resize-default-tool.js +4 -3
- package/lib/features/change-bounds/resize/resize-default-tool.js.map +1 -1
- package/lib/features/change-bounds/resize/resize-handler.js +1 -2
- package/lib/features/change-bounds/resize/resize-handler.js.map +1 -1
- package/lib/features/change-bounds/resize/resize-tool.js +4 -3
- package/lib/features/change-bounds/resize/resize-tool.js.map +1 -1
- package/lib/features/change-bounds/tracker.js +1 -2
- package/lib/features/change-bounds/tracker.js.map +1 -1
- package/lib/features/command-palette/command-palette-tool.js +3 -2
- package/lib/features/command-palette/command-palette-tool.js.map +1 -1
- package/lib/features/command-palette/command-palette.js +2 -3
- package/lib/features/command-palette/command-palette.js.map +1 -1
- package/lib/features/context-menu/glsp-context-menu-mouse-listener.js +2 -3
- package/lib/features/context-menu/glsp-context-menu-mouse-listener.js.map +1 -1
- package/lib/features/copy-paste/copy-paste-handler.d.ts +1 -1
- package/lib/features/copy-paste/copy-paste-handler.d.ts.map +1 -1
- package/lib/features/copy-paste/copy-paste-handler.js +3 -5
- package/lib/features/copy-paste/copy-paste-handler.js.map +1 -1
- package/lib/features/copy-paste/copy-paste-standalone.js +6 -9
- package/lib/features/copy-paste/copy-paste-standalone.js.map +1 -1
- package/lib/features/debug/debug-bounds-decorator.js +9 -12
- package/lib/features/debug/debug-bounds-decorator.js.map +1 -1
- package/lib/features/debug/debug-model.js +1 -1
- package/lib/features/debug/debug-model.js.map +1 -1
- package/lib/features/decoration/decoration-placer.js +3 -2
- package/lib/features/decoration/decoration-placer.js.map +1 -1
- package/lib/features/element-template/add-template-element.d.ts +6 -1
- package/lib/features/element-template/add-template-element.d.ts.map +1 -1
- package/lib/features/element-template/add-template-element.js +17 -5
- package/lib/features/element-template/add-template-element.js.map +1 -1
- package/lib/features/element-template/mouse-tracking-element-position-listener.js +1 -1
- package/lib/features/element-template/mouse-tracking-element-position-listener.js.map +1 -1
- package/lib/features/element-template/remove-template-element.js +1 -1
- package/lib/features/element-template/remove-template-element.js.map +1 -1
- package/lib/features/export/default-png-diagram-exporter.js +4 -7
- package/lib/features/export/default-png-diagram-exporter.js.map +1 -1
- package/lib/features/export/diagram-export-postprocessor.js +1 -2
- package/lib/features/export/diagram-export-postprocessor.js.map +1 -1
- package/lib/features/export/glsp-svg-exporter.d.ts.map +1 -1
- package/lib/features/export/glsp-svg-exporter.js +5 -6
- package/lib/features/export/glsp-svg-exporter.js.map +1 -1
- package/lib/features/export/request-export-command.js +1 -1
- package/lib/features/export/request-export-command.js.map +1 -1
- package/lib/features/grid/grid-model.js +1 -1
- package/lib/features/grid/grid-model.js.map +1 -1
- package/lib/features/helper-lines/helper-line-feedback.js +7 -8
- package/lib/features/helper-lines/helper-line-feedback.js.map +1 -1
- package/lib/features/helper-lines/model.d.ts +1 -1
- package/lib/features/helper-lines/model.d.ts.map +1 -1
- package/lib/features/helper-lines/model.js +3 -4
- package/lib/features/helper-lines/model.js.map +1 -1
- package/lib/features/hints/type-hint-provider.js +3 -5
- package/lib/features/hints/type-hint-provider.js.map +1 -1
- package/lib/features/label-edit/edit-label-tool.js +3 -2
- package/lib/features/label-edit/edit-label-tool.js.map +1 -1
- package/lib/features/label-edit-ui/label-edit-ui.js +2 -3
- package/lib/features/label-edit-ui/label-edit-ui.js.map +1 -1
- package/lib/features/navigation/navigation-target-resolver.js +1 -1
- package/lib/features/navigation/navigation-target-resolver.js.map +1 -1
- package/lib/features/routing/sticky-manhattan-anchors.js +9 -6
- package/lib/features/routing/sticky-manhattan-anchors.js.map +1 -1
- package/lib/features/routing/sticky-manhattan-edge-router.js +10 -12
- package/lib/features/routing/sticky-manhattan-edge-router.js.map +1 -1
- package/lib/features/search-palette/search-palette.js +3 -2
- package/lib/features/search-palette/search-palette.js.map +1 -1
- package/lib/features/search-palette/suggestions/edge-element-suggestions.js +2 -3
- package/lib/features/search-palette/suggestions/edge-element-suggestions.js.map +1 -1
- package/lib/features/search-palette/suggestions/named-element-suggestions.js +8 -11
- package/lib/features/search-palette/suggestions/named-element-suggestions.js.map +1 -1
- package/lib/features/select/select-feedback-command.js +1 -1
- package/lib/features/select/select-feedback-command.js.map +1 -1
- package/lib/features/select/select-mouse-listener.js +1 -2
- package/lib/features/select/select-mouse-listener.js.map +1 -1
- package/lib/features/status/status-overlay.js +4 -4
- package/lib/features/status/status-overlay.js.map +1 -1
- package/lib/features/tool-palette/tool-palette.d.ts.map +1 -1
- package/lib/features/tool-palette/tool-palette.js +16 -23
- package/lib/features/tool-palette/tool-palette.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-manager.js +4 -6
- package/lib/features/tools/change-bounds/change-bounds-manager.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js +3 -4
- package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js +4 -8
- package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool.js +6 -6
- package/lib/features/tools/change-bounds/change-bounds-tool.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tracker.js +7 -10
- package/lib/features/tools/change-bounds/change-bounds-tracker.js.map +1 -1
- package/lib/features/tools/deletion/delete-tool.js +6 -4
- package/lib/features/tools/deletion/delete-tool.js.map +1 -1
- package/lib/features/tools/edge-creation/dangling-edge-feedback.d.ts +1 -1
- package/lib/features/tools/edge-creation/dangling-edge-feedback.d.ts.map +1 -1
- package/lib/features/tools/edge-creation/dangling-edge-feedback.js +7 -5
- package/lib/features/tools/edge-creation/dangling-edge-feedback.js.map +1 -1
- package/lib/features/tools/edge-creation/edge-creation-tool.js +5 -6
- package/lib/features/tools/edge-creation/edge-creation-tool.js.map +1 -1
- package/lib/features/tools/edge-creation/view.js +1 -2
- package/lib/features/tools/edge-creation/view.js.map +1 -1
- package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts +1 -1
- package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts.map +1 -1
- package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js +8 -5
- package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js.map +1 -1
- package/lib/features/tools/edge-edit/edge-edit-tool.js +3 -2
- package/lib/features/tools/edge-edit/edge-edit-tool.js.map +1 -1
- package/lib/features/tools/marquee-selection/marquee-mouse-tool.js +3 -2
- package/lib/features/tools/marquee-selection/marquee-mouse-tool.js.map +1 -1
- package/lib/features/tools/marquee-selection/marquee-tool-feedback.js +2 -2
- package/lib/features/tools/marquee-selection/marquee-tool-feedback.js.map +1 -1
- package/lib/features/tools/marquee-selection/marquee-tool.js +3 -2
- package/lib/features/tools/marquee-selection/marquee-tool.js.map +1 -1
- package/lib/features/tools/marquee-selection/model.d.ts +1 -1
- package/lib/features/tools/marquee-selection/model.d.ts.map +1 -1
- package/lib/features/tools/marquee-selection/model.js +3 -2
- package/lib/features/tools/marquee-selection/model.js.map +1 -1
- package/lib/features/tools/node-creation/container-manager.js +3 -4
- package/lib/features/tools/node-creation/container-manager.js.map +1 -1
- package/lib/features/tools/node-creation/insert-indicator.d.ts +1 -1
- package/lib/features/tools/node-creation/insert-indicator.d.ts.map +1 -1
- package/lib/features/tools/node-creation/insert-indicator.js +5 -5
- package/lib/features/tools/node-creation/insert-indicator.js.map +1 -1
- package/lib/features/tools/node-creation/node-creation-tool.js +5 -6
- package/lib/features/tools/node-creation/node-creation-tool.js.map +1 -1
- package/lib/features/tools/node-creation/node-creation-views.js +1 -2
- package/lib/features/tools/node-creation/node-creation-views.js.map +1 -1
- package/lib/features/validation/issue-marker.d.ts +2 -2
- package/lib/features/validation/issue-marker.d.ts.map +1 -1
- package/lib/features/validation/issue-marker.js +7 -2
- package/lib/features/validation/issue-marker.js.map +1 -1
- package/lib/features/validation/marker-navigator.js +1 -1
- package/lib/features/validation/marker-navigator.js.map +1 -1
- package/lib/features/validation/validate.js +4 -6
- package/lib/features/validation/validate.js.map +1 -1
- package/lib/features/viewport/origin-viewport.js +1 -1
- package/lib/features/viewport/origin-viewport.js.map +1 -1
- package/lib/features/viewport/reposition.js +2 -3
- package/lib/features/viewport/reposition.js.map +1 -1
- package/lib/features/viewport/viewport-handler.js +2 -3
- package/lib/features/viewport/viewport-handler.js.map +1 -1
- package/lib/features/viewport/viewport-tool.js +4 -3
- package/lib/features/viewport/viewport-tool.js.map +1 -1
- package/lib/features/zorder/bring-to-front-command.js +1 -2
- package/lib/features/zorder/bring-to-front-command.js.map +1 -1
- package/lib/model.js +2 -2
- package/lib/model.js.map +1 -1
- package/lib/utils/argument-utils.js +5 -5
- package/lib/utils/argument-utils.js.map +1 -1
- package/lib/utils/gmodel-util.d.ts +13 -1
- package/lib/utils/gmodel-util.d.ts.map +1 -1
- package/lib/utils/gmodel-util.js +15 -7
- package/lib/utils/gmodel-util.js.map +1 -1
- package/lib/utils/layout-utils.js +1 -2
- package/lib/utils/layout-utils.js.map +1 -1
- package/lib/views/glsp-projection-view.js +1 -2
- package/lib/views/glsp-projection-view.js.map +1 -1
- package/package.json +18 -17
- package/src/base/feedback/feedback-command.ts +1 -1
- package/src/base/model/glsp-model-source.ts +1 -1
- package/src/features/accessibility/README.md +5 -5
- package/src/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.ts +1 -1
- package/src/features/bounds/glsp-hidden-bounds-updater.ts +133 -60
- package/src/features/copy-paste/copy-paste-handler.ts +3 -3
- package/src/features/element-template/add-template-element.ts +17 -2
- package/src/features/export/glsp-svg-exporter.ts +2 -2
- package/src/features/helper-lines/model.ts +4 -5
- package/src/features/tool-palette/tool-palette.ts +2 -4
- package/src/features/tools/edge-creation/dangling-edge-feedback.ts +4 -2
- package/src/features/tools/edge-edit/edge-edit-tool-feedback.ts +5 -3
- package/src/features/tools/marquee-selection/model.ts +3 -2
- package/src/features/tools/node-creation/insert-indicator.ts +5 -5
- package/src/features/validation/issue-marker.ts +7 -2
- package/src/utils/gmodel-util.ts +23 -1
- package/src/base/action-dispatcher.spec.ts +0 -366
- package/src/base/feedback/feedback-emitter.spec.ts +0 -176
- package/src/base/model/model-initialization-constraint.spec.ts +0 -95
- package/src/base/selection-service.spec.ts +0 -318
- package/src/default-modules.spec.ts +0 -56
- package/src/features/bounds/freeform-layout.spec.ts +0 -216
- package/src/features/bounds/hbox-layout.spec.ts +0 -170
- package/src/features/bounds/layouter-test-util.spec.ts +0 -127
- package/src/features/bounds/vbox-layout.spec.ts +0 -170
- package/src/features/change-bounds/point-position-updater.spec.ts +0 -81
- package/src/features/grid/grid-snapper.spec.ts +0 -30
- package/src/features/hints/type-hint-provider.spec.ts +0 -360
- package/src/features/layout/layout-elements-action.spec.ts +0 -426
- package/src/features/navigation/navigation-target-resolver.spec.ts +0 -56
- package/src/features/routing/sticky-manhattan-edge-router.spec.ts +0 -212
- package/src/features/tools/marquee-selection/marquee-behavior.spec.ts +0 -176
- package/src/features/validation/marker-navigator.spec.ts +0 -183
- package/src/utils/gmodel-util.spec.ts +0 -221
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2023-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 { ActionHandlerRegistry, Deferred, IActionHandler, RequestAction, ResponseAction, TYPES } from '@eclipse-glsp/sprotty';
|
|
17
|
-
import { expect } from 'chai';
|
|
18
|
-
import { Container } from 'inversify';
|
|
19
|
-
|
|
20
|
-
/** Yields to the event loop long enough for pending microtasks (and already-queued timers) to run. */
|
|
21
|
-
const flushMicrotasks = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 0));
|
|
22
|
-
|
|
23
|
-
import { GLSPActionDispatcher } from './action-dispatcher';
|
|
24
|
-
import { defaultModule } from './default.module';
|
|
25
|
-
import { IDiagramOptions } from './model/diagram-loader';
|
|
26
|
-
|
|
27
|
-
const container = new Container();
|
|
28
|
-
container.load(defaultModule);
|
|
29
|
-
container.bind(TYPES.IDiagramOptions).toConstantValue(<IDiagramOptions>(<unknown>{
|
|
30
|
-
clientId: 'client1',
|
|
31
|
-
diagramType: 'diagramType',
|
|
32
|
-
glspClientProvider: async () => ({}) as any
|
|
33
|
-
}));
|
|
34
|
-
const registry = container.get(ActionHandlerRegistry);
|
|
35
|
-
const actionDispatcher = container.get(GLSPActionDispatcher);
|
|
36
|
-
|
|
37
|
-
let testHandlerDelay = 0;
|
|
38
|
-
const testHandler: IActionHandler = {
|
|
39
|
-
handle: action => {
|
|
40
|
-
const request = action as RequestAction<ResponseAction>;
|
|
41
|
-
new Promise(resolve => setTimeout(resolve, testHandlerDelay)).then(() =>
|
|
42
|
-
actionDispatcher.dispatch({
|
|
43
|
-
kind: 'response',
|
|
44
|
-
responseId: request.requestId
|
|
45
|
-
} as ResponseAction)
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
registry.register('request', testHandler);
|
|
50
|
-
|
|
51
|
-
registry.register('response', { handle: () => {} });
|
|
52
|
-
actionDispatcher.initialize().then(() => {
|
|
53
|
-
actionDispatcher['blockUntil'] = undefined;
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('GLSPActionDispatcher', () => {
|
|
57
|
-
describe('requestUntil', () => {
|
|
58
|
-
it('should resolve successfully if response dispatched within timeout', async () => {
|
|
59
|
-
testHandlerDelay = 15;
|
|
60
|
-
const requestAction = { kind: 'request', requestId: '' };
|
|
61
|
-
const response = await actionDispatcher.requestUntil(requestAction, 150);
|
|
62
|
-
expect(response?.responseId).to.be.equal(requestAction.requestId);
|
|
63
|
-
});
|
|
64
|
-
it('should resolve to `undefined` if no response dispatched within timeout & `rejectOnTimeout` flag is false', async () => {
|
|
65
|
-
testHandlerDelay = 30;
|
|
66
|
-
const requestAction = { kind: 'request', requestId: '' };
|
|
67
|
-
const response = await actionDispatcher.requestUntil(requestAction, 5);
|
|
68
|
-
expect(response).to.be.undefined;
|
|
69
|
-
});
|
|
70
|
-
it('should be rejected if no response dispatched within timeout & `rejectOnTimeout` flag is true', async () => {
|
|
71
|
-
testHandlerDelay = 30;
|
|
72
|
-
const requestAction = { kind: 'request', requestId: '' };
|
|
73
|
-
const gotRejected = await actionDispatcher.requestUntil(requestAction, 5, true).then(
|
|
74
|
-
() => false,
|
|
75
|
-
() => true
|
|
76
|
-
);
|
|
77
|
-
expect(gotRejected, 'Response promise should be rejected').to.be.true;
|
|
78
|
-
});
|
|
79
|
-
it('should not leak timeout entries once the request settles', async () => {
|
|
80
|
-
const timeouts = actionDispatcher['timeouts'] as Map<string, unknown>;
|
|
81
|
-
|
|
82
|
-
// resolved-within-timeout path
|
|
83
|
-
testHandlerDelay = 5;
|
|
84
|
-
await actionDispatcher.requestUntil({ kind: 'request', requestId: '' }, 150);
|
|
85
|
-
// timed-out path
|
|
86
|
-
testHandlerDelay = 50;
|
|
87
|
-
await actionDispatcher.requestUntil({ kind: 'request', requestId: '' }, 5);
|
|
88
|
-
// missing-handler path: rejects the request, must still clear the timeout
|
|
89
|
-
await actionDispatcher.requestUntil({ kind: 'noHandlerRequest', requestId: '' }, 50).catch(() => undefined);
|
|
90
|
-
await flushMicrotasks();
|
|
91
|
-
|
|
92
|
-
expect(timeouts.size, 'all timeout entries should be cleared after the requests settle').to.equal(0);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
describe('request & re-dispatch', () => {
|
|
96
|
-
it('should be possible to re-dispatch the response of a `request` call', async () => {
|
|
97
|
-
const requestAction = { kind: 'request', requestId: '' };
|
|
98
|
-
const response = await actionDispatcher.request(requestAction);
|
|
99
|
-
const dispatchSuccessful = await actionDispatcher.dispatch(response).then(
|
|
100
|
-
() => true,
|
|
101
|
-
err => false
|
|
102
|
-
);
|
|
103
|
-
expect(dispatchSuccessful, 'Promise of re-dispatch should resolve successfully').to.be.true;
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
describe('async action handlers', () => {
|
|
107
|
-
it('should handle async action handlers correctly', async () => {
|
|
108
|
-
let handlerExecuted = false;
|
|
109
|
-
const asyncHandler: IActionHandler = {
|
|
110
|
-
handle: async () => {
|
|
111
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
112
|
-
handlerExecuted = true;
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
registry.register('asyncTest1', asyncHandler);
|
|
117
|
-
await actionDispatcher.dispatch({ kind: 'asyncTest1' });
|
|
118
|
-
|
|
119
|
-
expect(handlerExecuted).to.be.true;
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('should invoke all handlers in one synchronous burst (parallel-start), without serializing on async ones', async () => {
|
|
123
|
-
// asyncHandler1 (registered first) has the longer delay. Serial execution would yield [1, 2];
|
|
124
|
-
// parallel-start lets the shorter handler finish first, yielding [2, 1].
|
|
125
|
-
const executionOrder: number[] = [];
|
|
126
|
-
const asyncHandler1: IActionHandler = {
|
|
127
|
-
handle: async () => {
|
|
128
|
-
await new Promise(resolve => setTimeout(resolve, 20));
|
|
129
|
-
executionOrder.push(1);
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
const asyncHandler2: IActionHandler = {
|
|
133
|
-
handle: async () => {
|
|
134
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
135
|
-
executionOrder.push(2);
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
registry.register('multiAsyncTest', asyncHandler1);
|
|
140
|
-
registry.register('multiAsyncTest', asyncHandler2);
|
|
141
|
-
await actionDispatcher.dispatch({ kind: 'multiAsyncTest' });
|
|
142
|
-
|
|
143
|
-
expect(executionOrder).to.deep.equal([2, 1]);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should not let a slow async handler starve a synchronous sibling registered after it', async () => {
|
|
147
|
-
// Sync handler registered after the gated async one must run during the burst, before the
|
|
148
|
-
// async handler is released.
|
|
149
|
-
const executionOrder: number[] = [];
|
|
150
|
-
const gate = new Deferred<void>();
|
|
151
|
-
const slowAsyncHandler: IActionHandler = {
|
|
152
|
-
handle: async () => {
|
|
153
|
-
await gate.promise;
|
|
154
|
-
executionOrder.push(1);
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
const syncHandler: IActionHandler = {
|
|
158
|
-
handle: () => {
|
|
159
|
-
executionOrder.push(2);
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
registry.register('starveTest', slowAsyncHandler);
|
|
164
|
-
registry.register('starveTest', syncHandler);
|
|
165
|
-
const dispatched = actionDispatcher.dispatch({ kind: 'starveTest' });
|
|
166
|
-
|
|
167
|
-
// Let the invocation burst run; the async handler is still gated.
|
|
168
|
-
await flushMicrotasks();
|
|
169
|
-
expect(executionOrder, 'sync sibling must run before the gated async handler resolves').to.deep.equal([2]);
|
|
170
|
-
|
|
171
|
-
gate.resolve();
|
|
172
|
-
await dispatched;
|
|
173
|
-
expect(executionOrder).to.deep.equal([2, 1]);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('should not let a never-resolving async handler starve a synchronous sibling', async () => {
|
|
177
|
-
// A handler whose promise never resolves must not prevent other handlers from being invoked.
|
|
178
|
-
const executionOrder: number[] = [];
|
|
179
|
-
const stuckHandler: IActionHandler = {
|
|
180
|
-
handle: () => new Promise<void>(() => undefined) // never resolves
|
|
181
|
-
};
|
|
182
|
-
const syncHandler: IActionHandler = {
|
|
183
|
-
handle: () => {
|
|
184
|
-
executionOrder.push(1);
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
registry.register('stuckTest', stuckHandler);
|
|
189
|
-
registry.register('stuckTest', syncHandler);
|
|
190
|
-
// Intentionally not awaited: the dispatch promise never resolves because of the stuck handler.
|
|
191
|
-
actionDispatcher.dispatch({ kind: 'stuckTest' });
|
|
192
|
-
|
|
193
|
-
await flushMicrotasks();
|
|
194
|
-
expect(executionOrder).to.deep.equal([1]);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('should not deadlock when an async handler awaits a nested dispatch while a sibling is registered after it', async () => {
|
|
198
|
-
// A serial loop would block the sibling behind the async handler that awaits a nested dispatch,
|
|
199
|
-
// risking deadlock. Parallel-start invokes the sibling in the burst, so nothing waits its turn.
|
|
200
|
-
// Order: 'B' (burst) -> 'sub' (nested) -> 'A' (async tail).
|
|
201
|
-
const executionOrder: string[] = [];
|
|
202
|
-
registry.register('nestedSub', {
|
|
203
|
-
handle: () => {
|
|
204
|
-
executionOrder.push('sub');
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
const nestedDispatchHandler: IActionHandler = {
|
|
208
|
-
handle: async () => {
|
|
209
|
-
await actionDispatcher.dispatch({ kind: 'nestedSub' });
|
|
210
|
-
executionOrder.push('A');
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
const siblingHandler: IActionHandler = {
|
|
214
|
-
handle: () => {
|
|
215
|
-
executionOrder.push('B');
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
registry.register('nestedTest', nestedDispatchHandler);
|
|
220
|
-
registry.register('nestedTest', siblingHandler);
|
|
221
|
-
await actionDispatcher.dispatch({ kind: 'nestedTest' });
|
|
222
|
-
|
|
223
|
-
expect(executionOrder).to.deep.equal(['B', 'sub', 'A']);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it('should handle mixed sync and async handlers correctly', async () => {
|
|
227
|
-
const executionOrder: number[] = [];
|
|
228
|
-
const syncHandler: IActionHandler = {
|
|
229
|
-
handle: () => {
|
|
230
|
-
executionOrder.push(1);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
const asyncHandler: IActionHandler = {
|
|
234
|
-
handle: async () => {
|
|
235
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
236
|
-
executionOrder.push(2);
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
registry.register('mixedTest', syncHandler);
|
|
241
|
-
registry.register('mixedTest', asyncHandler);
|
|
242
|
-
await actionDispatcher.dispatch({ kind: 'mixedTest' });
|
|
243
|
-
|
|
244
|
-
expect(executionOrder).to.deep.equal([1, 2]);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('should propagate errors from async handlers', async () => {
|
|
248
|
-
const errorMessage = 'Async handler error';
|
|
249
|
-
const errorHandler: IActionHandler = {
|
|
250
|
-
handle: async () => {
|
|
251
|
-
await new Promise(resolve => setTimeout(resolve, 5));
|
|
252
|
-
throw new Error(errorMessage);
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
registry.register('errorTest1', errorHandler);
|
|
257
|
-
let caughtError: Error | undefined;
|
|
258
|
-
try {
|
|
259
|
-
await actionDispatcher.dispatch({ kind: 'errorTest1' });
|
|
260
|
-
} catch (error) {
|
|
261
|
-
caughtError = error as Error;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
expect(caughtError).to.not.be.undefined;
|
|
265
|
-
expect(caughtError?.message).to.equal(errorMessage);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('should handle errors in one handler without affecting others when multiple handlers are registered', async () => {
|
|
269
|
-
const executionOrder: number[] = [];
|
|
270
|
-
const successHandler: IActionHandler = {
|
|
271
|
-
handle: async () => {
|
|
272
|
-
await new Promise(resolve => setTimeout(resolve, 5));
|
|
273
|
-
executionOrder.push(1);
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
const errorHandler: IActionHandler = {
|
|
277
|
-
handle: async () => {
|
|
278
|
-
await new Promise(resolve => setTimeout(resolve, 5));
|
|
279
|
-
throw new Error('Handler 2 error');
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
registry.register('multiHandlerErrorTest', successHandler);
|
|
284
|
-
registry.register('multiHandlerErrorTest', errorHandler);
|
|
285
|
-
|
|
286
|
-
let caughtError: Error | undefined;
|
|
287
|
-
try {
|
|
288
|
-
await actionDispatcher.dispatch({ kind: 'multiHandlerErrorTest' });
|
|
289
|
-
} catch (error) {
|
|
290
|
-
caughtError = error as Error;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// First handler should have executed successfully
|
|
294
|
-
expect(executionOrder).to.deep.equal([1]);
|
|
295
|
-
// Error should have been thrown
|
|
296
|
-
expect(caughtError).to.not.be.undefined;
|
|
297
|
-
expect(caughtError?.message).to.equal('Handler 2 error');
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
it('should handle synchronous errors in handlers', async () => {
|
|
301
|
-
const errorMessage = 'Sync handler error';
|
|
302
|
-
const syncErrorHandler: IActionHandler = {
|
|
303
|
-
handle: () => {
|
|
304
|
-
throw new Error(errorMessage);
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
registry.register('syncErrorTest', syncErrorHandler);
|
|
309
|
-
let caughtError: Error | undefined;
|
|
310
|
-
try {
|
|
311
|
-
await actionDispatcher.dispatch({ kind: 'syncErrorTest' });
|
|
312
|
-
} catch (error) {
|
|
313
|
-
caughtError = error as Error;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
expect(caughtError).to.not.be.undefined;
|
|
317
|
-
expect(caughtError?.message).to.equal(errorMessage);
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it('should handle async handlers that return actions', async () => {
|
|
321
|
-
const dispatchedActions: string[] = [];
|
|
322
|
-
const returningHandler: IActionHandler = {
|
|
323
|
-
handle: async () => {
|
|
324
|
-
await new Promise(resolve => setTimeout(resolve, 5));
|
|
325
|
-
return { kind: 'returnedAction1' };
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
const receivingHandler: IActionHandler = {
|
|
329
|
-
handle: action => {
|
|
330
|
-
dispatchedActions.push(action.kind);
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
registry.register('asyncReturnTest', returningHandler);
|
|
335
|
-
registry.register('returnedAction1', receivingHandler);
|
|
336
|
-
await actionDispatcher.dispatch({ kind: 'asyncReturnTest' });
|
|
337
|
-
|
|
338
|
-
expect(dispatchedActions).to.include('returnedAction1');
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
it('should wait for all async handlers to complete before resolving dispatch promise', async () => {
|
|
342
|
-
let handler1Completed = false;
|
|
343
|
-
let handler2Completed = false;
|
|
344
|
-
const asyncHandler1: IActionHandler = {
|
|
345
|
-
handle: async () => {
|
|
346
|
-
await new Promise(resolve => setTimeout(resolve, 30));
|
|
347
|
-
handler1Completed = true;
|
|
348
|
-
}
|
|
349
|
-
};
|
|
350
|
-
const asyncHandler2: IActionHandler = {
|
|
351
|
-
handle: async () => {
|
|
352
|
-
await new Promise(resolve => setTimeout(resolve, 20));
|
|
353
|
-
handler2Completed = true;
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
registry.register('completionTest', asyncHandler1);
|
|
358
|
-
registry.register('completionTest', asyncHandler2);
|
|
359
|
-
await actionDispatcher.dispatch({ kind: 'completionTest' });
|
|
360
|
-
|
|
361
|
-
// Both handlers should be completed when dispatch resolves
|
|
362
|
-
expect(handler1Completed).to.be.true;
|
|
363
|
-
expect(handler2Completed).to.be.true;
|
|
364
|
-
});
|
|
365
|
-
});
|
|
366
|
-
});
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2024 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 { Action, Command, CommandExecutionContext, Disposable } from '@eclipse-glsp/sprotty';
|
|
17
|
-
import { expect } from 'chai';
|
|
18
|
-
import { IFeedbackActionDispatcher, IFeedbackEmitter } from './feedback-action-dispatcher';
|
|
19
|
-
import { FeedbackEmitter } from './feedback-emitter';
|
|
20
|
-
|
|
21
|
-
class MockFeedbackActionDispatcher implements IFeedbackActionDispatcher {
|
|
22
|
-
protected feedbackEmitters: Map<IFeedbackEmitter, Action[]> = new Map();
|
|
23
|
-
|
|
24
|
-
registerFeedback(feedbackEmitter: IFeedbackEmitter, actions: Action[]): Disposable {
|
|
25
|
-
this.feedbackEmitters.set(feedbackEmitter, actions);
|
|
26
|
-
return Disposable.create(() => this.deregisterFeedback(feedbackEmitter));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
deregisterFeedback(feedbackEmitter: IFeedbackEmitter, _actions?: Action[]): void {
|
|
30
|
-
this.feedbackEmitters.delete(feedbackEmitter);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getRegisteredFeedback(): Action[] {
|
|
34
|
-
const result: Action[] = [];
|
|
35
|
-
this.feedbackEmitters.forEach((value, key) => result.push(...value));
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
getFeedbackCommands(): Command[] {
|
|
40
|
-
return [];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
createEmitter(): FeedbackEmitter {
|
|
44
|
-
return new FeedbackEmitter(this);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async applyFeedbackCommands(context: CommandExecutionContext): Promise<void> {}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
describe('FeedbackEmitter', () => {
|
|
51
|
-
describe('Initial State', () => {
|
|
52
|
-
it('On creation nothing should be submitted.', () => {
|
|
53
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
54
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
55
|
-
feedback.submit();
|
|
56
|
-
expect(feedbackActionDispatcher['feedbackEmitters']).to.be.empty;
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe('Adding Feedback', () => {
|
|
61
|
-
it('Should add an action as part of the emitter feedback.', () => {
|
|
62
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
63
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
64
|
-
const action: Action = { kind: 'action' };
|
|
65
|
-
feedback.add(action);
|
|
66
|
-
expect(feedback['feedbackActions']).to.deep.equal([action]);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('Should add an action and cleanup action as part of the emitter feedback.', () => {
|
|
70
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
71
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
72
|
-
const action: Action = { kind: 'action' };
|
|
73
|
-
const cleanupAction: Action = { kind: 'cleanup' };
|
|
74
|
-
feedback.add(action, cleanupAction);
|
|
75
|
-
expect(feedback['feedbackActions']).to.deep.equal([action]);
|
|
76
|
-
expect(feedback['cleanupActions']).to.deep.equal([cleanupAction]);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe('Merging Feedback', () => {
|
|
81
|
-
it('Should merge the feedback of another emitter into this emitter.', () => {
|
|
82
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
83
|
-
const feedback1 = feedbackActionDispatcher.createEmitter();
|
|
84
|
-
const feedback2 = feedbackActionDispatcher.createEmitter();
|
|
85
|
-
const action1: Action = { kind: 'action1' };
|
|
86
|
-
const action2: Action = { kind: 'action2' };
|
|
87
|
-
feedback1.add(action1);
|
|
88
|
-
feedback2.add(action2);
|
|
89
|
-
feedback1.merge(feedback2);
|
|
90
|
-
expect(feedback1['feedbackActions']).to.deep.equal([action1, action2]);
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
describe('Removing Feedback', () => {
|
|
95
|
-
it('Should remove the action from the emitter feedback.', () => {
|
|
96
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
97
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
98
|
-
const action: Action = { kind: 'action' };
|
|
99
|
-
feedback.add(action);
|
|
100
|
-
feedback.remove(action);
|
|
101
|
-
expect(feedback['feedbackActions']).to.be.empty;
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('Should remove the action together with the cleanup action from the emitter feedback.', () => {
|
|
105
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
106
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
107
|
-
const action: Action = { kind: 'action' };
|
|
108
|
-
const cleanupAction: Action = { kind: 'cleanup' };
|
|
109
|
-
feedback.add(action, cleanupAction);
|
|
110
|
-
feedback.remove(action);
|
|
111
|
-
expect(feedback['feedbackActions']).to.be.empty;
|
|
112
|
-
expect(feedback['cleanupActions']).to.be.empty;
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe('Clearing Feedback', () => {
|
|
117
|
-
it('Should clear any pending feedback actions and cleanup actions.', () => {
|
|
118
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
119
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
120
|
-
const action: Action = { kind: 'action' };
|
|
121
|
-
const cleanupAction: Action = { kind: 'cleanup' };
|
|
122
|
-
feedback.add(action, cleanupAction);
|
|
123
|
-
feedback.clear();
|
|
124
|
-
expect(feedback['feedbackActions']).to.be.empty;
|
|
125
|
-
expect(feedback['cleanupActions']).to.be.empty;
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
describe('Submitting Feedback', () => {
|
|
130
|
-
it('Should register any pending actions as feedback.', () => {
|
|
131
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
132
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
133
|
-
const action: Action = { kind: 'action' };
|
|
134
|
-
feedback.add(action);
|
|
135
|
-
feedback.submit();
|
|
136
|
-
expect(feedbackActionDispatcher['feedbackEmitters'].size).to.equal(1);
|
|
137
|
-
expect(feedbackActionDispatcher['feedbackEmitters'].get(feedback)).to.deep.equal([action]);
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
describe('Discarding Feedback', () => {
|
|
142
|
-
it('Should remove the registered feedback without calling any cleanup actions.', () => {
|
|
143
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
144
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
145
|
-
const action: Action = { kind: 'action' };
|
|
146
|
-
feedback.add(action);
|
|
147
|
-
feedback.submit();
|
|
148
|
-
feedback.discard();
|
|
149
|
-
expect(feedbackActionDispatcher['feedbackEmitters']).to.be.empty;
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
describe('Reverting Feedback', () => {
|
|
154
|
-
it('Should remove the registered feedback and call the registered cleanup actions.', () => {
|
|
155
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
156
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
157
|
-
const action: Action = { kind: 'action' };
|
|
158
|
-
const cleanupAction: Action = { kind: 'cleanup' };
|
|
159
|
-
feedback.add(action, cleanupAction);
|
|
160
|
-
feedback.submit();
|
|
161
|
-
feedback.revert();
|
|
162
|
-
expect(feedbackActionDispatcher['feedbackEmitters']).to.be.empty;
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
describe('Disposing Feedback', () => {
|
|
167
|
-
it('Should dispose the registered feedback and any pending feedback actions.', () => {
|
|
168
|
-
const feedbackActionDispatcher = new MockFeedbackActionDispatcher();
|
|
169
|
-
const feedback = feedbackActionDispatcher.createEmitter();
|
|
170
|
-
const action: Action = { kind: 'action' };
|
|
171
|
-
feedback.add(action);
|
|
172
|
-
feedback.dispose();
|
|
173
|
-
expect(feedbackActionDispatcher['feedbackEmitters']).to.be.empty;
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
});
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2023-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 { expect } from 'chai';
|
|
17
|
-
import { Container } from 'inversify';
|
|
18
|
-
import 'reflect-metadata';
|
|
19
|
-
import * as sinon from 'sinon';
|
|
20
|
-
import { Deferred, EMPTY_ROOT, InitializeCanvasBoundsAction, SetModelAction, UpdateModelAction } from '@eclipse-glsp/sprotty';
|
|
21
|
-
import { DefaultModelInitializationConstraint, ModelInitializationConstraint } from './model-initialization-constraint';
|
|
22
|
-
const sandbox = sinon.createSandbox();
|
|
23
|
-
const container = new Container();
|
|
24
|
-
let constraint: ModelInitializationConstraint;
|
|
25
|
-
|
|
26
|
-
const listener = sandbox.spy((): void => {});
|
|
27
|
-
|
|
28
|
-
describe('DefaultModelInitializationConstraint', () => {
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
constraint = container.resolve(DefaultModelInitializationConstraint);
|
|
31
|
-
sandbox.reset();
|
|
32
|
-
});
|
|
33
|
-
it('should complete after dispatching non empty SetModelAction and `InitializeCanvasBoundsAction`', () => {
|
|
34
|
-
expect(constraint.isCompleted).to.be.false;
|
|
35
|
-
constraint.notifyDispatched(SetModelAction.create({ id: 'model', type: 'graph' }));
|
|
36
|
-
expect(constraint.isCompleted).to.be.false;
|
|
37
|
-
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND });
|
|
38
|
-
expect(constraint.isCompleted).to.be.true;
|
|
39
|
-
});
|
|
40
|
-
it('should complete after dispatching non empty UpdateModelAction and `InitializeCanvasBoundsAction`', () => {
|
|
41
|
-
expect(constraint.isCompleted).to.be.false;
|
|
42
|
-
constraint.notifyDispatched(UpdateModelAction.create({ id: 'model', type: 'graph' }));
|
|
43
|
-
expect(constraint.isCompleted).to.be.false;
|
|
44
|
-
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND });
|
|
45
|
-
expect(constraint.isCompleted).to.be.true;
|
|
46
|
-
});
|
|
47
|
-
it('should note complete after dispatching empty SetModelAction and `InitializeCanvasBoundsAction` ', () => {
|
|
48
|
-
expect(constraint.isCompleted).to.be.false;
|
|
49
|
-
constraint.notifyDispatched(SetModelAction.create(EMPTY_ROOT));
|
|
50
|
-
expect(constraint.isCompleted).to.be.false;
|
|
51
|
-
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND });
|
|
52
|
-
expect(constraint.isCompleted).to.be.false;
|
|
53
|
-
});
|
|
54
|
-
it('should note complete after dispatching empty UpdateModelAction and `InitializeCanvasBoundsAction ', () => {
|
|
55
|
-
expect(constraint.isCompleted).to.be.false;
|
|
56
|
-
constraint.notifyDispatched(UpdateModelAction.create(EMPTY_ROOT));
|
|
57
|
-
expect(constraint.isCompleted).to.be.false;
|
|
58
|
-
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND });
|
|
59
|
-
expect(constraint.isCompleted).to.be.false;
|
|
60
|
-
});
|
|
61
|
-
describe('onInitialized', () => {
|
|
62
|
-
it('returned promise should resolve once the constraint is initialized', async () => {
|
|
63
|
-
const initializeDeferred = new Deferred<void>();
|
|
64
|
-
const initializePromise = constraint.onInitialized();
|
|
65
|
-
initializePromise.then(() => initializeDeferred.resolve());
|
|
66
|
-
expect(initializeDeferred.state).to.be.equal('unresolved');
|
|
67
|
-
// Directly trigger the completion method simplify test logic
|
|
68
|
-
constraint['setCompleted']();
|
|
69
|
-
// Short delay of test execution to ensure that the deferred state is updated.
|
|
70
|
-
await new Promise(resolve => setTimeout(resolve, 5));
|
|
71
|
-
expect(initializeDeferred.state).to.be.equal('resolved');
|
|
72
|
-
});
|
|
73
|
-
it('registered listener should be invoked once the constraint is initialized', () => {
|
|
74
|
-
constraint.onInitialized(listener);
|
|
75
|
-
expect(listener.called).to.be.false;
|
|
76
|
-
// Directly trigger the completion method simplify test logic
|
|
77
|
-
constraint['setCompleted']();
|
|
78
|
-
expect(listener.called).to.be.true;
|
|
79
|
-
});
|
|
80
|
-
it('registered listener should be invoked directly on registration if the constraint is already initialized', () => {
|
|
81
|
-
// Directly trigger the completion method simplify test logic
|
|
82
|
-
constraint['setCompleted']();
|
|
83
|
-
constraint.onInitialized(listener);
|
|
84
|
-
expect(listener.called).to.be.true;
|
|
85
|
-
});
|
|
86
|
-
it('Disposed listener should not be invoked once the constraint is initialized', () => {
|
|
87
|
-
const toDispose = constraint.onInitialized(listener);
|
|
88
|
-
expect(listener.called).to.be.false;
|
|
89
|
-
toDispose.dispose();
|
|
90
|
-
// Directly trigger the completion method simplify test logic
|
|
91
|
-
constraint['setCompleted']();
|
|
92
|
-
expect(listener.called).to.be.false;
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
});
|