@eclipse-emfcloud/model-validation
Version:
Generic model validation framework.
286 lines • 12.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// *****************************************************************************
// 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
// *****************************************************************************
const chai_1 = require("chai");
const diagnostic_1 = require("../diagnostic");
describe('Diagnostic functions', () => {
describe('ok', () => {
it('yields an OK diagnostic', () => {
const actual = (0, diagnostic_1.ok)();
(0, chai_1.expect)(actual.severity, 'not ok').to.be.equal('ok');
(0, chai_1.expect)(actual.source).to.be.equal('@eclipse-emfcloud/model-validation');
});
it('always yields a new instance', () => {
const first = (0, diagnostic_1.ok)();
const second = (0, diagnostic_1.ok)();
(0, chai_1.expect)(second, 'not distinct').not.to.be.equal(first);
});
it('supports a custom source', () => {
const custom = (0, diagnostic_1.ok)('@example/test');
(0, chai_1.expect)(custom.source, 'stock source').to.be.equal('@example/test');
});
});
describe('merge', () => {
const defaultOKInstance = (0, diagnostic_1.ok)();
const customOKInstance = {
severity: 'ok',
source: '@example/test',
code: '0',
path: '',
message: 'Hello.',
};
const infoInstance = {
severity: 'info',
source: '@example/test',
code: '1',
path: 'foo/infoProp',
message: 'I have information for you.',
};
const warningInstance = {
severity: 'warn',
source: '@example/test',
code: '2',
path: 'foo/warningProp',
message: 'This is a warning.',
};
const errorInstance = {
severity: 'error',
source: '@example/test',
code: '4',
path: 'foo/errorProp',
message: 'Error, error!',
children: [], // Empty children array is equivalent to absent children array
};
const multiWarningInstance = {
severity: 'warn',
source: '@example/test',
path: 'foo/warningObject',
message: '',
children: [warningInstance, infoInstance],
};
const multiErrorInstance = {
severity: 'error',
source: '@example/test',
path: 'foo/errorObject',
message: '',
children: [customOKInstance, errorInstance],
};
// This one contains itself and is, therefore, invalid
const cyclicInstance = {
severity: 'error',
source: '@example/test',
path: 'bar/cyclic',
message: '',
children: [multiWarningInstance],
};
cyclicInstance.children?.push(cyclicInstance);
it('merges no diagnostics', () => {
const actual = (0, diagnostic_1.merge)();
(0, chai_1.expect)(actual.severity, 'not ok').to.be.equal('ok');
verifySerializable(actual);
});
it('merges one diagnostic', () => {
const actual = (0, diagnostic_1.merge)(infoInstance);
(0, chai_1.expect)(actual, 'input not returned').to.be.equal(infoInstance);
verifySerializable(actual);
});
it('merges only OK diagnostics', () => {
const actual = (0, diagnostic_1.merge)(defaultOKInstance, customOKInstance);
(0, chai_1.expect)(actual.severity, 'not ok').to.be.equal('ok');
(0, chai_1.expect)(actual, 'returned one of the inputs')
.not.to.equal(defaultOKInstance)
.and.not.to.equal(customOKInstance);
verifySerializable(actual);
});
it('merges an OK and a problem', () => {
const actual = (0, diagnostic_1.merge)(customOKInstance, warningInstance);
(0, chai_1.expect)(actual).to.equal(warningInstance);
verifySerializable(actual);
});
it('merges a leaf and another leaf', () => {
const actual = (0, diagnostic_1.merge)(infoInstance, warningInstance);
(0, chai_1.expect)(actual).to.deep.equal({
severity: 'warn',
source: '@example/test',
path: 'foo',
message: '2 problems found.',
children: [infoInstance, warningInstance],
});
verifySerializable(actual);
});
it('merges a leaf and a non-leaf', () => {
const actual = (0, diagnostic_1.merge)(errorInstance, multiWarningInstance);
(0, chai_1.expect)(actual).to.deep.equal({
severity: 'error',
source: '@example/test',
path: 'foo',
message: '3 problems found.',
children: [errorInstance, warningInstance, infoInstance],
});
verifySerializable(actual);
});
it('merges a leaf and a non-leaf in which some child is OK', () => {
const actual = (0, diagnostic_1.merge)(warningInstance, multiErrorInstance);
(0, chai_1.expect)(actual).to.deep.equal({
severity: 'error',
source: '@example/test',
path: 'foo',
message: '2 problems found.',
children: [warningInstance, errorInstance], // `customOKInstance` was elided
});
verifySerializable(actual);
});
it('merges a non-leaf and a leaf', () => {
const actual = (0, diagnostic_1.merge)(multiWarningInstance, errorInstance);
(0, chai_1.expect)(actual).to.deep.equal({
severity: 'error',
source: '@example/test',
path: 'foo',
message: '3 problems found.',
children: [warningInstance, infoInstance, errorInstance],
});
verifySerializable(actual);
});
it('merges a non-leaf in which some child is OK and a leaf', () => {
const actual = (0, diagnostic_1.merge)(multiErrorInstance, warningInstance);
(0, chai_1.expect)(actual).to.deep.equal({
severity: 'error',
source: '@example/test',
path: 'foo',
message: '2 problems found.',
children: [errorInstance, warningInstance], // `customOKInstance` was elided
});
verifySerializable(actual);
});
it('merges a non-leaf and another non-leaf', () => {
const actual = (0, diagnostic_1.merge)(multiWarningInstance, multiErrorInstance);
(0, chai_1.expect)(actual).to.deep.equal({
severity: 'error',
source: '@example/test',
path: 'foo',
message: '3 problems found.',
children: [warningInstance, infoInstance, errorInstance], // `customOKInstance` was elided
});
verifySerializable(actual);
});
it('tolerates a cyclic diagnostic', () => {
const actual = (0, diagnostic_1.merge)(multiErrorInstance, cyclicInstance);
(0, chai_1.expect)(actual).to.include({
severity: 'error',
source: '@example/test',
path: '',
message: '3 problems found.',
});
(0, chai_1.expect)(actual.children)
.to.be.an('array')
.of.length(3)
.that.includes(errorInstance)
.and.that.includes(multiWarningInstance)
.and.that.includes(cyclicInstance);
// Don't try to serialize this cyclic structure
});
it('merges more than two diagnostics', () => {
const newInstance = {
severity: 'info',
source: '@example/test',
path: 'foo',
message: "You've got mail!",
};
const actual = (0, diagnostic_1.merge)(infoInstance, warningInstance, multiErrorInstance, newInstance);
(0, chai_1.expect)(actual).to.deep.equal({
severity: 'error',
source: '@example/test',
path: 'foo',
message: '4 problems found.',
children: [infoInstance, warningInstance, errorInstance, newInstance], // `customOKInstance` was elided
});
verifySerializable(actual);
});
it('merges non-leaf diagnostics that only have OK children', () => {
const silly1 = {
severity: 'info', // This doesn't make sense
source: '@example/test',
path: 'foo/silly/1',
message: 'This is a silly diagnostic.',
children: [defaultOKInstance, customOKInstance],
};
const silly2 = {
severity: 'warn', // This doesn't make sense
source: '@example/test',
path: 'foo/silly/2',
message: 'This is another silly diagnostic.',
children: [(0, diagnostic_1.ok)(), defaultOKInstance],
};
const actual = (0, diagnostic_1.merge)(silly1, silly2);
(0, chai_1.expect)(actual, 'merge is not reduced').to.be.deep.equal((0, diagnostic_1.ok)());
});
it('treats empty children array the same as no children array', () => {
const emptyChildren = {
severity: 'warn',
source: '@example/test',
path: 'foo/emptyChildren',
message: 'This diagnostic has an empty children array.',
children: [],
};
const actual = (0, diagnostic_1.merge)(emptyChildren);
(0, chai_1.expect)(actual, 'leaf should have stood for itself').to.be.equal(emptyChildren);
});
it('merge of a single multi-diagnostic filters its children', () => {
const actual = (0, diagnostic_1.merge)(multiErrorInstance);
(0, chai_1.expect)(actual, 'merge is not reduced').to.be.equal(errorInstance);
});
it('tolerates missing paths', () => {
const missingPath = {
severity: 'warn',
source: '@example/test',
message: 'None.',
};
const hasPath = {
severity: 'info',
source: '@example/test',
path: 'foo/whatever',
message: 'None.',
};
const missingFirst = (0, diagnostic_1.merge)(missingPath, hasPath);
delete missingFirst.children;
const missingSecond = (0, diagnostic_1.merge)(hasPath, missingPath);
delete missingSecond.children;
(0, chai_1.expect)(missingSecond).to.be.deep.equal(missingFirst);
(0, chai_1.expect)(missingFirst).to.be.deep.equal({
severity: 'warn',
source: '@example/test',
path: '',
message: '2 problems found.',
});
});
it('reduces mixed sources to nil', () => {
const source1 = { source: '@example/1' };
const source2a = { source: '@example/2' };
const source2b = { source: '@example/2' };
const actual = (0, diagnostic_1.merge)(source1, source2a, source2b);
(0, chai_1.expect)(actual.source).not.to.be.ok; // Chai's version of '.to.be.falsy'
});
it('source of empty merge is defaulted', () => {
const actual = (0, diagnostic_1.merge)();
(0, chai_1.expect)(actual.source).to.be.equal('@eclipse-emfcloud/model-validation');
});
});
});
const verifySerializable = (d) => {
const transmitted = JSON.parse(JSON.stringify(d));
(0, chai_1.expect)(transmitted).to.deep.equal(d);
};
//# sourceMappingURL=diagnostic.spec.js.map