Files
Battle-for-Tismo/tests/data_test.js
T

117 lines
4.9 KiB
JavaScript

import { TestCase } from "./framework/test_case.js";
import {
CIVILISATIONS,
PROTO_UNITS,
BUILDINGS,
GOVERNMENTS,
TECHNOLOGIES,
TRAINABLE_UNIT_IDS,
protoUnitById,
buildingById,
governmentById,
technologyById,
pillageSteps,
PILLAGE,
} from "../shared/data.js";
export class DataTest extends TestCase {
test_lookups_return_the_matching_entry_or_null() {
this.assertEqual(protoUnitById("modern_infantry"), PROTO_UNITS.find((u) => u.id === "modern_infantry"));
this.assertEqual(buildingById("barracks"), BUILDINGS.find((b) => b.id === "barracks"));
this.assertEqual(governmentById("republic"), GOVERNMENTS[0]);
this.assertEqual(technologyById("scientific_method"), TECHNOLOGIES[0]);
this.assertNull(protoUnitById("nope"));
this.assertNull(buildingById("nope"));
this.assertNull(governmentById("nope"));
this.assertNull(technologyById("nope"));
}
test_every_civilisation_is_well_formed() {
this.assertGreaterOrEqual(CIVILISATIONS.length, 2);
for (const civ of CIVILISATIONS) {
this.assertTrue(civ.id.length > 0, "id");
this.assertTrue(civ.name.length > 0, "name");
this.assertTrue(civ.primaryColour.startsWith("#"), `primary colour of ${civ.id}`);
this.assertTrue(civ.flag.endsWith(".png"), `flag of ${civ.id}`);
this.assertTrue(civ.demonym.length > 0, `demonym of ${civ.id}`);
this.assertNotEmpty(civ.cityNames, `city names of ${civ.id}`);
}
}
test_trainable_units_exist_in_the_catalogue() {
this.assertNotEmpty(TRAINABLE_UNIT_IDS);
for (const id of TRAINABLE_UNIT_IDS) {
this.assertNotNull(protoUnitById(id), `trainable unit ${id}`);
}
}
test_pillage_steps_compound_per_unit() {
const one = pillageSteps(100000, 1);
this.assertApprox(one.steps[0].removed, 10000, 1e-6);
this.assertApprox(one.steps[0].heal, 10, 1e-9);
this.assertApprox(one.productionMultiplier, PILLAGE.productionPenalty, 1e-9);
const two = pillageSteps(100000, 2);
this.assertApprox(two.steps[0].removed, 10000, 1e-6);
this.assertApprox(two.steps[1].removed, 9000, 1e-6);
this.assertApprox(two.steps[1].heal, 9, 1e-9);
this.assertApprox(two.steps[1].remaining, 81000, 1e-6);
this.assertApprox(two.productionMultiplier, 0.49, 1e-9);
}
test_buildings_and_governments_carry_effects() {
for (const building of BUILDINGS) {
// A building carries either stat effects or a rule-based mechanic.
this.assertTrue(
building.effects.length > 0 || typeof building.mechanic === "string",
`${building.id} effects or mechanic`
);
this.assertGreater(building.costAlpha, 1, `${building.id} cost growth`);
this.assertTrue(building.icon && building.icon.endsWith(".svg"), `${building.id} icon`);
for (const effect of building.effects) {
this.assertTrue(effect.stat.length > 0);
this.assertGreater(effect.baseValue, 0);
}
}
for (const government of GOVERNMENTS) {
this.assertNotEmpty(government.effects, `${government.id} effects`);
}
// The gating buildings declare their placement requirements.
this.assertTrue(buildingById("port").coastal, "a port needs the coast");
this.assertNull(buildingById("port").requiresBuilding, "a port stands on its own");
this.assertEqual(buildingById("shipyard").requiresBuilding, "port", "a shipyard needs a port");
this.assertTrue(buildingById("shipyard").coastal, "a shipyard needs the coast too");
this.assertNull(buildingById("airport").requiresBuilding, "an airport stands on its own");
}
test_technologies_form_a_tree() {
const ids = new Set(TECHNOLOGIES.map((t) => t.id));
for (const tech of TECHNOLOGIES) {
this.assertGreater(tech.cost, 0, `${tech.id} cost`);
// Most technologies carry a numeric effect; a few exist only to unlock
// content (the spy behind Intelligence Agencies), so they opt out.
if (!tech.unlocks) this.assertNotEmpty(tech.effects, `${tech.id} effects`);
for (const prerequisite of tech.prerequisites) {
this.assertTrue(ids.has(prerequisite), `${tech.id} prerequisite ${prerequisite} exists`);
}
}
}
test_aircraft_and_warships_are_gated_and_fuelled() {
for (const id of ["jet_fighter", "bomber"]) {
const plane = protoUnitById(id);
this.assertTrue(plane.air, `${id} is an aircraft`);
this.assertEqual(plane.requiresBuilding, "airport", `${id} needs an airport`);
this.assertGreater(plane.speed, 1, `${id} is fast`);
this.assertGreater(plane.enduranceHours, 0, `${id} has endurance`);
this.assertGreater(plane.missionRange, 0, `${id} has a mission radius`);
this.assertTrue(plane.icon.endsWith(".svg"));
}
this.assertTrue(protoUnitById("bomber").strike, "the bomber strikes from afar");
const battleship = protoUnitById("battleship");
this.assertEqual(battleship.requiresBuilding, "shipyard");
this.assertEqual(battleship.traversableTerrains, ["Sea"]);
this.assertTrue(battleship.icon.endsWith(".svg"));
}
}