0ad/binaries/data/mods/public/simulation/components/tests/setup.js
Freagarach 2c33c28a09 Add the ability to do simple (de)serialisation cycle in the JS unit tests. (And change the PQ, Trainer and Researcher serialisation.)
To catch e.g. typos.

- Use the same structure in the ProductionQueue item (de)serialisation
as in Trainer and Researcher.
- Also iterate over the serialisable attributes on deserialize, as
proposed by @elexis (on IRC), for its symmetry.

Proposed by: @Stan
Differential revision: D4388
This was SVN commit r26133.
2021-12-28 08:23:59 +00:00

166 lines
3.2 KiB
JavaScript

var g_NewIID = 1000; // some arbitrary not-yet-used number
var g_NewMTID = 1000; // some arbitrary not-yet-used number
var g_ComponentTypes = {};
var g_Components = {};
// Emulate some engine functions:
Engine.RegisterComponentType = function(iid, name, ctor)
{
TS_ASSERT(!g_ComponentTypes[name]);
g_ComponentTypes[name] = { "iid": iid, "ctor": ctor };
};
Engine.RegisterSystemComponentType = function(iid, name, ctor)
{
TS_ASSERT(!g_ComponentTypes[name]);
g_ComponentTypes[name] = { "iid": iid, "ctor": ctor };
};
Engine.RegisterInterface = function(name)
{
global["IID_" + name] = g_NewIID++;
};
Engine.RegisterMessageType = function(name)
{
global["MT_" + name] = g_NewMTID++;
};
Engine.QueryInterface = function(ent, iid)
{
if (g_Components[ent] && g_Components[ent][iid])
return g_Components[ent][iid];
return null;
};
Engine.RegisterGlobal = function(name, value)
{
global[name] = value;
};
Engine.DestroyEntity = function(ent)
{
for (let cid in g_Components[ent])
{
let cmp = g_Components[ent][cid];
if (cmp && cmp.Deinit)
cmp.Deinit();
}
delete g_Components[ent];
// TODO: should send Destroy message
};
Engine.PostMessage = function(ent, iid, message)
{
// TODO: make this send a message if necessary
};
Engine.BroadcastMessage = function(iid, message)
{
// TODO: make this send a message if necessary
};
global.ResetState = function()
{
g_Components = {};
};
global.AddMock = function(ent, iid, mock)
{
if (!g_Components[ent])
g_Components[ent] = {};
g_Components[ent][iid] = mock;
return g_Components[ent][iid];
};
global.DeleteMock = function(ent, iid)
{
if (!g_Components[ent])
g_Components[ent] = {};
delete g_Components[ent][iid];
};
global.ConstructComponent = function(ent, name, template)
{
let cmp = new g_ComponentTypes[name].ctor();
Object.defineProperties(cmp, {
"entity": {
"value": ent,
"configurable": false,
"enumerable": false,
"writable": false
},
"template": {
"value": template && deepfreeze(clone(template)),
"configurable": false,
"enumerable": false,
"writable": false
},
"_cmpName": {
"value": name,
"configurable": false,
"enumerable": false,
"writable": false
}
});
cmp.Init();
if (!g_Components[ent])
g_Components[ent] = {};
g_Components[ent][g_ComponentTypes[name].iid] = cmp;
return cmp;
};
/**
* A simple Spy proxy that tracks and forward function calls.
* NB: this immediately replaces obj's func.
*/
global.Spy = function(obj, func)
{
this._called = 0;
this._callargs = [];
let og_func = obj[func];
let spy = (...args) => {
++this._called;
this._callargs.push(args);
return og_func.apply(obj, args);
};
obj[func] = spy;
this._reset = () => {
this._called = 0;
this._callargs = [];
};
return this;
};
global.SerializationCycle = function(cmp)
{
let data;
if (typeof cmp.Serialize === "function")
data = cmp.Serialize();
else
{
data = {};
for (const att of cmp)
if (cmp.hasOwnProperty(att))
data[att] = cmp[att];
}
const newCmp = ConstructComponent(cmp.entity, cmp._cmpName, cmp.template);
if (typeof newCmp.Deserialize === "function")
newCmp.Deserialize(data);
else
for (const att in data)
newCmp[att] = data[att];
return newCmp;
};