-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Refactor diagram loader - Remove dispatching of temporary empty set model action and instead call `actionDispatcher.initialize()` earlier which also dispatches an empty set model action under the hood - Add additional `postModelInitalization` hook for startup services that want execute logic after the model is fully initialized - Rework `ModelInitializationConstraint` - Provide `onInitialized` override that allows sync registration of listener callbacks - Refactor `setCompleted` method and remove the possiblity to set the initialized state to false. Model initialization is a one-time action. Once initialized there should be no way to "uninitialize" the constraint - Provide test cases - Add `dispatchOnceModelInitialized` utility function to action dispatcher - Ensure that type hints are requested after the model has been initialized Part-of: eclipse-glsp/glsp#1116 Part-of: eclipse-glsp/glsp#606
- Loading branch information
Showing
13 changed files
with
239 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
packages/client/src/base/model/model-initialization-constraint.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2023 EclipseSource and others. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License v. 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* This Source Code may also be made available under the following Secondary | ||
* Licenses when the conditions for such availability set forth in the Eclipse | ||
* Public License v. 2.0 are satisfied: GNU General Public License, version 2 | ||
* with the GNU Classpath Exception which is available at | ||
* https://www.gnu.org/software/classpath/license.html. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||
********************************************************************************/ | ||
import { expect } from 'chai'; | ||
import { Container } from 'inversify'; | ||
import 'reflect-metadata'; | ||
import * as sinon from 'sinon'; | ||
import { Deferred, EMPTY_ROOT, InitializeCanvasBoundsAction, SetModelAction, UpdateModelAction } from '~glsp-sprotty'; | ||
import { DefaultModelInitializationConstraint, ModelInitializationConstraint } from './model-initialization-constraint'; | ||
const sandbox = sinon.createSandbox(); | ||
const container = new Container(); | ||
let constraint: ModelInitializationConstraint; | ||
// eslint-disable-next-line @typescript-eslint/no-empty-function | ||
const listener = sandbox.spy((): void => {}); | ||
|
||
describe('DefaultModelInitializationConstraint', () => { | ||
beforeEach(() => { | ||
constraint = container.resolve(DefaultModelInitializationConstraint); | ||
sandbox.reset(); | ||
}); | ||
it('should complete after dispatching non empty SetModelAction and `InitializeCanvasBoundsAction`', () => { | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched(SetModelAction.create({ id: 'model', type: 'graph' })); | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND }); | ||
expect(constraint.isCompleted).to.be.true; | ||
}); | ||
it('should complete after dispatching non empty UpdateModelAction and `InitializeCanvasBoundsAction`', () => { | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched(UpdateModelAction.create({ id: 'model', type: 'graph' })); | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND }); | ||
expect(constraint.isCompleted).to.be.true; | ||
}); | ||
it('should note complete after dispatching empty SetModelAction and `InitializeCanvasBoundsAction` ', () => { | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched(SetModelAction.create(EMPTY_ROOT)); | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND }); | ||
expect(constraint.isCompleted).to.be.false; | ||
}); | ||
it('should note complete after dispatching empty UpdateModelAction and `InitializeCanvasBoundsAction ', () => { | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched(UpdateModelAction.create(EMPTY_ROOT)); | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND }); | ||
expect(constraint.isCompleted).to.be.false; | ||
}); | ||
describe('onInitialized', () => { | ||
it('returned promise should resolve once the constraint is initialized', async () => { | ||
const initializeDeferred = new Deferred<void>(); | ||
const initializePromise = constraint.onInitialized(); | ||
initializePromise.then(() => initializeDeferred.resolve()); | ||
expect(initializeDeferred.state).to.be.equal('unresolved'); | ||
// Directly trigger the completion method simplify test logic | ||
constraint['setCompleted'](); | ||
// Short delay of test execution to ensure that the deferred state is updated. | ||
await new Promise(resolve => setTimeout(resolve, 5)); | ||
expect(initializeDeferred.state).to.be.equal('resolved'); | ||
}); | ||
it('registered listener should be invoked once the constraint is initialized', () => { | ||
constraint.onInitialized(listener); | ||
expect(listener.called).to.be.false; | ||
// Directly trigger the completion method simplify test logic | ||
constraint['setCompleted'](); | ||
expect(listener.called).to.be.true; | ||
}); | ||
it('registered listener should be invoked directly on registration if the constraint is already initialized', () => { | ||
// Directly trigger the completion method simplify test logic | ||
constraint['setCompleted'](); | ||
constraint.onInitialized(listener); | ||
expect(listener.called).to.be.true; | ||
}); | ||
it('Disposed listener should not be invoked once the constraint is initialized', () => { | ||
const toDispose = constraint.onInitialized(listener); | ||
expect(listener.called).to.be.false; | ||
toDispose.dispose(); | ||
// Directly trigger the completion method simplify test logic | ||
constraint['setCompleted'](); | ||
expect(listener.called).to.be.false; | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.