Files
SpineViewer/tests/compound-extensions.test.js
2026-09-11 14:02:48 +08:00

50 lines
3.2 KiB
JavaScript

'use strict';
const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const os = require('os');
const utils = require('../js/spine-utils');
const manifest = require('../manifest.json');
const registered = Object.keys(manifest.preview).flatMap(key => key.split(','));
// Eagle uses path.extname for item.ext, then dispatches by that exact key.
for (const name of ['hero.atlas.txt', 'hero.skel.bytes', 'HERO.ATLAS.TXT', 'HERO.SKEL.BYTES']) {
assert(registered.includes(path.extname(name).slice(1).toLowerCase()));
assert.equal(utils.stemOf(name).toLowerCase(), 'hero');
}
for (const name of ['notes.txt', 'payload.bytes', 'hero.atlas.txt.bak']) assert.equal(utils.extOf(name), null);
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'spine-extensions-test-'));
try {
// Sibling directories with identical filenames must not share stale indexes.
for (const version of ['3.4', '3.5', '3.6', '3.7', '3.8', '4.0', '4.1', '4.2', '4.3']) {
const directory = path.join(root, version); fs.mkdirSync(directory);
const skeleton = path.join(directory, 'hero.skel.bytes');
const atlas = path.join(directory, 'hero.atlas.txt');
// These tests cover routing/discovery; real binary decoding is tested by
// legacy-binary.test.js and the all-version official sample smoke tests.
fs.writeFileSync(skeleton, Buffer.from('\0' + version + '.1\0'));
fs.writeFileSync(atlas, 'hero.png\nsize: 64,64\nformat: RGBA8888\nfilter: Linear,Linear\nrepeat: none\nregion\n rotate: false\n xy: 0,0\n size: 64,64\n');
fs.writeFileSync(path.join(directory, 'hero.png'), 'texture');
for (const selected of [skeleton, atlas]) for (const strictStem of [false, true]) {
const assets = utils.discoverAssets(selected, { strictStem });
assert.equal(assets.skeletonPath, skeleton); assert.equal(assets.atlasPath, atlas);
assert.equal(assets.isBinary, true); assert.equal(utils.chooseRuntimeDir(utils.detectVersion(skeleton), true), version);
}
}
const late = path.join(root, 'late'); fs.mkdirSync(late);
const lateAtlas = path.join(late, 'hero.atlas.txt'); fs.writeFileSync(lateAtlas, 'hero.png\nsize: 64,64\n');
assert.equal(utils.discoverAssets(lateAtlas, { strictStem: true }).skeletonPath, null);
const lateSkeleton = path.join(late, 'hero.skel.bytes'); fs.writeFileSync(lateSkeleton, Buffer.from('\0' + '3.8.1\0'));
assert.equal(utils.discoverAssets(lateAtlas, { strictStem: true, refreshIndex: true }).skeletonPath, lateSkeleton);
for (const [name, json, expected] of [
['spine.json', { skeleton: { spine: '4.2.43' }, bones: [] }, 'spine'],
['empty-version.json', { skeleton: { spine: '' }, bones: [] }, 'other'],
['null-version.json', { skeleton: { spine: null }, bones: [] }, 'other'],
['fake-version.json', { skeleton: { spine: 'latest' }, bones: [] }, 'other'],
['ordinary.json', { bones: [], slots: [] }, 'other'],
]) {
const file = path.join(root, name); fs.writeFileSync(file, JSON.stringify(json));
assert.equal(utils.classifySkeletonJson(file), expected, name);
}
console.log('PASS: Eagle routing, case handling, ordinary-file exclusion, cache isolation and late-arriving skeleton');
} finally { fs.rmSync(root, { recursive: true, force: true }); }