diff --git a/.changeset/lobby-fail.md b/.changeset/lobby-fail.md new file mode 100644 index 00000000..434daf23 --- /dev/null +++ b/.changeset/lobby-fail.md @@ -0,0 +1,10 @@ +--- +"@empirica/core": patch +--- + +Fix lobby fail strategy and similar straight to exit steps cases. + +There was a check for the presence of the `player.game` object in front of the +exit steps. If the game never starts, the `player.game` object is never +created, and the exit steps are never executed. This also addresses the case +where the player is never assigned a game at all (custom assignment). diff --git a/lib/@empirica/core/src/player/classic/react/EmpiricaContext.tsx b/lib/@empirica/core/src/player/classic/react/EmpiricaContext.tsx index 4e4a3038..2da24241 100644 --- a/lib/@empirica/core/src/player/classic/react/EmpiricaContext.tsx +++ b/lib/@empirica/core/src/player/classic/react/EmpiricaContext.tsx @@ -258,6 +258,16 @@ function useGameReady() { const players = usePlayers(); const game = useGame(); + // Player was never even assigned to a game, so no game. + if (player && !player.get("gameID")) { + return true; + } + + // Game never started, so no player.game. + if (player && game && !game.get("start")) { + return true; + } + if (!player || !players || !game || !player.game) { return false; } diff --git a/package-lock.json b/package-lock.json index b92f15d9..b416d25d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,7 +79,7 @@ } }, "lib/@empirica/core": { - "version": "1.9.9", + "version": "1.11.0", "license": "Apache-2.0", "dependencies": { "@empirica/tajriba": "1.7.0", diff --git a/tests/stress/experiment/client/package.json b/tests/stress/experiment/client/package.json index 3fda8a10..4b7efed5 100644 --- a/tests/stress/experiment/client/package.json +++ b/tests/stress/experiment/client/package.json @@ -26,7 +26,10 @@ }, "version": "0.0.0", "volta": { - "node": "20.10.0", - "npm": "10.2.3" + "node": "20.12.0", + "npm": "10.5.0" + }, + "engines": { + "node": ">= 20.12.0" } } diff --git a/tests/stress/experiment/server/package.json b/tests/stress/experiment/server/package.json index 63c5a477..d48788fa 100644 --- a/tests/stress/experiment/server/package.json +++ b/tests/stress/experiment/server/package.json @@ -14,7 +14,10 @@ "serve": "node --trace-warnings --enable-source-maps --unhandled-rejections=warn-with-error-code index.js" }, "volta": { - "node": "20.10.0", - "npm": "10.2.3" + "node": "20.12.0", + "npm": "10.5.0" + }, + "engines": { + "node": ">= 20.12.0" } } diff --git a/tests/stress/tests/lobby.spec.js b/tests/stress/tests/lobby.spec.js index db89242f..8bbb587b 100644 --- a/tests/stress/tests/lobby.spec.js +++ b/tests/stress/tests/lobby.spec.js @@ -2,9 +2,10 @@ /// const { test } = require("@playwright/test"); -import { Context } from "./context"; import { adminNewBatch, quickGame } from "./admin"; +import { Context } from "./context"; import { + playerSignIn, playerStart, submitStage, waitGameFinished, @@ -42,7 +43,7 @@ test("lobby shared ignore", async ({ browser }) => { lobbyConfig: { name: "Fast shared ignore", kind: "shared", - duration: 5_000_000_000, + duration: 2_000_000_000, strategy: "ignore", }, }) @@ -67,3 +68,41 @@ test("lobby shared ignore", async ({ browser }) => { await ctx.close(); }); + +// This test is a test for the lobby with configuration shared/fail, which +// means that all players share a timer and we fail the game if not enough +// players to start the game. +// To test this, we set a very short duration for the lobby. +test("lobby shared fail", async ({ browser }) => { + const ctx = new Context(browser); + + const playerCount = 2; + const roundCount = 1; + const stageCount = 2; + + await ctx.start(); + await ctx.addPlayers(playerCount); + ctx.players[0].logWS(); + ctx.players[0].listenScope("game"); + ctx.logMatching(/HERE/); + + await ctx.applyAdmin( + adminNewBatch({ + treatmentConfig: quickGame(playerCount, roundCount, stageCount), + lobbyConfig: { + name: "Fast shared fail", + kind: "shared", + duration: 2_000_000_000, // 2s, in ns... + strategy: "fail", + }, + }) + ); + + await ctx.players[0].apply(playerSignIn); + await ctx.players[0].screenshot("start-game"); + await sleep(2500); + await ctx.players[0].screenshot("end-maybe"); + await ctx.players[0].apply(waitGameFinished); + + await ctx.close(); +}); diff --git a/tests/stress/tests/player.js b/tests/stress/tests/player.js index 16fd2e06..d8b5ebf4 100644 --- a/tests/stress/tests/player.js +++ b/tests/stress/tests/player.js @@ -490,6 +490,7 @@ function playerReceivedPrinter(actor) { console.log(receive, "UNKNOWN", change["__typename"], change); } } catch (e) { + console.error(e); console.log(receive, "FAIL", payload); } };