moddle
Advanced tools
Comparing version 0.6.3 to 0.6.4
@@ -113,3 +113,3 @@ # moddle Descriptor | ||
"name": "DomainPackage", | ||
"prefix": "d" | ||
"prefix": "d", | ||
"types": [ | ||
@@ -120,3 +120,7 @@ { | ||
"properties": [ | ||
{ "name": "id", "type": "Integer", redefines: "b:BaseWithId#id" } | ||
{ | ||
"name": "id", | ||
"type": "Integer", | ||
"redefines": "b:BaseWithId#id" | ||
} | ||
] | ||
@@ -148,2 +152,2 @@ }, | ||
Reading and writing XML from moddle is possible via [moddle-xml](https://github.com/bpmn-io/moddle-xml). It requires [additional meta-data](https://github.com/bpmn-io/moddle-xml/blob/master/docs/descriptor-xml.md) to be specified in your moddle descriptor. | ||
Reading and writing XML from moddle is possible via [moddle-xml](https://github.com/bpmn-io/moddle-xml). It requires [additional meta-data](https://github.com/bpmn-io/moddle-xml/blob/master/docs/descriptor-xml.md) to be specified in your moddle descriptor. |
@@ -17,3 +17,4 @@ 'use strict'; | ||
/** | ||
* Sets a named property on the target element | ||
* Sets a named property on the target element. | ||
* If the value is undefined, the property gets deleted. | ||
* | ||
@@ -28,10 +29,24 @@ * @param {Object} target | ||
if (!property) { | ||
target.$attrs[name] = value; | ||
var propertyName = property && property.name; | ||
if (isUndefined(value)) { | ||
// unset the property, if the specified value is undefined; | ||
// delete from $attrs (for extensions) or the target itself | ||
if (property) { | ||
delete target[propertyName]; | ||
} else { | ||
delete target.$attrs[name]; | ||
} | ||
} else { | ||
Object.defineProperty(target, property.name, { | ||
enumerable: !property.isReference, | ||
writable: true, | ||
value: value | ||
}); | ||
// set the property, defining well defined properties on the fly | ||
// or simply updating them in target.$attrs (for extensions) | ||
if (property) { | ||
if (propertyName in target) { | ||
target[propertyName] = value; | ||
} else { | ||
defineProperty(target, property, value); | ||
} | ||
} else { | ||
target.$attrs[name] = value; | ||
} | ||
} | ||
@@ -60,7 +75,3 @@ }; | ||
if (!target[propertyName] && property.isMany) { | ||
Object.defineProperty(target, propertyName, { | ||
enumerable: !property.isReference, | ||
writable: true, | ||
value: [] | ||
}); | ||
defineProperty(target, property, []); | ||
} | ||
@@ -96,2 +107,16 @@ | ||
this.define(target, '$model', { value: model }); | ||
}; | ||
}; | ||
function isUndefined(val) { | ||
return typeof val === 'undefined'; | ||
} | ||
function defineProperty(target, property, value) { | ||
Object.defineProperty(target, property.name, { | ||
enumerable: !property.isReference, | ||
writable: true, | ||
value: value, | ||
configurable: true | ||
}); | ||
} |
{ | ||
"name": "moddle", | ||
"version": "0.6.3", | ||
"version": "0.6.4", | ||
"description": "A library for importing meta-model based file formats into JS", | ||
@@ -5,0 +5,0 @@ "directories": { |
@@ -12,137 +12,114 @@ 'use strict'; | ||
describe('api', function() { | ||
it('should provide types', function() { | ||
it('should provide types', function() { | ||
// when | ||
var ComplexType = model.getType('props:Complex'); | ||
var SimpleBody = model.getType('props:SimpleBody'); | ||
var Attributes = model.getType('props:Attributes'); | ||
// given | ||
// then | ||
expect(ComplexType).to.exist; | ||
expect(SimpleBody).to.exist; | ||
expect(Attributes).to.exist; | ||
}); | ||
// when | ||
var ComplexType = model.getType('props:Complex'); | ||
var SimpleBody = model.getType('props:SimpleBody'); | ||
var Attributes = model.getType('props:Attributes'); | ||
// then | ||
expect(ComplexType).to.exist; | ||
expect(SimpleBody).to.exist; | ||
expect(Attributes).to.exist; | ||
}); | ||
it('should provide packages by prefix', function() { | ||
// when | ||
var propertiesPackage = model.getPackage('props'); | ||
it('should provide packages by prefix', function() { | ||
// then | ||
expect(propertiesPackage).to.exist; | ||
expect(propertiesPackage.name).to.equal('Properties'); | ||
expect(propertiesPackage.uri).to.equal('http://properties'); | ||
expect(propertiesPackage.prefix).to.equal('props'); | ||
}); | ||
// given | ||
// when | ||
var propertiesPackage = model.getPackage('props'); | ||
it('should provide packages by uri', function() { | ||
// then | ||
expect(propertiesPackage).to.exist; | ||
expect(propertiesPackage.name).to.equal('Properties'); | ||
expect(propertiesPackage.uri).to.equal('http://properties'); | ||
expect(propertiesPackage.prefix).to.equal('props'); | ||
}); | ||
// when | ||
var propertiesPackage = model.getPackage('http://properties'); | ||
// then | ||
expect(propertiesPackage).to.exist; | ||
expect(propertiesPackage.name).to.equal('Properties'); | ||
expect(propertiesPackage.uri).to.equal('http://properties'); | ||
expect(propertiesPackage.prefix).to.equal('props'); | ||
}); | ||
it('should provide packages by uri', function() { | ||
// given | ||
it('should provide type descriptor', function() { | ||
// when | ||
var propertiesPackage = model.getPackage('http://properties'); | ||
// given | ||
var expectedDescriptorNs = { name: 'props:Complex', prefix: 'props', localName: 'Complex' }; | ||
// then | ||
expect(propertiesPackage).to.exist; | ||
expect(propertiesPackage.name).to.equal('Properties'); | ||
expect(propertiesPackage.uri).to.equal('http://properties'); | ||
expect(propertiesPackage.prefix).to.equal('props'); | ||
}); | ||
var expectedDescriptorProperties = [ | ||
{ | ||
name: 'id', | ||
type: 'String', | ||
isAttr: true, | ||
ns: { name: 'props:id', prefix: 'props', localName: 'id' }, | ||
inherited: true | ||
} | ||
]; | ||
var expectedDescriptorPropertiesByName = { | ||
it('should provide type descriptor', function() { | ||
'id': { | ||
name: 'id', | ||
type: 'String', | ||
isAttr: true, | ||
ns: { name: 'props:id', prefix: 'props', localName: 'id' }, | ||
inherited: true | ||
}, | ||
'props:id': { | ||
name: 'id', | ||
type: 'String', | ||
isAttr: true, | ||
ns: { name: 'props:id', prefix: 'props', localName: 'id' }, | ||
inherited: true | ||
} | ||
}; | ||
// given | ||
var expectedDescriptorNs = { name: 'props:Complex', prefix: 'props', localName: 'Complex' }; | ||
// when | ||
var ComplexType = model.getType('props:Complex'); | ||
var expectedDescriptorProperties = [ | ||
{ | ||
name: 'id', | ||
type: 'String', | ||
isAttr: true, | ||
ns: { name: 'props:id', prefix: 'props', localName: 'id' }, | ||
inherited: true | ||
} | ||
]; | ||
var descriptor = model.getElementDescriptor(ComplexType); | ||
var expectedDescriptorPropertiesByName = { | ||
// then | ||
expect(descriptor).to.exist; | ||
expect(descriptor.name).to.equal('props:Complex'); | ||
'id': { | ||
name: 'id', | ||
type: 'String', | ||
isAttr: true, | ||
ns: { name: 'props:id', prefix: 'props', localName: 'id' }, | ||
inherited: true | ||
}, | ||
'props:id': { | ||
name: 'id', | ||
type: 'String', | ||
isAttr: true, | ||
ns: { name: 'props:id', prefix: 'props', localName: 'id' }, | ||
inherited: true | ||
} | ||
}; | ||
expect(descriptor.ns).to.jsonEqual(expectedDescriptorNs); | ||
expect(descriptor.properties).to.jsonEqual(expectedDescriptorProperties); | ||
expect(descriptor.propertiesByName).to.jsonEqual(expectedDescriptorPropertiesByName); | ||
}); | ||
// when | ||
var ComplexType = model.getType('props:Complex'); | ||
var descriptor = model.getElementDescriptor(ComplexType); | ||
it('should provide type descriptor via $descriptor property', function() { | ||
// then | ||
expect(descriptor).to.exist; | ||
expect(descriptor.name).to.equal('props:Complex'); | ||
// given | ||
var ComplexType = model.getType('props:Complex'); | ||
var expectedDescriptor = model.getElementDescriptor(ComplexType); | ||
expect(descriptor.ns).to.jsonEqual(expectedDescriptorNs); | ||
expect(descriptor.properties).to.jsonEqual(expectedDescriptorProperties); | ||
expect(descriptor.propertiesByName).to.jsonEqual(expectedDescriptorPropertiesByName); | ||
}); | ||
// when | ||
var descriptor = ComplexType.$descriptor; | ||
// then | ||
expect(descriptor).to.equal(expectedDescriptor); | ||
}); | ||
it('should provide type descriptor via $descriptor property', function() { | ||
// given | ||
var ComplexType = model.getType('props:Complex'); | ||
var expectedDescriptor = model.getElementDescriptor(ComplexType); | ||
it('should provide model via $model property', function() { | ||
// when | ||
var descriptor = ComplexType.$descriptor; | ||
// given | ||
var ComplexType = model.getType('props:Complex'); | ||
// then | ||
expect(descriptor).to.equal(expectedDescriptor); | ||
}); | ||
// when | ||
var foundModel = ComplexType.$model; | ||
it('should provide model via $model property', function() { | ||
// given | ||
var ComplexType = model.getType('props:Complex'); | ||
// when | ||
var foundModel = ComplexType.$model; | ||
// then | ||
expect(foundModel).to.equal(model); | ||
}); | ||
describe('instance', function() { | ||
it('should query types via $instanceOf', function() { | ||
// given | ||
var instance = model.create('props:BaseWithNumericId'); | ||
// then | ||
expect(instance.$instanceOf('props:BaseWithNumericId')).to.equal(true); | ||
expect(instance.$instanceOf('props:Base')).to.equal(true); | ||
}); | ||
}); | ||
// then | ||
expect(foundModel).to.equal(model); | ||
}); | ||
@@ -154,3 +131,2 @@ | ||
it('should provide meta-data', function() { | ||
// given | ||
@@ -171,3 +147,2 @@ // when | ||
it('should provide attrs + basic meta-data', function() { | ||
// given | ||
@@ -188,3 +163,2 @@ // when | ||
it('should provide ns meta-data', function() { | ||
// given | ||
@@ -207,27 +181,14 @@ // when | ||
describe('base', function() { | ||
describe('getType', function() { | ||
it('should provide type in instance', function() { | ||
it('should provide instantiatable type', function() { | ||
// given | ||
var SimpleBody = model.getType('props:SimpleBody'); | ||
// when | ||
var instance = new SimpleBody(); | ||
// then | ||
expect(instance.$type).to.equal('props:SimpleBody'); | ||
}); | ||
it('should provide type descriptor in instance', function() { | ||
// given | ||
var SimpleBody = model.getType('props:SimpleBody'); | ||
// when | ||
var instance = new SimpleBody(); | ||
var instance = new SimpleBody({ body: 'BAR' }); | ||
// then | ||
expect(instance.$descriptor).to.eql(SimpleBody.$descriptor); | ||
expect(instance instanceof SimpleBody).to.be.true; | ||
expect(instance.body).to.eql('BAR'); | ||
}); | ||
@@ -238,243 +199,38 @@ | ||
describe('properties', function() { | ||
describe('instance', function() { | ||
describe('descriptor', function() { | ||
it('should query types via $instanceOf', function() { | ||
it('should provide default id', function() { | ||
// given | ||
var instance = model.create('props:BaseWithNumericId'); | ||
// given | ||
// when | ||
var SimpleBody = model.getType('props:SimpleBody'); | ||
var descriptor = model.getElementDescriptor(SimpleBody); | ||
var idProperty = descriptor.propertiesByName['id']; | ||
// then | ||
expect(idProperty).to.exist; | ||
expect(descriptor.properties.indexOf(idProperty)).to.equal(0); | ||
}); | ||
xit('should inherit properties'); | ||
// then | ||
expect(instance.$instanceOf('props:BaseWithNumericId')).to.equal(true); | ||
expect(instance.$instanceOf('props:Base')).to.equal(true); | ||
}); | ||
describe('instance', function() { | ||
it('should provide $type in instance', function() { | ||
it('should set simple properties in constructor', function() { | ||
// given | ||
var SimpleBody = model.getType('props:SimpleBody'); | ||
// given | ||
// when | ||
var instance = new SimpleBody(); | ||
// when | ||
var attributes = model.create('props:Attributes', { id: 'ATTR_1', booleanValue: false, integerValue: -1000 }); | ||
// then | ||
// expect constructor to have set values | ||
expect(attributes.id).to.equal('ATTR_1'); | ||
expect(attributes.booleanValue).to.equal(false); | ||
expect(attributes.integerValue).to.equal(-1000); | ||
}); | ||
it('should set collection properties in constructor (referencing)', function() { | ||
// given | ||
// given | ||
var reference1 = model.create('props:ComplexCount'); | ||
var reference2 = model.create('props:ComplexNesting'); | ||
// when | ||
var referencingCollection = model.create('props:ReferencingCollection', { | ||
references: [ reference1, reference2 ] | ||
}); | ||
// then | ||
expect(referencingCollection.references).to.jsonEqual([ reference1, reference2 ]); | ||
// TODO: validate not parent -> child relationship | ||
}); | ||
it('should set collection properties in constructor (containment)', function() { | ||
// given | ||
var child1 = model.create('props:ComplexCount'); | ||
var child2 = model.create('props:ComplexNesting'); | ||
// when | ||
var containedCollection = model.create('props:ContainedCollection', { | ||
children: [ child1, child2 ] | ||
}); | ||
// then | ||
expect(containedCollection.children).to.jsonEqual([ child1, child2 ]); | ||
// TODO: establish parent relationship | ||
}); | ||
it('should provide default values', function() { | ||
// given | ||
var Attributes = model.getType('props:Attributes'); | ||
// when | ||
var instance = new Attributes(); | ||
// then | ||
expect(instance.defaultBooleanValue).to.equal(true); | ||
}); | ||
it('should provide inherited default values', function() { | ||
// given | ||
var SubAttributes = model.getType('props:SubAttributes'); | ||
// when | ||
var instance = new SubAttributes(); | ||
// then | ||
expect(instance.defaultBooleanValue).to.equal(true); | ||
}); | ||
xit('should set collection properties in constructor'); | ||
it('should lazy init collection properties', function() { | ||
// given | ||
var Root = model.getType('props:Root'); | ||
var instance = new Root(); | ||
// assume | ||
expect(instance.any).not.to.exist; | ||
// when | ||
var any = instance.get('props:any'); | ||
// then | ||
expect(any).to.eql([]); | ||
expect(instance.any).to.equal(any); | ||
}); | ||
it('should set single property', function() { | ||
// given | ||
var Attributes = model.getType('props:Attributes'); | ||
var instance = new Attributes(); | ||
// when | ||
instance.set('id', 'ATTR_1'); | ||
// then | ||
expect(instance.id).to.equal('ATTR_1'); | ||
}); | ||
it('should set single property (ns)', function() { | ||
// given | ||
var Attributes = model.getType('props:Attributes'); | ||
var instance = new Attributes(); | ||
// when | ||
instance.set('props:booleanValue', true); | ||
instance.set('props:integerValue', -1000); | ||
// then | ||
expect(instance.booleanValue).to.equal(true); | ||
expect(instance.integerValue).to.equal(-1000); | ||
}); | ||
// then | ||
expect(instance.$type).to.equal('props:SimpleBody'); | ||
}); | ||
describe('should redefine property', function() { | ||
it('should provide $descriptor in instance', function() { | ||
it('descriptor', function() { | ||
// given | ||
var SimpleBody = model.getType('props:SimpleBody'); | ||
// given | ||
// when | ||
var instance = new SimpleBody(); | ||
// when | ||
var BaseWithId = model.getType('props:BaseWithId'); | ||
var BaseWithNumericId = model.getType('props:BaseWithNumericId'); | ||
var baseDescriptor = BaseWithId.$descriptor; | ||
var redefinedDescriptor = BaseWithNumericId.$descriptor; | ||
var originalIdProperty = baseDescriptor.propertiesByName['id']; | ||
var refinedIdProperty = redefinedDescriptor.propertiesByName['id']; | ||
var numericIdProperty = redefinedDescriptor.propertiesByName['idNumeric']; | ||
// then | ||
expect(refinedIdProperty).not.to.jsonEqual(originalIdProperty); | ||
expect(refinedIdProperty).to.exist; | ||
expect(refinedIdProperty).to.eql(numericIdProperty); | ||
}); | ||
describe('instance', function() { | ||
it('init in constructor', function() { | ||
// given | ||
var BaseWithNumericId = model.getType('props:BaseWithNumericId'); | ||
// when | ||
var instance = new BaseWithNumericId({ 'id': 1000 }); | ||
// then | ||
expect(instance.idNumeric).to.equal(1000); | ||
}); | ||
it('access via original name', function() { | ||
// given | ||
var BaseWithNumericId = model.getType('props:BaseWithNumericId'); | ||
// when | ||
var instance = new BaseWithNumericId({ 'id': 1000 }); | ||
// then | ||
expect(instance.get('props:id')).to.equal(1000); | ||
}); | ||
it('should return $attrs property on non-metamodel defined property access', function() { | ||
// given | ||
var BaseWithNumericId = model.getType('props:BaseWithNumericId'); | ||
// when | ||
var instance = new BaseWithNumericId({ 'id': 1000 }); | ||
instance.$attrs.unknown = 'UNKNOWN'; | ||
// then | ||
expect(instance.get('unknown')).to.eql('UNKNOWN'); | ||
}); | ||
it('access via original name', function() { | ||
// given | ||
var BaseWithNumericId = model.getType('props:BaseWithNumericId'); | ||
// when | ||
var instance = new BaseWithNumericId({ 'id': 1000 }); | ||
// then | ||
expect(instance.get('props:idNumeric')).to.equal(1000); | ||
}); | ||
}); | ||
// then | ||
expect(instance.$descriptor).to.eql(SimpleBody.$descriptor); | ||
}); | ||
@@ -481,0 +237,0 @@ |
'use strict'; | ||
var Helper = require('../helper'); | ||
var ns = require('../../lib/ns'); | ||
@@ -6,0 +4,0 @@ |
'use strict'; | ||
var Helper = require('../helper'); | ||
var Types = require('../../lib/types'); | ||
@@ -6,0 +4,0 @@ |
60220
34
1699