RED: scaffold.test.js — 17 tests for constants, Phaser config, fixtures GREEN: src/constants.js (25 GDD-derived values), src/main.js (CANVAS + arcade) GREEN: webpack.config.js + .babelrc + index.html (dark theme) GREEN: Dockerfile (nginx:alpine) + docker-compose.yml (Traefik + CF Tunnel) GREEN: jest-canvas-mock + tests/helpers/setup.js (headless Phaser) Verified: npm run build -> dist/, docker deploy -> https://iron-requiem.damascusfront.net
145 lines
4.5 KiB
JavaScript
145 lines
4.5 KiB
JavaScript
/**
|
|
* Scaffold tests — Slice 1 foundation verification.
|
|
*
|
|
* Tests that the project skeleton compiles, the Phaser game config
|
|
* is valid, and all game balance constants are defined and in range.
|
|
*/
|
|
|
|
const { createHeadlessGame } = require('./helpers/setup');
|
|
const { createTankState, createCrewState } = require('./helpers/fixtures');
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Constants validation
|
|
// ---------------------------------------------------------------------------
|
|
describe('Game constants', () => {
|
|
let constants;
|
|
|
|
beforeAll(() => {
|
|
constants = require('../src/constants');
|
|
});
|
|
|
|
test('TANK_MAX_SPEED is a positive number', () => {
|
|
expect(constants.TANK_MAX_SPEED).toBeGreaterThan(0);
|
|
expect(typeof constants.TANK_MAX_SPEED).toBe('number');
|
|
});
|
|
|
|
test('TANK_ACCELERATION is a positive number', () => {
|
|
expect(constants.TANK_ACCELERATION).toBeGreaterThan(0);
|
|
expect(typeof constants.TANK_ACCELERATION).toBe('number');
|
|
});
|
|
|
|
test('TANK_FRICTION is a positive number', () => {
|
|
expect(constants.TANK_FRICTION).toBeGreaterThan(0);
|
|
expect(typeof constants.TANK_FRICTION).toBe('number');
|
|
});
|
|
|
|
test('TURRET_MAX_ROTATION equals 15 deg/sec', () => {
|
|
expect(constants.TURRET_MAX_ROTATION).toBe(15);
|
|
});
|
|
|
|
test('MORALE_MAX is 100', () => {
|
|
expect(constants.MORALE_MAX).toBe(100);
|
|
});
|
|
|
|
test('MORALE_BUFF_THRESHOLD is 70', () => {
|
|
expect(constants.MORALE_BUFF_THRESHOLD).toBe(70);
|
|
});
|
|
|
|
test('MORALE_RECOVERY_RATE is a positive number', () => {
|
|
expect(constants.MORALE_RECOVERY_RATE).toBeGreaterThan(0);
|
|
expect(typeof constants.MORALE_RECOVERY_RATE).toBe('number');
|
|
});
|
|
|
|
test('HEAT_MAX is 100', () => {
|
|
expect(constants.HEAT_MAX).toBe(100);
|
|
});
|
|
|
|
test('heat rates are positive numbers', () => {
|
|
expect(constants.HEAT_IDLE_RATE).toBeGreaterThan(0);
|
|
expect(constants.HEAT_MAX_SPEED_RATE).toBeGreaterThan(0);
|
|
expect(constants.HEAT_COOLING_RATE).toBeGreaterThan(0);
|
|
});
|
|
|
|
test('PERISCOPE_FOV is 180 degrees', () => {
|
|
expect(constants.PERISCOPE_FOV).toBe(180);
|
|
});
|
|
|
|
test('PERISCOPE_RANGE is 200 pixels', () => {
|
|
expect(constants.PERISCOPE_RANGE).toBe(200);
|
|
});
|
|
|
|
test('UNBUTTONED_FOV is 270 degrees', () => {
|
|
expect(constants.UNBUTTONED_FOV).toBe(270);
|
|
});
|
|
|
|
test('UNBUTTONED_RANGE is 350 pixels', () => {
|
|
expect(constants.UNBUTTONED_RANGE).toBe(350);
|
|
});
|
|
|
|
test('all required constants are defined', () => {
|
|
const required = [
|
|
'TANK_MAX_SPEED',
|
|
'TANK_ACCELERATION',
|
|
'TANK_FRICTION',
|
|
'TURRET_MAX_ROTATION',
|
|
'MORALE_MAX',
|
|
'MORALE_BUFF_THRESHOLD',
|
|
'MORALE_RECOVERY_RATE',
|
|
'HEAT_MAX',
|
|
'HEAT_IDLE_RATE',
|
|
'HEAT_MAX_SPEED_RATE',
|
|
'HEAT_COOLING_RATE',
|
|
'PERISCOPE_FOV',
|
|
'PERISCOPE_RANGE',
|
|
'UNBUTTONED_FOV',
|
|
'UNBUTTONED_RANGE',
|
|
];
|
|
for (const key of required) {
|
|
expect(constants).toHaveProperty(key);
|
|
}
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Phaser game config
|
|
// ---------------------------------------------------------------------------
|
|
describe('Phaser game config', () => {
|
|
test('game config has the correct properties', () => {
|
|
// Verify the config object from main.js without actually booting a game
|
|
// (Phaser HEADLESS still needs a real canvas implementation in jsdom)
|
|
const config = require('../src/main').gameConfig;
|
|
|
|
expect(config.type).toBeDefined();
|
|
expect(config.width).toBe(640);
|
|
expect(config.height).toBe(360);
|
|
expect(config.pixelArt).toBe(true);
|
|
expect(config.roundPixels).toBe(true);
|
|
expect(config.physics).toBeDefined();
|
|
expect(config.physics.default).toBe('arcade');
|
|
expect(config.physics.arcade.gravity).toEqual({ x: 0, y: 0 });
|
|
expect(config.scene).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Fixtures
|
|
// ---------------------------------------------------------------------------
|
|
describe('Test fixtures', () => {
|
|
test('createTankState returns defaults and accepts overrides', () => {
|
|
const state = createTankState();
|
|
expect(state.x).toBe(320);
|
|
expect(state.y).toBe(180);
|
|
expect(state.isButtonedUp).toBe(true);
|
|
|
|
const custom = createTankState({ x: 100, isButtonedUp: false });
|
|
expect(custom.x).toBe(100);
|
|
expect(custom.isButtonedUp).toBe(false);
|
|
});
|
|
|
|
test('createCrewState defaults morale to 50', () => {
|
|
const state = createCrewState();
|
|
expect(state.morale).toBe(50);
|
|
expect(state.commanderAlive).toBe(true);
|
|
});
|
|
});
|