airship-phaser-deploy/tests/assets.test.mjs

118 lines
4.3 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import topHud from '../src/assets/controller/top-hud.js';
import leftStatus from '../src/assets/controller/left-status.js';
import rightControls from '../src/assets/controller/right-controls.js';
import cannonRoundel from '../src/assets/controller/cannon-roundel.js';
import helmFrame from '../src/assets/controller/helm-frame.js';
import helmKnob from '../src/assets/controller/helm-knob.js';
import playerHealth from '../src/assets/controller/player-health.js';
import playerHealthHqFrame from '../src/assets/controller/player-health-hq-frame.js';
import enemyHealth from '../src/assets/controller/enemy-health.js';
const assets = {
topHud,
leftStatus,
rightControls,
cannonRoundel,
helmFrame,
helmKnob,
playerHealth,
enemyHealth,
};
const decodeWebP = (name, dataUrl) => {
const match = /^data:image\/webp;base64,([A-Za-z0-9+/=]+)$/.exec(dataUrl);
assert.ok(match, `${name} must be a WebP data URL`);
const bytes = Buffer.from(match[1], 'base64');
assert.equal(bytes.subarray(0, 4).toString('ascii'), 'RIFF', `${name} RIFF header`);
assert.equal(bytes.subarray(8, 12).toString('ascii'), 'WEBP', `${name} WEBP signature`);
const declaredSize = bytes.readUInt32LE(4) + 8;
assert.equal(
bytes.length,
declaredSize,
`${name} must not be truncated: declared ${declaredSize}, actual ${bytes.length}`,
);
assert.ok(bytes.length > 100, `${name} should contain real image data`);
};
for (const [name, dataUrl] of Object.entries(assets)) {
test(`${name} WebP payload is structurally complete`, () => {
decodeWebP(name, dataUrl);
});
}
const alphaAssets = {
topHud,
playerHealth,
enemyHealth,
};
for (const [name, dataUrl] of Object.entries(alphaAssets)) {
test(`${name} carries WebP transparency data`, () => {
const match = /^data:image\/webp;base64,([A-Za-z0-9+/=]+)$/.exec(dataUrl);
assert.ok(match, `${name} must be a WebP data URL`);
const bytes = Buffer.from(match[1], 'base64');
const hasAlphaChunk = bytes.includes(Buffer.from('ALPH'));
const usesLosslessWebP = bytes.includes(Buffer.from('VP8L'));
assert.ok(hasAlphaChunk || usesLosslessWebP, `${name} should preserve transparent background data`);
});
}
const webpDimensions = (name, dataUrl) => {
const match = /^data:image\/webp;base64,([A-Za-z0-9+/=]+)$/.exec(dataUrl);
assert.ok(match, `${name} must be a WebP data URL`);
const bytes = Buffer.from(match[1], 'base64');
let offset = 12;
while (offset + 18 <= bytes.length) {
const type = bytes.subarray(offset, offset + 4).toString('ascii');
const size = bytes.readUInt32LE(offset + 4);
const dataOffset = offset + 8;
if (type === 'VP8X') {
const width =
1 +
bytes[dataOffset + 4] +
(bytes[dataOffset + 5] << 8) +
(bytes[dataOffset + 6] << 16);
const height =
1 +
bytes[dataOffset + 7] +
(bytes[dataOffset + 8] << 8) +
(bytes[dataOffset + 9] << 16);
return { width, height };
}
offset = dataOffset + size + (size % 2);
}
assert.fail(`${name} must expose VP8X dimensions`);
};
test('playerHealth native frame preserves usable HUD resolution', () => {
const { width, height } = webpDimensions('playerHealth', playerHealth);
assert.ok(width >= 300, `playerHealth width must stay >= 300px, got ${width}px`);
assert.ok(height >= 96, `playerHealth height must stay >= 96px, got ${height}px`);
});
test('enemyHealth health sheet stays high resolution', () => {
const { width, height } = webpDimensions('enemyHealth', enemyHealth);
assert.ok(width >= 1200, `enemyHealth width must stay >= 1200px, got ${width}px`);
assert.ok(height >= 300, `enemyHealth height must stay >= 300px, got ${height}px`);
assert.ok(width / 4 >= 300, 'enemyHealth frame width must stay >= 300px');
assert.ok(height / 3 >= 100, 'enemyHealth frame height must stay >= 100px');
});
test('high-resolution player health frame is complete and retina-ready', () => {
decodeWebP('playerHealthHqFrame', playerHealthHqFrame);
const { width, height } = webpDimensions('playerHealthHqFrame', playerHealthHqFrame);
assert.ok(width >= 600, `playerHealthHqFrame width must stay >= 600px, got ${width}px`);
assert.ok(height >= 216, `playerHealthHqFrame height must stay >= 216px, got ${height}px`);
});