'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); console.log('PASS: Eagle routing, case handling, ordinary-file exclusion, cache isolation and late-arriving skeleton'); } finally { fs.rmSync(root, { recursive: true, force: true }); }