Skip to content

Commit

Permalink
feat(dcs): add test coverage
Browse files Browse the repository at this point in the history
Signed-off-by: Jonathan Casey <[email protected]>
  • Loading branch information
jonathan-casey committed Oct 2, 2023
1 parent e07ee44 commit 8d5dae2
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 2 deletions.
3 changes: 1 addition & 2 deletions packages/concerto-core/lib/decoratormanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,8 @@ class DecoratorManager {

break;
default:
throw new Error('Unrecognised Element value found: ' + target.element );
throw new Error('Decorator Command contains invalid target element: ' + target.element );
}

} else if (target.type) {
if (this.falsyOrEqual(target.type, declaration.key.$class)) {
this.applyDecorator(declaration.key, type, decorator);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$class" : "[email protected]",
"name" : "invalid-target-element",
"version": "1.0.0",
"commands" : [
{
"$class" : "[email protected]",
"type" : "UPSERT",
"target" : {
"$class" : "[email protected]",
"namespace" : "[email protected]",
"declaration" : "Dictionary",
"element" : "INVALID_ELEMENT"
},
"decorator" : {
"$class" : "[email protected]",
"name" : "Test"
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"$class" : "[email protected]",
"name" : "web",
"version": "1.0.0",
"commands" : [
{
"$class" : "[email protected]",
"type" : "UPSERT",
"target" : {
"$class" : "[email protected]",
"namespace" : "[email protected]",
"declaration" : "Dictionary",
"type" : "[email protected]",
"element": "KEY"
},
"decorator" : {
"$class" : "[email protected]",
"name" : "Foo",
"arguments" : []
}
},
{
"$class" : "[email protected]",
"type" : "UPSERT",
"target" : {
"$class" : "[email protected]",
"namespace" : "[email protected]",
"declaration" : "Dictionary",
"type" : "[email protected]",
"element": "VALUE"
},
"decorator" : {
"$class" : "[email protected]",
"name" : "Bar",
"arguments" : []
}
},
{
"$class" : "[email protected]",
"type" : "UPSERT",
"target" : {
"$class" : "[email protected]",
"namespace" : "[email protected]",
"declaration" : "Dictionary",
"element": "*"
},
"decorator" : {
"$class" : "[email protected]",
"name" : "Baz",
"arguments" : []
}
},
{
"$class" : "[email protected]",
"type" : "UPSERT",
"target" : {
"$class" : "[email protected]",
"namespace" : "[email protected]",
"declaration" : "Dictionary",
"type" : "[email protected]"
},
"decorator" : {
"$class" : "[email protected]",
"name" : "DecoratesKeyByType",
"arguments" : []
}
},
{
"$class" : "[email protected]",
"type" : "UPSERT",
"target" : {
"$class" : "[email protected]",
"namespace" : "[email protected]",
"declaration" : "Dictionary",
"type" : "[email protected]"
},
"decorator" : {
"$class" : "[email protected]",
"name" : "DecoratesValueByType",
"arguments" : []
}
},
{
"$class" : "[email protected]",
"type" : "UPSERT",
"target" : {
"$class" : "[email protected]",
"namespace" : "[email protected]",
"type" : "[email protected]"
},
"decorator" : {
"$class" : "[email protected]",
"name" : "DecoratesAllMapKeys",
"arguments" : []
}
},
{
"$class" : "[email protected]",
"type" : "UPSERT",
"target" : {
"$class" : "[email protected]",
"namespace" : "[email protected]",
"type" : "[email protected]"
},
"decorator" : {
"$class" : "[email protected]",
"name" : "DecoratesAllMapValues",
"arguments" : []
}
}
]
}
11 changes: 11 additions & 0 deletions packages/concerto-core/test/data/decoratorcommands/test.cto
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,15 @@ concept Person {
o String lastName
o String bio
o SSN ssn
o Dictionary dictionary
}

map Dictionary {
o String
o String
}

map Rolodex {
o String
o String
}
115 changes: 115 additions & 0 deletions packages/concerto-core/test/decoratormanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,107 @@ describe('DecoratorManager', () => {
decoratorUnversionedNamespace.should.not.be.null;
});

it('should decorate the specified element on the specified Map Declaration (Map Key)', async function() {
// load a model to decorate
const testModelManager = new ModelManager({strict:true, skipLocationNodes: true});
const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8');
testModelManager.addCTOModel(modelText, 'test.cto');

const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8');
const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs),
{validate: true, validateCommands: true});

const dictionary = decoratedModelManager.getType('[email protected]');
dictionary.should.not.be.null;
dictionary.key.getDecorator('Foo').should.not.be.null;
});

it('should decorate the specified type on the specified Map Declaration (Map Key)', async function() {
// load a model to decorate
const testModelManager = new ModelManager({strict:true, skipLocationNodes: true});
const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8');
testModelManager.addCTOModel(modelText, 'test.cto');

const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8');
const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs),
{validate: true, validateCommands: true});

const dictionary = decoratedModelManager.getType('[email protected]');
dictionary.should.not.be.null;
dictionary.key.getDecorator('DecoratesKeyByType').should.not.be.null;
});

