Files
GDevelop/GDevelop.js/__tests__/GDJSBehaviorCodeGenerationIntegrationTests.js
T
Florian Rival 7597dbe0d1 Add (new) conditions and expressions to compare the number of instances picked or living on the scene (#3842)
* Add `PickedInstancesCount` and `SceneInstancesCount` expressions, to replace `Count`. These expressions don't do any "picking" of instances, so they are safe to use anywhere without "weird" side effects.
* Equivalent conditions are available for all objects. These conditions allow to check at any point in your events the number of instances living on the scene or picked by actions/conditions.
  * This is useful to check if enough objects are picked by a condition before launching an action. 
  * Because this condition does not change the already picked objects, it's safe to use anywhere without any side effect.

Only show the rest in the developer changelog:
* Allow to read events missing some fields (like `disabled`, `folded`).
* Reduce the useless information stored in project JSON files by not storing the fields if they have their default value.
2022-04-23 16:35:10 +02:00

166 lines
4.8 KiB
JavaScript

const initializeGDevelopJs = require('../../Binaries/embuild/GDevelop.js/libGD.js');
const { makeMinimalGDJSMock } = require('../TestUtils/GDJSMocks');
describe('libGD.js - GDJS Behavior Code Generation integration tests', function () {
let gd = null;
beforeAll((done) =>
initializeGDevelopJs().then((module) => {
gd = module;
done();
})
);
it('generates a working empty behavior', function () {
// Create an empty behavior
const project = new gd.ProjectHelper.createNewGDJSProject();
const eventsBasedBehavior = new gd.EventsBasedBehavior();
eventsBasedBehavior.setName('MyBehavior');
eventsBasedBehavior.setFullName('My descriptive name');
eventsBasedBehavior.setDescription('My description');
const makeCompiledRuntimeBehavior = generateCompiledRuntimeBehaviorMaker(
gd,
project,
eventsBasedBehavior
);
eventsBasedBehavior.delete();
project.delete();
// Instanciate the behavior
const { gdjs, runtimeScene } = makeMinimalGDJSMock();
const CompiledRuntimeBehavior = makeCompiledRuntimeBehavior(gdjs);
const behaviorData = {};
const ownerRuntimeObject = {};
const behavior = new CompiledRuntimeBehavior(
runtimeScene,
behaviorData,
ownerRuntimeObject
);
// Check that doStepPreEvents is always defined
expect(behavior.doStepPreEvents).not.toBeUndefined();
});
it('generates a working behavior with doStepPreEvents using "Trigger Once" condition', function () {
// Create a new behavior with events in doStepPreEvents
const project = new gd.ProjectHelper.createNewGDJSProject();
const eventsBasedBehavior = new gd.EventsBasedBehavior();
eventsBasedBehavior.setName('MyBehavior');
eventsBasedBehavior.setFullName('My descriptive name');
eventsBasedBehavior.setDescription('My description');
const eventsSerializerElement = gd.Serializer.fromJSObject([
{
type: 'BuiltinCommonInstructions::Standard',
conditions: [
{
type: {
value: 'BuiltinCommonInstructions::Once',
},
parameters: [],
},
],
actions: [
{
type: { value: 'ModVarScene' },
parameters: ['SuccessVariable', '+', '1'],
},
],
},
]);
eventsBasedBehavior
.getEventsFunctions()
.insertNewEventsFunction('doStepPreEvents', 0)
.getEvents()
.unserializeFrom(project, eventsSerializerElement);
// Instanciate the behavior twice
const makeCompiledRuntimeBehavior = generateCompiledRuntimeBehaviorMaker(
gd,
project,
eventsBasedBehavior
);
eventsBasedBehavior.delete();
project.delete();
const { gdjs, runtimeScene } = makeMinimalGDJSMock();
const CompiledRuntimeBehavior = makeCompiledRuntimeBehavior(gdjs);
const behaviorData = {};
const ownerRuntimeObject = {};
const behavior = new CompiledRuntimeBehavior(
runtimeScene,
behaviorData,
ownerRuntimeObject
);
const behavior2 = new CompiledRuntimeBehavior(
runtimeScene,
behaviorData,
ownerRuntimeObject
);
// Check that Trigger once is working, separately handled by each behavior instance:
expect(behavior.doStepPreEvents).not.toBeUndefined();
behavior.doStepPreEvents();
behavior2.doStepPreEvents();
expect(runtimeScene.getVariables().has('SuccessVariable')).toBe(true);
expect(
runtimeScene.getVariables().get('SuccessVariable').getAsNumber()
).toBe(2);
behavior.doStepPreEvents();
behavior2.doStepPreEvents();
expect(
runtimeScene.getVariables().get('SuccessVariable').getAsNumber()
).toBe(2);
});
});
function generateCompiledRuntimeBehaviorMaker(
gd,
project,
eventsBasedBehavior
) {
const includeFiles = new gd.SetString();
const codeNamespace = 'behaviorNamespace';
const behaviorCodeGenerator = new gd.BehaviorCodeGenerator(project);
// Generate "mangled names" as required by the code generation
const behaviorMethodMangledNames = new gd.MapStringString();
for (
let i = 0;
i < eventsBasedBehavior.getEventsFunctions().getEventsFunctionsCount();
i++
) {
const eventsFunction = eventsBasedBehavior
.getEventsFunctions()
.getEventsFunctionAt(i);
behaviorMethodMangledNames.set(
eventsFunction.getName(),
eventsFunction.getName()
);
}
const code = behaviorCodeGenerator.generateRuntimeBehaviorCompleteCode(
'MyExtension',
eventsBasedBehavior,
codeNamespace,
behaviorMethodMangledNames,
includeFiles,
true
);
// Create a function with the generated behavior.
const makeCompiledBehavior = new Function(
'gdjs',
`let behaviorNamespace = {};
let Hashtable = gdjs.Hashtable;
${code}
return behaviorNamespace.MyBehavior;`
);
includeFiles.delete();
return makeCompiledBehavior;
}