fix(tools): skin.mjs 显式报错尺寸不可读,补全测试覆盖

Finding 1: 尺寸校验不能无声跳过(null 被当作通过)。
新增 size-unreadable 错误码,当图片无法读取尺寸时显式报错。

Finding 2: 测试 10 是伪测试(.wav 太短,被长度守卫拦下)。
改用真实 PNG 字节但 .wav 扩展名,验证 isImage() 门控在。

新增两条用例:
- size-unreadable 错误场景(override 侧非 PNG)
- PNG 签名检查(长度足够但签名不对)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-27 21:32:01 +08:00
co-authored by Claude Opus 5
parent 000f9e4290
commit 44264db8ba
2 changed files with 42 additions and 3 deletions
@@ -147,13 +147,41 @@ test('图片尺寸不同但自带 meta(例外通道)→ 通过', () => {
test('非图片资源(音效)不做尺寸校验', () => {
const d = makeDirs();
try {
writeFile(d.fw, 'audio/click.wav', 'aaaa');
writeFile(d.ov, 'audio/click.wav', 'bbbbbbbbbbbb');
// 用真实的、有效的、尺寸不同的 PNG 字节,但扩展名是 .wav
// 如果 isImage() 门控被删掉,因为尺寸不同会报 size-mismatch,用例失败
writeFile(d.fw, 'audio/click.wav', makePng(64, 64));
writeFile(d.ov, 'audio/click.wav', makePng(256, 256));
const r = validateOverrides(d.fw, d.ov);
assert.deepEqual(r.errors, []);
} finally { cleanup(d.root); }
});
// ---- validateOverrides:尺寸不可读 ----
test('图片尺寸无法读取(非 PNG)→ size-unreadable', () => {
const d = makeDirs();
try {
png(d.fw, 'atlas-hall/btn.png', 64, 64);
writeFile(d.ov, 'atlas-hall/btn.png', 'this is not a png but it is long enough to pass the 24-byte length check');
const r = validateOverrides(d.fw, d.ov);
assert.equal(r.errors.length, 1);
assert.equal(r.errors[0].code, 'size-unreadable');
assert.match(r.errors[0].message, /无法读取尺寸/);
assert.match(r.errors[0].message, /PNG/);
assert.equal(r.matched.length, 0);
} finally { cleanup(d.root); }
});
test('readPngSize 长度足够但签名不对 → 返回 null', () => {
const d = makeDirs();
try {
// 构造一个 24 字节以上、但 PNG 签名不对的数据
const buf = Buffer.alloc(30, 0x00);
buf.write('NOTPNG', 1, 'ascii');
const p = writeFile(d.fw, 'test.png', buf);
assert.equal(readPngSize(p), null);
} finally { cleanup(d.root); }
});
// ---- validateOverrides:Spine ----
test('Spine 整套覆盖 → 通过,且贴图豁免尺寸校验', () => {
const d = makeDirs();