it('should decorate the specified element on the specified Map Declaration (Map Value)', async function() {
// load a model to decorate
const testModelManager = new ModelManager({strict:true, skipLocationNodes: true});
const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8');
testModelManager.addCTOModel(modelText, 'test.cto');

const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8');
const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs),
{validate: true, validateCommands: true});

const dictionary = decoratedModelManager.getType('[email protected]');

dictionary.should.not.be.null;
dictionary.value.getDecorator('Bar').should.not.be.null;
});

it('should decorate the specified type on the specified Map Declaration (Map Value)', async function() {
// load a model to decorate
const testModelManager = new ModelManager({strict:true, skipLocationNodes: true});
const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8');
testModelManager.addCTOModel(modelText, 'test.cto');

const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8');
const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs),
{validate: true, validateCommands: true});

const dictionary = decoratedModelManager.getType('[email protected]');
dictionary.should.not.be.null;
dictionary.value.getDecorator('DecoratesValueByType').should.not.be.null;
});

it('should decorate both Key and Value elements on the specified Map Declaration', async function() {
// load a model to decorate
const testModelManager = new ModelManager({strict:true, skipLocationNodes: true});
const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8');
testModelManager.addCTOModel(modelText, 'test.cto');

const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8');
const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs),
{validate: true, validateCommands: true});

const dictionary = decoratedModelManager.getType('[email protected]');

dictionary.should.not.be.null;
dictionary.key.getDecorator('Baz').should.not.be.null;
dictionary.value.getDecorator('Baz').should.not.be.null;
});

it('should decorate all Map Declaration Key and Value elements on the model when a declaration is not specified', async function() {
// load a model to decorate
const testModelManager = new ModelManager({strict:true, skipLocationNodes: true});
const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8');
testModelManager.addCTOModel(modelText, 'test.cto');

const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8');
const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs),
{validate: true, validateCommands: true});


const dictionary = decoratedModelManager.getType('[email protected]');
const rolodex = decoratedModelManager.getType('[email protected]');

dictionary.should.not.be.null;
dictionary.key.getDecorator('DecoratesAllMapKeys').should.not.be.null;
dictionary.value.getDecorator('DecoratesAllMapValues').should.not.be.null;

rolodex.should.not.be.null;
rolodex.key.getDecorator('DecoratesAllMapKeys').should.not.be.null;
rolodex.value.getDecorator('DecoratesAllMapValues').should.not.be.null;
});

it('should fail with invalid command', async function() {
// load a model to decorate
const testModelManager = new ModelManager({strict:true});
Expand Down Expand Up @@ -197,6 +298,20 @@ describe('DecoratorManager', () => {
{validate: true, validateCommands: true});
}).should.throw(/Decorator Command references property "test@1.0.0.Person.missing" which does not exist./);
});

it('should detect invalid target element', async function() {
// load a model to decorate
const testModelManager = new ModelManager({strict:true});
const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8');
testModelManager.addCTOModel(modelText, 'test.cto');

const dcs = fs.readFileSync('./test/data/decoratorcommands/invalid-target-element.json', 'utf-8');

(() => {
DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs),
{validate: true, validateCommands: true});
}).should.throw(/Decorator Command contains invalid target element: INVALID_ELEMENT/);
});
});

describe('#validate', function() {
Expand Down

0 comments on commit 8d5dae2

Please sign in to comment.