diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelect.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelect.cs index a480e51adf..f47eafc937 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelect.cs @@ -659,6 +659,51 @@ namespace osu.Game.Tests.Visual.SongSelectV2 AddAssert("options disabled", () => !this.ChildrenOfType().Single().Enabled.Value); } + /// + /// tests that clicking the osu! logo immediately after selecting a different difficulty + /// (before the selection debounce completes) starts the correct beatmap. + /// this tests the fix for https://github.com/ppy/osu/issues/36074 + /// + [Test] + public void TestPlayCorrectBeatmapWhenSelectionNotFullyLoaded() + { + // import a beatmap set with multiple difficulties + ImportBeatmapForRuleset(0); + + LoadSongSelect(); + + // wait for initial beatmap to be selected + AddUntilStep("wait for first beatmap selected", () => !Beatmap.IsDefault); + + BeatmapInfo? firstBeatmap = null; + AddStep("store first difficulty", () => firstBeatmap = Beatmap.Value.BeatmapInfo); + + // start loading the first difficulty + AddStep("click logo to start loading", () => this.ChildrenOfType().Single().TriggerClick()); + AddUntilStep("wait for player loader", () => Stack.CurrentScreen is PlayerLoader); + + // return to song select + AddStep("press escape to return", () => InputManager.Key(Key.Escape)); + AddUntilStep("wait for return to song select", () => SongSelect.IsCurrentScreen()); + + // press down and schedule logo click to happen shortly after (but before 150ms debounce) + // this reproduces the race condition where Beatmap.Value hasn't updated yet + AddStep("select next difficulty and click logo immediately", () => + { + InputManager.Key(Key.Down); + Schedule(() => this.ChildrenOfType().Single().TriggerClick()); + }); + + AddUntilStep("wait for player loader", () => Stack.CurrentScreen is PlayerLoader); + + // verify we're loading the second difficulty, not the first + // without the fix, this would fail because Beatmap.Value still has the old value + AddAssert("player is loading second difficulty", () => + Beatmap.Value.BeatmapInfo.ID != firstBeatmap!.ID); + + AddUntilStep("wait for return to song select", () => SongSelect.IsCurrentScreen()); + } + #endregion } } diff --git a/osu.Game/Screens/SelectV2/SongSelect.cs b/osu.Game/Screens/SelectV2/SongSelect.cs index 944c93bd5f..4bee63b57c 100644 --- a/osu.Game/Screens/SelectV2/SongSelect.cs +++ b/osu.Game/Screens/SelectV2/SongSelect.cs @@ -756,6 +756,7 @@ namespace osu.Game.Screens.SelectV2 logo.Action = () => { + ensureGlobalBeatmapValid(); SelectAndRun(Beatmap.Value.BeatmapInfo, OnStart); return false; }; @@ -999,6 +1000,7 @@ namespace osu.Game.Screens.SelectV2 // one of which is filtering out all visible beatmaps and attempting to start gameplay. // in that case, users still expect a `Select` press to advance to gameplay anyway, using the ambient selected beatmap if there is one, // which matches the behaviour resulting from clicking the osu! cookie in that scenario. + ensureGlobalBeatmapValid(); SelectAndRun(Beatmap.Value.BeatmapInfo, OnStart); return true;