90 lines
3.4 KiB
JavaScript
90 lines
3.4 KiB
JavaScript
/**
|
||
* rbxl-lua-tween.test.js — тесты TweenService.
|
||
*/
|
||
import { LuaFactory } from 'wasmoon';
|
||
import { registerRobloxApi } from '../src/engine/roblox-shim.js';
|
||
import { RobloxScheduler } from '../src/engine/roblox-scheduler.js';
|
||
import { RobloxTweenManager } from '../src/engine/roblox-tween.js';
|
||
|
||
const SCENE = {
|
||
primitives: {
|
||
1: { id: 1, type: 'cube', name: 'Movable', x: 0, y: 5, z: 0, sx: 1, sy: 1, sz: 1,
|
||
color: '#ffffff', material: 'glossy', anchored: false, canCollide: true, opacity: 1 },
|
||
},
|
||
};
|
||
|
||
async function run(luaSource, ticks = []) {
|
||
const factory = new LuaFactory();
|
||
const lua = await factory.createEngine();
|
||
const sent = [];
|
||
const send = (cmd, payload) => sent.push({ cmd, payload });
|
||
registerRobloxApi(lua, { getSceneSnap: () => SCENE, targetPrimitiveId: 1, send });
|
||
const sched = new RobloxScheduler(lua);
|
||
sched.install();
|
||
const tweenMgr = new RobloxTweenManager();
|
||
tweenMgr.install(lua);
|
||
|
||
await sched.spawnMain(luaSource);
|
||
for (const dt of ticks) {
|
||
await sched.tick(dt);
|
||
tweenMgr.tick(dt);
|
||
}
|
||
lua.global.close();
|
||
return { logs: sent.filter(s => s.cmd === 'log').map(s => s.payload),
|
||
partSets: sent.filter(s => s.cmd === 'partSet').map(s => s.payload) };
|
||
}
|
||
|
||
const TESTS = [
|
||
{
|
||
name: 'TweenInfo создаётся',
|
||
lua: `
|
||
local info = TweenInfo.new(2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out)
|
||
print("time:", info.Time, "style:", info.EasingStyle)
|
||
`,
|
||
ticks: [],
|
||
expectLogs: [{ level: 'info', text: 'time:\t2\tstyle:\tLinear' }],
|
||
},
|
||
{
|
||
name: 'TweenService:Create + Play (Linear)',
|
||
lua: `
|
||
local TS = game:GetService("TweenService")
|
||
local p = workspace:FindFirstChild("Movable")
|
||
local info = TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.Out)
|
||
local tw = TS:Create(p, info, { Position = Vector3.new(10, 5, 0) })
|
||
tw:Play()
|
||
print("started")
|
||
`,
|
||
ticks: [0.5, 0.5, 0.1], // больше 1 сек — должен завершиться
|
||
// Ожидаем что хотя бы один partSet с prop=position
|
||
expectPartSet: { primId: 1, prop: 'position' },
|
||
},
|
||
];
|
||
|
||
(async () => {
|
||
let passed = 0, failed = 0;
|
||
for (const t of TESTS) {
|
||
try {
|
||
const r = await run(t.lua, t.ticks);
|
||
let ok = true;
|
||
let reason = '';
|
||
for (const exp of (t.expectLogs || [])) {
|
||
const found = r.logs.find(l => l.level === exp.level && l.text === exp.text);
|
||
if (!found) { ok = false; reason = `missing log: ${exp.text}`; break; }
|
||
}
|
||
if (t.expectPartSet) {
|
||
const found = r.partSets.find(p => p.primId === t.expectPartSet.primId && p.prop === t.expectPartSet.prop);
|
||
if (!found) {
|
||
ok = false; reason = `missing partSet: ${JSON.stringify(t.expectPartSet)}; got: ${JSON.stringify(r.partSets.slice(0,3))}`;
|
||
}
|
||
}
|
||
if (ok) { console.log(`✓ ${t.name}`); passed++; }
|
||
else { console.log(`✗ ${t.name} — ${reason}`); failed++; }
|
||
} catch (e) {
|
||
console.log(`✗ ${t.name} — exception: ${e}`);
|
||
failed++;
|
||
}
|
||
}
|
||
console.log(`\n${passed} passed, ${failed} failed`);
|
||
process.exit(failed > 0 ? 1 : 0);
|
||
})();
|