@eclipse-glsp/server 2.8.0-next.1 → 2.8.0-next.10
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/lib/browser/launch/worker-server-launcher.js +3 -5
- package/lib/browser/launch/worker-server-launcher.js.map +1 -1
- package/lib/common/actions/action-dispatcher.js +5 -8
- package/lib/common/actions/action-dispatcher.js.map +1 -1
- package/lib/common/actions/action-handler-registry.js +1 -1
- package/lib/common/actions/action-handler-registry.js.map +1 -1
- package/lib/common/actions/global-action-provider.js +1 -2
- package/lib/common/actions/global-action-provider.js.map +1 -1
- package/lib/common/command/command.js +1 -2
- package/lib/common/command/command.js.map +1 -1
- package/lib/common/command/recording-command.js +3 -6
- package/lib/common/command/recording-command.js.map +1 -1
- package/lib/common/di/diagram-module.js +5 -6
- package/lib/common/di/diagram-module.js.map +1 -1
- package/lib/common/di/glsp-module.js +1 -1
- package/lib/common/di/glsp-module.js.map +1 -1
- package/lib/common/di/server-module.js +1 -1
- package/lib/common/di/server-module.js.map +1 -1
- package/lib/common/features/directediting/context-edit-validator.js +3 -3
- package/lib/common/features/directediting/context-edit-validator.js.map +1 -1
- package/lib/common/features/directediting/label-edit-validator.js +1 -1
- package/lib/common/features/directediting/label-edit-validator.js.map +1 -1
- package/lib/common/features/layout/computed-bounds-action-handler.d.ts +16 -1
- package/lib/common/features/layout/computed-bounds-action-handler.d.ts.map +1 -1
- package/lib/common/features/layout/computed-bounds-action-handler.js +41 -4
- package/lib/common/features/layout/computed-bounds-action-handler.js.map +1 -1
- package/lib/common/features/layout/layout-operation-handler.js +1 -2
- package/lib/common/features/layout/layout-operation-handler.js.map +1 -1
- package/lib/common/features/model/gmodel-index.js +3 -5
- package/lib/common/features/model/gmodel-index.js.map +1 -1
- package/lib/common/features/model/gmodel-serializer.js +1 -2
- package/lib/common/features/model/gmodel-serializer.js.map +1 -1
- package/lib/common/features/model/model-submission-handler.d.ts +1 -2
- package/lib/common/features/model/model-submission-handler.d.ts.map +1 -1
- package/lib/common/features/model/model-submission-handler.js +3 -6
- package/lib/common/features/model/model-submission-handler.js.map +1 -1
- package/lib/common/features/model/request-model-action-handler.js +4 -6
- package/lib/common/features/model/request-model-action-handler.js.map +1 -1
- package/lib/common/features/navigation/navigation-target-resolution.js +1 -1
- package/lib/common/features/navigation/navigation-target-resolution.js.map +1 -1
- package/lib/common/features/progress/progress-service.d.ts.map +1 -1
- package/lib/common/features/progress/progress-service.js +1 -2
- package/lib/common/features/progress/progress-service.js.map +1 -1
- package/lib/common/features/validation/request-markers-handler.js +1 -2
- package/lib/common/features/validation/request-markers-handler.js.map +1 -1
- package/lib/common/gmodel/change-routing-points-operation-handler.js +1 -2
- package/lib/common/gmodel/change-routing-points-operation-handler.js.map +1 -1
- package/lib/common/gmodel/gmodel-create-node-operation-handler.js +3 -5
- package/lib/common/gmodel/gmodel-create-node-operation-handler.js.map +1 -1
- package/lib/common/gmodel/paste-operation-handler.d.ts +1 -1
- package/lib/common/gmodel/paste-operation-handler.d.ts.map +1 -1
- package/lib/common/gmodel/paste-operation-handler.js +8 -11
- package/lib/common/gmodel/paste-operation-handler.js.map +1 -1
- package/lib/common/launch/glsp-server-launcher.d.ts +8 -1
- package/lib/common/launch/glsp-server-launcher.d.ts.map +1 -1
- package/lib/common/launch/glsp-server-launcher.js +11 -1
- package/lib/common/launch/glsp-server-launcher.js.map +1 -1
- package/lib/common/launch/jsonrpc-server-launcher.d.ts +51 -2
- package/lib/common/launch/jsonrpc-server-launcher.d.ts.map +1 -1
- package/lib/common/launch/jsonrpc-server-launcher.js +82 -3
- package/lib/common/launch/jsonrpc-server-launcher.js.map +1 -1
- package/lib/common/operations/compound-operation-handler.js +1 -1
- package/lib/common/operations/compound-operation-handler.js.map +1 -1
- package/lib/common/operations/json-operation-handler.js +2 -3
- package/lib/common/operations/json-operation-handler.js.map +1 -1
- package/lib/common/protocol/glsp-server.js +6 -7
- package/lib/common/protocol/glsp-server.js.map +1 -1
- package/lib/common/session/client-session-manager.js +3 -5
- package/lib/common/session/client-session-manager.js.map +1 -1
- package/lib/common/utils/action-queue.js +2 -4
- package/lib/common/utils/action-queue.js.map +1 -1
- package/lib/common/utils/client-options-util.js +2 -2
- package/lib/common/utils/client-options-util.js.map +1 -1
- package/lib/common/utils/glsp-server-error.d.ts +2 -3
- package/lib/common/utils/glsp-server-error.d.ts.map +1 -1
- package/lib/common/utils/glsp-server-error.js +1 -1
- package/lib/common/utils/glsp-server-error.js.map +1 -1
- package/lib/common/utils/layout-util.d.ts +5 -5
- package/lib/common/utils/layout-util.d.ts.map +1 -1
- package/lib/common/utils/layout-util.js +17 -19
- package/lib/common/utils/layout-util.js.map +1 -1
- package/lib/common/utils/logger.js +1 -2
- package/lib/common/utils/logger.js.map +1 -1
- package/lib/node/abstract-json-model-storage.js +2 -4
- package/lib/node/abstract-json-model-storage.js.map +1 -1
- package/lib/node/launch/socket-server-launcher.d.ts +39 -2
- package/lib/node/launch/socket-server-launcher.d.ts.map +1 -1
- package/lib/node/launch/socket-server-launcher.js +50 -31
- package/lib/node/launch/socket-server-launcher.js.map +1 -1
- package/lib/node/launch/websocket-server-launcher.d.ts +36 -5
- package/lib/node/launch/websocket-server-launcher.d.ts.map +1 -1
- package/lib/node/launch/websocket-server-launcher.js +54 -13
- package/lib/node/launch/websocket-server-launcher.js.map +1 -1
- package/package.json +17 -21
- package/src/common/features/directediting/context-edit-validator.ts +2 -2
- package/src/common/features/layout/computed-bounds-action-handler.ts +52 -4
- package/src/common/features/model/model-submission-handler.ts +3 -2
- package/src/common/features/progress/progress-service.ts +2 -3
- package/src/common/gmodel/paste-operation-handler.ts +6 -6
- package/src/common/launch/glsp-server-launcher.ts +12 -1
- package/src/common/launch/jsonrpc-server-launcher.ts +89 -2
- package/src/common/utils/glsp-server-error.ts +3 -5
- package/src/common/utils/layout-util.ts +13 -12
- package/src/node/launch/socket-server-launcher.ts +54 -31
- package/src/node/launch/websocket-server-launcher.ts +72 -14
- package/src/browser/di/browser-action-dispatch-scope.spec.ts +0 -75
- package/src/common/actions/action-handler-registry.spec.ts +0 -52
- package/src/common/actions/global-action-provider.spec.ts +0 -68
- package/src/common/command/command-stack.spec.ts +0 -239
- package/src/common/command/command.spec.ts +0 -92
- package/src/common/command/recording-command.spec.ts +0 -86
- package/src/common/di/binding-target.spec.ts +0 -147
- package/src/common/di/multi-bindings.spec.ts +0 -133
- package/src/common/features/contextactions/context-actions-provider-registry.spec.ts +0 -69
- package/src/common/features/contextactions/request-context-actions-handler.spec.ts +0 -75
- package/src/common/features/contextactions/tool-palette-item-provider.spec.ts +0 -46
- package/src/common/features/directediting/context-edit-validator-registry.spec.ts +0 -54
- package/src/common/features/directediting/request-edit-validation-handler.spec.ts +0 -131
- package/src/common/features/model/gmodel-serializer.spec.ts +0 -141
- package/src/common/features/type-hints/request-type-hints-action-handler.spec.ts +0 -59
- package/src/common/operations/operation-handler-registry.spec.ts +0 -50
- package/src/common/protocol/glsp-server.spec.ts +0 -154
- package/src/common/session/client-session-factory.spec.ts +0 -60
- package/src/common/session/client-session-manager.spec.ts +0 -83
- package/src/common/test/mock-util.ts +0 -281
- package/src/common/utils/action-queue.spec.ts +0 -133
- package/src/common/utils/promise-queue.spec.ts +0 -142
- package/src/common/utils/registry.spec.ts +0 -225
- package/src/node/actions/action-dispatcher.spec.ts +0 -678
- package/src/node/launch/cli-parser.spec.ts +0 -61
- package/src/node/launch/socket-cli-parser.spec.ts +0 -73
- package/src/node/launch/socket-server-launcher.spec.ts +0 -74
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 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 { Container, ContainerModule } from 'inversify';
|
|
18
|
-
import * as sinon from 'sinon';
|
|
19
|
-
import { expectToThrowAsync, StubCommand, StubLogger } from '../test/mock-util';
|
|
20
|
-
import { Logger } from '../utils/logger';
|
|
21
|
-
import { DefaultCommandStack } from './command-stack';
|
|
22
|
-
|
|
23
|
-
describe('test DefaultCommandStack', () => {
|
|
24
|
-
const sandbox = sinon.createSandbox();
|
|
25
|
-
const container = new Container();
|
|
26
|
-
|
|
27
|
-
const command1 = sandbox.stub(new StubCommand());
|
|
28
|
-
const command2 = sandbox.stub(new StubCommand());
|
|
29
|
-
let commandStack: DefaultCommandStack;
|
|
30
|
-
|
|
31
|
-
container.load(
|
|
32
|
-
new ContainerModule(bind => {
|
|
33
|
-
bind(Logger).toConstantValue(new StubLogger());
|
|
34
|
-
})
|
|
35
|
-
);
|
|
36
|
-
commandStack = container.resolve(DefaultCommandStack);
|
|
37
|
-
|
|
38
|
-
afterEach(() => {
|
|
39
|
-
sandbox.reset();
|
|
40
|
-
commandStack = container.resolve(DefaultCommandStack);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe('execute', () => {
|
|
44
|
-
it('should execute the given command and become dirty', async () => {
|
|
45
|
-
expect(commandStack.isDirty).to.be.false;
|
|
46
|
-
await commandStack.execute(command1);
|
|
47
|
-
expect(command1.execute.calledOnce).to.be.true;
|
|
48
|
-
expect(commandStack.isDirty).to.be.true;
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should execute the given commands in order and become dirty', async () => {
|
|
52
|
-
expect(commandStack.isDirty).to.be.false;
|
|
53
|
-
await commandStack.execute(command1);
|
|
54
|
-
await commandStack.execute(command2);
|
|
55
|
-
|
|
56
|
-
expect(command1.execute.calledOnce).to.be.true;
|
|
57
|
-
expect(command2.execute.calledOnce).to.be.true;
|
|
58
|
-
expect(command2.execute.calledAfter(command1.execute)).to.be.true;
|
|
59
|
-
expect(commandStack.isDirty).to.be.true;
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should be able to undo after execute', async () => {
|
|
63
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
64
|
-
await commandStack.execute(command1);
|
|
65
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should clear the redo stack after execution', async () => {
|
|
69
|
-
commandStack['commands'].push(command2);
|
|
70
|
-
commandStack['top'] = -1;
|
|
71
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
72
|
-
|
|
73
|
-
await commandStack.execute(command1);
|
|
74
|
-
expect(commandStack.canRedo()).to.be.false;
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should flush the stack in case of an execution error', async () => {
|
|
78
|
-
command2.execute.throwsException();
|
|
79
|
-
const flushSpy = sandbox.spy(commandStack, 'flush');
|
|
80
|
-
|
|
81
|
-
await expectToThrowAsync(() => commandStack.execute(command2));
|
|
82
|
-
expect(command2.execute.calledOnce).to.be.true;
|
|
83
|
-
expect(flushSpy.calledOnce).to.be.true;
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('undo', () => {
|
|
88
|
-
it('should do nothing if the command stack is empty', async () => {
|
|
89
|
-
expect(commandStack.isDirty).to.be.false;
|
|
90
|
-
|
|
91
|
-
await commandStack.undo();
|
|
92
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
93
|
-
expect(commandStack.canRedo()).to.be.false;
|
|
94
|
-
expect(commandStack.isDirty).to.be.false;
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('should undo the command and become non-dirty again', async () => {
|
|
98
|
-
commandStack['commands'].push(command1);
|
|
99
|
-
commandStack['top'] = 0;
|
|
100
|
-
expect(commandStack.isDirty).to.be.true;
|
|
101
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
102
|
-
expect(commandStack.canRedo()).to.be.false;
|
|
103
|
-
|
|
104
|
-
await commandStack.undo();
|
|
105
|
-
expect(command1.undo.calledOnce).to.be.true;
|
|
106
|
-
expect(commandStack.isDirty).to.be.false;
|
|
107
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
108
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should undo multiple command and become non-dirty again', async () => {
|
|
112
|
-
commandStack['commands'].push(command1, command2);
|
|
113
|
-
commandStack['top'] = 1;
|
|
114
|
-
expect(commandStack.isDirty).to.be.true;
|
|
115
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
116
|
-
expect(commandStack.canRedo()).to.be.false;
|
|
117
|
-
|
|
118
|
-
await commandStack.undo();
|
|
119
|
-
expect(command2.undo.calledOnce).to.be.true;
|
|
120
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
121
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
122
|
-
expect(commandStack.isDirty).to.be.true;
|
|
123
|
-
|
|
124
|
-
await commandStack.undo();
|
|
125
|
-
expect(command1.undo.calledOnce).to.be.true;
|
|
126
|
-
expect(command1.undo.calledAfter(command2.undo)).to.be.true;
|
|
127
|
-
expect(commandStack.isDirty).to.be.false;
|
|
128
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
129
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
130
|
-
});
|
|
131
|
-
it('should flush the stack in case of an execution error', async () => {
|
|
132
|
-
command2.undo.throwsException();
|
|
133
|
-
const flushSpy = sandbox.spy(commandStack, 'flush');
|
|
134
|
-
commandStack['commands'].push(command2);
|
|
135
|
-
commandStack['top'] = 0;
|
|
136
|
-
|
|
137
|
-
await expectToThrowAsync(() => commandStack.undo());
|
|
138
|
-
expect(command2.undo.calledOnce).to.be.true;
|
|
139
|
-
expect(flushSpy.calledOnce).to.be.true;
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
describe('redo', () => {
|
|
144
|
-
it('should do nothing if the command stack is empty', async () => {
|
|
145
|
-
expect(commandStack.isDirty).to.be.false;
|
|
146
|
-
|
|
147
|
-
await commandStack.redo();
|
|
148
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
149
|
-
expect(commandStack.canRedo()).to.be.false;
|
|
150
|
-
expect(commandStack.isDirty).to.be.false;
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should redo the command and become dirty again', async () => {
|
|
154
|
-
commandStack['commands'].push(command1);
|
|
155
|
-
commandStack['top'] = -1;
|
|
156
|
-
expect(commandStack.isDirty).to.be.false;
|
|
157
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
158
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
159
|
-
|
|
160
|
-
await commandStack.redo();
|
|
161
|
-
expect(command1.redo.calledOnce).to.be.true;
|
|
162
|
-
expect(commandStack.isDirty).to.be.true;
|
|
163
|
-
expect(commandStack.canRedo()).to.be.false;
|
|
164
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('should undo multiple command and become non-dirty again', async () => {
|
|
168
|
-
commandStack['commands'].push(command2, command1);
|
|
169
|
-
commandStack['top'] = -1;
|
|
170
|
-
commandStack['saveIndex'] = -1;
|
|
171
|
-
expect(commandStack.isDirty).to.be.false;
|
|
172
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
173
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
174
|
-
|
|
175
|
-
await commandStack.redo();
|
|
176
|
-
expect(command2.redo.calledOnce).to.be.true;
|
|
177
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
178
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
179
|
-
expect(commandStack.isDirty).to.be.true;
|
|
180
|
-
|
|
181
|
-
await commandStack.redo();
|
|
182
|
-
expect(command1.redo.calledOnce).to.be.true;
|
|
183
|
-
expect(command1.redo.calledAfter(command2.redo)).to.be.true;
|
|
184
|
-
expect(commandStack.isDirty).to.be.true;
|
|
185
|
-
expect(commandStack.canRedo()).to.be.false;
|
|
186
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
187
|
-
});
|
|
188
|
-
it('should flush the stack in case of an execution error', async () => {
|
|
189
|
-
command2.redo.throwsException();
|
|
190
|
-
const flushSpy = sandbox.spy(commandStack, 'flush');
|
|
191
|
-
commandStack['commands'].push(command2);
|
|
192
|
-
commandStack['top'] = -1;
|
|
193
|
-
|
|
194
|
-
await expectToThrowAsync(() => commandStack.redo());
|
|
195
|
-
expect(command2.redo.calledOnce).to.be.true;
|
|
196
|
-
expect(flushSpy.calledOnce).to.be.true;
|
|
197
|
-
});
|
|
198
|
-
it('should be able to undo after redo', async () => {
|
|
199
|
-
commandStack['commands'].push(command1);
|
|
200
|
-
commandStack['top'] = -1;
|
|
201
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
202
|
-
await commandStack.redo();
|
|
203
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
describe('flush', () => {
|
|
208
|
-
it('should reset the internal state of the command stack', () => {
|
|
209
|
-
commandStack['commands'].push(command1, command1);
|
|
210
|
-
commandStack['top'] = 0;
|
|
211
|
-
|
|
212
|
-
commandStack.flush();
|
|
213
|
-
expect(commandStack.isDirty).to.be.false;
|
|
214
|
-
expect(commandStack.canUndo()).to.be.false;
|
|
215
|
-
expect(commandStack.canRedo()).to.be.false;
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
describe('isSaveDone', () => {
|
|
220
|
-
it('should become non-dirty after execution', () => {
|
|
221
|
-
commandStack['commands'].push(command1);
|
|
222
|
-
commandStack['top'] = 0;
|
|
223
|
-
expect(commandStack.isDirty).to.be.true;
|
|
224
|
-
|
|
225
|
-
commandStack.saveIsDone();
|
|
226
|
-
expect(commandStack.isDirty).to.be.false;
|
|
227
|
-
});
|
|
228
|
-
it('should maintain undo/redo history after execution', () => {
|
|
229
|
-
commandStack['commands'].push(command1, command2);
|
|
230
|
-
commandStack['top'] = 0;
|
|
231
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
232
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
233
|
-
|
|
234
|
-
commandStack.saveIsDone();
|
|
235
|
-
expect(commandStack.canUndo()).to.be.true;
|
|
236
|
-
expect(commandStack.canRedo()).to.be.true;
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 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 * as sinon from 'sinon';
|
|
18
|
-
import { expectToThrowAsync, StubCommand } from '../test/mock-util';
|
|
19
|
-
import { CompoundCommand } from './command';
|
|
20
|
-
|
|
21
|
-
describe('CompoundCommand', () => {
|
|
22
|
-
const sandbox = sinon.createSandbox();
|
|
23
|
-
|
|
24
|
-
const command1 = sandbox.stub(new StubCommand());
|
|
25
|
-
const command2 = sandbox.stub(new StubCommand());
|
|
26
|
-
const command3 = sandbox.stub(new StubCommand());
|
|
27
|
-
|
|
28
|
-
const compoundCommand = new CompoundCommand(command1, command2, command3);
|
|
29
|
-
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
sandbox.reset();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe('execute', () => {
|
|
35
|
-
it('Should execute the subcommands in order', async () => {
|
|
36
|
-
await compoundCommand.execute();
|
|
37
|
-
expect(command1.execute.calledOnce).to.be.true;
|
|
38
|
-
expect(command2.execute.calledOnce).to.be.true;
|
|
39
|
-
expect(command3.execute.calledOnce).to.be.true;
|
|
40
|
-
expect(command1.execute.calledBefore(command2.execute)).to.be.true;
|
|
41
|
-
expect(command2.execute.calledBefore(command3.execute)).to.be.true;
|
|
42
|
-
});
|
|
43
|
-
it('Should undo partially executed subcommands in case of an error', async () => {
|
|
44
|
-
command3.execute.throwsException();
|
|
45
|
-
|
|
46
|
-
await expectToThrowAsync(() => compoundCommand.execute());
|
|
47
|
-
|
|
48
|
-
expect(command1.execute.calledOnce).to.be.true;
|
|
49
|
-
expect(command2.execute.calledOnce).to.be.true;
|
|
50
|
-
expect(command3.execute.calledOnce).to.be.true;
|
|
51
|
-
expect(command1.undo.calledOnce).to.be.true;
|
|
52
|
-
expect(command2.undo.calledOnce).to.be.true;
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('undo', () => {
|
|
57
|
-
it('Should undo the subcommands in reverse order', async () => {
|
|
58
|
-
await compoundCommand.undo();
|
|
59
|
-
expect(command1.undo.calledOnce).to.be.true;
|
|
60
|
-
expect(command2.undo.calledOnce).to.be.true;
|
|
61
|
-
expect(command3.undo.calledOnce).to.be.true;
|
|
62
|
-
expect(command1.undo.calledAfter(command2.undo)).to.be.true;
|
|
63
|
-
expect(command2.undo.calledAfter(command3.undo)).to.be.true;
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('Should redo partially undone subcommands in case of an error', async () => {
|
|
67
|
-
command1.undo.throwsException();
|
|
68
|
-
await expectToThrowAsync(() => compoundCommand.undo());
|
|
69
|
-
|
|
70
|
-
expect(command1.undo.calledOnce).to.be.true;
|
|
71
|
-
expect(command2.undo.calledOnce).to.be.true;
|
|
72
|
-
expect(command3.undo.calledOnce).to.be.true;
|
|
73
|
-
expect(command3.redo.calledOnce).to.be.true;
|
|
74
|
-
expect(command2.redo.calledOnce).to.be.true;
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('canUndo', () => {
|
|
79
|
-
it('should return true if all subcommands can be undone', () => {
|
|
80
|
-
command1.canUndo?.returns(true);
|
|
81
|
-
command2.canUndo?.returns(true);
|
|
82
|
-
command3.canUndo?.returns(true);
|
|
83
|
-
expect(compoundCommand.canUndo()).to.be.true;
|
|
84
|
-
});
|
|
85
|
-
it('should return true if anyof the subcommands cannot be undone', () => {
|
|
86
|
-
command1.canUndo?.returns(true);
|
|
87
|
-
command2.canUndo?.returns(false);
|
|
88
|
-
command3.canUndo?.returns(true);
|
|
89
|
-
expect(compoundCommand.canUndo()).to.be.true;
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
});
|
|
@@ -1,86 +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
|
-
|
|
17
|
-
import { AnyObject, MaybePromise } from '@eclipse-glsp/protocol';
|
|
18
|
-
import { expect } from 'chai';
|
|
19
|
-
import { AbstractRecordingCommand } from './recording-command';
|
|
20
|
-
|
|
21
|
-
interface TestModel {
|
|
22
|
-
string: string;
|
|
23
|
-
number: number;
|
|
24
|
-
flag: boolean;
|
|
25
|
-
maybe?: AnyObject;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let jsonObject: TestModel;
|
|
29
|
-
|
|
30
|
-
class TestRecordingCommand<JsonObject extends AnyObject = AnyObject> extends AbstractRecordingCommand<JsonObject> {
|
|
31
|
-
constructor(
|
|
32
|
-
protected jsonObject: JsonObject,
|
|
33
|
-
protected doExecute: () => MaybePromise<void>
|
|
34
|
-
) {
|
|
35
|
-
super();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
protected getJsonObject(): MaybePromise<JsonObject> {
|
|
39
|
-
return this.jsonObject;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
describe('RecordingCommand', () => {
|
|
44
|
-
let beforeState: TestModel;
|
|
45
|
-
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
jsonObject = {
|
|
48
|
-
string: 'foo',
|
|
49
|
-
number: 0,
|
|
50
|
-
flag: true
|
|
51
|
-
};
|
|
52
|
-
beforeState = JSON.parse(JSON.stringify(jsonObject));
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should be undoable after execution', async () => {
|
|
56
|
-
const command = new TestRecordingCommand(jsonObject, () => {});
|
|
57
|
-
expect(command.canUndo()).to.be.false;
|
|
58
|
-
await command.execute();
|
|
59
|
-
expect(command.canUndo()).to.be.true;
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should restore the pre execution state when undo is called', async () => {
|
|
63
|
-
const command = new TestRecordingCommand(jsonObject, () => {
|
|
64
|
-
jsonObject.string = 'bar';
|
|
65
|
-
jsonObject.flag = false;
|
|
66
|
-
jsonObject.maybe = { hello: 'world' };
|
|
67
|
-
});
|
|
68
|
-
await command.execute();
|
|
69
|
-
expect(jsonObject).to.not.be.deep.equals(beforeState);
|
|
70
|
-
await command.undo();
|
|
71
|
-
expect(jsonObject).to.be.deep.equals(beforeState);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('should restore the post execution state when redo is called', async () => {
|
|
75
|
-
const command = new TestRecordingCommand(jsonObject, () => {
|
|
76
|
-
jsonObject.string = 'bar';
|
|
77
|
-
jsonObject.flag = false;
|
|
78
|
-
jsonObject.maybe = { hello: 'world' };
|
|
79
|
-
});
|
|
80
|
-
await command.execute();
|
|
81
|
-
const afterState = JSON.parse(JSON.stringify(jsonObject));
|
|
82
|
-
jsonObject = JSON.parse(JSON.stringify(afterState));
|
|
83
|
-
await command.redo();
|
|
84
|
-
expect(jsonObject).to.be.deep.equals(afterState);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2022-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 { Container, ContainerModule, interfaces } from 'inversify';
|
|
18
|
-
import * as sinon from 'sinon';
|
|
19
|
-
import { applyBindingTarget } from './binding-target';
|
|
20
|
-
// Simple no op classes to construct inversify binding syntaxes.
|
|
21
|
-
class Target {}
|
|
22
|
-
|
|
23
|
-
class SubTarget extends Target {}
|
|
24
|
-
|
|
25
|
-
describe('BindingTarget', () => {
|
|
26
|
-
describe('bindTarget()', () => {
|
|
27
|
-
// Setup nested spies for the fluent inversify binding API
|
|
28
|
-
let context: {
|
|
29
|
-
bind: sinon.SinonStub<[serviceIdentifier: interfaces.ServiceIdentifier<any>], interfaces.BindingToSyntax<any>>;
|
|
30
|
-
isBound: sinon.SinonStub<[serviceIdentifier: interfaces.ServiceIdentifier<any>], boolean>;
|
|
31
|
-
};
|
|
32
|
-
let toSyntax: sinon.SinonStubbedInstance<interfaces.BindingToSyntax<any>>;
|
|
33
|
-
let whenOnSyntax: sinon.SinonStubbedInstance<interfaces.BindingWhenOnSyntax<any>>;
|
|
34
|
-
|
|
35
|
-
const setupStubs = (): {
|
|
36
|
-
context: {
|
|
37
|
-
bind: sinon.SinonStub<[serviceIdentifier: interfaces.ServiceIdentifier<any>], interfaces.BindingToSyntax<any>>;
|
|
38
|
-
isBound: sinon.SinonStub<[serviceIdentifier: interfaces.ServiceIdentifier<any>], boolean>;
|
|
39
|
-
};
|
|
40
|
-
toSyntax: sinon.SinonStubbedInstance<interfaces.BindingToSyntax<any>>;
|
|
41
|
-
inWhenOnSyntax: sinon.SinonStubbedInstance<interfaces.BindingInWhenOnSyntax<any>>;
|
|
42
|
-
whenOnSyntax: sinon.SinonStubbedInstance<interfaces.BindingWhenOnSyntax<any>>;
|
|
43
|
-
} => {
|
|
44
|
-
const container = new Container();
|
|
45
|
-
const bind = sinon.stub<[serviceIdentifier: interfaces.ServiceIdentifier<any>], interfaces.BindingToSyntax<any>>();
|
|
46
|
-
const isBound = sinon.stub<[serviceIdentifier: interfaces.ServiceIdentifier<any>], boolean>();
|
|
47
|
-
|
|
48
|
-
let toSyntax: sinon.SinonStubbedInstance<interfaces.BindingToSyntax<any>> = {} as any;
|
|
49
|
-
let inWhenOnSyntax: sinon.SinonStubbedInstance<interfaces.BindingInWhenOnSyntax<any>> = {} as any;
|
|
50
|
-
container.load(
|
|
51
|
-
new ContainerModule(_bind => {
|
|
52
|
-
const toStub = _bind('StubMe');
|
|
53
|
-
inWhenOnSyntax = sinon.stub(toStub.to(Target));
|
|
54
|
-
whenOnSyntax = sinon.stub(toStub.toConstantValue(''));
|
|
55
|
-
toSyntax = sinon.stub(toStub);
|
|
56
|
-
|
|
57
|
-
bind.returns(toSyntax);
|
|
58
|
-
toSyntax.to.returns(inWhenOnSyntax);
|
|
59
|
-
toSyntax.toSelf.returns(inWhenOnSyntax);
|
|
60
|
-
toSyntax.toDynamicValue.returns(inWhenOnSyntax);
|
|
61
|
-
toSyntax.toService.returns();
|
|
62
|
-
})
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
context: { bind, isBound },
|
|
67
|
-
toSyntax,
|
|
68
|
-
inWhenOnSyntax,
|
|
69
|
-
whenOnSyntax
|
|
70
|
-
};
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
beforeEach(() => {
|
|
74
|
-
const stubs = setupStubs();
|
|
75
|
-
context = stubs.context;
|
|
76
|
-
toSyntax = stubs.toSyntax;
|
|
77
|
-
whenOnSyntax = stubs.whenOnSyntax;
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe('Bind to constructor', () => {
|
|
81
|
-
it('Should bind the service identifier `to` the given target with no scope', () => {
|
|
82
|
-
applyBindingTarget(context, Target, SubTarget);
|
|
83
|
-
expect(toSyntax.to.calledOnceWith(SubTarget)).to.be.true;
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('Should bind the service identifier `toSelf` with no scope', () => {
|
|
87
|
-
applyBindingTarget(context, Target, Target);
|
|
88
|
-
expect(toSyntax.toSelf.calledOnce).to.be.true;
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe('Bind to service', () => {
|
|
93
|
-
it('Should bind the service identifier `service` using the given target service with no scope', () => {
|
|
94
|
-
context.isBound.returns(true);
|
|
95
|
-
applyBindingTarget(context, Target, { service: SubTarget });
|
|
96
|
-
expect(toSyntax.toService.calledOnceWith(SubTarget)).to.be.true;
|
|
97
|
-
});
|
|
98
|
-
it('Should throw an error because the given target service is not bound', () => {
|
|
99
|
-
context.isBound.returns(false);
|
|
100
|
-
expect(() => applyBindingTarget(context, Target, { service: SubTarget, autoBind: false })).to.throw();
|
|
101
|
-
});
|
|
102
|
-
it('Should bind the unbound target service to itself before applying the toService binding', () => {
|
|
103
|
-
context.isBound.returns(false);
|
|
104
|
-
applyBindingTarget(context, Target, { service: SubTarget });
|
|
105
|
-
expect(context.bind.calledWith(Target)).to.be.true;
|
|
106
|
-
});
|
|
107
|
-
it('The return syntax should be no op and invocation of a syntax function should throw an error', () => {
|
|
108
|
-
context.isBound.returns(true);
|
|
109
|
-
const syntax = applyBindingTarget(context, Target, { service: SubTarget });
|
|
110
|
-
expect(() => {
|
|
111
|
-
syntax.inRequestScope();
|
|
112
|
-
}).to.throw(
|
|
113
|
-
`${Target.toString()} has been bound to 'service'.` +
|
|
114
|
-
"Using 'in','when' or 'on' bindings after" +
|
|
115
|
-
"a 'toService' binding is not possible."
|
|
116
|
-
);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
describe('Bind to constant value', () => {
|
|
121
|
-
it('Should bind the service identifier `toConstantValue` using the given target with no scope', () => {
|
|
122
|
-
const subTarget = new SubTarget();
|
|
123
|
-
applyBindingTarget(context, Target, { constantValue: subTarget });
|
|
124
|
-
expect(toSyntax.toConstantValue.calledOnceWith(subTarget)).to.be.true;
|
|
125
|
-
});
|
|
126
|
-
it("The return syntax's in functions should be no op and invocation should log a warning", () => {
|
|
127
|
-
const spy = sinon.spy(console, 'warn');
|
|
128
|
-
const subTarget = new SubTarget();
|
|
129
|
-
const syntax = applyBindingTarget(context, Target, { constantValue: subTarget });
|
|
130
|
-
syntax.inSingletonScope();
|
|
131
|
-
expect(
|
|
132
|
-
spy.calledWith(
|
|
133
|
-
`${Target.toString()} has been bound to 'constantValue'. Binding in Singleton scope has no effect.` +
|
|
134
|
-
'Constant value bindings are effectively Singleton bindings.'
|
|
135
|
-
)
|
|
136
|
-
).to.be.true;
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
describe('Bind to dynamic value', () => {
|
|
141
|
-
it('Should bind the service identifier `toDynamicValue` using the given factory function with no scope', () => {
|
|
142
|
-
applyBindingTarget(context, Target, { dynamicValue: context => new SubTarget() });
|
|
143
|
-
expect(toSyntax.toDynamicValue.calledOnce);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
});
|