Files
AnimationDirector-Blockbenc…/test/stage-autoplay.test.js
T
2026-09-29 14:54:06 +02:00

67 lines
3.5 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const vm = require('node:vm');
function harness() {
const h = { Plugin: { register() {} }, Animation: { selected: null, all: [] }, Format: { id: 'geckolib_model' },
Animator: { preview() { h.rendered = h.Animation.selected; } },
Timeline: { playing: true, custom_range: [0, 0], loop() { this.playing = false; }, setTime(time) { this.time = time; }, start() { this.playing = true; this.loop(); } } };
const source = fs.readFileSync(path.join(__dirname, '..', 'AnimationDirector.js'), 'utf8').replace(' Plugin.register(PLUGIN_ID, {',
' globalThis.api = { installStageAutoplay, removeStageAutoplay, nextAutoplayStage, setEnabled(value) { autoplayStagesAction = { value }; } };\n Plugin.register(PLUGIN_ID, {');
vm.runInNewContext(source, h);
h.clip = (name, loop = 'once') => ({ name, length: 2, loop, select() { h.Animation.selected = this; } });
h.api.setEnabled(true); h.api.installStageAutoplay();
return h;
}
test('autoplay advances completed non-looping stages by number within the same ID', () => {
const h = harness(), first = h.clip('example.p1'), next = h.clip('example.p2');
h.Animation.selected = first; h.Animation.all = [h.clip('other.p2'), h.clip('example.p10'), next, first];
h.Timeline.loop();
assert.equal(h.Animation.selected, next);
assert.equal(h.Timeline.time, 0);
assert.equal(h.Timeline.playing, true);
assert.equal(h.rendered, next);
});
test('autoplay leaves looping stages, custom ranges, disabled toggle and final stage alone', () => {
for (const mode of ['loop', 'range', 'disabled', 'final']) {
const h = harness(), first = h.clip('example.p1', mode === 'loop' ? 'loop' : 'hold');
h.Animation.selected = first; h.Animation.all = mode === 'final' ? [first] : [first, h.clip('example.p2')];
if (mode === 'range') h.Timeline.custom_range = [0, 1];
if (mode === 'disabled') h.api.setEnabled(false);
h.Timeline.loop();
assert.equal(h.pending, undefined);
assert.equal(h.Animation.selected, first);
}
});
test('manual playback stops do not advance and unload restores playback', () => {
const h = harness(), first = h.clip('example.p1'), next = h.clip('example.p2');
h.Animation.selected = first; h.Animation.all = [first, next];
h.Timeline.playing = false; h.Timeline.loop();
assert.equal(h.pending, undefined);
assert.equal(h.Animation.selected, first);
assert.equal(h.Timeline.playing, false);
const wrapper = h.Timeline.loop; h.api.removeStageAutoplay();
assert.notEqual(h.Timeline.loop, wrapper);
});
test('autoplay overrides global looping for once stages and restores it even on failure', () => {
const h = harness(); h.api.removeStageAutoplay();
h.BarItems = { looped_animation_playback: { value: true } };
h.Timeline.loop = function() { if (!h.BarItems.looped_animation_playback.value) this.playing = false; };
const first = h.clip('example.p1'), next = h.clip('example.p2');
h.Animation.selected = first; h.Animation.all = [first, next];
h.api.installStageAutoplay(); h.Timeline.loop();
assert.equal(h.Animation.selected, next);
assert.equal(h.BarItems.looped_animation_playback.value, true);
h.api.removeStageAutoplay();
h.Timeline.loop = () => { throw new Error('preview failed'); };
h.api.installStageAutoplay();
assert.throws(() => h.Timeline.loop(), /preview failed/);
assert.equal(h.BarItems.looped_animation_playback.value, true);
});