@eclipse-glsp/server 2.8.0-next.5 → 2.8.0-next.7

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 (31) hide show
  1. package/lib/common/features/directediting/context-edit-validator.js +3 -3
  2. package/lib/common/features/directediting/context-edit-validator.js.map +1 -1
  3. package/package.json +8 -8
  4. package/src/common/features/directediting/context-edit-validator.ts +2 -2
  5. package/src/browser/di/browser-action-dispatch-scope.spec.ts +0 -75
  6. package/src/common/actions/action-handler-registry.spec.ts +0 -52
  7. package/src/common/actions/global-action-provider.spec.ts +0 -68
  8. package/src/common/command/command-stack.spec.ts +0 -239
  9. package/src/common/command/command.spec.ts +0 -92
  10. package/src/common/command/recording-command.spec.ts +0 -86
  11. package/src/common/di/binding-target.spec.ts +0 -147
  12. package/src/common/di/multi-bindings.spec.ts +0 -133
  13. package/src/common/features/contextactions/context-actions-provider-registry.spec.ts +0 -69
  14. package/src/common/features/contextactions/request-context-actions-handler.spec.ts +0 -75
  15. package/src/common/features/contextactions/tool-palette-item-provider.spec.ts +0 -46
  16. package/src/common/features/directediting/context-edit-validator-registry.spec.ts +0 -54
  17. package/src/common/features/directediting/request-edit-validation-handler.spec.ts +0 -131
  18. package/src/common/features/model/gmodel-serializer.spec.ts +0 -141
  19. package/src/common/features/type-hints/request-type-hints-action-handler.spec.ts +0 -59
  20. package/src/common/operations/operation-handler-registry.spec.ts +0 -50
  21. package/src/common/protocol/glsp-server.spec.ts +0 -154
  22. package/src/common/session/client-session-factory.spec.ts +0 -60
  23. package/src/common/session/client-session-manager.spec.ts +0 -83
  24. package/src/common/test/mock-util.ts +0 -281
  25. package/src/common/utils/action-queue.spec.ts +0 -133
  26. package/src/common/utils/promise-queue.spec.ts +0 -142
  27. package/src/common/utils/registry.spec.ts +0 -225
  28. package/src/node/actions/action-dispatcher.spec.ts +0 -678
  29. package/src/node/launch/cli-parser.spec.ts +0 -61
  30. package/src/node/launch/socket-cli-parser.spec.ts +0 -73
  31. package/src/node/launch/socket-server-launcher.spec.ts +0 -74
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ValidateLabelEditAdapter = exports.ContextEditValidator = void 0;
4
4
  /********************************************************************************
5
- * Copyright (c) 2022-2024 STMicroelectronics and others.
5
+ * Copyright (c) 2022-2026 STMicroelectronics and others.
6
6
  *
7
7
  * This program and the accompanying materials are made available under the
8
8
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -16,7 +16,7 @@ exports.ValidateLabelEditAdapter = exports.ContextEditValidator = void 0;
16
16
  *
17
17
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
18
18
  ********************************************************************************/
19
- const gmodel_element_1 = require("@eclipse-glsp/graph/lib/gmodel-element");
19
+ const graph_1 = require("@eclipse-glsp/graph");
20
20
  const protocol_1 = require("@eclipse-glsp/protocol");
21
21
  const label_edit_validator_1 = require("./label-edit-validator");
22
22
  exports.ContextEditValidator = Symbol('ContextEditValidator');
@@ -30,7 +30,7 @@ class ValidateLabelEditAdapter {
30
30
  }
