UNPKG

@eclipse-emfcloud/model-validation

Version:

Generic model validation framework.

229 lines 13 kB
"use strict"; // ***************************************************************************** // 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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = __importStar(require("chai")); const sinon_1 = __importDefault(require("sinon")); const sinon_chai_1 = __importDefault(require("sinon-chai")); const model_validation_service_1 = require("../model-validation-service"); const diagnostic_1 = require("../diagnostic"); chai_1.default.use(sinon_chai_1.default); describe('ModelValidationServiceImpl', () => { let modelValidationService; let validatorOK; let validatorError; let validatorException; let validatorReject; const customOKInstance = { severity: 'ok', source: '@example/test', code: '0', path: '', message: 'Hello.', }; const errorInstance = { severity: 'error', source: '@example/test', code: '4', path: 'foo/errorProp', message: 'Error, error!', }; let consoleWarnStub; beforeEach(() => { modelValidationService = new model_validation_service_1.ModelValidationServiceImpl(); validatorOK = { validate: (_modelId, _model) => { return Promise.resolve(customOKInstance); }, }; validatorError = { validate: (_modelId, _model) => { return Promise.resolve(errorInstance); }, }; validatorException = { validate: (_modelId, _model) => { throw new Error('This is an error'); }, }; validatorReject = { validate: (_modelId, _model) => { return Promise.reject('rejected Promise'); }, }; consoleWarnStub = sinon_1.default.stub(console, 'warn'); }); afterEach(() => { consoleWarnStub.restore(); }); describe('validate', () => { it('validate w/o validator', async () => { const result = await modelValidationService.validate('key1', {}); (0, chai_1.expect)(result).to.be.deep.equal((0, diagnostic_1.ok)()); }); it('getValidationState for ok Diagnostic validate', async () => { modelValidationService.addValidator(validatorOK); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(modelValidationService.getValidationState('key1')).to.be.deep.equal((0, diagnostic_1.ok)()); }); it('getValidationState for multi validate', async () => { modelValidationService.addValidator(validatorOK); modelValidationService.addValidator(validatorError); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(modelValidationService.getValidationState('key1')).to.be.deep.equal(errorInstance); }); it('throws exception from validator do not crash the whole process', async () => { modelValidationService.addValidator(validatorOK); modelValidationService.addValidator(validatorException); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(modelValidationService.getValidationState('key1')).to.be.deep.equal((0, diagnostic_1.ok)()); const msg = `An error occurred within a validator during the validation of 'key1'. Error: This is an error. Validation continues ignoring the failed validator`; (0, chai_1.expect)(consoleWarnStub.calledWith('model-validation/model-validation-service:', msg)).to.be.true; }); it('rejects the promises from validator do not crash the whole process', async () => { modelValidationService.addValidator(validatorOK); modelValidationService.addValidator(validatorReject); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(modelValidationService.getValidationState('key1')).to.be.deep.equal((0, diagnostic_1.ok)()); const msg = `An error occurred within a validator during the validation of 'key1' (cause: rejected Promise). Validation continues ignoring the failed validator`; (0, chai_1.expect)(consoleWarnStub.calledWith('model-validation/model-validation-service:', msg)).to.be.true; }); }); describe('subscribe', () => { it('subscribe to the updates to the validation state of a single model', async () => { const subscription = modelValidationService.subscribe('key1'); subscription.onValidationChanged = sinon_1.default.spy(); await modelValidationService.validate('key1', {}); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(subscription.onValidationChanged).to.be.calledOnce; await modelValidationService.validate('key2', {}); (0, chai_1.expect)(subscription.onValidationChanged).to.be.calledOnce; subscription.close(); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(subscription.onValidationChanged).to.be.calledOnce; }); it('subscribe to the updates to the validation state w/o onValidationChanges', async () => { const subscriptionA = modelValidationService.subscribe('key1'); const subscriptionB = modelValidationService.subscribe('key1'); subscriptionA.onValidationChanged = sinon_1.default.spy(); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(subscriptionA.onValidationChanged).to.be.calledOnce; subscriptionB.close(); subscriptionB.close(); }); it('subscribe to the updates to the validation state of several models', async () => { const subscription = modelValidationService.subscribe('key1', 'key2', 'key3'); subscription.onValidationChanged = sinon_1.default.spy(); await modelValidationService.validate('key1', {}); await modelValidationService.validate('key2', {}); (0, chai_1.expect)(subscription.onValidationChanged).to.be.calledTwice; subscription.close(); await modelValidationService.validate('key1', {}); await modelValidationService.validate('key2', {}); await modelValidationService.validate('key3', {}); (0, chai_1.expect)(subscription.onValidationChanged).to.be.calledTwice; }); it('subscribe to the updates to the validation state of all models', async () => { const subscription = modelValidationService.subscribe(); subscription.onValidationChanged = sinon_1.default.spy(); await modelValidationService.validate('key1', {}); await modelValidationService.validate('key2', {}); (0, chai_1.expect)(subscription.onValidationChanged).to.be.calledTwice; await modelValidationService.validate('key2', {}); (0, chai_1.expect)(subscription.onValidationChanged).to.be.calledTwice; subscription.close(); await modelValidationService.validate('key3', {}); (0, chai_1.expect)(subscription.onValidationChanged).to.be.calledTwice; }); it('subscribe to the updates to the validation state of all models w/o onValidationChanges', async () => { const subscriptionA = modelValidationService.subscribe(); subscriptionA.onValidationChanged = sinon_1.default.spy(); const subscriptionB = modelValidationService.subscribe(); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(subscriptionA.onValidationChanged).to.be.calledOnce; subscriptionB.close(); subscriptionB.close(); }); it('subscribe to the updates of the validation state of several models with one onValidationChanged throwing an error', async () => { const subscriptionA = modelValidationService.subscribe('key1', 'key2', 'key3'); subscriptionA.onValidationChanged = (_modelId, _model, _diagnostic) => { throw new Error('This is an onValidationChanged exception'); }; const subscriptionB = modelValidationService.subscribe('key1', 'key2', 'key3'); subscriptionB.onValidationChanged = sinon_1.default.spy(); await modelValidationService.validate('key1', {}); const msg1 = `An error occurred within the onValidationChanged callback for 'key1'. Error: This is an onValidationChanged exception. Other subscribers will still be notified ignoring the failed callback`; (0, chai_1.expect)(consoleWarnStub.calledWith('model-validation/model-validation-service:', msg1)).to.be.true; await modelValidationService.validate('key2', {}); const msg2 = `An error occurred within the onValidationChanged callback for 'key2'. Error: This is an onValidationChanged exception. Other subscribers will still be notified ignoring the failed callback`; (0, chai_1.expect)(consoleWarnStub.calledWith('model-validation/model-validation-service:', msg2)).to.be.true; (0, chai_1.expect)(subscriptionB.onValidationChanged).to.be.calledTwice; subscriptionA.close(); subscriptionB.close(); }); it('subscribe to the updates of the validation state of all models with one onValidationChanged throwing an error', async () => { const subscriptionA = modelValidationService.subscribe(); subscriptionA.onValidationChanged = (_modelId, _model, _diagnostic) => { throw new Error('This is an onValidationChanged exception'); }; const subscriptionB = modelValidationService.subscribe(); subscriptionB.onValidationChanged = sinon_1.default.spy(); await modelValidationService.validate('key1', {}); (0, chai_1.expect)(subscriptionB.onValidationChanged).to.be.calledOnce; const msg = `An error occurred within the onValidationChanged callback for 'key1'. Error: This is an onValidationChanged exception. Other subscribers will still be notified ignoring the failed callback`; (0, chai_1.expect)(consoleWarnStub.calledWith('model-validation/model-validation-service:', msg)).to.be.true; subscriptionA.close(); subscriptionB.close(); }); it('get current validation state in subscription', async () => { modelValidationService.addValidator(validatorError); const subscriptionA = modelValidationService.subscribe(); let currentState; subscriptionA.onValidationChanged = (modelId, _model, _diagnostic) => { currentState = modelValidationService.getValidationState(modelId); }; const diagnostic = await modelValidationService.validate('key1', {}); (0, chai_1.expect)(currentState).to.equal(diagnostic); (0, chai_1.expect)(currentState?.severity).to.equal('error'); }); }); }); //# sourceMappingURL=model-validation-service.spec.js.map