@eclipse-glsp/layout-elk
Version:
Integration of ELK graph layout algorithms in GLSP Node Server
111 lines (97 loc) • 4.77 kB
text/typescript
/********************************************************************************
* Copyright (c) 2022-2023 STMicroelectronics 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 {
DefaultModelState,
DiagramConfiguration,
EdgeTypeHint,
GGraph,
GModelElementConstructor,
ModelState,
ServerLayoutKind,
ShapeTypeHint
} from '@eclipse-glsp/server';
import { expect } from 'chai';
import { Container, ContainerModule, injectable } from 'inversify';
import * as sinon from 'sinon';
import { configureELKLayoutModule } from './di.config';
import { DefaultElementFilter, ElementFilter } from './element-filter';
import { AbstractLayoutConfigurator, FallbackLayoutConfigurator, LayoutConfigurator } from './layout-configurator';
@injectable()
class CustomLayoutConfigurator extends AbstractLayoutConfigurator {}
@injectable()
class CustomElementFilter extends DefaultElementFilter {}
class StubDiagramConfiguration implements DiagramConfiguration {
typeMapping = new Map<string, GModelElementConstructor>();
shapeTypeHints: ShapeTypeHint[] = [];
edgeTypeHints: EdgeTypeHint[] = [];
layoutKind = ServerLayoutKind.NONE;
needsClientLayout = true;
animatedUpdate = true;
}
describe('test configureELKLayoutModule', () => {
const sandbox = sinon.createSandbox();
const mockDiagramConfiguration = new StubDiagramConfiguration();
const typeMappings = new Map<string, GModelElementConstructor>();
typeMappings.set('graph', GGraph);
sandbox.stub(mockDiagramConfiguration, 'typeMapping').value(typeMappings);
const modelState = new DefaultModelState();
const baseModule = new ContainerModule(bind => {
bind(ModelState).toConstantValue(modelState);
});
it('configure with minimal options', () => {
const algorithm = 'layered';
const elkModule = configureELKLayoutModule({ algorithms: [algorithm] });
const container = new Container();
container.load(baseModule, elkModule);
const filter = container.get<ElementFilter>(ElementFilter);
expect(filter).to.be.an.instanceOf(DefaultElementFilter);
const configurator = container.get<LayoutConfigurator>(LayoutConfigurator);
expect(configurator).to.be.an.instanceOf(FallbackLayoutConfigurator);
const graphOptions = configurator.apply(new GGraph());
expect(graphOptions).not.to.be.undefined;
expect(graphOptions!['elk.algorithm']).to.equal(algorithm);
});
it('configure with additional default layout options', () => {
const algorithm = 'layered';
const defaultLayoutOptions = {
'elk.direction': 'LEFT',
'elk.edgeRouting': 'POLYLINE'
};
const elkModule = configureELKLayoutModule({ algorithms: [algorithm], defaultLayoutOptions });
const container = new Container();
container.load(baseModule, elkModule);
const configurator = container.get<LayoutConfigurator>(LayoutConfigurator);
const graphOptions = configurator.apply(new GGraph());
expect(graphOptions).not.to.be.undefined;
expect(graphOptions).to.include(defaultLayoutOptions);
});
it('configure with custom layout configurator', () => {
const algorithm = 'layered';
const elkModule = configureELKLayoutModule({ algorithms: [algorithm], layoutConfigurator: CustomLayoutConfigurator });
const container = new Container();
container.load(baseModule, elkModule);
const configurator = container.get<LayoutConfigurator>(LayoutConfigurator);
expect(configurator).to.be.an.instanceOf(CustomLayoutConfigurator);
});
it('configure with custom element filter', () => {
const algorithm = 'layered';
const elkModule = configureELKLayoutModule({ algorithms: [algorithm], elementFilter: CustomElementFilter });
const container = new Container();
container.load(baseModule, elkModule);
const filter = container.get<ElementFilter>(ElementFilter);
expect(filter).to.be.an.instanceOf(CustomElementFilter);
});
});