mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Improve GDJS code generation integration tests
This commit is contained in:

committed by
Florian Rival

parent
b91a2da81c
commit
93e8dd4002
295
GDevelop.js/__tests__/GDJSCodeGenerationIntegrationTests.js
Normal file
295
GDevelop.js/__tests__/GDJSCodeGenerationIntegrationTests.js
Normal file
@@ -0,0 +1,295 @@
|
||||
const initializeGDevelopJs = require('../../Binaries/embuild/GDevelop.js/libGD.js');
|
||||
|
||||
describe('libGD.js - GDJS Code Generation integration tests', function () {
|
||||
let gd = null;
|
||||
beforeAll((done) =>
|
||||
initializeGDevelopJs().then((module) => {
|
||||
gd = module;
|
||||
done();
|
||||
})
|
||||
);
|
||||
|
||||
it('generates a working function for While event', function () {
|
||||
// Create nested events using And and StrEqual conditions
|
||||
const serializerElement = gd.Serializer.fromJSON(
|
||||
JSON.stringify([
|
||||
{
|
||||
disabled: false,
|
||||
folded: false,
|
||||
type: 'BuiltinCommonInstructions::Standard',
|
||||
conditions: [],
|
||||
actions: [
|
||||
{
|
||||
type: { inverted: false, value: 'ModVarScene' },
|
||||
parameters: ['Counter', '=', '0'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
events: [],
|
||||
},
|
||||
{
|
||||
disabled: false,
|
||||
folded: false,
|
||||
infiniteLoopWarning: true,
|
||||
type: 'BuiltinCommonInstructions::While',
|
||||
whileConditions: [
|
||||
{
|
||||
type: { inverted: false, value: 'VarScene' },
|
||||
parameters: ['Counter', '<', '4'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
conditions: [],
|
||||
actions: [
|
||||
{
|
||||
type: { inverted: false, value: 'ModVarScene' },
|
||||
parameters: ['Counter', '+', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
events: [],
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
var runCompiledEvents = generateCompiledEvents(gd, serializerElement);
|
||||
|
||||
const { gdjs, runtimeScene } = makeMinimalGDJSMock();
|
||||
runCompiledEvents(gdjs, runtimeScene);
|
||||
|
||||
expect(runtimeScene.getVariables().has('Counter')).toBe(true);
|
||||
expect(runtimeScene.getVariables().get('Counter').getAsNumber()).toBe(4);
|
||||
});
|
||||
|
||||
it('generates a working function with nested Or and StrEqual', function () {
|
||||
// Create nested events using Or and StrEqual conditions
|
||||
const serializerElement = gd.Serializer.fromJSON(
|
||||
JSON.stringify([
|
||||
{
|
||||
disabled: false,
|
||||
folded: false,
|
||||
type: 'BuiltinCommonInstructions::Standard',
|
||||
conditions: [
|
||||
{
|
||||
type: {
|
||||
inverted: false,
|
||||
value: 'BuiltinCommonInstructions::Or',
|
||||
},
|
||||
parameters: [],
|
||||
subInstructions: [
|
||||
{
|
||||
type: { inverted: false, value: 'Egal' },
|
||||
parameters: ['1', '=', '2'],
|
||||
subInstructions: [],
|
||||
},
|
||||
{
|
||||
type: {
|
||||
inverted: false,
|
||||
value: 'BuiltinCommonInstructions::Or',
|
||||
},
|
||||
parameters: [],
|
||||
subInstructions: [
|
||||
// This should be true and make the entire conditions true.
|
||||
{
|
||||
type: { inverted: false, value: 'StrEqual' },
|
||||
parameters: ['"1"', '=', '"1"'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: { inverted: false, value: 'StrEqual' },
|
||||
parameters: ['"1"', '=', '"2"'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: { inverted: false, value: 'ModVarScene' },
|
||||
parameters: ['SuccessVariable', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
events: [],
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
var runCompiledEvents = generateCompiledEvents(gd, serializerElement);
|
||||
|
||||
const { gdjs, runtimeScene } = makeMinimalGDJSMock();
|
||||
runCompiledEvents(gdjs, runtimeScene);
|
||||
|
||||
expect(runtimeScene.getVariables().has('SuccessVariable')).toBe(true);
|
||||
expect(
|
||||
runtimeScene.getVariables().get('SuccessVariable').getAsNumber()
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
it('generates a working function with nested And and StrEqual', function () {
|
||||
// Create nested events using And and StrEqual conditions
|
||||
const serializerElement = gd.Serializer.fromJSON(
|
||||
JSON.stringify([
|
||||
{
|
||||
disabled: false,
|
||||
folded: false,
|
||||
type: 'BuiltinCommonInstructions::Standard',
|
||||
conditions: [
|
||||
{
|
||||
type: {
|
||||
inverted: false,
|
||||
value: 'BuiltinCommonInstructions::And',
|
||||
},
|
||||
parameters: [],
|
||||
subInstructions: [
|
||||
{
|
||||
type: { inverted: false, value: 'Egal' },
|
||||
parameters: ['1', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
{
|
||||
type: {
|
||||
inverted: false,
|
||||
value: 'BuiltinCommonInstructions::And',
|
||||
},
|
||||
parameters: [],
|
||||
subInstructions: [
|
||||
{
|
||||
type: { inverted: false, value: 'Egal' },
|
||||
parameters: ['1', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
{
|
||||
type: {
|
||||
inverted: false,
|
||||
value: 'BuiltinCommonInstructions::And',
|
||||
},
|
||||
parameters: [],
|
||||
subInstructions: [
|
||||
{
|
||||
type: { inverted: false, value: 'Egal' },
|
||||
parameters: ['1', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
{
|
||||
type: { inverted: false, value: 'StrEqual' },
|
||||
parameters: ['"1"', '=', '"1"'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: { inverted: false, value: 'StrEqual' },
|
||||
parameters: ['"1"', '=', '"1"'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: { inverted: false, value: 'StrEqual' },
|
||||
parameters: ['"1"', '=', '"1"'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: { inverted: false, value: 'ModVarScene' },
|
||||
parameters: ['SuccessVariable', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
events: [],
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
var runCompiledEvents = generateCompiledEvents(gd, serializerElement);
|
||||
|
||||
const { gdjs, runtimeScene } = makeMinimalGDJSMock();
|
||||
runCompiledEvents(gdjs, runtimeScene);
|
||||
|
||||
expect(runtimeScene.getVariables().has('SuccessVariable')).toBe(true);
|
||||
expect(
|
||||
runtimeScene.getVariables().get('SuccessVariable').getAsNumber()
|
||||
).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Generate the code from events (using GDJS platform)
|
||||
* and create a JavaScript function that runs it.
|
||||
*
|
||||
* The JavaScript function must be called with the `runtimeScene` to be used.
|
||||
* In this context, GDJS game engine does not exist, so you must pass a mock
|
||||
* to it to validate that the events are working properly.
|
||||
*/
|
||||
function generateCompiledEvents(gd, eventsSerializerElement) {
|
||||
const project = new gd.ProjectHelper.createNewGDJSProject();
|
||||
const includeFiles = new gd.SetString();
|
||||
const eventsFunction = new gd.EventsFunction();
|
||||
|
||||
eventsFunction.getEvents().unserializeFrom(project, eventsSerializerElement);
|
||||
|
||||
const namespace = 'functionNamespace';
|
||||
const eventsFunctionsExtensionCodeGenerator = new gd.EventsFunctionsExtensionCodeGenerator(
|
||||
project
|
||||
);
|
||||
const code = eventsFunctionsExtensionCodeGenerator.generateFreeEventsFunctionCompleteCode(
|
||||
eventsFunction,
|
||||
namespace,
|
||||
includeFiles,
|
||||
true
|
||||
);
|
||||
|
||||
// Create a function with the generated code.
|
||||
const runCompiledEvents = new Function(
|
||||
'gdjs',
|
||||
'runtimeScene',
|
||||
`${code}
|
||||
return functionNamespace.func(runtimeScene, runtimeScene);`
|
||||
);
|
||||
|
||||
eventsFunctionsExtensionCodeGenerator.delete();
|
||||
eventsFunction.delete();
|
||||
includeFiles.delete();
|
||||
project.delete();
|
||||
|
||||
return runCompiledEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a minimal mock of GDJS with a RuntimeScene (`gdjs.RuntimeScene`),
|
||||
* supporting setting a variable (just enough to validate events logic).
|
||||
*/
|
||||
function makeMinimalGDJSMock() {
|
||||
const runtimeSceneVariables = {};
|
||||
|
||||
return {
|
||||
gdjs: {
|
||||
evtTools: {
|
||||
common: { getVariableNumber: (variable) => variable.getAsNumber() },
|
||||
},
|
||||
},
|
||||
// A minimal implementation of `gdjs.RuntimeScene` and variables for testing:
|
||||
runtimeScene: {
|
||||
getVariables: () => ({
|
||||
get: (variableName) => ({
|
||||
add: (value) => {
|
||||
runtimeSceneVariables[variableName] += value;
|
||||
},
|
||||
setNumber: (value) => {
|
||||
runtimeSceneVariables[variableName] = value;
|
||||
},
|
||||
getAsNumber: () => {
|
||||
return runtimeSceneVariables[variableName];
|
||||
},
|
||||
}),
|
||||
has: (variableName) => !!runtimeSceneVariables[variableName],
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
@@ -1,130 +0,0 @@
|
||||
const initializeGDevelopJs = require('../../Binaries/embuild/GDevelop.js/libGD.js');
|
||||
|
||||
describe('libGD.js - GDJS integration tests', function () {
|
||||
let gd = null;
|
||||
beforeAll((done) =>
|
||||
initializeGDevelopJs().then((module) => {
|
||||
gd = module;
|
||||
done();
|
||||
})
|
||||
);
|
||||
|
||||
describe('EventsFunctionsExtensionCodeGenerator', () => {
|
||||
it('can generate code for an events function', function () {
|
||||
const project = new gd.ProjectHelper.createNewGDJSProject();
|
||||
|
||||
const includeFiles = new gd.SetString();
|
||||
const eventsFunction = new gd.EventsFunction();
|
||||
|
||||
// Create a repeat event with...
|
||||
const eventsList = eventsFunction.getEvents();
|
||||
const serializerElement = gd.Serializer.fromJSON(
|
||||
JSON.stringify([
|
||||
{
|
||||
disabled: false,
|
||||
folded: false,
|
||||
type: 'BuiltinCommonInstructions::Standard',
|
||||
conditions: [
|
||||
{
|
||||
type: {
|
||||
inverted: false,
|
||||
value: 'BuiltinCommonInstructions::And',
|
||||
},
|
||||
parameters: [],
|
||||
subInstructions: [
|
||||
{
|
||||
type: { inverted: false, value: 'Egal' },
|
||||
parameters: ['1', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
{
|
||||
type: {
|
||||
inverted: false,
|
||||
value: 'BuiltinCommonInstructions::And',
|
||||
},
|
||||
parameters: [],
|
||||
subInstructions: [
|
||||
{
|
||||
type: { inverted: false, value: 'Egal' },
|
||||
parameters: ['1', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
{
|
||||
type: {
|
||||
inverted: false,
|
||||
value: 'BuiltinCommonInstructions::And',
|
||||
},
|
||||
parameters: [],
|
||||
subInstructions: [
|
||||
{
|
||||
type: { inverted: false, value: 'Egal' },
|
||||
parameters: ['1', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
{
|
||||
type: { inverted: false, value: 'StrEqual' },
|
||||
parameters: ['"1"', '=', '"1"'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: { inverted: false, value: 'StrEqual' },
|
||||
parameters: ['"1"', '=', '"1"'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: { inverted: false, value: 'StrEqual' },
|
||||
parameters: ['"1"', '=', '"1"'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: { inverted: false, value: 'ModVarScene' },
|
||||
parameters: ['MyVariable', '=', '1'],
|
||||
subInstructions: [],
|
||||
},
|
||||
],
|
||||
events: [],
|
||||
},
|
||||
])
|
||||
);
|
||||
eventsList.unserializeFrom(project, serializerElement);
|
||||
|
||||
const namespace = 'functionNamespace';
|
||||
const eventsFunctionsExtensionCodeGenerator = new gd.EventsFunctionsExtensionCodeGenerator(
|
||||
project
|
||||
);
|
||||
const code = eventsFunctionsExtensionCodeGenerator.generateFreeEventsFunctionCompleteCode(
|
||||
eventsFunction,
|
||||
namespace,
|
||||
includeFiles,
|
||||
true
|
||||
);
|
||||
|
||||
var compiledFunction = new Function(
|
||||
'runtimeScene',
|
||||
`${code}
|
||||
return functionNamespace.func(runtimeScene, runtimeScene);`
|
||||
);
|
||||
expect.assertions(2);
|
||||
compiledFunction({
|
||||
getVariables: () => ({
|
||||
get: (variableName) => {
|
||||
expect(variableName).toBe('MyVariable');
|
||||
return {
|
||||
setNumber: (value) => {
|
||||
expect(value).toBe(1);
|
||||
},
|
||||
};
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user