读取 gameabc_{Object,Layer,GroupList,Image}.json, 跳过 {} 占位槽,
校验多帧图的网格与帧数一致(不符即显式抛错, 不兜底)。
真实数据回归护栏: 991 对象 / 55 界面 / 80 组 / 439 图 / 139 多帧图。
引入 pngjs devDep 供后续切图使用(仅迁移工具, 不进框架运行时)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
79 lines
3.4 KiB
JavaScript
79 lines
3.4 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { join } from 'node:path';
|
|
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { ROOT } from '../lib/paths.mjs';
|
|
import { loadSource, SourceError } from '../ui-migration/gameabc-source.mjs';
|
|
|
|
const REAL_SOURCE = join(ROOT, '..', 'projects', 'Game_Surface_3', 'output');
|
|
|
|
function fakeSource(overrides = {}) {
|
|
const dir = mkdtempSync(join(tmpdir(), 'gameabc-src-'));
|
|
const files = {
|
|
'gameabc_Object.json': {
|
|
ObjectList: [
|
|
{},
|
|
{ Property: { ObjectID: 1, ObjectType: 2, ObjectName: '背景', Left: 0, Top: 0, Width: 1280, Height: 720, BelongLayerID: 1, IndexOfLayer: 1, ImageFileID: 1, FrameStyle: 0, FrameIndex: 0, L9: 0, T9: 0, R9: 0, B9: 0, GroupID: 1, VoiceFileID: 0, TimerInterval: 0 }, Event: { mousedown: 1, mouseup: 1 } },
|
|
],
|
|
},
|
|
'gameabc_Layer.json': { LayerList: [{}, { Property: { LayerID: 1, LayerName: 'Logo_Layer' }, ObjectList: [1] }] },
|
|
'gameabc_GroupList.json': { GroupList: [{ GroupID: 1, ObjectList: [1] }] },
|
|
'gameabc_Image.json': { ImageFileList: [{}, { id: 1, w_all: 1280, h_all: 720, w: 1, h: 1, frame_all: 1, bmp: '00001.png', w1: 1280, h1: 720 }] },
|
|
...overrides,
|
|
};
|
|
for (const [name, content] of Object.entries(files)) {
|
|
writeFileSync(join(dir, name), JSON.stringify(content));
|
|
}
|
|
return dir;
|
|
}
|
|
|
|
test('loadSource 解析对象、层、组、图,并附上 events', () => {
|
|
const dir = fakeSource();
|
|
try {
|
|
const s = loadSource(dir);
|
|
assert.equal(s.objects.size, 1);
|
|
assert.equal(s.objects.get(1).ObjectName, '背景');
|
|
assert.deepEqual(s.objects.get(1).events, ['mousedown', 'mouseup']);
|
|
assert.deepEqual(s.layers, [{ layerId: 1, name: 'Logo_Layer', objectIds: [1] }]);
|
|
assert.deepEqual(s.groups, [{ groupId: 1, objectIds: [1] }]);
|
|
assert.equal(s.images.get(1).bmp, '00001.png');
|
|
} finally { rmSync(dir, { recursive: true, force: true }); }
|
|
});
|
|
|
|
test('loadSource 跳过源数据里的空占位槽 {}', () => {
|
|
const dir = fakeSource();
|
|
try {
|
|
const s = loadSource(dir);
|
|
assert.equal(s.objects.size, 1, '首个 {} 占位不应变成对象');
|
|
assert.equal(s.layers.length, 1);
|
|
} finally { rmSync(dir, { recursive: true, force: true }); }
|
|
});
|
|
|
|
test('loadSource 对网格与帧数不符的图显式抛错(不兜底)', () => {
|
|
const dir = fakeSource({
|
|
'gameabc_Image.json': { ImageFileList: [{}, { id: 1, w_all: 100, h_all: 100, w: 3, h: 4, frame_all: 11, bmp: 'bad.png', w1: 33, h1: 25 }] },
|
|
});
|
|
try {
|
|
assert.throws(() => loadSource(dir), SourceError);
|
|
assert.throws(() => loadSource(dir), /bad\.png/);
|
|
} finally { rmSync(dir, { recursive: true, force: true }); }
|
|
});
|
|
|
|
test('loadSource 对缺失文件显式抛错', () => {
|
|
const dir = mkdtempSync(join(tmpdir(), 'gameabc-empty-'));
|
|
try {
|
|
assert.throws(() => loadSource(dir), /缺少源数据文件/);
|
|
} finally { rmSync(dir, { recursive: true, force: true }); }
|
|
});
|
|
|
|
test('loadSource 在真实源数据上得到已知规模(回归护栏)', () => {
|
|
const s = loadSource(REAL_SOURCE);
|
|
assert.equal(s.objects.size, 991, '对象总数');
|
|
assert.equal(s.layers.length, 55, '界面数');
|
|
assert.equal(s.groups.length, 80, '分组数');
|
|
assert.equal(s.images.size, 439, '图片数');
|
|
const multi = [...s.images.values()].filter((i) => i.frame_all > 1);
|
|
assert.equal(multi.length, 139, '多帧图数');
|
|
});
|