@eclipse-emfcloud/model-service-theia
Version:
Model service Theia
303 lines • 13.1 kB
JavaScript
;
// *****************************************************************************
// Copyright (C) 2023-2024 STMicroelectronics.
//
// 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: MIT License which is
// available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: EPL-2.0 OR MIT
// *****************************************************************************
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MockProvider = void 0;
const model_manager_1 = require("@eclipse-emfcloud/model-manager");
const model_service_1 = require("@eclipse-emfcloud/model-service");
const inversify_1 = require("@theia/core/shared/inversify");
const chai_1 = require("chai");
const sinon_1 = __importDefault(require("sinon"));
const common_1 = require("../../common");
const backend_module_1 = __importDefault(require("../backend-module"));
const model_hub_provider_1 = require("../model-hub-provider");
const model_service_contribution_1 = require("../model-service-contribution");
const fake_json_rpc_1 = require("./fake-json-rpc");
const FAKE_MODEL_ID = 'test.fake-model';
function createTestContainer(contrib) {
const container = new inversify_1.Container();
container.load(backend_module_1.default);
container.bind(model_service_contribution_1.ModelServiceContribution).toConstantValue(contrib);
(0, fake_json_rpc_1.bindFakeRpcConnectionFactory)(container);
return container;
}
describe('Model Accessor Bus Server', () => {
const appContext = 'test-app';
let sandbox;
let modelAccessorBusServer;
let fakeContribution;
let clientProxy;
beforeEach(async () => {
sandbox = sinon_1.default.createSandbox();
fakeContribution = new FakeContribution();
const container = createTestContainer(fakeContribution);
const factory = container.get(fake_json_rpc_1.RpcConnectionFactory);
clientProxy = {
onAccessorChanged: sandbox.stub(),
closeSubscription: sandbox.stub(),
};
modelAccessorBusServer = await factory.getServer(common_1.ModelAccessorBusProtocolServicePath, clientProxy);
// Some tests need to start interacting with the model service
// right away, so initialize the context's provided hub
await container.get(model_hub_provider_1.ModelHubProvider)(appContext);
});
afterEach(() => {
sandbox.restore();
});
describe('getClient', async () => {
beforeEach(() => {
sandbox = sinon_1.default.createSandbox();
});
afterEach(() => {
sandbox.restore();
});
it('expect not undefined', async () => {
(0, chai_1.expect)(modelAccessorBusServer.getClient()).not.to.be.undefined;
});
it('expect undefined', async () => {
modelAccessorBusServer.setClient(undefined);
(0, chai_1.expect)(modelAccessorBusServer.getClient()).to.be.undefined;
});
it('expect specific client', async () => {
const alternateProxy = {
onAccessorChanged: sandbox.stub(),
closeSubscription: sandbox.stub(),
};
modelAccessorBusServer.setClient(alternateProxy);
(0, chai_1.expect)(modelAccessorBusServer.getClient()).to.be.equal(alternateProxy);
});
});
describe('setClient', async () => {
beforeEach(() => {
sandbox = sinon_1.default.createSandbox();
});
afterEach(() => {
sandbox.restore();
});
it('expect undefined', async () => {
modelAccessorBusServer.setClient(undefined);
(0, chai_1.expect)(modelAccessorBusServer.getClient()).to.be.undefined;
});
it('expect same client', async () => {
modelAccessorBusServer.setClient(clientProxy);
(0, chai_1.expect)(modelAccessorBusServer.getClient()).to.be.equal(clientProxy);
});
it('expect client change with disposeSubscriptions', async () => {
const alternateProxy = {
onAccessorChanged: sandbox.stub(),
closeSubscription: sandbox.stub(),
};
(0, chai_1.expect)(await modelAccessorBusServer.subscribe(appContext, 'test')).to.be.eql({
id: 1,
accessorId: 'test',
}, 'Subscribe did not provide the expected result.');
modelAccessorBusServer.setClient(alternateProxy);
(0, chai_1.expect)(modelAccessorBusServer.getClient()).to.be.equal(alternateProxy, 'Client does not match expected result');
});
});
describe('subscribe', async () => {
beforeEach(() => {
sandbox = sinon_1.default.createSandbox();
});
afterEach(() => {
sandbox.restore();
});
it('no client', async () => {
modelAccessorBusServer.setClient(undefined);
(0, chai_1.expect)(await modelAccessorBusServer.subscribe(appContext, 'test')).to.be.eql({
id: 1,
accessorId: 'test',
});
});
it('expect subscription token', async () => {
(0, chai_1.expect)(await modelAccessorBusServer.subscribe(appContext, 'test')).to.be.eql({
id: 1,
accessorId: 'test',
});
});
it('expect 2 different subscription token', async () => {
(0, chai_1.expect)(await modelAccessorBusServer.subscribe(appContext, 'test1')).to.be.eql({
id: 1,
accessorId: 'test1',
});
(0, chai_1.expect)(await modelAccessorBusServer.subscribe(appContext, 'test2')).to.be.eql({
id: 2,
accessorId: 'test2',
});
});
});
describe('closeSubscription', async () => {
beforeEach(() => {
sandbox = sinon_1.default.createSandbox();
});
afterEach(() => {
sandbox.restore();
});
it('execute closeSubscription with no subscription', async () => {
(0, chai_1.expect)(() => modelAccessorBusServer.closeSubscription({
id: 1,
accessorId: 'test',
})).not.to.throw();
});
it('execute closeSubscription', async () => {
const token = await modelAccessorBusServer.subscribe(appContext, 'test');
(0, chai_1.expect)(token).to.be.eql({
id: 1,
accessorId: 'test',
}, 'Subscribe did not provide the expected result.');
(0, chai_1.expect)(() => modelAccessorBusServer.closeSubscription(token)).not.to.throw();
});
it('execute dispose', async () => {
const token = await modelAccessorBusServer.subscribe(appContext, 'test');
(0, chai_1.expect)(token).to.be.eql({
id: 1,
accessorId: 'test',
}, 'Subscribe did not provide the expected result.');
modelAccessorBusServer.dispose();
});
});
describe('get', async () => {
it('expect undefined : existing context, not existing accessor', async () => {
(0, chai_1.expect)(await modelAccessorBusServer.get(appContext, 'empty')).to.be
.undefined;
});
});
describe('trigger subscription', () => {
it('expect subscription token', async () => {
const providerChangeSubToken = await modelAccessorBusServer.subscribe(appContext, 'fake-provider.get');
const fakeService = fakeContribution.getModelService();
(0, chai_1.expect)(providerChangeSubToken).to.be.eql({
id: 1,
accessorId: 'fake-provider.get',
}, 'Subscription did not provide the expected result.');
await fakeService.setName('Fake Model 2');
(0, chai_1.expect)(clientProxy.onAccessorChanged.calledOnceWith(1)).to.be.true;
});
});
describe('getModelAccessorBus', async () => {
it('expect to be different on different contexts', async () => {
const spiedAccessorBusAccess = sandbox.spy(modelAccessorBusServer);
await Promise.all([
modelAccessorBusServer.get(appContext, 'empty'),
modelAccessorBusServer.get(`${appContext}-2`, 'empty'),
]);
(0, chai_1.expect)(spiedAccessorBusAccess.getModelAccessorBus.calledTwice).to.be.true;
const bus_0 = await spiedAccessorBusAccess.getModelAccessorBus
.returnValues[0];
const bus_1 = await spiedAccessorBusAccess.getModelAccessorBus
.returnValues[1];
(0, chai_1.expect)(bus_0 !== bus_1).to.be.true;
});
it('expect to be same for same contexts', async () => {
const spiedAccessorBusAccess = sandbox.spy(modelAccessorBusServer);
await Promise.all([
modelAccessorBusServer.get(appContext, 'empty'),
modelAccessorBusServer.get(appContext, 'empty'),
]);
(0, chai_1.expect)(spiedAccessorBusAccess.getModelAccessorBus.calledTwice).to.be.true;
const bus_0 = await spiedAccessorBusAccess.getModelAccessorBus
.returnValues[0];
const bus_1 = await spiedAccessorBusAccess.getModelAccessorBus
.returnValues[1];
(0, chai_1.expect)(bus_0 === bus_1).to.be.true;
});
});
});
class MockProvider extends model_service_1.HubAwareProvider {
constructor() {
super('fake-provider');
this.getId = this.getId.bind(this);
this.accessors.set('get', this.getId);
}
setModelHub(modelHub) {
super.setModelHub(modelHub);
const subscription = modelHub.subscribe(FAKE_MODEL_ID);
subscription.onModelChanged = (_modelId, _model, delta) => {
if (delta?.some((op) => op.path === '/name')) {
this.notify('get');
}
};
}
getId() {
return this.id;
}
}
exports.MockProvider = MockProvider;
const mockProvider = new MockProvider();
class FakeContribution extends model_service_1.AbstractModelServiceContribution {
getModelService() {
return this.modelService;
}
setModelManager(modelManager) {
super.setModelManager(modelManager);
this.commandStack = modelManager.getCommandStack(FAKE_MODEL_ID);
}
constructor() {
super();
this.model = {
name: 'Fake Model 1',
};
this.modelService = {
getModel: () => {
let model = this.modelManager.getModel(FAKE_MODEL_ID);
if (!model) {
this.modelManager.setModel(FAKE_MODEL_ID, this.model);
model = this.modelManager.getModel(FAKE_MODEL_ID);
}
if (!model) {
throw new Error('No model to edit');
}
return model;
},
setName: async (newName) => {
this.modelService.getModel(); // Ensure the model is loaded
const command = createSetNameCommand(FAKE_MODEL_ID, newName);
await this.commandStack.execute(command);
},
};
this.initialize({
id: 'test.contrib1',
persistenceContribution: {
canHandle: (modelId) => Promise.resolve(modelId === FAKE_MODEL_ID),
loadModel: (modelId) => modelId === FAKE_MODEL_ID
? Promise.resolve(this.model)
: Promise.reject(new Error(`No such model: ${modelId}`)),
saveModel: async (modelId, model) => {
if (modelId !== FAKE_MODEL_ID) {
throw new Error(`Unsupported model ${modelId}`);
}
const newImage = { ...model };
Array.from(Object.keys(this.model)).forEach((key) => delete this.model[key]);
Object.assign(this.model, newImage);
return true;
},
},
modelAccessorContribution: {
getProviders() {
return [mockProvider];
},
},
});
}
}
function createSetNameCommand(modelId, newName) {
return (0, model_manager_1.createModelUpdaterCommand)('Set Name', modelId, (model) => {
model.name = newName;
});
}
//# sourceMappingURL=model-accessor-bus-server.spec.js.map