31
31
  validate(action) {
32
32
  const element = this.modelState.index.get(action.modelElementId);
33
- if (element instanceof gmodel_element_1.GModelElement) {
33
+ if (element instanceof graph_1.GModelElement) {
34
34
  return this.labelEditValidator.validate(action.text, element);
35
35
  }
36
36
  return { severity: protocol_1.ValidationStatus.Severity.OK };
@@ -1 +1 @@
1
- {"version":3,"file":"context-edit-validator.js","sourceRoot":"","sources":["../../../../src/common/features/directediting/context-edit-validator.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;kFAckF;AAClF,2EAAuE;AACvE,qDAAuF;AAEvF,iEAA4D;AAE/C,QAAA,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAiBnE,MAAa,wBAAwB;IAEjC,YACa,UAAsB,EAC/B,kBAAsC;QAD7B,eAAU,GAAV,UAAU,CAAY;QAG/B,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;IACjD,CAAC;IAED,IAAI,SAAS;QACT,OAAO,yCAAkB,CAAC,UAAU,CAAC;IACzC,CAAC;IAED,QAAQ,CAAC,MAAmC;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACjE,IAAI,OAAO,YAAY,8BAAa,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,2BAAgB,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;IACtD,CAAC;CACJ;AApBD,4DAoBC"}
1
+ {"version":3,"file":"context-edit-validator.js","sourceRoot":"","sources":["../../../../src/common/features/directediting/context-edit-validator.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;kFAckF;AAClF,+CAAoD;AACpD,qDAAuF;AAEvF,iEAA4D;AAE/C,QAAA,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAiBnE,MAAa,wBAAwB;IAEjC,YACa,UAAsB,EAC/B,kBAAsC;QAD7B,eAAU,GAAV,UAAU,CAAY;QAG/B,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;IACjD,CAAC;IAED,IAAI,SAAS;QACT,OAAO,yCAAkB,CAAC,UAAU,CAAC;IACzC,CAAC;IAED,QAAQ,CAAC,MAAmC;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACjE,IAAI,OAAO,YAAY,qBAAa,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,2BAAgB,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;IACtD,CAAC;CACJ;AApBD,4DAoBC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eclipse-glsp/server",
3
- "version": "2.8.0-next.5",
3
+ "version": "2.8.0-next.7",
4
4
  "description": "A js server framework for Eclipse GLSP",
5
5
  "keywords": [
6
6
  "eclipse",
@@ -45,7 +45,10 @@
45
45
  "browser.d.ts",
46
46
  "browser.js",
47
47
  "common.d.ts",
48
- "common.js"
48
+ "common.js",
49
+ "!**/*.spec.ts",
50
+ "!**/*.spec.tsx",
51
+ "!**/test/**"
49
52
  ],
50
53
  "dependencies": {
51
54
  "@eclipse-glsp/protocol": "next",
@@ -54,7 +57,7 @@
54
57
  "vscode-jsonrpc": "8.2.0",
55
58
  "winston": "^3.3.3",
56
59
  "ws": "^8.12.1",
57
- "@eclipse-glsp/graph": "2.8.0-next.5"
60
+ "@eclipse-glsp/graph": "2.8.0-next.7"
58
61
  },
59
62
  "devDependencies": {
60
63
  "@types/ws": "^8.5.4"
@@ -68,11 +71,8 @@
68
71
  },
69
72
  "scripts": {
70
73
  "build": "tsc -b",
71
- "clean": "rimraf lib *.tsbuildinfo coverage .nyc_output",
74
+ "clean": "rimraf lib *.tsbuildinfo coverage",
72
75
  "generate:index": "glsp generateIndex src/browser src/common src/node -s -f",
73
- "lint": "eslint ./src",
74
- "test": "mocha --config ../../.mocharc \"./src/**/*.spec.?(ts|tsx)\"",
75
- "test:ci": "pnpm test --reporter mocha-ctrf-json-reporter",
76
- "test:coverage": "nyc pnpm test:ci"
76
+ "lint": "eslint ./src"
77
77
  }
78
78
  }
@@ -1,5 +1,5 @@
1
1
  /********************************************************************************
2
- * Copyright (c) 2022-2024 STMicroelectronics and others.
2
+ * Copyright (c) 2022-2026 STMicroelectronics and others.
3
3
  *
4
4
  * This program and the accompanying materials are made available under the
5
5
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { GModelElement } from '@eclipse-glsp/graph/lib/gmodel-element';
16
+ import { GModelElement } from '@eclipse-glsp/graph';
17
17
  import { RequestEditValidationAction, ValidationStatus } from '@eclipse-glsp/protocol';
18
18
  import { ModelState } from '../model/model-state';
19
19
  import { LabelEditValidator } from './label-edit-validator';
@@ -1,75 +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 { Action } from '@eclipse-glsp/protocol';
17
- import { expect } from 'chai';
18
- import { ClientAction } from '../../common/protocol/client-action';
19
- import * as mock from '../../common/test/mock-util';
20
- import { BrowserActionDispatchScope } from './browser-action-dispatch-scope';
21
-
22
- describe('BrowserActionDispatchScope', () => {
23
- const action: Action = { kind: 'foo' };
24
- const markedClientAction = ((): Action => {
25
- const a: Action = { kind: 'bar' };
26
- ClientAction.mark(a);
27
- return a;
28
- })();
29
-
30
- let scope: BrowserActionDispatchScope;
31
- beforeEach(() => {
32
- scope = new BrowserActionDispatchScope();
33
- });
34
-
35
- it('isReentrant is false outside enter()', () => {
36
- expect(scope.isReentrant(action)).to.be.false;
37
- });
38
-
39
- it('isReentrant is true during a synchronous enter()', () => {
40
- scope.enter(() => {
41
- expect(scope.isReentrant(action)).to.be.true;
42
- });
43
- expect(scope.isReentrant(action)).to.be.false;
44
- });
45
-
46
- it('isReentrant is true during an async enter() and false after settle', async () => {
47
- const probe: Promise<boolean> = scope.enter(async () => {
48
- await Promise.resolve();
49
- return scope.isReentrant(action);
50
- });
51
- expect(await probe).to.be.true;
52
- expect(scope.isReentrant(action)).to.be.false;
53
- });
54
-
55
- it('resets active flag when callback throws synchronously', () => {
56
- expect(() =>
57
- scope.enter(() => {
58
- throw new Error('boom');
59
- })
60
- ).to.throw('boom');
61
- expect(scope.isReentrant(action)).to.be.false;
62
- });
63
-
64
- it('resets active flag when async callback rejects', async () => {
65
- await mock.expectToThrowAsync(() => scope.enter(() => Promise.reject(new Error('boom'))), 'boom');
66
- expect(scope.isReentrant(action)).to.be.false;
67
- });
68
-
69
- it('isReentrant is false for client-originated actions even when scope is active', () => {
70
- scope.enter(() => {
71
- expect(scope.isReentrant(markedClientAction)).to.be.false;
72
- expect(scope.isReentrant(action)).to.be.true;
73
- });
74
- });
75
- });
@@ -1,52 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2022-2023 STMicroelectronics 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 * as mock from '../test/mock-util';
17
- import { ActionHandlerRegistry } from './action-handler-registry';
18
- import { expect } from 'chai';
19
-
20
- describe('Test ActionHandlerRegistry (only functionality that is not covered by "registry.spec.ts"', () => {
21
- const singleAction = 'singleHandledAction';
22
- const multiAction = 'multiHandledAction';
23
-
24
- const h1 = new mock.StubActionHandler([singleAction]);
25
- const h2 = new mock.StubActionHandler([multiAction]);
26
- const h3 = new mock.StubActionHandler([multiAction]);
27
- const h4 = new mock.StubActionHandler([multiAction]);
28
- const registry: ActionHandlerRegistry = new ActionHandlerRegistry();
29
-
30
- it('registerHandler - should register given handlers', () => {
31
- // setup
32
- registry.registerHandler(h1);
33
- registry.registerHandler(h2);
34
- registry.registerHandler(h3);
35
- registry.registerHandler(h4);
36
-
37
- const result = registry.getAll();
38
- expect(result).to.have.length(4);
39
- expect(result.includes(h1)).true;
40
- expect(result.includes(h2)).true;
41
- expect(result.includes(h3)).true;
42
- expect(result.includes(h4)).true;
43
- });
44
-
45
- it('get - should return three handlers sorted by priority', () => {
46
- const result = registry.get(multiAction);
47
- expect(result.length).to.be.equal(3);
48
- expect(result[0]).to.be.deep.equal(h4);
49
- expect(result[1]).to.be.deep.equal(h2);
50
- expect(result[2]).to.be.deep.equal(h3);
51
- });
52
- });
@@ -1,68 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2022-2023 STMicroelectronics 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 { DiagramModules, InjectionContainer } from '../di/service-identifiers';
20
- import { ClientSessionInitializer } from '../session/client-session-initializer';
21
- import * as mock from '../test/mock-util';
22
- import { Logger } from '../utils/logger';
23
- import { ActionHandler } from './action-handler';
24
- import { ActionHandlerRegistry } from './action-handler-registry';
25
- import { DefaultGlobalActionProvider } from './global-action-provider';
26
-
27
- describe('test DefaultGlobalActionProvider', () => {
28
- const container = new Container();
29
- const serverActions = ['A1', 'A2', 'A3'];
30
- const diagramType = 'myDiagramType';
31
-
32
- const handler1Actions = ['A1', 'A2'];
33
- const handler2Actions = ['A2', 'A3'];
34
-
35
- const h1 = new mock.StubActionHandler(handler1Actions);
36
- const h2 = new mock.StubActionHandler(handler2Actions);
37
-
38
- const handlerRegistry = new ActionHandlerRegistry();
39
- sinon.stub(handlerRegistry, 'getAll').returns([h1, h2]);
40
-
41
- const diagramModule1 = new ContainerModule(bind => {
42
- bind(ClientSessionInitializer).toConstantValue(new mock.StubClientSessionInitializer());
43
- bind(ActionHandler).toConstantValue(new mock.StubActionHandler(handler1Actions));
44
- bind(ActionHandler).toConstantValue(new mock.StubActionHandler(handler2Actions));
45
- bind(ActionHandlerRegistry).toConstantValue(handlerRegistry);
46
- });
47
-
48
- const diagramModules = new Map<string, ContainerModule[]>();
49
- diagramModules.set(diagramType, [diagramModule1]);
50
-
51
- container.load(
52
- new ContainerModule(bind => {
53
- bind(Logger).toConstantValue(new mock.StubLogger());
54
- bind(InjectionContainer).toConstantValue(container);
55
- bind(DiagramModules).toConstantValue(diagramModules);
56
- })
57
- );
58
-
59
- const actionProvider = container.resolve(DefaultGlobalActionProvider);
60
-
61
- it('serverActionsKinds', () => {
62
- const result = actionProvider.actionKinds;
63
- expect(result.size).to.be.equal(1);
64
- const resultServerActions = result.get(diagramType);
65
- expect(resultServerActions).to.not.be.undefined;
66
- expect(serverActions.every(action => resultServerActions!.includes(action))).true;
67
- });
68
- });
@@ -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
- });