diff --git a/cypress/e2e/screenshots.cy.ts b/cypress/e2e/screenshots.cy.ts index cf6c7942..f90865f7 100644 --- a/cypress/e2e/screenshots.cy.ts +++ b/cypress/e2e/screenshots.cy.ts @@ -60,7 +60,10 @@ describe("Game Visual Documentation", () => { win.dispatchEvent(new CustomEvent('test:targetClick')); win.dispatchEvent(new CustomEvent('test:targetClick')); }); - + + // Wait for React to process the state updates (consistent with gameplay.cy.ts pattern) + cy.wait(100); + // Verify score updated cy.get("[data-testid=score-value]").should("not.contain", "0"); diff --git a/package-lock.json b/package-lock.json index e7149128..d0a20b2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7101,9 +7101,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.31.5", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.5.tgz", - "integrity": "sha512-5SyLdip4/3alxD4Kh+63bUQTJmu7YMfYQTC+koZy7X73HgNqZSD2P4wOZQWtUncvPvcEmnfIjCoygN4MRoEejQ==", + "version": "5.31.6", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.6.tgz", + "integrity": "sha512-Uv2b2uGGM6ns+26czgW2cYRabYdnswM0ddSOOlryHOaelzsmDSet1iM/NT7VOYxW8x/BW+HkY+b1Ve2pLTSGSA==", "dev": true, "license": "MIT", "os": [ diff --git a/src/App.tsx b/src/App.tsx index 342d798c..a30ff160 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,5 @@ import { Canvas } from "@react-three/fiber"; -import { useRef, useState, useCallback, useEffect } from "react"; +import { useRef, useState, useCallback, useEffect, useLayoutEffect } from "react"; import type { JSX } from "react"; import { useGameState } from "./hooks/useGameState"; import { useAudioManager } from "./hooks/useAudioManager"; @@ -96,7 +96,10 @@ function App(): JSX.Element { const gameStateRef = useRef(gameState); gameStateRef.current = gameState; - useEffect(() => { + // useLayoutEffect (not useEffect) ensures the listener is registered synchronously + // before the browser paints, preventing a race where Cypress finds the target-sphere + // in the DOM before the test event listener is ready to receive events. + useLayoutEffect(() => { const handleTestTargetClick = (): void => { const gs = gameStateRef.current; if (gs.isPlaying && gs.timeLeft > 0 && gs.targets.length > 0) {