@civ-clone/core-city-build
Version:
The repo contains the `CityBuild` and associated objects that deal with building items in `City`s.
164 lines (126 loc) • 4.9 kB
text/typescript
import { Build, IBuildCriterion } from '../Rules/Build';
import { Horseman, Spearman, Warrior } from '@civ-clone/civ1-unit/Units';
import {
Barracks,
Granary,
Temple,
} from '@civ-clone/civ1-city-improvement/CityImprovements';
import { expect, use, spy } from 'chai';
import AvailableCityBuildItemsRegistry from '../AvailableCityBuildItemsRegistry';
import { BuildProgress } from '../Yields';
import Buildable from '../Buildable';
import BuildingCancelled from '../Rules/BulidingCancelled';
import BuildingComplete from '../Rules/BulidingComplete';
import CityBuild from '../CityBuild';
import Criterion from '@civ-clone/core-rule/Criterion';
import Effect from '@civ-clone/core-rule/Effect';
import RuleRegistry from '@civ-clone/core-rule/RuleRegistry';
import { buildCost } from '../Rules/BuildCost';
import { setUpCity } from '@civ-clone/civ1-city/tests/lib/setUpCity';
import * as spies from 'chai-spies';
use(spies);
describe('CityBuild', (): void => {
class Unit extends Buildable {
public static build() {
return new Unit();
}
}
it('should be possible to register well defined items', async () => {
const availableBuildItemsRegistry = new AvailableCityBuildItemsRegistry();
availableBuildItemsRegistry.register(
Horseman,
Spearman,
Warrior,
Barracks,
Granary,
Temple
);
});
it('should have expected initial state', async (): Promise<void> => {
const cityBuild = new CityBuild(await setUpCity());
expect(cityBuild.progress().value()).equal(0);
expect(cityBuild.cost().value()).equal(Infinity);
expect(cityBuild.building()).null;
});
it('should correctly use `Rule`s to determine the cost and availability of BuildItems', async (): Promise<void> => {
const availableBuildItemsRegistry = new AvailableCityBuildItemsRegistry(),
ruleRegistry = new RuleRegistry(),
cityBuild = new CityBuild(
await setUpCity(),
availableBuildItemsRegistry,
ruleRegistry
),
effectSpy = spy();
ruleRegistry.register(
new Build(new Effect((): IBuildCriterion => new Criterion(() => true))),
new BuildingCancelled(new Effect(effectSpy))
);
expect(() => cityBuild.build(Unit)).throw(TypeError);
availableBuildItemsRegistry.register(Unit);
expect(() => cityBuild.build(Unit)).not.throw(TypeError);
expect(cityBuild.cost().value()).not.finite;
expect(cityBuild.building()!.item()).equal(Unit);
availableBuildItemsRegistry.unregister(Unit);
cityBuild.revalidate();
expect(effectSpy).called.once;
});
it('should accept `BuildProgress` until the `cost` is reached', async (): Promise<void> => {
const availableBuildItemsRegistry = new AvailableCityBuildItemsRegistry(),
ruleRegistry = new RuleRegistry(),
cityBuild = new CityBuild(
await setUpCity(),
availableBuildItemsRegistry,
ruleRegistry
),
effectSpy = spy();
ruleRegistry.register(
new Build(new Effect((): IBuildCriterion => new Criterion(() => true))),
...buildCost(Unit, 10),
new BuildingComplete(new Effect(effectSpy))
);
availableBuildItemsRegistry.register(Unit);
cityBuild.build(Unit);
expect(cityBuild.cost().value()).equal(10);
expect(effectSpy).not.called.once;
cityBuild.add(new BuildProgress(5));
cityBuild.check();
expect(effectSpy).not.called;
expect(cityBuild.remaining()).equal(5);
cityBuild.add(new BuildProgress(5));
cityBuild.check();
expect(effectSpy).called.once;
});
it("should throw and error if a `Build` `Rule` doesn't return a `Criterion`", async (): Promise<void> => {
const availableBuildItemsRegistry = new AvailableCityBuildItemsRegistry(),
ruleRegistry = new RuleRegistry(),
cityBuild = new CityBuild(
await setUpCity(),
availableBuildItemsRegistry,
ruleRegistry
);
ruleRegistry.register(
new Build(new Effect(() => 0 as unknown as IBuildCriterion))
);
availableBuildItemsRegistry.register(Unit);
expect(() => cityBuild.build(Unit)).throw(TypeError);
});
it("should remove an item that's no longer available on `revalidate()`", async (): Promise<void> => {
const availableBuildItemsRegistry = new AvailableCityBuildItemsRegistry(),
ruleRegistry = new RuleRegistry(),
cityBuild = new CityBuild(
await setUpCity(),
availableBuildItemsRegistry,
ruleRegistry
);
ruleRegistry.register(
new Build(new Effect((): IBuildCriterion => new Criterion(() => true))),
...buildCost(Unit, 10)
);
availableBuildItemsRegistry.register(Unit);
cityBuild.build(Unit);
expect(cityBuild.building()!.item()).equal(Unit);
availableBuildItemsRegistry.unregister(Unit);
cityBuild.revalidate();
expect(cityBuild.building()).null;
});
});