143 lines
5.4 KiB
JavaScript
143 lines
5.4 KiB
JavaScript
import { TestCase } from "./framework/test_case.js";
|
|
import { setupDom, teardownDom } from "./framework/dom.js";
|
|
import { smallState } from "./framework/helpers.js";
|
|
import { NationModal } from "../client/js/modals.js";
|
|
import { GOVERNMENTS, TECHNOLOGIES } from "../shared/data.js";
|
|
|
|
function tileOwnedBy(state, owner) {
|
|
for (const [k, tileOwner] of state.territory) {
|
|
if (tileOwner !== owner) continue;
|
|
const i = k.indexOf(",");
|
|
const coords = { x: Number(k.slice(0, i)), y: Number(k.slice(i + 1)) };
|
|
if (state.unitAt(coords) || state.cityAt(coords)) continue;
|
|
return coords;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function findEmptyLandPair(state) {
|
|
for (const cell of state.landCells) {
|
|
if (state.unitAt(cell) || state.cityAt(cell)) continue;
|
|
for (const neighbour of state.topology.neighbours(cell.x, cell.y)) {
|
|
if (!state._isLand(neighbour)) continue;
|
|
if (state.unitAt(neighbour) || state.cityAt(neighbour)) continue;
|
|
return { a: { x: cell.x, y: cell.y }, b: { x: neighbour.x, y: neighbour.y } };
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export class ConflictsStateTest extends TestCase {
|
|
test_declaring_war_opens_a_dated_conflict() {
|
|
const state = smallState();
|
|
for (let i = 0; i < 7; i++) state.advanceHour();
|
|
this.assertTrue(state.requestDeclareWar(0, 1));
|
|
|
|
this.assertSize(state.conflicts, 1, "one conflict is recorded");
|
|
const conflict = state.snapshot(0).conflicts[0];
|
|
this.assertEqual(conflict.a, 0);
|
|
this.assertEqual(conflict.b, 1);
|
|
this.assertEqual(conflict.startHours, 7);
|
|
this.assertTrue(conflict.started.includes("07:00"), `the start hour is kept: ${conflict.started}`);
|
|
this.assertSize(conflict.sides, 2);
|
|
this.assertEqual(conflict.sides[0], { civ: 0, military: 0, civilians: 0 });
|
|
this.assertEqual(conflict.sides[1], { civ: 1, military: 0, civilians: 0 });
|
|
}
|
|
|
|
test_military_deaths_are_tallied_per_side() {
|
|
const state = smallState();
|
|
state.requestDeclareWar(0, 1);
|
|
const pair = findEmptyLandPair(state);
|
|
const attacker = state._spawnUnit(pair.a, 0, state.protoUnits[0]);
|
|
const defender = state._spawnUnit(pair.a, 1, state.protoUnits[0]);
|
|
attacker.hp = attacker.maxHp;
|
|
defender.hp = 1;
|
|
state._resolveCombatRound();
|
|
|
|
const conflict = state.conflicts.values().next().value;
|
|
this.assertEqual(conflict.military.get(1), 1, "the fallen defender's civ is credited the loss");
|
|
this.assertFalse(conflict.military.has(0), "the surviving attacker lost no unit");
|
|
}
|
|
|
|
test_pillaging_counts_civilian_casualties() {
|
|
const state = smallState();
|
|
state.requestDeclareWar(0, 1);
|
|
const coords = tileOwnedBy(state, 1);
|
|
this.assertNotNull(coords, "found an enemy tile");
|
|
const k = `${coords.x},${coords.y}`;
|
|
state.tilePopulation.set(k, 100000);
|
|
const unit = state._spawnUnit(coords, 0, state.protoUnits[0]);
|
|
unit.hp = 100;
|
|
|
|
this.assertTrue(state.requestPillage([unit.id]));
|
|
|
|
const conflict = state.conflicts.values().next().value;
|
|
this.assertEqual(conflict.civilians.get(1), 10000, "the civilians driven off are counted");
|
|
}
|
|
|
|
test_conflicts_are_shared_by_every_viewer() {
|
|
const state = smallState();
|
|
state.requestDeclareWar(0, 1);
|
|
this.assertEqual(state.snapshot(0).conflicts, state.snapshot(1).conflicts);
|
|
}
|
|
}
|
|
|
|
export class ConflictsModalTest extends TestCase {
|
|
async test_conflicts_tab_lists_and_expands() {
|
|
const env = await setupDom();
|
|
try {
|
|
const modal = new NationModal();
|
|
const civs = [{ name: "France" }, { name: "Britain" }, { name: "Poland" }];
|
|
const conflicts = [
|
|
{
|
|
a: 0,
|
|
b: 1,
|
|
started: "1 January 2000, 00:00",
|
|
startHours: 0,
|
|
sides: [
|
|
{ civ: 0, military: 12, civilians: 3400 },
|
|
{ civ: 1, military: 7, civilians: 900 },
|
|
],
|
|
},
|
|
];
|
|
modal.show(
|
|
GOVERNMENTS, 0, TECHNOLOGIES, new Set(), 1.0e9, 1.0e15, 1.0e6, {},
|
|
{ civs, localCiv: 0, relations: [[0, 1, "war"]] },
|
|
conflicts
|
|
);
|
|
env.$("#modal-nation .tab[data-tab=conflicts]").click();
|
|
this.assertTrue(env.$("#tab-conflicts").hasClass("active"));
|
|
this.assertTrue(env.$("#conflicts-sub").text().includes("1 ongoing conflict"));
|
|
|
|
const rows = env.$("#conflicts-list .conflict-card");
|
|
this.assertSize(rows, 1);
|
|
this.assertTrue(rows.eq(0).find(".name").text().includes("France vs Britain"));
|
|
|
|
const detail = rows.eq(0).find(".conflict-detail");
|
|
this.assertTrue(detail.hasClass("hidden"), "details start collapsed");
|
|
rows.eq(0).click();
|
|
this.assertFalse(detail.hasClass("hidden"), "clicking a conflict reveals its details");
|
|
const text = detail.text();
|
|
this.assertTrue(text.includes("Conflict started 1 January 2000, 00:00"));
|
|
this.assertTrue(text.includes("France — Military: 12 · Civilians: 3 400"));
|
|
this.assertTrue(text.includes("Britain — Military: 7 · Civilians: 900"));
|
|
modal.close();
|
|
} finally {
|
|
teardownDom(env);
|
|
}
|
|
}
|
|
|
|
async test_conflicts_tab_reports_peace() {
|
|
const env = await setupDom();
|
|
try {
|
|
const modal = new NationModal();
|
|
modal.show(GOVERNMENTS, 0, TECHNOLOGIES, new Set(), 1.0e9, 1.0e15, 1.0e6, {}, null, []);
|
|
this.assertTrue(env.$("#conflicts-sub").text().includes("No ongoing conflicts"));
|
|
this.assertTrue(env.$("#conflicts-list").text().includes("at peace"));
|
|
modal.close();
|
|
} finally {
|
|
teardownDom(env);
|
|
}
|
|
}
|
|
}
|