Files
GDevelop/GDevelop.js/__tests__/Core.js
T
2020-07-25 14:23:00 +01:00

3405 lines
120 KiB
JavaScript

const initializeGDevelopJs = require('../../Binaries/embuild/GDevelop.js/libGD.js');
const path = require('path');
const extend = require('extend');
describe('libGD.js', function() {
let gd = null;
beforeAll(done =>
initializeGDevelopJs().then(module => {
gd = module;
done();
})
);
describe('gd.VersionWrapper', function() {
it('can return the version number of the library', function() {
expect(typeof gd.VersionWrapper.major()).toBe('number');
expect(typeof gd.VersionWrapper.minor()).toBe('number');
expect(typeof gd.VersionWrapper.build()).toBe('number');
expect(typeof gd.VersionWrapper.revision()).toBe('number');
expect(typeof gd.VersionWrapper.fullString()).toBe('string');
});
});
describe('gd.Project', function() {
let project = null;
beforeAll(() => (project = gd.ProjectHelper.createNewGDJSProject()));
it('has properties that can be read and changed', function() {
project.setName('My super project');
expect(project.getName()).toBe('My super project');
project.setVersion('1.2.34');
expect(project.getVersion()).toBe('1.2.34');
project.setPackageName('com.test.package');
expect(project.getPackageName()).toBe('com.test.package');
project.setOrientation('portrait');
expect(project.getOrientation()).toBe('portrait');
project.setOrientation('landscape');
expect(project.getOrientation()).toBe('landscape');
project.setAuthor('Me');
expect(project.getAuthor()).toBe('Me');
project.setMaximumFPS(15);
expect(project.getMaximumFPS()).toBe(15);
project.setMinimumFPS(15);
expect(project.getMinimumFPS()).toBe(15);
project.setFolderProject(true);
expect(project.isFolderProject()).toBe(true);
project.setFolderProject(false);
expect(project.isFolderProject()).toBe(false);
});
it('can store loading screen setup', function() {
project.getLoadingScreen().showGDevelopSplash(true);
expect(project.getLoadingScreen().isGDevelopSplashShown()).toBe(true);
project.getLoadingScreen().showGDevelopSplash(false);
expect(project.getLoadingScreen().isGDevelopSplashShown()).toBe(false);
});
it('handles layouts', function() {
expect(project.hasLayoutNamed('Scene')).toBe(false);
project.insertNewLayout('Scene', 0);
expect(project.hasLayoutNamed('Scene')).toBe(true);
expect(project.getLayout('Scene').getName()).toBe('Scene');
project.removeLayout('Scene');
expect(project.hasLayoutNamed('Scene')).toBe(false);
});
it('handles external events', function() {
expect(project.hasExternalEventsNamed('My events')).toBe(false);
project.insertNewExternalEvents('My events', 0);
expect(project.hasExternalEventsNamed('My events')).toBe(true);
expect(project.getExternalEvents('My events').getName()).toBe(
'My events'
);
project.removeExternalEvents('My events');
expect(project.hasExternalEventsNamed('My events')).toBe(false);
});
it('handles external layouts', function() {
expect(project.hasExternalLayoutNamed('My layout')).toBe(false);
project.insertNewExternalLayout('My layout', 0);
expect(project.hasExternalLayoutNamed('My layout')).toBe(true);
expect(project.getExternalLayout('My layout').getName()).toBe(
'My layout'
);
project.removeExternalLayout('My layout');
expect(project.hasExternalLayoutNamed('My layout')).toBe(false);
});
it('should validate object names', function() {
expect(gd.Project.validateName('ThisNameIs_Ok_123')).toBe(true);
expect(gd.Project.validateName('ThisName IsNot_Ok_123')).toBe(
false
);
expect(gd.Project.validateName('ThisNameIsNot_Ok!')).toBe(false);
});
it('should have a list of extensions', function() {
expect(typeof project.getUsedExtensions().size()).toBe('number');
project.getUsedExtensions().clear();
expect(project.getUsedExtensions().size()).toBe(0);
});
it('handles events functions extensions', function() {
expect(project.hasEventsFunctionsExtensionNamed('Ext')).toBe(false);
project.insertNewEventsFunctionsExtension('Ext', 0);
expect(project.hasEventsFunctionsExtensionNamed('Ext')).toBe(true);
expect(project.getEventsFunctionsExtension('Ext').getName()).toBe('Ext');
project.removeEventsFunctionsExtension('Ext');
expect(project.hasEventsFunctionsExtensionNamed('Ext')).toBe(false);
});
afterAll(function() {
project.delete();
});
});
describe('gd.Layout', function() {
let project = null;
let layout = null;
beforeAll(() => {
project = gd.ProjectHelper.createNewGDJSProject();
layout = project.insertNewLayout('Scene', 0);
});
it('can have a new name', function() {
expect(layout.getName()).toBe('Scene');
layout.setName('My super layout');
expect(layout.getName()).toBe('My super layout');
});
it('can have a name with UTF8 characters', function() {
layout.setName('Scene with a 官话 name');
expect(layout.getName()).toBe('Scene with a 官话 name');
});
it('can store events', function() {
var evts = layout.getEvents();
expect(evts.getEventsCount()).toBe(0);
var evt = evts.insertNewEvent(
project,
'BuiltinCommonInstructions::Standard',
0
);
expect(evts.getEventsCount()).toBe(1);
evt
.getSubEvents()
.insertNewEvent(project, 'BuiltinCommonInstructions::Standard', 0);
expect(
evts
.getEventAt(0)
.getSubEvents()
.getEventsCount()
).toBe(1);
});
it('can have objects', function() {
var object = layout.insertNewObject(project, 'Sprite', 'MyObject', 0);
var object2 = layout.insertNewObject(
project,
'TextObject::Text',
'MyObject2',
1
);
expect(layout.getObjectAt(0).ptr).toBe(object.ptr);
expect(layout.getObjectAt(1).ptr).toBe(object2.ptr);
expect(layout.getObjectAt(0).getType()).toBe('Sprite');
expect(layout.getObjectAt(1).getType()).toBe('TextObject::Text');
});
afterAll(function() {
project.delete();
});
});
describe('gd.Layer', function() {
it('can have a name and visibility', function() {
const layer = new gd.Layer();
layer.setName('GUI');
layer.setVisibility(false);
expect(layer.getName()).toBe('GUI');
expect(layer.getVisibility()).toBe(false);
layer.delete();
});
it('can have effects', function() {
const layer = new gd.Layer();
expect(layer.hasEffectNamed('EffectThatDoesNotExist')).toBe(false);
expect(layer.getEffectsCount()).toBe(0);
layer.insertNewEffect('MyEffect', 0);
expect(layer.hasEffectNamed('EffectThatDoesNotExist')).toBe(false);
expect(layer.hasEffectNamed('MyEffect')).toBe(true);
expect(layer.getEffectsCount()).toBe(1);
expect(layer.getEffectPosition('MyEffect')).toBe(0);
const effect2 = new gd.Effect();
effect2.setName('MyEffect2');
layer.insertEffect(effect2, 1);
expect(layer.hasEffectNamed('MyEffect2')).toBe(true);
expect(layer.getEffectsCount()).toBe(2);
expect(layer.getEffectPosition('MyEffect')).toBe(0);
expect(layer.getEffectPosition('MyEffect2')).toBe(1);
layer.swapEffects(0, 1);
expect(layer.getEffectPosition('MyEffect2')).toBe(0);
expect(layer.getEffectPosition('MyEffect')).toBe(1);
layer.delete();
});
});
describe('gd.Effect', function() {
it('can have a name, effect name and parameters', function() {
const effect = new gd.Effect();
effect.setName('MyEffect');
effect.setEffectType('Sepia');
expect(effect.getName()).toBe('MyEffect');
expect(effect.getEffectType()).toBe('Sepia');
effect.setDoubleParameter('Brightness', 1);
effect.setDoubleParameter('Darkness', 0.3);
effect.setDoubleParameter('Param3', 6);
expect(
effect
.getAllDoubleParameters()
.keys()
.size()
).toBe(3);
expect(effect.getDoubleParameter('Brightness')).toBe(1);
expect(effect.getDoubleParameter('Darkness')).toBe(0.3);
expect(effect.getDoubleParameter('Param3')).toBe(6);
effect.setStringParameter('SomeImage', 'myImageResource');
expect(effect.getStringParameter('SomeImage')).toBe('myImageResource');
expect(
effect
.getAllStringParameters()
.keys()
.size()
).toBe(1);
effect.setBooleanParameter('SomeBoolean', true);
expect(effect.getBooleanParameter('SomeBoolean')).toBe(true);
effect.setBooleanParameter('SomeBoolean', false);
expect(effect.getBooleanParameter('SomeBoolean')).toBe(false);
expect(
effect
.getAllBooleanParameters()
.keys()
.size()
).toBe(1);
effect.delete();
});
});
describe('gd.ObjectsContainer (using gd.Layout)', function() {
let project = null;
beforeAll(() => (project = gd.ProjectHelper.createNewGDJSProject()));
it('can move objects', function() {
var layout = project.insertNewLayout('Scene', 0);
var object = layout.insertNewObject(project, 'Sprite', 'MyObject', 0);
var object2 = layout.insertNewObject(
project,
'TextObject::Text',
'MyObject2',
1
);
var object3 = layout.insertNewObject(
project,
'TextObject::Text',
'MyObject3',
2
);
expect(layout.getObjectAt(0).getName()).toBe('MyObject');
expect(layout.getObjectAt(1).getName()).toBe('MyObject2');
expect(layout.getObjectAt(2).getName()).toBe('MyObject3');
layout.moveObject(0, 2);
expect(layout.getObjectAt(0).getName()).toBe('MyObject2');
expect(layout.getObjectAt(1).getName()).toBe('MyObject3');
expect(layout.getObjectAt(2).getName()).toBe('MyObject');
layout.moveObject(0, 0);
expect(layout.getObjectAt(0).getName()).toBe('MyObject2');
expect(layout.getObjectAt(1).getName()).toBe('MyObject3');
expect(layout.getObjectAt(2).getName()).toBe('MyObject');
layout.moveObject(1, 0);
expect(layout.getObjectAt(0).getName()).toBe('MyObject3');
expect(layout.getObjectAt(1).getName()).toBe('MyObject2');
expect(layout.getObjectAt(2).getName()).toBe('MyObject');
layout.moveObject(0, 999);
expect(layout.getObjectAt(0).getName()).toBe('MyObject3');
expect(layout.getObjectAt(1).getName()).toBe('MyObject2');
expect(layout.getObjectAt(2).getName()).toBe('MyObject');
});
it('can find position of objects', function() {
var layout = project.insertNewLayout('Scene2', 0);
var object = layout.insertNewObject(project, 'Sprite', 'MyObject', 0);
var object2 = layout.insertNewObject(
project,
'TextObject::Text',
'MyObject2',
1
);
var object3 = layout.insertNewObject(
project,
'TextObject::Text',
'MyObject3',
2
);
expect(layout.getObjectPosition('MyObject')).toBe(0);
expect(layout.getObjectPosition('MyObject2')).toBe(1);
expect(layout.getObjectPosition('MyObject3')).toBe(2);
expect(layout.getObjectPosition('MyObject4')).toBe(-1);
});
afterAll(function() {
project.delete();
});
});
describe('gd.ObjectsContainer', function() {
it('can move objects between containers, without moving them in memory', function() {
// Prepare two containers, one with 3 objects and one empty
const objectsContainer1 = new gd.ObjectsContainer();
const objectsContainer2 = new gd.ObjectsContainer();
const mySpriteObject = new gd.SpriteObject('MySprite');
const mySprite2Object = new gd.SpriteObject('MySprite2');
const mySprite3Object = new gd.SpriteObject('MySprite3');
objectsContainer1.insertObject(mySpriteObject, 0);
objectsContainer1.insertObject(mySprite2Object, 1);
objectsContainer1.insertObject(mySprite3Object, 2);
// Objects are copied when inserted in the container, so we delete them:
mySpriteObject.delete();
mySprite2Object.delete();
mySprite3Object.delete();
// Find the pointer to the objects in memory
expect(objectsContainer1.getObjectsCount()).toBe(3);
expect(objectsContainer2.getObjectsCount()).toBe(0);
const mySpriteObjectPtr = gd.getPointer(objectsContainer1.getObjectAt(0));
const mySprite2ObjectPtr = gd.getPointer(
objectsContainer1.getObjectAt(1)
);
const mySprite3ObjectPtr = gd.getPointer(
objectsContainer1.getObjectAt(2)
);
// Move objects between containers
objectsContainer1.moveObjectToAnotherContainer(
'MySprite2',
objectsContainer2,
0
);
expect(objectsContainer1.getObjectsCount()).toBe(2);
expect(objectsContainer1.getObjectAt(0).getName()).toBe('MySprite');
expect(objectsContainer1.getObjectAt(1).getName()).toBe('MySprite3');
expect(objectsContainer2.getObjectsCount()).toBe(1);
expect(objectsContainer2.getObjectAt(0).getName()).toBe('MySprite2');
objectsContainer1.moveObjectToAnotherContainer(
'MySprite3',
objectsContainer2,
1
);
expect(objectsContainer1.getObjectsCount()).toBe(1);
expect(objectsContainer1.getObjectAt(0).getName()).toBe('MySprite');
expect(objectsContainer2.getObjectsCount()).toBe(2);
expect(objectsContainer2.getObjectAt(0).getName()).toBe('MySprite2');
expect(objectsContainer2.getObjectAt(1).getName()).toBe('MySprite3');
// Check that the object in memory are the same, even if moved to another container
expect(gd.getPointer(objectsContainer1.getObjectAt(0))).toBe(
mySpriteObjectPtr
);
expect(gd.getPointer(objectsContainer2.getObjectAt(0))).toBe(
mySprite2ObjectPtr
);
expect(gd.getPointer(objectsContainer2.getObjectAt(1))).toBe(
mySprite3ObjectPtr
);
objectsContainer2.moveObjectToAnotherContainer(
'MySprite2',
objectsContainer1,
0
);
expect(objectsContainer1.getObjectsCount()).toBe(2);
expect(objectsContainer1.getObjectAt(0).getName()).toBe('MySprite2');
expect(objectsContainer1.getObjectAt(1).getName()).toBe('MySprite');
expect(objectsContainer2.getObjectsCount()).toBe(1);
expect(objectsContainer2.getObjectAt(0).getName()).toBe('MySprite3');
// Check again that the object in memory are the same, even if moved to another container
expect(gd.getPointer(objectsContainer1.getObjectAt(0))).toBe(
mySprite2ObjectPtr
);
expect(gd.getPointer(objectsContainer1.getObjectAt(1))).toBe(
mySpriteObjectPtr
);
expect(gd.getPointer(objectsContainer2.getObjectAt(0))).toBe(
mySprite3ObjectPtr
);
});
});
describe('gd.InitialInstancesContainer', function() {
let container = null;
let containerCopy = null;
beforeAll(() => {
container = new gd.InitialInstancesContainer();
});
it('initial state', function() {
expect(container.getInstancesCount()).toBe(0);
});
it('adding instances', function() {
var instance = container.insertNewInitialInstance();
instance.setObjectName('MyObject1');
instance.setZOrder(10);
var instance2 = new gd.InitialInstance();
instance2.setObjectName('MyObject2');
instance2 = container.insertInitialInstance(instance2);
var instance3 = container.insertNewInitialInstance();
instance3.setObjectName('MyObject3');
instance3.setZOrder(-1);
instance3.setLayer('OtherLayer');
expect(container.getInstancesCount()).toBe(3);
});
it('iterating', function() {
var i = 0;
var functor = new gd.InitialInstanceJSFunctor();
functor.invoke = function(instance) {
instance = gd.wrapPointer(instance, gd.InitialInstance);
expect(
(i === 0 && instance.getObjectName() === 'MyObject1') ||
(i === 1 && instance.getObjectName() === 'MyObject2') ||
(i === 2 && instance.getObjectName() === 'MyObject3')
).toBe(true);
i++;
};
container.iterateOverInstances(functor);
});
it('can rename instances', function() {
container.renameInstancesOfObject('MyObject1', 'MyObject');
var i = 0;
var functor = new gd.InitialInstanceJSFunctor();
functor.invoke = function(instance) {
instance = gd.wrapPointer(instance, gd.InitialInstance);
expect(
(i === 0 && instance.getObjectName() === 'MyObject') ||
(i === 1 && instance.getObjectName() === 'MyObject2') ||
(i === 2 && instance.getObjectName() === 'MyObject3')
).toBe(true);
i++;
};
container.iterateOverInstances(functor);
});
it('iterating with z ordering', function() {
var i = 0;
var functor = new gd.InitialInstanceJSFunctor();
functor.invoke = function(instance) {
instance = gd.wrapPointer(instance, gd.InitialInstance);
expect(
(i === 0 && instance.getObjectName() === 'MyObject2') ||
(i === 1 && instance.getObjectName() === 'MyObject')
).toBe(true);
i++;
};
container.iterateOverInstancesWithZOrdering(functor, '');
});
it('moving from layers to another', function() {
container.moveInstancesToLayer('OtherLayer', 'YetAnotherLayer');
var functor = new gd.InitialInstanceJSFunctor();
functor.invoke = function(instance) {
instance = gd.wrapPointer(instance, gd.InitialInstance);
expect(instance.getObjectName()).toBe('MyObject3');
};
container.iterateOverInstancesWithZOrdering(functor, 'YetAnotherLayer');
});
it('can be cloned', function() {
containerCopy = container.clone();
expect(containerCopy.getInstancesCount()).toBe(3);
var instance = containerCopy.insertNewInitialInstance();
instance.setObjectName('MyObject4');
expect(containerCopy.getInstancesCount()).toBe(4);
expect(container.getInstancesCount()).toBe(3);
containerCopy.delete();
containerCopy = null;
});
it('removing instances', function() {
container.removeInitialInstancesOfObject('MyObject');
expect(container.getInstancesCount()).toBe(2);
});
it('removing instances on a layer', function() {
container.removeAllInstancesOnLayer('YetAnotherLayer');
expect(container.getInstancesCount()).toBe(1);
});
it('can be serialized', function() {
expect(container.serializeTo).not.toBe(undefined);
expect(container.unserializeFrom).not.toBe(undefined);
});
afterAll(function() {
container.delete();
});
});
describe('gd.InitialInstance', function() {
let project = null;
let layout = null;
let initialInstance = null;
beforeAll(() => {
project = gd.ProjectHelper.createNewGDJSProject();
layout = project.insertNewLayout('Scene', 0);
layout.insertNewObject(project, 'Sprite', 'MySpriteObject', 0);
initialInstance = layout.getInitialInstances().insertNewInitialInstance();
});
it('properties', function() {
initialInstance.setObjectName('MySpriteObject');
expect(initialInstance.getObjectName()).toBe('MySpriteObject');
initialInstance.setX(150);
expect(initialInstance.getX()).toBe(150);
initialInstance.setY(140);
expect(initialInstance.getY()).toBe(140);
initialInstance.setAngle(45);
expect(initialInstance.getAngle()).toBe(45);
initialInstance.setZOrder(12);
expect(initialInstance.getZOrder()).toBe(12);
initialInstance.setLayer('MyLayer');
expect(initialInstance.getLayer()).toBe('MyLayer');
initialInstance.setLocked(true);
expect(initialInstance.isLocked()).toBe(true);
initialInstance.setHasCustomSize(true);
expect(initialInstance.hasCustomSize()).toBe(true);
initialInstance.setCustomWidth(34);
expect(initialInstance.getCustomWidth()).toBe(34);
initialInstance.setCustomHeight(30);
expect(initialInstance.getCustomHeight()).toBe(30);
});
it('Sprite object custom properties', function() {
initialInstance.updateCustomProperty('Animation', '2', project, layout);
expect(
initialInstance
.getCustomProperties(project, layout)
.get('Animation')
.getValue()
).toBe('2');
expect(initialInstance.getRawFloatProperty('animation')).toBe(2);
});
it('can be serialized', function() {
expect(initialInstance.serializeTo).not.toBe(undefined);
expect(initialInstance.unserializeFrom).not.toBe(undefined);
var element = new gd.SerializerElement();
initialInstance.serializeTo(element);
var initialInstance2 = layout
.getInitialInstances()
.insertNewInitialInstance();
initialInstance2.unserializeFrom(element);
expect(initialInstance2.getObjectName()).toBe('MySpriteObject');
expect(initialInstance2.getX()).toBe(150);
expect(initialInstance2.getY()).toBe(140);
expect(initialInstance2.getAngle()).toBe(45);
expect(initialInstance2.getZOrder()).toBe(12);
expect(initialInstance2.getLayer()).toBe('MyLayer');
expect(initialInstance2.isLocked()).toBe(true);
expect(initialInstance2.hasCustomSize()).toBe(true);
expect(initialInstance2.getCustomWidth()).toBe(34);
expect(initialInstance2.getCustomHeight()).toBe(30);
});
it('can be serialized with a persistent UUID called persistentUuid', function() {
const initialInstance = new gd.InitialInstance();
initialInstance.setObjectName("MyObject");
// Serialized object must have a non empty "persistentUuid".
var element = new gd.SerializerElement();
initialInstance.serializeTo(element);
const persistentUuid = element.getStringAttribute("persistentUuid");
expect(persistentUuid).toBeTruthy();
// The UUID must persist across serializations.
const initialInstance2 = new gd.InitialInstance();
initialInstance2.unserializeFrom(element);
var element2 = new gd.SerializerElement();
initialInstance.serializeTo(element2);
const persistentUuid2 = element2.getStringAttribute("persistentUuid");
expect(persistentUuid2).toBe(persistentUuid);
// The UUID can be reset
initialInstance2.resetPersistentUuid();
var element3 = new gd.SerializerElement();
initialInstance2.serializeTo(element3);
const persistentUuid3 = element3.getStringAttribute("persistentUuid");
expect(persistentUuid3).not.toBe(persistentUuid2);
element.delete();
element2.delete();
element3.delete();
initialInstance.delete();
initialInstance2.delete();
});
afterAll(function() {
project.delete();
});
});
describe('gd.VariablesContainer', function() {
it('container is empty after being created', function() {
var container = new gd.VariablesContainer();
expect(container.has('Variable')).toBe(false);
expect(container.count()).toBe(0);
container.delete();
});
it('can insert variables', function() {
var container = new gd.VariablesContainer();
container.insertNew('Variable', 0);
expect(container.has('Variable')).toBe(true);
expect(container.count()).toBe(1);
container.insertNew('SecondVariable', 0);
expect(container.has('SecondVariable')).toBe(true);
expect(container.count()).toBe(2);
container.delete();
});
it('can rename variables', function() {
var container = new gd.VariablesContainer();
container.insertNew('Variable', 0);
container
.insertNew('SecondVariable', 0)
.setString('String of SecondVariable');
container.insertNew('ThirdVariable', 0);
expect(container.has('SecondVariable')).toBe(true);
expect(container.has('NewName')).toBe(false);
container.rename('SecondVariable', 'NewName');
expect(container.has('SecondVariable')).toBe(false);
expect(container.has('NewName')).toBe(true);
expect(container.get('NewName').getString()).toBe(
'String of SecondVariable'
);
container.delete();
});
it('can swap variables', function() {
var container = new gd.VariablesContainer();
container.insertNew('Variable', 0).setValue(4);
container
.insertNew('SecondVariable', 1)
.setString('String of SecondVariable');
container
.insertNew('ThirdVariable', 2)
.getChild('Child1')
.setValue(7);
expect(container.getNameAt(0)).toBe('Variable');
expect(container.getNameAt(2)).toBe('ThirdVariable');
container.swap(0, 2);
expect(container.getNameAt(0)).toBe('ThirdVariable');
expect(container.getNameAt(2)).toBe('Variable');
expect(container.getAt(2).getValue()).toBe(4);
container.delete();
});
it('can move variables', function() {
var container = new gd.VariablesContainer();
container.insertNew('Variable', 0).setValue(4);
container
.insertNew('SecondVariable', 1)
.setString('String of SecondVariable');
container
.insertNew('ThirdVariable', 2)
.getChild('Child1')
.setValue(7);
container.move(1, 2);
expect(container.getNameAt(0)).toBe('Variable');
expect(container.getNameAt(1)).toBe('ThirdVariable');
expect(container.getNameAt(2)).toBe('SecondVariable');
container.move(1, 9999);
expect(container.getNameAt(0)).toBe('Variable');
expect(container.getNameAt(1)).toBe('ThirdVariable');
expect(container.getNameAt(2)).toBe('SecondVariable');
container.move(2, 0);
expect(container.getNameAt(0)).toBe('SecondVariable');
expect(container.getNameAt(1)).toBe('Variable');
expect(container.getNameAt(2)).toBe('ThirdVariable');
container.delete();
});
});
describe('gd.Variable', function() {
let variable = null;
beforeAll(() => (variable = new gd.Variable()));
it('should have initial value', function() {
expect(variable.getValue()).toBe(0);
expect(variable.isNumber()).toBe(true);
});
it('can have a value', function() {
variable.setValue(5);
expect(variable.getValue()).toBe(5);
expect(variable.isNumber()).toBe(true);
});
it('can have a string', function() {
variable.setString('Hello');
expect(variable.getString()).toBe('Hello');
expect(variable.isNumber()).toBe(false);
});
it('can be a structure', function() {
variable.getChild('FirstChild').setValue(1);
variable.getChild('SecondChild').setString('two');
expect(variable.hasChild('FirstChild')).toBe(true);
expect(variable.hasChild('SecondChild')).toBe(true);
expect(variable.hasChild('NotExisting')).toBe(false);
expect(variable.getChild('SecondChild').getString()).toBe('two');
variable.removeChild('FirstChild');
expect(variable.hasChild('FirstChild')).toBe(false);
});
it('can expose its children', function() {
variable.getChild('FirstChild').setValue(1);
var childrenNames = variable.getAllChildrenNames();
expect(childrenNames.size()).toBe(2);
variable.getChild(childrenNames.get(0)).setString('one');
variable.getChild(childrenNames.get(1)).setValue(2);
expect(variable.getChild('FirstChild').getString()).toBe('one');
expect(variable.getChild('SecondChild').getValue()).toBe(2);
expect(childrenNames.size()).toBe(2);
});
it('can search inside children and remove them recursively', function() {
var parentVariable = new gd.Variable();
var child1 = parentVariable.getChild('Child1');
var child2 = parentVariable.getChild('Child2');
var grandChild = parentVariable.getChild('Child1').getChild('GrandChild');
expect(parentVariable.contains(grandChild, true)).toBe(true);
expect(parentVariable.contains(grandChild, false)).toBe(false);
expect(parentVariable.contains(child1, true)).toBe(true);
expect(parentVariable.contains(child2, true)).toBe(true);
expect(parentVariable.contains(child1, false)).toBe(true);
expect(parentVariable.contains(child2, false)).toBe(true);
expect(child1.contains(grandChild, true)).toBe(true);
expect(child1.contains(grandChild, false)).toBe(true);
expect(child2.contains(grandChild, true)).toBe(false);
expect(child2.contains(grandChild, false)).toBe(false);
expect(grandChild.contains(grandChild, true)).toBe(false);
expect(grandChild.contains(grandChild, false)).toBe(false);
expect(grandChild.contains(child1, true)).toBe(false);
expect(grandChild.contains(child2, true)).toBe(false);
expect(grandChild.contains(parentVariable, true)).toBe(false);
expect(grandChild.contains(child1, false)).toBe(false);
expect(grandChild.contains(child2, false)).toBe(false);
expect(grandChild.contains(parentVariable, false)).toBe(false);
parentVariable.removeRecursively(grandChild);
expect(child1.hasChild('GrandChild')).toBe(false);
expect(child1.getChildrenCount()).toBe(0);
expect(parentVariable.getChildrenCount()).toBe(2);
parentVariable.removeRecursively(child2);
expect(parentVariable.getChildrenCount()).toBe(1);
expect(parentVariable.hasChild('Child1')).toBe(true);
expect(parentVariable.hasChild('Child2')).toBe(false);
parentVariable.delete();
});
afterAll(function() {
variable.delete();
});
});
describe('gd.ImageResource', function() {
it('should have name and file', function() {
const resource = new gd.ImageResource();
resource.setName('MyResource');
resource.setFile('MyFile');
expect(resource.getName()).toBe('MyResource');
expect(resource.getFile()).toBe('MyFile');
resource.delete();
});
it('can have metadata', function() {
const resource = new gd.ImageResource();
expect(resource.getMetadata()).toBe('');
resource.setMetadata(JSON.stringify({ hello: 'world' }));
expect(resource.getMetadata()).toBe('{"hello":"world"}');
resource.delete();
});
it('has smooth and alreadyLoaded custom properties', function() {
const project = gd.ProjectHelper.createNewGDJSProject();
const resource = new gd.ImageResource();
const properties = resource.getProperties();
expect(properties.get('Smooth the image').getValue()).toBe('true');
expect(properties.get('Always loaded in memory').getValue()).toBe(
'false'
);
// Note: updateProperty expect the booleans in an usual "0" or "1" format.
resource.updateProperty('Smooth the image', '0');
resource.updateProperty('Always loaded in memory', '1');
const updatedProperties = resource.getProperties();
expect(updatedProperties.get('Smooth the image').getValue()).toBe(
'false'
);
expect(updatedProperties.get('Always loaded in memory').getValue()).toBe(
'true'
);
resource.delete();
project.delete();
});
});
describe('gd.AudioResource', function() {
it('should have name and file', function() {
const resource = new gd.AudioResource();
resource.setName('MyAudioResource');
resource.setFile('MyAudioFile');
expect(resource.getName()).toBe('MyAudioResource');
expect(resource.getFile()).toBe('MyAudioFile');
resource.delete();
});
it('can have metadata', function() {
const resource = new gd.AudioResource();
expect(resource.getMetadata()).toBe('');
resource.setMetadata(JSON.stringify({ hello: 'world' }));
expect(resource.getMetadata()).toBe('{"hello":"world"}');
resource.delete();
});
});
describe('gd.FontResource', function() {
it('should have name and file', function() {
const resource = new gd.FontResource();
resource.setName('MyFontResource');
resource.setFile('MyFontFile');
expect(resource.getName()).toBe('MyFontResource');
expect(resource.getFile()).toBe('MyFontFile');
resource.delete();
});
it('can have metadata', function() {
const resource = new gd.FontResource();
expect(resource.getMetadata()).toBe('');
resource.setMetadata(JSON.stringify({ hello: 'world' }));
expect(resource.getMetadata()).toBe('{"hello":"world"}');
resource.delete();
});
});
describe('gd.VideoResource', function() {
it('should have name and file', function() {
const resource = new gd.VideoResource();
resource.setName('MyVideoResource');
resource.setFile('MyVideoFile');
expect(resource.getName()).toBe('MyVideoResource');
expect(resource.getFile()).toBe('MyVideoFile');
resource.delete();
});
it('can have metadata', function() {
const resource = new gd.VideoResource();
expect(resource.getMetadata()).toBe('');
resource.setMetadata(JSON.stringify({ hello: 'world' }));
expect(resource.getMetadata()).toBe('{"hello":"world"}');
resource.delete();
});
});
describe('gd.JsonResource', function() {
it('should have name and file', function() {
const resource = new gd.JsonResource();
resource.setName('MyJsonResource');
resource.setFile('MyJsonFile');
expect(resource.getName()).toBe('MyJsonResource');
expect(resource.getFile()).toBe('MyJsonFile');
resource.delete();
});
it('can have metadata', function() {
const resource = new gd.JsonResource();
expect(resource.getMetadata()).toBe('');
resource.setMetadata(JSON.stringify({ hello: 'world' }));
expect(resource.getMetadata()).toBe('{"hello":"world"}');
resource.delete();
});
it('has disablePreload custom properties', function() {
const project = gd.ProjectHelper.createNewGDJSProject();
const resource = new gd.JsonResource();
const properties = resource.getProperties();
expect(properties.get('disablePreload').getValue()).toBe('false');
// Note: updateProperty expect the booleans in an usual "0" or "1" format.
resource.updateProperty('disablePreload', '1');
const updatedProperties = resource.getProperties();
expect(updatedProperties.get('disablePreload').getValue()).toBe('true');
resource.delete();
project.delete();
});
});
describe('gd.ResourcesManager', function() {
it('should support adding resources', function() {
var project = gd.ProjectHelper.createNewGDJSProject();
var resource = new gd.Resource();
var resource2 = new gd.Resource();
resource.setName('MyResource');
resource2.setName('MyResource2');
project.getResourcesManager().addResource(resource);
project.getResourcesManager().addResource(resource2);
var allResources = project.getResourcesManager().getAllResourceNames();
expect(allResources.size()).toBe(2);
project.delete();
});
it('should support finding resources', function() {
var project = gd.ProjectHelper.createNewGDJSProject();
var resource = new gd.Resource();
var resource2 = new gd.Resource();
resource.setName('MyResource');
resource2.setName('MyResource2');
project.getResourcesManager().addResource(resource);
project.getResourcesManager().addResource(resource2);
expect(
project.getResourcesManager().getResourcePosition('MyResource')
).toBe(0);
expect(
project.getResourcesManager().getResourcePosition('MyResource2')
).toBe(1);
expect(
project.getResourcesManager().getResourcePosition('MyResource3')
).toBe(-1);
project.delete();
});
it('should support removing resources', function() {
var project = gd.ProjectHelper.createNewGDJSProject();
var resource = new gd.Resource();
resource.setName('MyResource');
project.getResourcesManager().addResource(resource);
project.getResourcesManager().removeResource('MyResource');
var allResources = project.getResourcesManager().getAllResourceNames();
expect(allResources.size()).toBe(0);
project.delete();
});
});
describe('gd.ProjectResourcesAdder', function() {
it('should support removing useless resources', function() {
var project = gd.ProjectHelper.createNewGDJSProject();
var resource1 = new gd.ImageResource();
resource1.setName('Useless');
var resource2 = new gd.ImageResource();
resource2.setName('Used');
project.getResourcesManager().addResource(resource1);
project.getResourcesManager().addResource(resource2);
//Create an object using a resource
var obj = project.insertNewObject(project, 'Sprite', 'MyObject', 0);
var sprite1 = new gd.Sprite();
sprite1.setImageName('Used');
var anim1 = new gd.Animation();
anim1.setDirectionsCount(1);
anim1.getDirection(0).addSprite(sprite1);
gd.castObject(obj, gd.SpriteObject).addAnimation(anim1);
var allResources = project.getResourcesManager().getAllResourceNames();
expect(allResources.size()).toBe(2);
gd.ProjectResourcesAdder.removeAllUseless(project, 'image');
var allResources = project.getResourcesManager().getAllResourceNames();
expect(allResources.size()).toBe(1);
expect(allResources.get(0)).toBe('Used');
project.delete();
});
});
describe('gd.ArbitraryResourceWorker', function() {
it('should be called with resources of the project', function(done) {
var project = gd.ProjectHelper.createNewGDJSProject();
var obj = project.insertNewObject(project, 'Sprite', 'MyObject', 0);
const spriteObject = gd.asSpriteObject(obj);
var sprite1 = new gd.Sprite();
sprite1.setImageName('Used');
const animation = new gd.Animation();
animation.setDirectionsCount(1);
animation.getDirection(0).addSprite(sprite1);
spriteObject.addAnimation(animation);
var worker = extend(new gd.ArbitraryResourceWorkerJS(), {
exposeImage: function(image) {
expect(image).toBe('Used');
done();
return image;
},
});
project.exposeResources(worker);
project.delete();
});
});
describe('gd.ResourcesInUseHelper', function() {
it('should find the images used by objects', function() {
var sprite1 = new gd.Sprite();
sprite1.setImageName('Image1');
var sprite2 = new gd.Sprite();
sprite2.setImageName('Image2');
var sprite3 = new gd.Sprite();
sprite3.setImageName('Image3');
const spriteObject = new gd.SpriteObject('My sprite object');
const animation = new gd.Animation();
animation.setDirectionsCount(1);
animation.getDirection(0).addSprite(sprite1);
animation.getDirection(0).addSprite(sprite2);
animation.getDirection(0).addSprite(sprite1);
spriteObject.addAnimation(animation);
const spriteObject2 = new gd.SpriteObject('My sprite object');
const animation2 = new gd.Animation();
animation2.setDirectionsCount(1);
animation2.getDirection(0).addSprite(sprite1);
animation2.getDirection(0).addSprite(sprite3);
animation2.getDirection(0).addSprite(sprite1);
spriteObject2.addAnimation(animation2);
const resourcesInUse = new gd.ResourcesInUseHelper();
{
spriteObject.exposeResources(resourcesInUse);
const resourceNames = resourcesInUse
.getAllImages()
.toNewVectorString()
.toJSArray();
expect(resourceNames).toHaveLength(2);
expect(resourceNames).toContain('Image1');
expect(resourceNames).toContain('Image2');
}
{
spriteObject2.exposeResources(resourcesInUse);
const resourceNames = resourcesInUse
.getAllImages()
.toNewVectorString()
.toJSArray();
expect(resourceNames).toHaveLength(3);
expect(resourceNames).toContain('Image1');
expect(resourceNames).toContain('Image2');
expect(resourceNames).toContain('Image3');
}
resourcesInUse.delete();
spriteObject.delete();
spriteObject2.delete();
});
});
describe('gd.Behavior', function() {
it('update a not existing property', function() {
const project = gd.ProjectHelper.createNewGDJSProject();
const behavior = new gd.Behavior();
const serializerElement = new gd.SerializerElement();
expect(
behavior.updateProperty(
serializerElement,
'PropertyThatDoesNotExist',
'MyValue'
)
).toBe(false);
serializerElement.delete();
behavior.delete();
project.delete();
});
});
describe('gd.BehaviorsSharedData', function() {
it('can be created by gd.Layout.updateBehaviorsSharedData', function() {
var project = gd.ProjectHelper.createNewGDJSProject();
var layout = project.insertNewLayout('Scene', 0);
var object = layout.insertNewObject(project, 'Sprite', 'MyObject', 0);
layout.updateBehaviorsSharedData(project);
expect(layout.hasBehaviorSharedData('Physics')).toBe(false);
var behaviorContent = object.addNewBehavior(
project,
'PhysicsBehavior::PhysicsBehavior',
'Physics'
);
expect(layout.hasBehaviorSharedData('Physics')).toBe(false);
layout.updateBehaviorsSharedData(project);
expect(layout.hasBehaviorSharedData('Physics')).toBe(true);
layout.removeObject('MyObject');
expect(layout.hasBehaviorSharedData('Physics')).toBe(true);
layout.updateBehaviorsSharedData(project);
expect(layout.hasBehaviorSharedData('Physics')).toBe(false);
project.delete();
});
});
describe('gd.BehaviorSharedDataJsImplementation', function() {
it('can declare a gd.BehaviorSharedDataJsImplementation and pass sanity checks', function() {
var mySharedData = new gd.BehaviorSharedDataJsImplementation();
mySharedData.updateProperty = function(
behaviorContent,
propertyName,
newValue
) {
if (propertyName === 'My first property') {
behaviorContent.setStringAttribute('property1', newValue);
return true;
}
if (propertyName === 'My other property') {
behaviorContent.setBoolAttribute('property2', newValue === '1');
return true;
}
return false;
};
mySharedData.getProperties = function(behaviorContent) {
var properties = new gd.MapStringPropertyDescriptor();
properties.getOrCreate('My first property')
.setValue(behaviorContent.getStringAttribute('property1'));
properties.getOrCreate('My other property')
.setValue(behaviorContent.getBoolAttribute('property2') ? '1' : '0')
.setType('Boolean');
return properties;
};
mySharedData.initializeContent = function(behaviorContent) {
behaviorContent.setStringAttribute('property1', 'Initial value 1');
behaviorContent.setBoolAttribute('property2', true);
};
try {
expect(
gd.ProjectHelper.sanityCheckBehaviorsSharedDataProperty(
mySharedData,
'My first property',
'Value1'
)
).toBe('');
expect(
gd.ProjectHelper.sanityCheckBehaviorsSharedDataProperty(
mySharedData,
'My other property',
'0'
)
).toBe('');
} catch (ex) {
console.error(ex);
throw Error(
'Exception caught while launching sanityCheckBehavior on a gd.BehaviorSharedDataJsImplementation.'
);
}
});
});
describe('gd.NamedPropertyDescriptor', function() {
const makeNewProperty = () => {
const property = new gd.NamedPropertyDescriptor();
property
.setName('Property1')
.setLabel('The first property')
.setValue('Hello world')
.setType('string')
.addExtraInfo('Info1')
.addExtraInfo('Info2');
return property;
};
it('can be created and manipulated', function() {
const property = makeNewProperty();
expect(property.getName()).toBe('Property1');
expect(property.getLabel()).toBe('The first property');
expect(property.getValue()).toBe('Hello world');
expect(property.getType()).toBe('string');
expect(property.getExtraInfo().toJSArray()).toContain('Info1');
expect(property.getExtraInfo().toJSArray()).toContain('Info2');
property.delete();
});
it('can be serialized', function() {
const property = makeNewProperty();
var serializerElement = new gd.SerializerElement();
property.serializeTo(serializerElement);
property.delete();
const property2 = new gd.NamedPropertyDescriptor();
property2.unserializeFrom(serializerElement);
serializerElement.delete();
expect(property2.getName()).toBe('Property1');
expect(property2.getLabel()).toBe('The first property');
expect(property2.getValue()).toBe('Hello world');
expect(property2.getType()).toBe('string');
expect(property2.getExtraInfo().toJSArray()).toContain('Info1');
expect(property2.getExtraInfo().toJSArray()).toContain('Info2');
});
});
describe('gd.NamedPropertyDescriptorsList', function() {
it('can be used to store named properties', function() {
const list = new gd.NamedPropertyDescriptorsList();
const property1 = list.insertNew('Property1', 0);
expect(list.has('Property1')).toBe(true);
expect(list.getCount()).toBe(1);
expect(property1.getName()).toBe('Property1');
expect(list.getAt(0).getName()).toBe('Property1');
property1.setLabel('Property 1');
property1.setValue('123');
expect(list.getAt(0).getLabel()).toBe('Property 1');
expect(list.getAt(0).getValue()).toBe('123');
list.delete();
});
});
describe('gd.MapStringPropertyDescriptor', function() {
it('can be used to manipulate properties', function() {
var properties = new gd.MapStringPropertyDescriptor();
expect(properties.has('Property0')).toBe(false);
// Ensure the "set" method works (though in practice, prefer "getOrCreate")
const property1 = new gd.PropertyDescriptor('Hello Property1');
properties.set('Property1', property1);
property1.delete();
expect(properties.get('Property1').getValue()).toBe('Hello Property1');
expect(properties.get('Property1').getType()).toBe('string');
properties.get('Property1').setValue('Hello modified Property1');
expect(properties.get('Property1').getValue()).toBe(
'Hello modified Property1'
);
expect(properties.keys().toJSArray()).not.toContain('Property0');
expect(properties.keys().toJSArray()).toContain('Property1');
// Ensure the "getOrCreate" method works
expect(properties.has('Property0')).toBe(false);
properties.getOrCreate('Property0')
.setValue('Hello Property0')
.setType('another type')
.addExtraInfo('Info1')
.addExtraInfo('Info3');
expect(properties.has('Property0')).toBe(true);
expect(properties.get('Property0').getValue()).toBe('Hello Property0');
expect(properties.get('Property0').getType()).toBe('another type');
expect(
properties
.get('Property0')
.getExtraInfo()
.toJSArray()
).toContain('Info1');
expect(
properties
.get('Property0')
.getExtraInfo()
.toJSArray()
).not.toContain('Info2');
expect(
properties
.get('Property0')
.getExtraInfo()
.toJSArray()
).toContain('Info3');
expect(properties.has('Property0')).toBe(true);
expect(properties.has('Property1')).toBe(true);
expect(properties.keys().toJSArray()).toContain('Property0');
expect(properties.keys().toJSArray()).toContain('Property1');
properties.delete();
});
});
describe('gd.BehaviorJsImplementation', function() {
it('can declare a gd.BehaviorJsImplementation and pass sanity checks', function() {
var myBehavior = new gd.BehaviorJsImplementation();
myBehavior.updateProperty = function(
behaviorContent,
propertyName,
newValue
) {
if (propertyName === 'My first property') {
behaviorContent.setStringAttribute('property1', newValue);
return true;
}
if (propertyName === 'My other property') {
behaviorContent.setBoolAttribute('property2', newValue === '1');
return true;
}
return false;
};
myBehavior.getProperties = function(behaviorContent) {
var properties = new gd.MapStringPropertyDescriptor();
properties
.getOrCreate('My first property')
.setValue(
behaviorContent.getStringAttribute('property1')
);
properties
.getOrCreate('My other property')
.setValue(
behaviorContent.getBoolAttribute('property2') ? '1' : '0'
).setType('Boolean');
return properties;
};
myBehavior.initializeContent = function(behaviorContent) {
behaviorContent.setStringAttribute('property1', 'Initial value 1');
behaviorContent.setBoolAttribute('property2', true);
};
try {
expect(
gd.ProjectHelper.sanityCheckBehaviorProperty(
myBehavior,
'My first property',
'Value1'
)
).toBe('');
expect(
gd.ProjectHelper.sanityCheckBehaviorProperty(
myBehavior,
'My other property',
'0'
)
).toBe('');
} catch (ex) {
console.error(ex);
throw Error(
'Exception caught while launching sanityCheckBehavior on a gd.BehaviorJsImplementation.'
);
}
});
});
describe('gd.Object', function() {
var project = null;
var layout = null;
var object = null;
var object2 = null;
beforeAll(() => {
project = gd.ProjectHelper.createNewGDJSProject();
layout = project.insertNewLayout('Scene', 0);
object = layout.insertNewObject(project, 'Sprite', 'MyObject', 0);
object2 = layout.insertNewObject(project, 'Sprite', 'MyObject2', 1);
});
it('has properties and initial values', function() {
object.setName('TheObject');
expect(object.getName()).toBe('TheObject');
expect(object.hasBehaviorNamed('DoNotExists')).toBe(false);
});
it('can have its type retrieved with gd.getTypeOfObject', function() {
expect(gd.getTypeOfObject(project, layout, 'TheObject', true)).toBe(
'Sprite'
);
});
it('can have behaviors', function() {
var behavior = object.addNewBehavior(
project,
'DraggableBehavior::Draggable',
'Draggable'
);
expect(object.hasBehaviorNamed('Draggable')).toBe(true);
expect(object.getBehavior('Draggable')).toBe(behavior);
});
it('can have its behaviors retrieved with gd.getBehaviorsOfObject', function() {
var behaviors = gd.getBehaviorsOfObject(
project,
layout,
'TheObject',
true
);
expect(behaviors.size()).toBe(1);
expect(behaviors.get(0)).toBe('Draggable');
});
it('can be un/serialized (basic)', function() {
var serializerElement = new gd.SerializerElement();
object.serializeTo(serializerElement);
object2.unserializeFrom(project, serializerElement);
object2.unserializeFrom(project, serializerElement); // Also check that multiple
object2.unserializeFrom(project, serializerElement); // unserialization is idempotent
serializerElement.delete();
//Check that behaviors were persisted and restored
var behaviors = object2.getAllBehaviorNames();
expect(behaviors.size()).toBe(1);
expect(behaviors.at(0)).toBe('Draggable');
});
it('can be un/serialized (with behavior content)', function() {
const behaviorContent = object.getBehavior('Draggable');
behaviorContent.getContent().addChild('Child1');
behaviorContent
.getContent()
.addChild('Child2')
.setStringValue('Child2Value');
var serializerElement = new gd.SerializerElement();
object.serializeTo(serializerElement);
object2.unserializeFrom(project, serializerElement);
object2.unserializeFrom(project, serializerElement); // Also check that multiple
object2.unserializeFrom(project, serializerElement); // unserialization is idempotent
serializerElement.delete();
//Check that behaviors were persisted and restored
var behaviors = object2.getAllBehaviorNames();
expect(behaviors.size()).toBe(1);
expect(behaviors.at(0)).toBe('Draggable');
const behaviorContent2 = object2.getBehavior('Draggable');
expect(behaviorContent2.getContent().hasChild('Child1')).toBe(true);
expect(behaviorContent2.getContent().hasChild('Child2')).toBe(true);
expect(
behaviorContent2
.getContent()
.getChild('Child2')
.getStringValue()
).toBe('Child2Value');
});
afterAll(function() {
project.delete();
});
});
describe('gd.ObjectJsImplementation', function() {
const createSampleObjectJsImplementation = () => {
var myObject = new gd.ObjectJsImplementation();
myObject.updateProperty = function(content, propertyName, newValue) {
if (propertyName === 'My first property') {
content.property1 = newValue;
return true;
}
if (propertyName === 'My other property') {
content.property2 = newValue === '1';
return true;
}
return false;
};
myObject.getProperties = function(content) {
var properties = new gd.MapStringPropertyDescriptor();
properties
.getOrCreate('My first property')
.setValue(content.property1);
properties
.getOrCreate('My other property')
.setValue(content.property2 ? '1' : '0')
.setType('Boolean');
return properties;
};
myObject.setRawJSONContent(
JSON.stringify({
property1: 'Initial value 1',
property2: true,
})
);
myObject.updateInitialInstanceProperty = function(
content,
instance,
propertyName,
newValue,
project,
layout
) {
if (propertyName === 'My instance property') {
instance.setRawStringProperty('instanceprop1', newValue);
return true;
}
if (propertyName === 'My other instance property') {
instance.setRawFloatProperty('instanceprop2', parseFloat(newValue));
return true;
}
return false;
};
myObject.getInitialInstanceProperties = function(
content,
instance,
project,
layout
) {
var properties = new gd.MapStringPropertyDescriptor();
properties
.getOrCreate('My instance property')
.setValue(
instance.getRawStringProperty('instanceprop1')
);
properties
.getOrCreate('My other instance property')
.setValue(
instance.getRawFloatProperty('instanceprop2').toString()
).setType('number');
return properties;
};
// TODO: Workaround a bad design of ObjectJsImplementation. When getProperties
// and associated methods are redefined in JS, they have different arguments (
// see ObjectJsImplementation C++ implementation). If called directly here from JS,
// the arguments will be mismatched. To workaround this, always case the object to
// a base gdObject to ensure C++ methods are called.
return gd.castObject(myObject, gd.Object);
};
it('can create a gd.ObjectJsImplementation and pass sanity checks', function() {
const myObject = createSampleObjectJsImplementation();
try {
expect(
gd.ProjectHelper.sanityCheckObjectProperty(
myObject,
'My first property',
'Value1'
)
).toBe('');
expect(
gd.ProjectHelper.sanityCheckObjectProperty(
myObject,
'My other property',
'0'
)
).toBe('');
expect(
gd.ProjectHelper.sanityCheckObjectInitialInstanceProperty(
myObject,
'My instance property',
'Value1'
)
).toBe('');
expect(
gd.ProjectHelper.sanityCheckObjectInitialInstanceProperty(
myObject,
'My other instance property',
'0'
)
).toBe('');
} catch (ex) {
console.error(ex);
throw Error(
'Exception caught while launching sanityCheckObject on a gd.ObjectJsImplementation.'
);
}
});
it('can clone a gd.ObjectJsImplementation', function() {
const project = gd.ProjectHelper.createNewGDJSProject();
const object1 = createSampleObjectJsImplementation();
expect(
object1.getProperties().get('My first property').getValue() == 'Initial value 1'
);
object1.updateProperty('My first property', 'test1');
const object2 = object1.clone().release();
const object3 = object1.clone().release();
{
const propertiesObject1 = object1.getProperties();
expect(propertiesObject1.has('My first property'));
expect(
propertiesObject1.get('My first property').getValue() == 'test1'
);
const propertiesObject2 = object2.getProperties();
expect(propertiesObject2.has('My first property'));
expect(
propertiesObject2.get('My first property').getValue() == 'test1'
);
}
{
object1.updateProperty('My first property', 'updated value');
const propertiesObject1 = object1.getProperties();
expect(propertiesObject1.has('My first property'));
expect(
propertiesObject1.get('My first property').getValue() ==
'updated value'
);
const propertiesObject2 = object2.getProperties();
expect(propertiesObject2.has('My first property'));
expect(
propertiesObject2.get('My first property').getValue() == 'test1'
);
}
{
object2.updateProperty(
'My first property',
'updated value object 2'
);
const propertiesObject1 = object1.getProperties();
expect(propertiesObject1.has('My first property'));
expect(
propertiesObject1.get('My first property').getValue() ==
'updated value'
);
const propertiesObject2 = object2.getProperties();
expect(propertiesObject2.has('My first property'));
expect(
propertiesObject2.get('My first property').getValue() ==
'updated value object 2'
);
const propertiesObject3 = object3.getProperties();
expect(propertiesObject3.has('My first property'));
expect(
propertiesObject3.get('My first property').getValue() == 'test1'
);
}
project.delete();
});
});
describe('gd.ObjectGroupsContainer', function() {
var container = null;
var group1 = null;
var group2 = null;
var group3 = null;
beforeAll(() => (container = new gd.ObjectGroupsContainer()));
it('can have groups inserted', function() {
group1 = container.insertNew('Group1', 0);
group2 = container.insertNew('Group2', 1);
group3 = container.insertNew('Group3', 2);
expect(container.getAt(0).getName()).toBe('Group1');
expect(container.getAt(1).getName()).toBe('Group2');
expect(container.getAt(2).getName()).toBe('Group3');
expect(container.has('Group1')).toBe(true);
expect(container.has('Group2')).toBe(true);
expect(container.has('Group3')).toBe(true);
expect(container.has('Group4')).toBe(false);
expect(container.get('Group1').getName()).toBe('Group1');
expect(container.get('Group2').getName()).toBe('Group2');
expect(container.get('Group3').getName()).toBe('Group3');
expect(container.count()).toBe(3);
});
it('can move groups', function() {
container.move(0, 1);
expect(container.getAt(0).getName()).toBe('Group2');
expect(container.getAt(1).getName()).toBe('Group1');
expect(container.getAt(2).getName()).toBe('Group3');
});
it('can rename groups', function() {
container.rename('Inexisting', 'Whatever');
container.rename('Group1', 'Group1Renamed');
expect(container.has('Group1')).toBe(false);
expect(container.has('Group1Renamed')).toBe(true);
});
it('can remove groups', function() {
container.remove('Group2');
expect(container.has('Group2')).toBe(false);
expect(container.has('Group3')).toBe(true);
expect(container.count()).toBe(2);
});
});
describe('gd.Instruction', function() {
it('initial values', function() {
var instr = new gd.Instruction();
expect(instr.getParametersCount()).toBe(0);
expect(instr.getSubInstructions().size()).toBe(0);
instr.delete();
});
it('setting parameters', function() {
var instr = new gd.Instruction();
instr.setParametersCount(3);
expect(instr.getParametersCount()).toBe(3);
expect(instr.getParameter(1)).toBe('');
instr.setParameter(2, 'MyValue');
expect(instr.getParameter(2)).toBe('MyValue');
instr.delete();
});
it('can be cloned', function() {
var instr = new gd.Instruction();
instr.setParametersCount(3);
instr.setParameter(2, 'MyValue');
var newInstr = instr.clone();
expect(newInstr.getParametersCount()).toBe(3);
expect(newInstr.getParameter(1)).toBe('');
expect(newInstr.getParameter(2)).toBe('MyValue');
newInstr.setParameter(2, 'MyChangedValue');
expect(instr.getParameter(2)).toBe('MyValue');
expect(newInstr.getParameter(2)).toBe('MyChangedValue');
newInstr.delete();
expect(instr.getParameter(2)).toBe('MyValue');
instr.delete();
});
});
describe('gd.InstructionsList', function() {
var list = null;
beforeAll(() => (list = new gd.InstructionsList()));
it('can insert instructions', function() {
expect(list.size()).toBe(0);
list.insert(new gd.Instruction(), 0);
expect(list.size()).toBe(1);
});
it('can modify its instructions', function() {
expect(list.get(0).getType()).toBe('');
var newInstr = new gd.Instruction();
newInstr.setType('Type2');
list.set(0, newInstr);
expect(list.get(0).getType()).toBe('Type2');
expect(list.size()).toBe(1);
});
it('can remove its instructions', function() {
var newInstr = new gd.Instruction();
newInstr.setType('Type3');
var instruction = list.insert(newInstr, 1);
expect(list.get(1).getType()).toBe('Type3');
expect(list.size()).toBe(2);
expect(list.contains(instruction)).toBe(true);
list.remove(instruction);
expect(list.size()).toBe(1);
expect(list.get(0).getType()).toBe('Type2');
});
it('can clear its instructions', function() {
list.clear();
expect(list.size()).toBe(0);
});
it('can insert events from another list', function() {
var list1 = new gd.InstructionsList();
var list2 = new gd.InstructionsList();
var newInstr = new gd.Instruction();
newInstr.setType('Type1');
list1.insert(newInstr, 0);
var newInstr2 = new gd.Instruction();
newInstr2.setType('Type2');
list1.insert(newInstr2, 1);
list2.insertInstructions(list1, 0, list1.size(), 0);
expect(list2.size()).toBe(2);
expect(list2.get(0).getType()).toBe('Type1');
expect(list2.get(1).getType()).toBe('Type2');
list2.insertInstructions(list1, 0, list1.size(), 1);
expect(list2.size()).toBe(4);
expect(list2.get(0).getType()).toBe('Type1');
expect(list2.get(1).getType()).toBe('Type1');
expect(list2.get(2).getType()).toBe('Type2');
expect(list2.get(3).getType()).toBe('Type2');
list1.delete();
list2.delete();
});
it('can be un/serialized', function() {
var newInstr = new gd.Instruction();
newInstr.setType('Type1');
newInstr.setParametersCount(2);
newInstr.setParameter(0, 'Param1');
newInstr.setParameter(1, 'Param2');
var instruction = list.insert(newInstr, 1);
var newInstr2 = new gd.Instruction();
newInstr2.setType('Type2');
newInstr2.setParametersCount(1);
newInstr2.setParameter(0, 'Param3');
var instruction2 = list.insert(newInstr2, 1);
var project = gd.ProjectHelper.createNewGDJSProject();
var serializerElement = new gd.SerializerElement();
list.serializeTo(serializerElement);
var list2 = new gd.InstructionsList();
list2.unserializeFrom(project, serializerElement);
expect(list2.size()).toBe(2);
expect(list2.get(0).getType()).toBe('Type1');
expect(list2.get(1).getType()).toBe('Type2');
expect(list2.get(0).getParametersCount()).toBe(2);
expect(list2.get(1).getParametersCount()).toBe(1);
expect(list2.get(0).getParameter(0)).toBe('Param1');
expect(list2.get(0).getParameter(1)).toBe('Param2');
expect(list2.get(1).getParameter(0)).toBe('Param3');
list2.delete();
project.delete();
});
afterAll(function() {
list.delete();
});
});
describe('InstructionSentenceFormatter', function() {
it('should translate instructions (plain text or into a vector of text with formatting)', function() {
var action = new gd.Instruction(); //Create a simple instruction
action.setType('Delete');
action.setParametersCount(2);
action.setParameter(0, 'MyCharacter');
var actionSentenceInEnglish = gd.InstructionSentenceFormatter.get().translate(
action,
gd.MetadataProvider.getActionMetadata(gd.JsPlatform.get(), 'Delete')
);
expect(actionSentenceInEnglish).toBe('Delete MyCharacter');
var formattedTexts = gd.InstructionSentenceFormatter.get().getAsFormattedText(
action,
gd.MetadataProvider.getActionMetadata(gd.JsPlatform.get(), 'Delete')
);
expect(formattedTexts.size()).toBe(2);
expect(formattedTexts.getString(0)).toBe('Delete ');
expect(formattedTexts.getString(1)).toBe('MyCharacter');
expect(formattedTexts.getTextFormatting(0).getUserData()).not.toBe(0);
expect(formattedTexts.getTextFormatting(1).getUserData()).toBe(0);
action.delete();
});
});
describe('gd.EventsList', function() {
it('can have events', function() {
var list = new gd.EventsList();
list.insertEvent(new gd.StandardEvent(), 0);
var lastEvent = list.insertEvent(new gd.StandardEvent(), 1);
list.insertEvent(new gd.StandardEvent(), 1);
expect(list.getEventsCount()).toBe(3);
expect(list.getEventAt(2).ptr).toBe(lastEvent.ptr);
list.delete();
});
it('can create lots of new events', function() {
var project = new gd.ProjectHelper.createNewGDJSProject();
var list = new gd.EventsList();
for (var i = 0; i < 500; ++i) {
var evt = list.insertNewEvent(
project,
'BuiltinCommonInstructions::Standard',
0
);
expect(evt.getType()).toBe('BuiltinCommonInstructions::Standard');
expect(gd.asStandardEvent(list.getEventAt(0)).getType()).toBe(
'BuiltinCommonInstructions::Standard'
);
expect(list.getEventAt(0).getType()).toBe(
'BuiltinCommonInstructions::Standard'
);
}
project.delete();
list.delete();
});
it('can tell if it contains an event', function() {
var list = new gd.EventsList();
var parentEvent = list.insertEvent(new gd.StandardEvent(), 0);
var subEvent = parentEvent
.getSubEvents()
.insertEvent(new gd.StandardEvent(), 0);
expect(list.contains(parentEvent, false)).toBe(true);
expect(list.contains(subEvent, false)).toBe(false);
expect(list.contains(subEvent, true)).toBe(true);
list.delete();
});
it('can move an event to another list without invalidating it/copying it in memory', function() {
var list1 = new gd.EventsList();
var list2 = new gd.EventsList();
var list1ParentEvent = list1.insertEvent(new gd.StandardEvent(), 0);
var list2ParentEvent = list2.insertEvent(new gd.StandardEvent(), 0);
var originalSubEvent = list1ParentEvent
.getSubEvents()
.insertEvent(new gd.StandardEvent(), 0);
var originalSubEventPtr = originalSubEvent.ptr;
expect(
list1ParentEvent
.getSubEvents()
.moveEventToAnotherEventsList(
originalSubEvent,
list2ParentEvent.getSubEvents(),
0
)
).toBe(true);
expect(list2ParentEvent.getSubEvents().getEventsCount()).toBe(1);
var movedSubEvent = list2ParentEvent.getSubEvents().getEventAt(0);
expect(movedSubEvent.ptr).toBe(originalSubEventPtr);
list1.delete();
list2.delete();
});
});
describe('gd.BaseEvent', function() {
it('can have a type', function() {
var event = new gd.BaseEvent();
event.setType('Type1');
var event2 = new gd.BaseEvent();
event2.setType('Type2');
expect(event.getType()).toBe('Type1');
expect(event2.getType()).toBe('Type2');
event.delete();
event2.delete();
});
it('can be cloned', function() {
var event = new gd.BaseEvent();
event.setType('Type1');
var event2 = event.clone();
expect(event.getType()).toBe('Type1');
expect(event2.getType()).toBe('Type1');
event.delete();
event2.delete();
});
it('can be de/serialized', function() {
var event = new gd.BaseEvent();
expect(typeof event.serializeTo).toBe('function');
expect(typeof event.unserializeFrom).toBe('function');
event.delete();
});
});
describe('gd.ArbitraryEventsWorker', function() {
describe('gd.EventsParametersLister', function() {
it('can list parameters and their types', function() {
var project = new gd.ProjectHelper.createNewGDJSProject();
var list = new gd.EventsList();
var evt = new gd.StandardEvent();
var actions = evt.getActions();
var act = new gd.Instruction();
act.setType('Delete');
act.setParametersCount(1);
act.setParameter(0, 'MyObject');
actions.push_back(act);
evt = list.insertEvent(evt, 0);
var subEvt = new gd.StandardEvent();
var conditions = subEvt.getConditions();
var cnd = new gd.Instruction();
cnd.setType('PosX');
cnd.setParametersCount(3);
cnd.setParameter(0, 'MyObject');
cnd.setParameter(1, '<');
cnd.setParameter(2, '300');
conditions.push_back(cnd);
evt.getSubEvents().insertEvent(subEvt, 0);
var parametersLister = new gd.EventsParametersLister(project);
parametersLister.launch(list);
expect(
parametersLister
.getParametersAndTypes()
.keys()
.size()
).toBe(3);
expect(parametersLister.getParametersAndTypes().get('MyObject')).toBe(
'object'
);
expect(parametersLister.getParametersAndTypes().get('300')).toBe(
'expression'
);
project.delete();
list.delete();
});
});
});
describe('gd.GroupEvent', function() {
it('handle basic properties', function() {
const evt = new gd.GroupEvent();
evt.setName('MyName');
evt.setSource('http://source.url');
evt.setCreationTimestamp(150);
expect(evt.getName()).toBe('MyName');
expect(evt.getSource()).toBe('http://source.url');
expect(evt.getCreationTimestamp()).toBe(150);
});
it('can be folded', function() {
const evt = new gd.GroupEvent();
expect(evt.isFolded()).toBe(false);
evt.setFolded(true);
expect(evt.isFolded()).toBe(true);
});
it('can remember parameters used to create the group from a template event', function() {
const evt = new gd.GroupEvent();
var parameters = evt.getCreationParameters();
parameters.push_back('Param1');
parameters.push_back('Param2');
expect(evt.getCreationParameters().size()).toBe(2);
expect(evt.getCreationParameters().get(0)).toBe('Param1');
expect(evt.getCreationParameters().get(1)).toBe('Param2');
parameters.clear();
expect(evt.getCreationParameters().size()).toBe(0);
parameters.push_back('Param1');
expect(evt.getCreationParameters().get(0)).toBe('Param1');
});
});
describe('gd.StandardEvent', function() {
it('initial values', function() {
const evt = new gd.StandardEvent();
expect(evt.canHaveSubEvents()).toBe(true);
expect(evt.isExecutable()).toBe(true);
});
it('conditions and actions', function() {
const evt = new gd.StandardEvent();
var conditions = evt.getConditions();
expect(evt.getConditions().size()).toBe(0);
var cnd = new gd.Instruction();
conditions.push_back(cnd);
expect(evt.getConditions().size()).toBe(1);
var actions = evt.getActions();
expect(evt.getActions().size()).toBe(0);
var act = new gd.Instruction();
actions.push_back(act);
expect(evt.getActions().size()).toBe(1);
});
afterAll(function() {
evt.delete();
});
});
describe('gd.CommentEvent', function() {
it('initial values', function() {
const evt = new gd.CommentEvent();
expect(evt.canHaveSubEvents()).toBe(false);
expect(evt.isExecutable()).toBe(false);
});
it('can have a comment', function() {
const evt = new gd.CommentEvent();
evt.setComment('My nice comment about my events!');
expect(evt.getComment()).toBe('My nice comment about my events!');
});
it('can have a comment with UTF8 characters', function() {
const evt = new gd.CommentEvent();
evt.setComment('Hello 官话 world!');
expect(evt.getComment()).toBe('Hello 官话 world!');
});
it('can have a background color', function() {
const evt = new gd.CommentEvent();
evt.setBackgroundColor(100, 200, 255);
expect(evt.getBackgroundColorRed()).toBe(100);
expect(evt.getBackgroundColorGreen()).toBe(200);
expect(evt.getBackgroundColorBlue()).toBe(255);
});
it('can have a text color', function() {
const evt = new gd.CommentEvent();
evt.setTextColor(101, 201, 254);
expect(evt.getTextColorRed()).toBe(101);
expect(evt.getTextColorGreen()).toBe(201);
expect(evt.getTextColorBlue()).toBe(254);
});
});
describe('gd.SpriteObject', function() {
it('is a gd.Object and can have tags', function() {
var object = new gd.SpriteObject('MySpriteObject');
expect(object instanceof gd.Object).toBe(true);
object.setTags('tag1, tag2, tag3');
expect(object.getTags()).toBe('tag1, tag2, tag3');
expect(object.getVariables()).toBeTruthy();
object.delete();
});
it('can have animations', function() {
var obj = new gd.SpriteObject('MySpriteObject');
obj.addAnimation(new gd.Animation());
obj.addAnimation(new gd.Animation());
expect(obj.getAnimationsCount()).toBe(2);
obj.removeAnimation(1);
expect(obj.getAnimationsCount()).toBe(1);
});
it('can swap animations', function() {
var obj = new gd.SpriteObject('MySpriteObject');
obj.removeAllAnimations();
var anim1 = new gd.Animation();
var anim2 = new gd.Animation();
var sprite1 = new gd.Sprite();
var sprite2 = new gd.Sprite();
sprite1.setImageName('image1');
sprite2.setImageName('image2');
anim1.setDirectionsCount(1);
anim2.setDirectionsCount(1);
anim1.getDirection(0).addSprite(sprite1);
anim2.getDirection(0).addSprite(sprite2);
obj.addAnimation(anim1);
obj.addAnimation(anim2);
expect(
obj
.getAnimation(0)
.getDirection(0)
.getSprite(0)
.getImageName()
).toBe('image1');
obj.swapAnimations(0, 1);
expect(
obj
.getAnimation(0)
.getDirection(0)
.getSprite(0)
.getImageName()
).toBe('image2');
});
describe('gd.Direction', function() {
it('can swap sprites', function() {
const direction = new gd.Direction();
const sprite1 = new gd.Sprite();
const sprite2 = new gd.Sprite();
sprite1.setImageName('image1');
sprite2.setImageName('image2');
direction.addSprite(sprite1);
direction.addSprite(sprite2);
expect(direction.getSprite(0).getImageName()).toBe('image1');
direction.swapSprites(0, 1);
expect(direction.getSprite(0).getImageName()).toBe('image2');
direction.swapSprites(1, 0);
expect(direction.getSprite(0).getImageName()).toBe('image1');
direction.delete();
});
it('can move sprites', function() {
const direction = new gd.Direction();
const sprite1 = new gd.Sprite();
const sprite2 = new gd.Sprite();
const sprite3 = new gd.Sprite();
sprite1.setImageName('image1');
sprite2.setImageName('image2');
sprite3.setImageName('image3');
direction.addSprite(sprite1);
direction.addSprite(sprite2);
direction.addSprite(sprite3);
expect(direction.getSprite(0).getImageName()).toBe('image1');
direction.moveSprite(0, 2);
expect(direction.getSprite(0).getImageName()).toBe('image2');
expect(direction.getSprite(1).getImageName()).toBe('image3');
expect(direction.getSprite(2).getImageName()).toBe('image1');
direction.swapSprites(1, 1);
expect(direction.getSprite(0).getImageName()).toBe('image2');
expect(direction.getSprite(1).getImageName()).toBe('image3');
expect(direction.getSprite(2).getImageName()).toBe('image1');
direction.swapSprites(1, 0);
expect(direction.getSprite(0).getImageName()).toBe('image3');
expect(direction.getSprite(1).getImageName()).toBe('image2');
expect(direction.getSprite(2).getImageName()).toBe('image1');
direction.swapSprites(999, 998);
expect(direction.getSprite(0).getImageName()).toBe('image3');
expect(direction.getSprite(1).getImageName()).toBe('image2');
expect(direction.getSprite(2).getImageName()).toBe('image1');
direction.delete();
});
it('can have metadata', function() {
const direction = new gd.Direction();
expect(direction.getMetadata()).toBe('');
direction.setMetadata('{test: 1}');
expect(direction.getMetadata()).toBe('{test: 1}');
direction.delete();
});
});
describe('gd.Sprite', function() {
it('can have default points', function() {
var sprite1 = new gd.Sprite();
sprite1.getCenter().setX(2);
sprite1.getCenter().setY(3);
sprite1.getOrigin().setX(4);
sprite1.getOrigin().setY(5);
expect(sprite1.getCenter().getX()).toBe(2);
expect(sprite1.getCenter().getY()).toBe(3);
expect(sprite1.getOrigin().getX()).toBe(4);
expect(sprite1.getOrigin().getY()).toBe(5);
});
it('can have custom points', function() {
var sprite1 = new gd.Sprite();
var point = new gd.Point('test');
sprite1.addPoint(point);
point.delete();
expect(sprite1.hasPoint('test')).toBe(true);
sprite1.getPoint('test').setX(1);
sprite1.getPoint('test').setY(2);
expect(sprite1.getPoint('test').getX()).toBe(1);
expect(sprite1.getPoint('test').getY()).toBe(2);
});
});
});
describe('gd.MetadataProvider', function() {
it('can return metadata about expressions (even if they do not exist)', function() {
expect(
gd.MetadataProvider.hasExpression(
gd.JsPlatform.get(),
'NotExistingExpression'
)
).toBe(false);
expect(
gd.MetadataProvider.getExpressionMetadata(
gd.JsPlatform.get(),
'NotExistingExpression'
).getFullName()
).toBe('');
});
describe('gd.ObjectMetadata', function() {
it('can return standard information about Sprite object', function() {
var objMetadata = gd.MetadataProvider.getObjectMetadata(
gd.JsPlatform.get(),
'Sprite'
);
expect(objMetadata.getName()).toBe('Sprite');
expect(objMetadata.getFullName()).toBe('Sprite');
expect(objMetadata.getDescription().length).not.toBe(0);
expect(objMetadata.getIconFilename().length).not.toBe(0);
});
});
describe('gd.BehaviorMetadata', function() {
it('have standard methods to get information', function() {
var autoMetadata = gd.MetadataProvider.getBehaviorMetadata(
gd.JsPlatform.get(),
'NotExistingBehavior'
);
expect(autoMetadata.getFullName).not.toBe(undefined);
expect(autoMetadata.getDefaultName).not.toBe(undefined);
expect(autoMetadata.getDescription).not.toBe(undefined);
expect(autoMetadata.getGroup).not.toBe(undefined);
expect(autoMetadata.getIconFilename).not.toBe(undefined);
expect(autoMetadata.getObjectType).not.toBe(undefined);
});
});
describe('gd.EffectMetadata', function() {
it('have standard methods to get information', function() {
var autoMetadata = gd.MetadataProvider.getEffectMetadata(
gd.JsPlatform.get(),
'NotExistingEffect'
);
expect(autoMetadata.getType).not.toBe(undefined);
expect(autoMetadata.getFullName).not.toBe(undefined);
expect(autoMetadata.getDescription).not.toBe(undefined);
expect(autoMetadata.getProperties).not.toBe(undefined);
});
});
});
describe('gd.ResourcesMergingHelper (and gd.AbstractFileSystemJS)', function() {
it('should export files of the project', function() {
// Create a project with a mix of resources
const project = new gd.ProjectHelper.createNewGDJSProject();
const layout = project.insertNewLayout('Scene', 0);
const resource = new gd.ImageResource();
const resource2 = new gd.ImageResource();
const resource3 = new gd.ImageResource();
const resource4 = new gd.ImageResource();
const resource5 = new gd.ImageResource();
resource.setName('MyResource');
resource.setFile('MyResource.png');
resource2.setName('MyAudioResource');
resource2.setFile('MyResource.wav');
resource3.setName('test/MyResource.png');
resource3.setFile('test/MyResource.png');
resource4.setName('test/MyResourceWithExtension');
resource4.setFile('test/MyResourceWithExtension');
resource5.setName('test/sub/folder/MyResourceWithExtension');
resource5.setFile('test/sub/folder/MyResourceWithExtension');
project.getResourcesManager().addResource(resource);
project.getResourcesManager().addResource(resource2);
project.getResourcesManager().addResource(resource3);
project.getResourcesManager().addResource(resource4);
project.getResourcesManager().addResource(resource5);
// Create a fake file system
const fs = new gd.AbstractFileSystemJS();
fs.mkDir = fs.clearDir = function() {};
fs.getTempDir = function(path) {
return '/tmp/';
};
fs.fileNameFrom = function(fullpath) {
return path.posix.basename(fullpath);
};
fs.dirNameFrom = function(fullpath) {
return path.posix.dirname(fullpath);
};
fs.makeAbsolute = function(relativePath, baseDirectory) {
return path.posix.resolve(baseDirectory, relativePath);
};
fs.makeRelative = function(absolutePath, baseDirectory) {
return path.posix.relative(baseDirectory, absolutePath);
};
// Check that ResourcesMergingHelper can update the filenames
const resourcesMergingHelper = new gd.ResourcesMergingHelper(fs);
resourcesMergingHelper.setBaseDirectory('/my/project/');
project.exposeResources(resourcesMergingHelper);
const oldAndNewFilenames = resourcesMergingHelper.getAllResourcesOldAndNewFilename();
expect(oldAndNewFilenames.get('/my/project/MyResource.png')).toBe(
'MyResource.png'
);
expect(oldAndNewFilenames.get('/my/project/MyResource.wav')).toBe(
'MyResource.wav'
);
expect(oldAndNewFilenames.get('/my/project/test/MyResource.png')).toBe(
'MyResource2.png'
);
expect(
oldAndNewFilenames.get('/my/project/test/MyResourceWithExtension')
).toBe('MyResourceWithExtension');
expect(
oldAndNewFilenames.get(
'/my/project/test/sub/folder/MyResourceWithExtension'
)
).toBe('MyResourceWithExtension2');
resourcesMergingHelper.delete();
project.delete();
});
});
describe('gd.ProjectResourcesCopier (and gd.AbstractFileSystemJS)', function() {
it('should export files of the project', function() {
// Create a project with a mix of resources, stored in /my/project folder.
const project = new gd.ProjectHelper.createNewGDJSProject();
project.setProjectFile('/my/project/project.json');
const layout = project.insertNewLayout('Scene', 0);
const resource = new gd.ImageResource();
const resource2 = new gd.ImageResource();
const resource3 = new gd.ImageResource();
const resource4 = new gd.ImageResource();
const resource5 = new gd.ImageResource();
resource.setName('MyResource');
resource.setFile('MyResource.png');
resource2.setName('MyAudioResource');
resource2.setFile('MyResource.wav');
resource3.setName('MyAbsoluteResource');
resource3.setFile('/my/absolute/path/MyResource2.png');
resource4.setName('test/MyResourceWithoutExtension');
resource4.setFile('test/MyResourceWithoutExtension');
resource5.setName('test/sub/folder/MyResourceWithoutExtension');
resource5.setFile('test/sub/folder/MyResourceWithoutExtension'); // Same filename as resource4
project.getResourcesManager().addResource(resource);
project.getResourcesManager().addResource(resource2);
project.getResourcesManager().addResource(resource3);
project.getResourcesManager().addResource(resource4);
project.getResourcesManager().addResource(resource5);
// Create a fake file system
const fs = new gd.AbstractFileSystemJS();
fs.mkDir = fs.clearDir = function() {};
fs.getTempDir = function(path) {
return '/tmp/';
};
fs.fileNameFrom = function(fullPath) {
return path.posix.basename(fullPath);
};
fs.dirNameFrom = function(fullPath) {
return path.posix.dirname(fullPath);
};
fs.makeAbsolute = function(relativePath, baseDirectory) {
return path.posix.resolve(baseDirectory, relativePath);
};
fs.makeRelative = function(absolutePath, baseDirectory) {
return path.posix.relative(baseDirectory, absolutePath);
};
fs.isAbsolute = function(fullPath) {
return path.posix.isAbsolute(fullPath);
};
fs.dirExists = function(directoryPath) {
return true; // Fake that all directory required exist.
};
// In particular, create a mock copyFile, that we can track to verify
// files are properly copied.
fs.copyFile = jest.fn();
fs.copyFile.mockImplementation(function(srcPath, destPath) {
return true;
});
// Check that resources can be copied to another folder:
// * including absolute files.
// * preserving relative file structures
fs.copyFile.mockClear();
gd.ProjectResourcesCopier.copyAllResourcesTo(
project,
fs,
'/my/new/folder',
false,
false,
true
);
expect(fs.copyFile).toHaveBeenCalledTimes(5); // All 5 resources are copied
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/MyResource.png',
'/my/new/folder/MyResource.png'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/MyResource.wav',
'/my/new/folder/MyResource.wav'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/absolute/path/MyResource2.png',
'/my/new/folder/MyResource2.png'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/test/MyResourceWithoutExtension',
'/my/new/folder/test/MyResourceWithoutExtension'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/test/sub/folder/MyResourceWithoutExtension',
'/my/new/folder/test/sub/folder/MyResourceWithoutExtension'
);
// Check that resources can be copied to another folder:
// * including absolute files.
// * NOT preserving relative file structures
// Check that filename collisions are avoided.
fs.copyFile.mockClear();
gd.ProjectResourcesCopier.copyAllResourcesTo(
project,
fs,
'/my/new/folder',
false,
false,
false
);
expect(fs.copyFile).toHaveBeenCalledTimes(5); // All 5 resources are copied
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/MyResource.png',
'/my/new/folder/MyResource.png'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/MyResource.wav',
'/my/new/folder/MyResource.wav'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/absolute/path/MyResource2.png',
'/my/new/folder/MyResource2.png'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/test/MyResourceWithoutExtension',
'/my/new/folder/MyResourceWithoutExtension'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/test/sub/folder/MyResourceWithoutExtension',
'/my/new/folder/MyResourceWithoutExtension2'
);
// Check that resources can be copied to another folder:
// * without touching absolute files.
// * preserving relative file structures
fs.copyFile.mockClear();
gd.ProjectResourcesCopier.copyAllResourcesTo(
project,
fs,
'/my/new/folder',
false,
true,
true
);
expect(fs.copyFile).toHaveBeenCalledTimes(4); // Only the 4 relative resources are copied
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/MyResource.png',
'/my/new/folder/MyResource.png'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/MyResource.wav',
'/my/new/folder/MyResource.wav'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/test/MyResourceWithoutExtension',
'/my/new/folder/test/MyResourceWithoutExtension'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/test/sub/folder/MyResourceWithoutExtension',
'/my/new/folder/test/sub/folder/MyResourceWithoutExtension'
);
// Check that resources can be copied to another folder:
// * without touching absolute files.
// * NOT preserving relative file structures
// Check that filename collisions are avoided.
fs.copyFile.mockClear();
gd.ProjectResourcesCopier.copyAllResourcesTo(
project,
fs,
'/my/new/folder',
false,
true,
false
);
expect(fs.copyFile).toHaveBeenCalledTimes(5); // All 5 resources are copied
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/MyResource.png',
'/my/new/folder/MyResource.png'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/MyResource.wav',
'/my/new/folder/MyResource.wav'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/absolute/path/MyResource2.png',
'/my/new/folder/MyResource2.png'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/test/MyResourceWithoutExtension',
'/my/new/folder/MyResourceWithoutExtension'
);
expect(fs.copyFile).toHaveBeenCalledWith(
'/my/project/test/sub/folder/MyResourceWithoutExtension',
'/my/new/folder/MyResourceWithoutExtension2'
);
project.delete();
});
});
describe('gd.Exporter (and gd.AbstractFileSystemJS)', function() {
it('should export a layout for preview', function(done) {
var fs = new gd.AbstractFileSystemJS();
var project = new gd.ProjectHelper.createNewGDJSProject();
var layout = project.insertNewLayout('Scene', 0);
fs.mkDir = fs.clearDir = function() {};
fs.getTempDir = function(path) {
return '/tmp/';
};
fs.fileNameFrom = function(fullpath) {
return path.basename(fullpath);
};
fs.dirNameFrom = function(fullpath) {
return path.dirname(fullpath);
};
fs.readDir = function() {
return new gd.VectorString();
};
fs.writeToFile = function(path, content) {
//Validate that some code have been generated:
expect(content).toMatch('runtimeScene.getOnceTriggers().startNewFrame');
done();
};
const exporter = new gd.Exporter(fs);
const previewExportOptions =
new gd.PreviewExportOptions(project, '/path/for/export/');
previewExportOptions.setLayoutName('Scene');
exporter.exportProjectForPixiPreview(previewExportOptions);
previewExportOptions.delete();
exporter.delete();
});
});
describe('gd.EventsRemover', function() {
it('should remove events', function() {
var list = new gd.EventsList();
var event1 = list.insertEvent(new gd.StandardEvent(), 0);
var event2 = list.insertEvent(new gd.StandardEvent(), 1);
var event3 = list.insertEvent(new gd.StandardEvent(), 2);
var remover = new gd.EventsRemover();
remover.addEventToRemove(event1);
remover.addEventToRemove(event3);
remover.launch(list);
expect(list.getEventsCount()).toBe(1);
expect(list.getEventAt(0)).toBe(event2);
});
});
describe('gd.WholeProjectRefactorer', function() {
it('should rename and delete an object', function() {
var project = new gd.ProjectHelper.createNewGDJSProject();
var layout = project.insertNewLayout('Scene', 0);
var instance1 = layout.getInitialInstances().insertNewInitialInstance();
var instance2 = layout.getInitialInstances().insertNewInitialInstance();
instance1.setObjectName('Object1');
instance2.setObjectName('Object2');
gd.WholeProjectRefactorer.objectOrGroupRenamedInLayout(
project,
layout,
'Object1',
'Object3',
/* isObjectGroup=*/ false
);
expect(layout.getInitialInstances().hasInstancesOfObject('Object1')).toBe(
false
);
expect(layout.getInitialInstances().hasInstancesOfObject('Object2')).toBe(
true
);
expect(layout.getInitialInstances().hasInstancesOfObject('Object3')).toBe(
true
);
gd.WholeProjectRefactorer.objectOrGroupRemovedInLayout(
project,
layout,
'Object3',
/* isObjectGroup=*/ false,
true
);
expect(layout.getInitialInstances().hasInstancesOfObject('Object1')).toBe(
false
);
expect(layout.getInitialInstances().hasInstancesOfObject('Object2')).toBe(
true
);
expect(layout.getInitialInstances().hasInstancesOfObject('Object3')).toBe(
false
);
});
// See other tests in WholeProjectRefactorer.cpp
});
describe('gd.ExpressionParser2 and gd.ExpressionValidator', function() {
let project = null;
let layout = null;
beforeAll(() => {
project = new gd.ProjectHelper.createNewGDJSProject();
layout = project.insertNewLayout('Scene', 0);
layout.insertNewObject(project, 'Sprite', 'MySpriteObject', 0);
});
function testExpression(
type,
expression,
expectedError,
expectedErrorPosition
) {
const parser = new gd.ExpressionParser2(
gd.JsPlatform.get(),
project,
layout
);
const expressionNode = parser.parseExpression(type, expression).get();
const expressionValidator = new gd.ExpressionValidator();
expressionNode.visit(expressionValidator);
if (expectedError) {
expect(expressionValidator.getErrors().size()).toBe(1);
expect(
expressionValidator
.getErrors()
.at(0)
.getMessage()
).toBe(expectedError);
if (expectedErrorPosition)
expect(
expressionValidator
.getErrors()
.at(0)
.getStartPosition()
).toBe(expectedErrorPosition);
} else {
expect(expressionValidator.getErrors().size()).toBe(0);
}
expressionValidator.delete();
parser.delete();
}
it('can parse valid expressions', function() {
testExpression('number', '1+1');
testExpression('number', '2-3');
testExpression('number', '4/5');
testExpression('number', '6*7');
testExpression('number', '8 + 9');
testExpression('number', '10 + 11');
testExpression('number', '12 + 13 - 14');
testExpression('number', ' 15 + 16 - 17 ');
testExpression('number', '.14');
testExpression('number', '3.');
});
it('report errors in invalid expressions', function() {
testExpression(
'number',
'1//2',
'You must enter a number or a valid expression call.',
2
);
testExpression('number', 'bad expression', 'You must enter a number.', 0);
testExpression(
'number',
'1 + test()',
"Cannot find an expression with this name: test\nDouble check that you've not made any typo in the name.",
4
);
testExpression(
'number',
'3..14',
'No operator found. Did you forget to enter an operator (like +, -, * or /) between numbers or expressions?',
2
);
testExpression(
'string',
'="Mynewscene"',
'You must enter a text (between quotes) or a valid expression call.',
0
);
});
it('can parse valid expressions with free functions', function() {
testExpression('number', '1+sin(3.14)');
testExpression('number', 'abs(-5)');
testExpression('number', 'abs(-5) + cos(sin(3))');
testExpression('number', 'atan2(-5, 3)');
testExpression('number', 'MouseX("", 0) + 1');
});
it('can report errors when using too much arguments', function() {
testExpression(
'number',
'abs(-5, 3)',
"This parameter was not expected by this expression. Remove it or verify that you've entered the proper expression name."
);
testExpression(
'number',
'MouseX("", 0, 0) + 1',
"This parameter was not expected by this expression. Remove it or verify that you've entered the proper expression name."
);
});
it('can parse valid expressions with free functions having optional parameters', function() {
testExpression('number', 'MouseX() + 1');
testExpression('number', 'MouseX("") + 1');
});
it('can parse expressions with objects functions', function() {
testExpression('number', 'MySpriteObject.X()');
testExpression('number', 'MySpriteObject.X() + 1');
testExpression('number', 'MySpriteObject.PointX("Point")');
});
it('can report errors when using too much arguments in object functions', function() {
testExpression(
'number',
'MySpriteObject.PointX("Point", 2)',
"This parameter was not expected by this expression. Remove it or verify that you've entered the proper expression name."
);
});
it('can parse arguments being expressions', function() {
testExpression('number', 'MouseX(VariableString(myVariable), 0) + 1');
});
});
describe('gd.ExpressionCompletionFinder', function() {
let project = null;
let layout = null;
beforeAll(() => {
project = new gd.ProjectHelper.createNewGDJSProject();
layout = project.insertNewLayout('Scene', 0);
layout.insertNewObject(project, 'Sprite', 'MySpriteObject', 0);
});
function testCompletions(
type,
expressionWithCaret,
onCompletionDescription
) {
const caretPosition = expressionWithCaret.indexOf('|');
if (caretPosition === -1) {
throw new Error(
'Caret location not found in expression: ' + expressionWithCaret
);
}
const expression = expressionWithCaret.replace('|', '');
const parser = new gd.ExpressionParser2(
gd.JsPlatform.get(),
project,
layout
);
const expressionNode = parser.parseExpression(type, expression).get();
const completionDescriptions = gd.ExpressionCompletionFinder.getCompletionDescriptionsFor(
expressionNode,
// We're looking for completion for the character just before the caret.
Math.max(0, caretPosition - 1)
);
for (let i = 0; i < completionDescriptions.size(); i++) {
const completionDescription = completionDescriptions.at(i);
onCompletionDescription(completionDescription, i);
}
parser.delete();
}
it('completes an empty expression', function() {
expect.assertions(6);
testCompletions('number', '|', (completionDescription, index) => {
if (index === 0) {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Object
);
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('');
} else {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Expression
);
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('');
}
});
});
it('completes an expression with an operator', function() {
expect.assertions(6);
testCompletions('number', '1 +| ', (completionDescription, index) => {
if (index === 0) {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Object
);
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('');
} else {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Expression
);
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('');
}
});
});
it('completes an expression with an operator and a prefix', function() {
expect.assertions(6);
testCompletions('number', '1 + My| ', (completionDescription, index) => {
if (index === 0) {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Object
);
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('My');
} else {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Expression
);
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('My');
}
});
});
it('completes an expression with a partial object function', function() {
expect.assertions(8);
testCompletions(
'number',
'1 + MyObject.Func| ',
(completionDescription, index) => {
if (index == 0) {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Behavior
);
expect(completionDescription.getType()).toBe('');
expect(completionDescription.getPrefix()).toBe('Func');
expect(completionDescription.getObjectName()).toBe('MyObject');
} else {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Expression
);
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('Func');
expect(completionDescription.getObjectName()).toBe('MyObject');
}
}
);
});
it('completes an expression with a partial behavior function', function() {
expect.assertions(5);
testCompletions(
'number',
'1 + MyObject.MyBehavior::Func| ',
(completionDescription, index) => {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Expression
);
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('Func');
expect(completionDescription.getObjectName()).toBe('MyObject');
expect(completionDescription.getBehaviorName()).toBe('MyBehavior');
}
);
});
it('completes an expression parameters', function() {
expect.assertions(6);
testCompletions(
'number',
'1 + MySpriteObject.PointX(a| ',
(completionDescription, index) => {
if (index === 0) {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Object
);
expect(completionDescription.getType()).toBe('string');
expect(completionDescription.getPrefix()).toBe('a');
} else {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Expression
);
expect(completionDescription.getType()).toBe('string');
expect(completionDescription.getPrefix()).toBe('a');
}
}
);
});
// More tests are done in C++ for ExpressionCompletionFinder.
});
describe('gd.Vector2f', function() {
describe('gd.VectorVector2f', function() {
it('can be used to manipulate a vector of gd.Vector2f', function() {
const vectorVector2f = new gd.VectorVector2f();
const vector2f = new gd.Vector2f();
vectorVector2f.push_back(vector2f);
vectorVector2f.push_back(vector2f);
vectorVector2f.push_back(vector2f);
expect(vectorVector2f.size()).toBe(3);
vectorVector2f.at(0).set_x(1);
vectorVector2f.at(1).set_x(2);
vectorVector2f.at(2).set_x(3);
expect(vectorVector2f.at(0).get_x()).toBe(1);
expect(vectorVector2f.at(1).get_x()).toBe(2);
expect(vectorVector2f.at(2).get_x()).toBe(3);
gd.removeFromVectorVector2f(vectorVector2f, 1);
expect(vectorVector2f.size()).toBe(2);
expect(vectorVector2f.at(0).get_x()).toBe(1);
expect(vectorVector2f.at(1).get_x()).toBe(3);
vectorVector2f.clear();
expect(vectorVector2f.size()).toBe(0);
});
});
});
describe('gd.PlatformExtension', function() {
it('can be created and have basic information filled', function() {
const extension = new gd.PlatformExtension();
extension
.setExtensionInformation(
'TestExtensionName',
'Full name of test extension',
'Description of test extension',
'Author of test extension',
'License of test extension'
)
.setExtensionHelpPath('/path/to/extension/help');
expect(extension.getName()).toBe('TestExtensionName');
expect(extension.getFullName()).toBe('Full name of test extension');
expect(extension.getDescription()).toBe('Description of test extension');
expect(extension.getAuthor()).toBe('Author of test extension');
expect(extension.getLicense()).toBe('License of test extension');
expect(extension.getHelpPath()).toBe('/path/to/extension/help');
extension.delete();
});
});
describe('gd.Platform (using gd.JsPlatform)', function() {
it('can have extension added and removed', function() {
const extension = new gd.PlatformExtension();
extension.setExtensionInformation(
'MyNewExtension',
'Full name of test extension',
'Description of test extension',
'Author of test extension',
'License of test extension'
);
gd.JsPlatform.get().addNewExtension(extension);
expect(gd.JsPlatform.get().isExtensionLoaded('MyNewExtension')).toBe(
true
);
gd.JsPlatform.get().removeExtension('MyNewExtension');
expect(gd.JsPlatform.get().isExtensionLoaded('MyNewExtension')).toBe(
false
);
gd.JsPlatform.get().addNewExtension(extension);
gd.JsPlatform.get().addNewExtension(extension);
expect(gd.JsPlatform.get().isExtensionLoaded('MyNewExtension')).toBe(
true
);
gd.JsPlatform.get().removeExtension('MyNewExtension');
expect(gd.JsPlatform.get().isExtensionLoaded('MyNewExtension')).toBe(
false
);
extension.delete();
});
it('has a namespace separator', function() {
expect(gd.PlatformExtension.getNamespaceSeparator()).toBe('::');
});
});
describe('gd.ParameterMetadata', function() {
it('can tell the type of a parameter', function() {
expect(gd.ParameterMetadata.isObject('object')).toBe(true);
expect(gd.ParameterMetadata.isObject('objectPtr')).toBe(true);
expect(gd.ParameterMetadata.isObject('123')).toBe(false);
expect(gd.ParameterMetadata.isBehavior('behavior')).toBe(true);
expect(gd.ParameterMetadata.isBehavior('behavior34234')).toBe(false);
});
it('can have attributes and be serialized', function() {
const parameter1 = new gd.ParameterMetadata();
parameter1.setType('objectList');
parameter1.setName('MyObjectWithoutType');
parameter1.setDescription('The first object to be used');
parameter1.setLongDescription('A long description');
parameter1.setDefaultValue('Default value');
parameter1.setOptional(true);
const serializerElement = new gd.SerializerElement();
parameter1.serializeTo(serializerElement);
const parameter2 = new gd.ParameterMetadata();
parameter2.unserializeFrom(serializerElement);
expect(parameter1.getType()).toBe('objectList');
expect(parameter1.getName()).toBe('MyObjectWithoutType');
expect(parameter1.getDescription()).toBe('The first object to be used');
expect(parameter1.getLongDescription()).toBe('A long description');
expect(parameter1.getDefaultValue()).toBe('Default value');
expect(parameter1.isOptional()).toBe(true);
});
});
describe('gd.ParameterMetadataTools', function() {
it('can create an object container from parameters', function() {
const project = gd.ProjectHelper.createNewGDJSProject();
const parameters = new gd.VectorParameterMetadata();
const parameter1 = new gd.ParameterMetadata();
parameter1.setType('objectList');
parameter1.setName('MyObjectWithoutType');
parameter1.setDescription('The first object to be used');
const parameter2 = new gd.ParameterMetadata();
parameter2.setType('expression');
parameter2.setName('MyNumber');
parameter2.setDescription('Some number');
const parameter3 = new gd.ParameterMetadata();
parameter3.setType('objectList');
// parameter3.setName(''); No name for this parameter
parameter3.setDescription(
'This parameter will be skipped, as it has no name'
);
parameter3.setExtraInfo('Sprite');
const parameter4 = new gd.ParameterMetadata();
parameter4.setType('string');
parameter4.setName('MyString');
parameter4.setDescription('Some string');
const parameter5 = new gd.ParameterMetadata();
parameter5.setType('objectList');
parameter5.setName('MySpriteObject');
parameter5.setDescription('The second object to be used, a sprite');
parameter5.setExtraInfo('Sprite');
parameters.push_back(parameter1);
parameters.push_back(parameter2);
parameters.push_back(parameter3);
parameters.push_back(parameter4);
parameters.push_back(parameter5);
parameters.push_back(parameter5);
expect(parameters.size()).toBe(6);
gd.removeFromVectorParameterMetadata(parameters, 5);
expect(parameters.size()).toBe(5);
objectsContainer = new gd.ObjectsContainer();
gd.ParameterMetadataTools.parametersToObjectsContainer(
project,
parameters,
objectsContainer
);
expect(objectsContainer.getObjectsCount()).toBe(2);
expect(objectsContainer.hasObjectNamed('MyObjectWithoutType')).toBe(true);
expect(objectsContainer.getObject('MyObjectWithoutType').getType()).toBe(
''
);
expect(objectsContainer.hasObjectNamed('MySpriteObject')).toBe(true);
expect(objectsContainer.getObject('MySpriteObject').getType()).toBe(
'Sprite'
);
project.delete();
});
it('can give the previous object parameter', function() {
const parameters = new gd.VectorParameterMetadata();
const parameter1 = new gd.ParameterMetadata();
parameter1.setType('objectList');
const parameter2 = new gd.ParameterMetadata();
parameter2.setType('behavior');
const parameter3 = new gd.ParameterMetadata();
parameter3.setType('objectList');
const parameter4 = new gd.ParameterMetadata();
parameter4.setType('string');
const parameter5 = new gd.ParameterMetadata();
parameter5.setType('objectvar');
const parameter6 = new gd.ParameterMetadata();
parameter6.setType('objectvar');
parameters.push_back(parameter1);
parameters.push_back(parameter2);
parameters.push_back(parameter3);
parameters.push_back(parameter4);
parameters.push_back(parameter5);
parameters.push_back(parameter6);
objectsContainer = new gd.ObjectsContainer();
expect(
gd.ParameterMetadataTools.getObjectParameterIndexFor(parameters, 0)
).toBe(0);
expect(
gd.ParameterMetadataTools.getObjectParameterIndexFor(parameters, 1)
).toBe(0);
expect(
gd.ParameterMetadataTools.getObjectParameterIndexFor(parameters, 2)
).toBe(2);
expect(
gd.ParameterMetadataTools.getObjectParameterIndexFor(parameters, 3)
).toBe(2);
expect(
gd.ParameterMetadataTools.getObjectParameterIndexFor(parameters, 4)
).toBe(2);
expect(
gd.ParameterMetadataTools.getObjectParameterIndexFor(parameters, 5)
).toBe(2);
expect(
gd.ParameterMetadataTools.getObjectParameterIndexFor(parameters, 999)
).toBe(-1);
});
});
describe('gd.EventsFunction', () => {
it('can store events', function() {
const project = gd.ProjectHelper.createNewGDJSProject();
const eventsFunction = new gd.EventsFunction();
const events = eventsFunction.getEvents();
expect(events.getEventsCount()).toBe(0);
var evt = events.insertNewEvent(
project,
'BuiltinCommonInstructions::Standard',
0
);
expect(events.getEventsCount()).toBe(1);
eventsFunction.delete();
project.delete();
});
it('can have a name, fullname and description', function() {
const eventsFunction = new gd.EventsFunction();
eventsFunction.setName('My name');
eventsFunction.setFullName('My descriptive name');
eventsFunction.setDescription('My description');
expect(eventsFunction.getName()).toBe('My name');
expect(eventsFunction.getFullName()).toBe('My descriptive name');
expect(eventsFunction.getDescription()).toBe('My description');
eventsFunction.delete();
});
});
describe('gd.EventsFunctionsExtension', () => {
it('can have a namespace, version, name, fullname, description', function() {
const eventsFunctionsExtension = new gd.EventsFunctionsExtension();
eventsFunctionsExtension.setNamespace('MyExt');
eventsFunctionsExtension.setVersion('1.1');
eventsFunctionsExtension.setName('My name');
eventsFunctionsExtension.setFullName('My descriptive name');
eventsFunctionsExtension.setDescription('My description');
expect(eventsFunctionsExtension.getNamespace()).toBe('MyExt');
expect(eventsFunctionsExtension.getVersion()).toBe('1.1');
expect(eventsFunctionsExtension.getName()).toBe('My name');
expect(eventsFunctionsExtension.getFullName()).toBe(
'My descriptive name'
);
expect(eventsFunctionsExtension.getDescription()).toBe('My description');
const eventsFunction = eventsFunctionsExtension.insertNewEventsFunction(
'MyFunction',
0
);
expect(
eventsFunctionsExtension.hasEventsFunctionNamed('MyFunction')
).toBe(true);
expect(
eventsFunctionsExtension.hasEventsFunctionNamed('MyNotExistingFunction')
).toBe(false);
expect(eventsFunctionsExtension.getEventsFunctionsCount()).toBe(1);
expect(eventsFunctionsExtension.getEventsFunctionAt(0).getName()).toBe(
'MyFunction'
);
expect(
eventsFunctionsExtension.getEventsFunction('MyFunction').getName()
).toBe('MyFunction');
eventsFunctionsExtension.delete();
});
it('can have events based behaviors', function() {
const eventsFunctionsExtension = new gd.EventsFunctionsExtension();
expect(
eventsFunctionsExtension.getEventsBasedBehaviors().getCount()
).toBe(0);
eventsFunctionsExtension
.getEventsBasedBehaviors()
.insertNew('MyBehavior1', 0);
eventsFunctionsExtension
.getEventsBasedBehaviors()
.insertNew('MyBehavior2', 1);
expect(
eventsFunctionsExtension.getEventsBasedBehaviors().getCount()
).toBe(2);
expect(
eventsFunctionsExtension.getEventsBasedBehaviors().has('MyBehavior1')
).toBe(true);
expect(
eventsFunctionsExtension.getEventsBasedBehaviors().has('MyBehavior2')
).toBe(true);
expect(
eventsFunctionsExtension.getEventsBasedBehaviors().has('MyBehavior3')
).toBe(false);
expect(
eventsFunctionsExtension
.getEventsBasedBehaviors()
.getAt(1)
.getName()
).toBe('MyBehavior2');
expect(
eventsFunctionsExtension
.getEventsBasedBehaviors()
.get('MyBehavior1')
.getName()
).toBe('MyBehavior1');
});
});
describe('gd.EventsBasedBehavior', () => {
it('can have a name, fullname, description', function() {
const eventsBasedBehavior = new gd.EventsBasedBehavior();
eventsBasedBehavior.setName('My name');
eventsBasedBehavior.setFullName('My descriptive name');
eventsBasedBehavior.setDescription('My description');
expect(eventsBasedBehavior.getName()).toBe('My name');
expect(eventsBasedBehavior.getFullName()).toBe('My descriptive name');
expect(eventsBasedBehavior.getDescription()).toBe('My description');
});
});
describe('gd.InstructionMetadata', () => {
it('can have parameters', () => {
const instructionMetadata = new gd.InstructionMetadata();
expect(instructionMetadata.getParametersCount()).toBe(0);
instructionMetadata.addParameter('type', 'label', '', false);
instructionMetadata.setParameterLongDescription('Blabla');
expect(instructionMetadata.getParametersCount()).toBe(1);
expect(instructionMetadata.getParameter(0).getType()).toBe('type');
expect(instructionMetadata.getParameter(0).getDescription()).toBe(
'label'
);
expect(instructionMetadata.getParameter(0).getLongDescription()).toBe(
'Blabla'
);
});
});
describe('gd.ExpressionMetadata', () => {
it('can have parameters', () => {
const expressionMetadata = new gd.ExpressionMetadata(
'extensionNamespace',
'name',
'fullname',
'description',
'group',
'smallicon'
);
expect(expressionMetadata.getFullName()).toBe('fullname');
expect(expressionMetadata.getDescription()).toBe('description');
expect(expressionMetadata.getGroup()).toBe('group');
expect(expressionMetadata.getSmallIconFilename()).toBe('smallicon');
expect(expressionMetadata.isShown()).toBe(true);
expect(expressionMetadata.getParametersCount()).toBe(0);
expressionMetadata.addParameter('type', 'label', '', false);
expressionMetadata.setParameterLongDescription('Blabla');
expect(expressionMetadata.getParametersCount()).toBe(1);
expect(expressionMetadata.getParameter(0).getType()).toBe('type');
expect(expressionMetadata.getParameter(0).getDescription()).toBe('label');
expect(expressionMetadata.getParameter(0).getLongDescription()).toBe(
'Blabla'
);
});
});
});