feat: FM-967 QA Automation coverage for Replay level flow. (Playwrigh… - #2001
feat: FM-967 QA Automation coverage for Replay level flow. (Playwrigh…#2001ashwinnair-chimple wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughThe E2E assessment flow now runs through TC_017. TC_016 leaves the Level End screen open, and TC_017 replays Level 2, verifies fresh gameplay interaction, and confirms the level context. ChangesLevel replay E2E coverage
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant LevelEnd as Level End screen
participant TC017 as TC_017 replay test
participant Gameplay as Gameplay scene
participant Canvas as Gameplay canvas
participant GameState as Game state service
LevelEnd->>TC017: Verify Level End screen
TC017->>LevelEnd: Wait and click Replay
LevelEnd->>Gameplay: Reload gameplay scene
TC017->>Gameplay: Click monster hotspot
Gameplay->>Canvas: Render fresh puzzle content
TC017->>Canvas: Assert canvas content
TC017->>GameState: Read selected level
GameState-->>TC017: Return Level 2 context
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@e2e/tests/isolated/tc-017-level-replay.spec.ts`:
- Around line 35-60: Ensure the Replay flow waits for the level-end overlay to
deactivate before reading hitbox state or clicking the fresh puzzle. Update the
“Gameplay scene reloads after Replay” step or the gameplay scene wait helper
used by waitForGameplayScene() to verify `#levelEnd` is inactive, while preserving
the existing canvas and pause-button readiness checks.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d462e589-e472-44d5-9486-a25999b67c48
⛔ Files ignored due to path filters (2)
e2e/tests/README.mdis excluded by!**/*.mdspec/FM-967-replay-level-e2e-automation.mdis excluded by!**/*.md
📒 Files selected for processing (4)
e2e/constants/timeouts.tse2e/tests/ftm-assessment-survey-flow.spec.tse2e/tests/isolated/tc-016-level-completion.spec.tse2e/tests/isolated/tc-017-level-replay.spec.ts
| await test.step('Wait for UI to settle before interacting with Replay', async () => { | ||
| await page.waitForTimeout(Timeouts.replaySettleDelay); | ||
| }); | ||
|
|
||
| await test.step('Click Replay button', async () => { | ||
| await levelEndPage.clickRetryButton(); | ||
| }); | ||
|
|
||
| await test.step('Gameplay scene reloads after Replay', async () => { | ||
| await gameplayPage.waitForGameplayScene(); | ||
| }); | ||
|
|
||
| await test.step('Click the monster hotspot to trigger stones on the fresh puzzle', async () => { | ||
| await page.waitForFunction( | ||
| () => (window as any).__ftm?.gameStateService?.getHitBoxRanges?.() != null, | ||
| { timeout: Timeouts.sceneTransition }, | ||
| ); | ||
| const hitboxCenter = await getHitboxCenter(page); | ||
| expect(hitboxCenter).not.toBeNull(); | ||
| const canvasBB = await gameplayPage.mainCanvas.boundingBox(); | ||
| expect(canvasBB).not.toBeNull(); | ||
| await page.mouse.click( | ||
| canvasBB!.x + hitboxCenter!.x, | ||
| canvasBB!.y + hitboxCenter!.y, | ||
| ); | ||
| }); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
gameplay_files="$(fd -i -t f 'gameplay-page\.ts$' e2e || true)"
while IFS= read -r file; do
[ -z "$file" ] && continue
rg -n -A30 -B5 '\bwaitForGameplayScene\s*\(' "$file" || true
done <<< "$gameplay_files"
rg -n -A25 -B10 'levelend|clickRetryButton|retry-btn|Replay' e2e/pages e2e/helpers || trueRepository: curiouslearning/FeedTheMonsterJS
Length of output: 7158
🏁 Script executed:
#!/bin/bash
set -euo pipefail
test_file="e2e/tests/isolated/tc-017-level-replay.spec.ts"
if [ -f "${test_file}" ]; then
sed -n '1,140p' "${test_file}" | cat -n
else
echo "test file not found"
fi
playground_files="$(fd -i -t f 'playground|gameplay|level-end' e2e/src-e2e e2e pages 2>/dev/null || true)"
echo "PLAYGROUND_FILES=${playground_files}"
for file in $playground_files; do
[ -z "$file" ] && continue
base="$(basename "$file")"
echo "--- ${file} (size $(wc -l < "$file")) ---"
rg -n -A8 -B8 'getHitBoxRanges|hitBoxRanges|playground|canvas|levelEnd|gameStateService|Scene|setLevel|loadLevel|replay' "$file" || true
done
rg -n -A12 -B8 'getHitBoxRanges|hitBoxRanges|gameStateService' e2e || trueRepository: curiouslearning/FeedTheMonsterJS
Length of output: 50388
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "--- GameplayPage implementation ---"
sed -n '1,110p' e2e/pages/gameplay-page.ts | cat -n
echo "--- LevelEndPage retry implementation ---"
sed -n '80,115p' e2e/pages/level-end-page.ts | cat -n
echo "--- Reusable wait helpers around playable/gameplay state ---"
rg -n -A20 -B8 'playable|canPlay|isPlayable|isLevelPlayable|gamePlay.*loaded|gamePlay.*ready|loadLevel|reload|retry|GamePlay|gamePlayService|getHitBoxRanges|sceneHandler|currentScene' e2e e2e/src-e2e --glob '!e2e/tests/isolated/*' | head -n 240 || true
echo "--- Candidate source files containing retry/loadState/startPlayback ---"
rg -n 'retry|retryBtn|retry.*click|set.*Play|startPlayback|loadLevel|reset|reload|gameStateService.getHitBoxRanges|currentScene|activeScene' e2e/src-e2e e2e/pages e2e/includes --glob '!**/*.spec.ts' --glob '!**/*.test.ts' | head -n 240 || true
echo "--- Search for waitForStonesReady / getHitboxCenter wrappers beyond direct lines ---"
rg -n -A30 -B10 'waitForStonesReady|getHitboxCenter|gameStateService.*hitBoxRanges|hitBoxRanges' e2e e2e/src-e2e --glob '!e2e/tests/isolated/*' | head -n 260 || true
# Behavioral probe: model the current post-replay conditions and show stale-state risk.
node - <<'JS'
const conditions = {
timeoutIsOnlyElapsed: true,
waitForGameplaySceneOnlyChecks: ['`#canvas` visible', '`#pause-button` visible'],
replayButtonSelectorUsed: '`#levelend-retry-btn`',
hitboxPrecondition: 'window.__ftm?.gameStateService?.getHitBoxRanges() != null',
};
const staleScenario = {
oldLevelEndStillOverlaying: true,
oldGameplaySceneStillActive: true,
uiButtonsVisibleButOverlayBlocked: true,
gameHitBoxRangesAvailable: true,
};
console.log(
JSON.stringify(
{
conditions,
staleScenario,
currentTestWillWaitFor: [...conditions.waitForGameplaySceneOnlyChecks, conditions.hitboxPrecondition],
missingPostReplayConditions: [
'`#levelEnd` hidden / inactive',
'active gameplay scene not same as overlay before retry',
'gamePlayData.puzzles reset or currentPuzzleIndex reset',
'stoneHandler.stonesHasLoaded reset',
],
},
null,
2
)
);
JSRepository: curiouslearning/FeedTheMonsterJS
Length of output: 30316
Wait for the replay scene to clear before reading game state.
waitForGameplayScene() only checks that #canvas and #pause-button are visible, while getHitboxCenter() reads whatever __ftm.gameStateService.getHitBoxRanges() returns. If #levelEnd is still active after Replay, this step can click the stale Level End hitbox. Add the level-end deactivation check before reading hitbox state, or update waitForGameplayScene() to enforce it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@e2e/tests/isolated/tc-017-level-replay.spec.ts` around lines 35 - 60, Ensure
the Replay flow waits for the level-end overlay to deactivate before reading
hitbox state or clicking the fresh puzzle. Update the “Gameplay scene reloads
after Replay” step or the gameplay scene wait helper used by
waitForGameplayScene() to verify `#levelEnd` is inactive, while preserving the
existing canvas and pause-button readiness checks.
…t+Claude)
Changes
How to test
Ref: FM-967
Summary by CodeRabbit
New Features
Tests