- Political map country names were invisible because the label SVG had a zero-sized viewport, which some browsers never paint; size it to the world and guard it with a test. - Added a Devlog button showing the ten latest commits, generated into client/js/devlog_data.js by scripts/generate-devlog.js and refreshed by the pre-commit hook. - Worked through FIXME.md: the city button and a unit double-click now open the city, and the stat tooltip escapes the HUD so the unit panel cannot cover it. - The server creates its game at startup and clients only join it; the Create game screen and the configure_game path are gone, and testing is a --testing server flag. - A page on a loopback host signs in as adrien, claims France and gets the free, instant testing buttons, while the server grants free orders only to a loopback socket whose Origin is also loopback.
144 lines
5.6 KiB
JavaScript
144 lines
5.6 KiB
JavaScript
import { TestCase } from "./framework/test_case.js";
|
|
import { setupDom, teardownDom, FakeWebSocket } from "./framework/dom.js";
|
|
import { smallState } from "./framework/helpers.js";
|
|
|
|
const flush = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
|
|
export class AppTest extends TestCase {
|
|
async test_join_flow() {
|
|
const env = await setupDom();
|
|
try {
|
|
FakeWebSocket.reset();
|
|
await import(`../client/js/app.js?join=${Date.now()}`);
|
|
this.assertSize(env.$("#menu-create"), 0, "there is no Create game button");
|
|
|
|
env.$("#menu-join").click();
|
|
this.assertTrue(env.$("#screen-join").hasClass("active"));
|
|
const listSocket = FakeWebSocket.last;
|
|
listSocket.simulateOpen();
|
|
await flush();
|
|
this.assertEqual(listSocket.lastSent(), { t: "request_games" });
|
|
listSocket.simulateMessage({
|
|
t: "game_list",
|
|
games: [{ name: "Game 999", date: "1 January 2000, 00:00", players: 1, civs: ["France", "Britain"] }],
|
|
});
|
|
this.assertSize(env.$("#join-games li"), 1);
|
|
|
|
env.$("#join-name").val("Carol");
|
|
env.$("#join-password").val("pw");
|
|
env.$("#join-go").click();
|
|
const joinSocket = FakeWebSocket.last;
|
|
this.assert(joinSocket !== listSocket, "joining opens a fresh connection");
|
|
joinSocket.simulateOpen();
|
|
await flush();
|
|
this.assertEqual(joinSocket.lastSent(), { t: "login", name: "Carol", password: "pw" });
|
|
joinSocket.simulateMessage({ t: "assigned", playerId: 2, admin: false, name: "Carol" });
|
|
this.assertFalse(env.$("#screen-game").hasClass("active"), "no game screen before picking");
|
|
|
|
joinSocket.simulateMessage({
|
|
t: "choose_civ",
|
|
civs: [{ index: 1, id: "britain", name: "Britain" }],
|
|
});
|
|
this.assertTrue(env.$("#screen-choose").hasClass("active"));
|
|
this.assertSize(env.$("#choose-civs li"), 1);
|
|
env.$("#choose-civs li").first().click();
|
|
this.assertEqual(joinSocket.lastSent(), { t: "claim_civ", civ: 1 });
|
|
|
|
joinSocket.simulateMessage({ t: "civ_assigned", civ: 1 });
|
|
this.assertTrue(env.$("#screen-game").hasClass("active"));
|
|
joinSocket.simulateMessage({ t: "game_state", state: smallState().snapshot(1) });
|
|
this.assertEqual(env.$("#civ-name").text(), "Britain");
|
|
this.assertFalse(env.$("#stat-pop").text() === "0");
|
|
} finally {
|
|
teardownDom(env);
|
|
}
|
|
}
|
|
|
|
async test_join_without_a_free_nation_becomes_a_spectator() {
|
|
const env = await setupDom();
|
|
try {
|
|
FakeWebSocket.reset();
|
|
await import(`../client/js/app.js?spectate=${Date.now()}`);
|
|
env.$("#menu-join").click();
|
|
const listSocket = FakeWebSocket.last;
|
|
listSocket.simulateOpen();
|
|
await flush();
|
|
listSocket.simulateMessage({ t: "game_list", games: [{ name: "Game 999" }] });
|
|
|
|
env.$("#join-name").val("Carol");
|
|
env.$("#join-password").val("pw");
|
|
env.$("#join-go").click();
|
|
const joinSocket = FakeWebSocket.last;
|
|
joinSocket.simulateOpen();
|
|
await flush();
|
|
joinSocket.simulateMessage({ t: "assigned", playerId: 2, admin: false, name: "Carol" });
|
|
joinSocket.simulateMessage({ t: "choose_civ", civs: [] });
|
|
this.assertTrue(env.$("#screen-game").hasClass("active"), "no choice means a spectator view");
|
|
} finally {
|
|
teardownDom(env);
|
|
}
|
|
}
|
|
|
|
async test_missing_credentials_show_a_message() {
|
|
const env = await setupDom();
|
|
try {
|
|
FakeWebSocket.reset();
|
|
await import(`../client/js/app.js?validation=${Date.now()}`);
|
|
env.$("#menu-join").click();
|
|
const listSocket = FakeWebSocket.last;
|
|
listSocket.simulateOpen();
|
|
await flush();
|
|
listSocket.simulateMessage({ t: "game_list", games: [{ name: "Game 999" }] });
|
|
|
|
env.$("#join-name").val("");
|
|
env.$("#join-password").val("");
|
|
env.$("#join-go").click();
|
|
this.assertEqual(env.$("#join-status").text(), "Enter a name and a password.");
|
|
this.assertSize(FakeWebSocket.instances, 1, "no new connection is attempted");
|
|
} finally {
|
|
teardownDom(env);
|
|
}
|
|
}
|
|
|
|
async assertLocalPageAutoJoins(url, tag) {
|
|
const env = await setupDom({ url });
|
|
try {
|
|
FakeWebSocket.reset();
|
|
await import(`../client/js/app.js?local-${tag}=${Date.now()}`);
|
|
env.$("#menu-join").click();
|
|
this.assertFalse(env.$("#screen-join").hasClass("active"), "the login form is skipped");
|
|
|
|
const socket = FakeWebSocket.last;
|
|
socket.simulateOpen();
|
|
await flush();
|
|
this.assertEqual(socket.lastSent(), { t: "login", name: "adrien", password: "admin" });
|
|
|
|
socket.simulateMessage({ t: "assigned", playerId: 1, admin: true, name: "adrien" });
|
|
socket.simulateMessage({
|
|
t: "choose_civ",
|
|
civs: [
|
|
{ index: 4, id: "france", name: "France" },
|
|
{ index: 1, id: "britain", name: "Britain" },
|
|
],
|
|
});
|
|
this.assertEqual(socket.lastSent(), { t: "claim_civ", civ: 4 }, "France is claimed");
|
|
this.assertFalse(env.$("#screen-choose").hasClass("active"), "the picker is skipped");
|
|
|
|
socket.simulateMessage({ t: "civ_assigned", civ: 4 });
|
|
this.assertTrue(env.$("#screen-game").hasClass("active"));
|
|
socket.simulateMessage({ t: "game_state", state: smallState().snapshot(0) });
|
|
this.assertEqual(env.$("#civ-name").text(), "France");
|
|
} finally {
|
|
teardownDom(env);
|
|
}
|
|
}
|
|
|
|
async test_a_127_page_joins_as_adrien_with_france() {
|
|
await this.assertLocalPageAutoJoins("http://127.0.0.1/client/index.html", "127");
|
|
}
|
|
|
|
async test_a_localhost_page_joins_as_adrien_with_france() {
|
|
await this.assertLocalPageAutoJoins("http://localhost/client/index.html", "localhost");
|
|
}
|
|
}
|