Files
GDevelop/GDevelop.js/__tests__/GDJSBehaviorCodeGenerationIntegrationTests.js
T
Florian Rival b76df0247d Fix "Trigger Once" not working properly when used in a behavior
Don't show the rest in the changelog:

This was because the OnceTriggers were shared with the runtime scene. Now each behavior has its set of Once Triggers. This means that Once Triggers "survive" if the behavior is deactivated then activated again.

Added integration test for generated behavior

Fix #1843
2020-07-06 23:47:17 +02:00

172 lines
5.0 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([
{
disabled: false,
folded: false,
type: 'BuiltinCommonInstructions::Standard',
conditions: [
{
type: {
inverted: false,
value: 'BuiltinCommonInstructions::Once',
},
parameters: [],
subInstructions: [],
},
],
actions: [
{
type: { inverted: false, value: 'ModVarScene' },
parameters: ['SuccessVariable', '+', '1'],
subInstructions: [],
},
],
events: [],
},
]);
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;
}