Add combat regression tests

This commit is contained in:
Admin 2026-09-18 00:34:45 +00:00
parent 44663ba869
commit 90e44264a2

109
tests/game-logic.test.mjs Normal file
View File

@ -0,0 +1,109 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import {
DEFAULT_PIRATE_SHOT_DAMAGE,
PLAYER_HIT_COOLDOWN_MS,
PLAYER_MAX_HULL,
normalizePlayerDamage,
reducePlayerHitQueue,
} from '../src/game-logic.js';
test('first pirate hit removes exactly the default damage and does not end the game', () => {
const result = reducePlayerHitQueue({
hull: PLAYER_MAX_HULL,
lastHitAt: -Infinity,
now: 1000,
damages: [DEFAULT_PIRATE_SHOT_DAMAGE],
});
assert.equal(result.hull, 94);
assert.equal(result.appliedHits, 1);
assert.equal(result.ignoredHits, 0);
assert.equal(result.totalDamage, 6);
assert.equal(result.gameOver, false);
});
test('three cannonballs arriving in one broadside only apply one hull hit', () => {
const result = reducePlayerHitQueue({
hull: 100,
lastHitAt: -Infinity,
now: 2000,
damages: [6, 6, 6],
});
assert.equal(result.hull, 94);
assert.equal(result.appliedHits, 1);
assert.equal(result.ignoredHits, 2);
});
test('hit inside cooldown is ignored and exact cooldown boundary is accepted', () => {
const blocked = reducePlayerHitQueue({
hull: 94,
lastHitAt: 1000,
now: 1000 + PLAYER_HIT_COOLDOWN_MS - 1,
damages: [6],
});
assert.equal(blocked.hull, 94);
assert.equal(blocked.appliedHits, 0);
assert.equal(blocked.ignoredHits, 1);
const accepted = reducePlayerHitQueue({
hull: 94,
lastHitAt: 1000,
now: 1000 + PLAYER_HIT_COOLDOWN_MS,
damages: [6],
});
assert.equal(accepted.hull, 88);
assert.equal(accepted.appliedHits, 1);
});
test('damage normalization handles invalid and extreme values safely', () => {
assert.equal(normalizePlayerDamage(undefined), 6);
assert.equal(normalizePlayerDamage('not-a-number'), 6);
assert.equal(normalizePlayerDamage(999), 25);
assert.equal(normalizePlayerDamage(-12), 1);
assert.equal(normalizePlayerDamage('8'), 8);
});
test('invalid hull state recovers from max hull before applying damage', () => {
const result = reducePlayerHitQueue({
hull: Number.NaN,
lastHitAt: -Infinity,
now: 3000,
damages: [6],
});
assert.equal(result.hull, 94);
assert.equal(result.gameOver, false);
});
test('lethal hit clamps hull at zero and reports game over', () => {
const result = reducePlayerHitQueue({
hull: 5,
lastHitAt: -Infinity,
now: 4000,
damages: [6],
});
assert.equal(result.hull, 0);
assert.equal(result.totalDamage, 6);
assert.equal(result.gameOver, true);
});
test('empty hit queue is a no-op', () => {
const result = reducePlayerHitQueue({
hull: 72,
lastHitAt: 1234,
now: 5000,
damages: [],
});
assert.equal(result.hull, 72);
assert.equal(result.lastHitAt, 1234);
assert.equal(result.appliedHits, 0);
assert.equal(result.ignoredHits, 0);
assert.equal(result.gameOver, false);
});