1
0
Fork 0
tsgames/test/common/rpg/cooldown.test.ts

170 lines
5.1 KiB
TypeScript

import { describe, it, expect } from 'bun:test';
import { World } from '@common/rpg/core/world';
import { Cooldown } from '@common/rpg/components/cooldown';
import { CooldownSystem } from '@common/rpg/systems/cooldown';
function world() {
const w = new World();
w.addSystem(new CooldownSystem());
return w;
}
describe('Cooldown — initial state', () => {
it('starts not ready', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(5));
expect(e.get(Cooldown, 'cd')!.ready).toBeFalse();
});
it('remaining equals duration on creation', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(3));
const cd = e.get(Cooldown, 'cd')!;
expect(cd.state.remaining).toBe(3);
expect(cd.state.duration).toBe(3);
});
});
describe('Cooldown — clear()', () => {
it('marks as ready immediately', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(10));
const cd = e.get(Cooldown, 'cd')!;
cd.clear();
expect(cd.ready).toBeTrue();
});
it("emits 'ready' event", () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(10));
const events: unknown[] = [];
e.on('cd.ready', () => events.push(true));
e.get(Cooldown, 'cd')!.clear();
expect(events.length).toBe(1);
});
it('is no-op when already ready', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(1));
const cd = e.get(Cooldown, 'cd')!;
cd.clear();
const events: unknown[] = [];
e.on('cd.ready', () => events.push(true));
cd.clear();
expect(events.length).toBe(0);
});
});
describe('Cooldown — reset()', () => {
it('resets remaining to duration', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(5));
const cd = e.get(Cooldown, 'cd')!;
cd.clear();
cd.reset();
expect(cd.ready).toBeFalse();
expect(cd.state.remaining).toBe(5);
});
it('reset(duration) changes duration and remaining', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(5));
const cd = e.get(Cooldown, 'cd')!;
cd.reset(10);
expect(cd.state.duration).toBe(10);
expect(cd.state.remaining).toBe(10);
});
});
describe('Cooldown — update(dt)', () => {
it('counts down remaining', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(5));
const cd = e.get(Cooldown, 'cd')!;
cd.update(2);
expect(cd.state.remaining).toBe(3);
expect(cd.ready).toBeFalse();
});
it('becomes ready when remaining reaches zero', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(3));
const cd = e.get(Cooldown, 'cd')!;
cd.update(3);
expect(cd.ready).toBeTrue();
});
it("emits 'ready' when countdown completes", () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(2));
const events: unknown[] = [];
e.on('cd.ready', () => events.push(true));
e.get(Cooldown, 'cd')!.update(2);
expect(events.length).toBe(1);
});
it('does not go below zero', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(1));
const cd = e.get(Cooldown, 'cd')!;
cd.update(100);
expect(cd.state.remaining).toBe(0);
});
it('is no-op when already ready', () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(1));
const cd = e.get(Cooldown, 'cd')!;
cd.clear();
const events: unknown[] = [];
e.on('cd.ready', () => events.push(true));
cd.update(1);
expect(events.length).toBe(0);
});
});
describe('CooldownSystem', () => {
it('drives all cooldowns each tick', async () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(2));
await w.update(1);
expect(e.get(Cooldown, 'cd')!.state.remaining).toBe(1);
});
it('marks cooldown ready after enough ticks', async () => {
const w = world();
const e = w.createEntity();
e.add('cd', new Cooldown(2));
const events: unknown[] = [];
e.on('cd.ready', () => events.push(true));
await w.update(1);
await w.update(1);
expect(events.length).toBe(1);
expect(e.get(Cooldown, 'cd')!.ready).toBeTrue();
});
it('handles multiple cooldowns on different entities', async () => {
const w = world();
const a = w.createEntity('a');
const b = w.createEntity('b');
a.add('cd', new Cooldown(1));
b.add('cd', new Cooldown(3));
await w.update(2);
expect(a.get(Cooldown, 'cd')!.ready).toBeTrue();
expect(b.get(Cooldown, 'cd')!.ready).toBeFalse();
});
});