mirror of
https://github.com/ppy/osu.git
synced 2026-05-17 03:52:35 +08:00
090fe44f86
A few quick ones from https://github.com/ppy/osu/issues/37190. ## [Rewrite `TestSceneDeleteLocalScore` to have less context menu containers (and hopefully no longer flake)](https://github.com/ppy/osu/commit/ea0bc5b72374056d1749f8058f4874b7ef66a241) As seen in https://github.com/ppy/osu/actions/runs/23890777748#user-content-r3s3. This is a speculative fix but I'm feeling somewhat confident about this one. `BeatmapLeaderboardWedge` has TWO separate `ContextMenuContainer`s itself, and the test mentioned here was bringing a third. I have a feeling that the test flaking may have something to do with the fact that the test logic would attempt to click a menu item on specifically ONE of the three context menus. My bet is that when it fails, it's because it's trying the wrong one, but I don't have reproduction. ## [Wait for text to appear in flaking `TestSceneDrawableRoomPlaylist.TestSelectableMouseHandling` test](https://github.com/ppy/osu/commit/9d62eea8b56a0eb013e8116db0d38424b500876f) As seen in https://github.com/ppy/osu/actions/runs/23888446400#user-content-r1s1. Speculative. Banking on the fact that it takes time to load the sprite texts. ## [Remove all tests from `TestSceneWikiMarkdownContainer` dependent on existence of wiki on dev](https://github.com/ppy/osu/commit/8f319f91c98510b84e915bb61ec147618a584ce1) Deletes a flaky as seen in https://github.com/ppy/osu/actions/runs/23878899702#user-content-r2s2. The year is 2026 and LLM scrapers hammer [the entire](https://sourcehut.org/blog/2025-04-15-you-cannot-have-our-users-data/) [internet](https://blog.metabrainz.org/2025/12/11/we-cant-have-nice-things-because-of-ai-scrapers/) all over to scrape whatever ounce of Human Content there is left to feed the Moloch so that it can regurgitate it back in the form of The Most Average Speech You've Ever Read. We are not immune to this, and as such the LLM homunculi have hit the dev.ppy.sh wiki instance enough times for it to just completely [be banished to the blagole](https://www.youtube.com/watch?v=AfA_2Ku1aJY). Which means I get to freely delete flaky tests that should never have been running as part of CI because they're completely useless now and it's not like we're ever turning them back on again. ## [Use equality check in `TestSceneBeatmapCarouselScrolling.TestScrollPositionMaintainedOnRemove_SecondSelected` that's less sensitive to floating point](https://github.com/ppy/osu/commit/6f2a1de58f7e816830c430e89117ee4c594f529d) As seen in https://github.com/ppy/osu/actions/runs/23826420794#user-content-r0s1.
193 lines
7.3 KiB
C#
193 lines
7.3 KiB
C#
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using NUnit.Framework;
|
|
using osu.Framework.Allocation;
|
|
using osu.Framework.Audio;
|
|
using osu.Framework.Extensions;
|
|
using osu.Framework.Extensions.ObjectExtensions;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Platform;
|
|
using osu.Framework.Testing;
|
|
using osu.Framework.Utils;
|
|
using osu.Game.Beatmaps;
|
|
using osu.Game.Database;
|
|
using osu.Game.Graphics.UserInterface;
|
|
using osu.Game.Models;
|
|
using osu.Game.Online.API.Requests.Responses;
|
|
using osu.Game.Online.Leaderboards;
|
|
using osu.Game.Overlays;
|
|
using osu.Game.Rulesets;
|
|
using osu.Game.Rulesets.Osu;
|
|
using osu.Game.Scoring;
|
|
using osu.Game.Screens.Select;
|
|
using osu.Game.Tests.Resources;
|
|
using osuTK;
|
|
using osuTK.Input;
|
|
|
|
namespace osu.Game.Tests.Visual.UserInterface
|
|
{
|
|
public partial class TestSceneDeleteLocalScore : OsuManualInputManagerTestScene
|
|
{
|
|
private readonly BeatmapLeaderboardWedge leaderboard;
|
|
|
|
private RulesetStore rulesets = null!;
|
|
private BeatmapManager beatmapManager = null!;
|
|
private ScoreManager scoreManager = null!;
|
|
|
|
private readonly List<ScoreInfo> importedScores = new List<ScoreInfo>();
|
|
|
|
private BeatmapInfo beatmapInfo = null!;
|
|
|
|
private LeaderboardManager leaderboardManager { get; set; } = null!;
|
|
|
|
[Cached]
|
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
|
|
|
|
[Cached(typeof(IDialogOverlay))]
|
|
private readonly DialogOverlay dialogOverlay;
|
|
|
|
private IEnumerable<ScoreInfo> scores => leaderboardManager.Scores.Value?.AllScores ?? Enumerable.Empty<ScoreInfo>();
|
|
|
|
public TestSceneDeleteLocalScore()
|
|
{
|
|
Children = new Drawable[]
|
|
{
|
|
leaderboard = new BeatmapLeaderboardWedge
|
|
{
|
|
Origin = Anchor.Centre,
|
|
Anchor = Anchor.Centre,
|
|
Size = new Vector2(0.6f),
|
|
},
|
|
dialogOverlay = new DialogOverlay()
|
|
};
|
|
}
|
|
|
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
|
{
|
|
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
|
|
|
dependencies.Cache(rulesets = new RealmRulesetStore(Realm));
|
|
dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, Realm, null, dependencies.Get<AudioManager>(), Resources, dependencies.Get<GameHost>(), Beatmap.Default));
|
|
dependencies.Cache(scoreManager = new ScoreManager(dependencies.Get<RulesetStore>(), () => beatmapManager, LocalStorage, Realm, API));
|
|
dependencies.Cache(leaderboardManager = new LeaderboardManager());
|
|
Dependencies.Cache(Realm);
|
|
|
|
Add(leaderboardManager);
|
|
|
|
return dependencies;
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load() => Schedule(() =>
|
|
{
|
|
var imported = beatmapManager.Import(new ImportTask(TestResources.GetQuickTestBeatmapForImport())).GetResultSafely();
|
|
|
|
imported?.PerformRead(s =>
|
|
{
|
|
beatmapInfo = s.Beatmaps[0];
|
|
|
|
for (int i = 0; i < 50; i++)
|
|
{
|
|
var score = new ScoreInfo
|
|
{
|
|
OnlineID = i,
|
|
BeatmapInfo = beatmapInfo,
|
|
BeatmapHash = beatmapInfo.Hash,
|
|
Accuracy = RNG.NextDouble(),
|
|
TotalScore = RNG.Next(1, 1000000),
|
|
MaxCombo = RNG.Next(1, 1000),
|
|
Rank = ScoreRank.XH,
|
|
User = new APIUser { Username = "TestUser" },
|
|
Ruleset = new OsuRuleset().RulesetInfo,
|
|
Files = { new RealmNamedFileUsage(new RealmFile { Hash = $"{i}" }, string.Empty) }
|
|
};
|
|
|
|
importedScores.Add(scoreManager.Import(score)!.Value);
|
|
}
|
|
});
|
|
});
|
|
|
|
[SetUpSteps]
|
|
public void SetupSteps()
|
|
{
|
|
AddUntilStep("ensure scores imported", () => importedScores.Count == 50);
|
|
AddStep("undelete scores", () =>
|
|
{
|
|
Realm.Run(r =>
|
|
{
|
|
// Due to soft deletions, we can re-use deleted scores between test runs
|
|
scoreManager.Undelete(r.All<ScoreInfo>().Where(s => s.DeletePending).ToList());
|
|
});
|
|
});
|
|
AddStep("set up leaderboard", () =>
|
|
{
|
|
Beatmap.Value = beatmapManager.GetWorkingBeatmap(beatmapInfo);
|
|
leaderboard.Show();
|
|
});
|
|
|
|
// Ensure the leaderboard items have finished showing up
|
|
AddStep("finish transforms", () => leaderboard.FinishTransforms(true));
|
|
AddUntilStep("wait for drawables", () => leaderboard.ChildrenOfType<BeatmapLeaderboardScore>().Any());
|
|
}
|
|
|
|
[Test]
|
|
public void TestDeleteViaRightClick()
|
|
{
|
|
ScoreInfo scoreBeingDeleted = null!;
|
|
AddStep("open menu for top score", () =>
|
|
{
|
|
var leaderboardScore = leaderboard.ChildrenOfType<BeatmapLeaderboardScore>().First();
|
|
|
|
scoreBeingDeleted = leaderboardScore.Score;
|
|
|
|
InputManager.MoveMouseTo(leaderboardScore);
|
|
InputManager.Click(MouseButton.Right);
|
|
});
|
|
|
|
// Ensure the context menu has finished showing
|
|
AddStep("finish transforms", () => leaderboard.FinishTransforms(true));
|
|
|
|
AddStep("click delete option", () =>
|
|
{
|
|
InputManager.MoveMouseTo(leaderboard.ChildrenOfType<DrawableOsuMenuItem>()
|
|
.First(i => string.Equals(i.Item.Text.Value.ToString(), "delete", System.StringComparison.OrdinalIgnoreCase)));
|
|
InputManager.Click(MouseButton.Left);
|
|
});
|
|
|
|
// Ensure the dialog has finished showing
|
|
AddStep("finish transforms", () => dialogOverlay.FinishTransforms(true));
|
|
|
|
AddStep("click delete button", () =>
|
|
{
|
|
InputManager.MoveMouseTo(dialogOverlay.ChildrenOfType<DialogButton>().First());
|
|
InputManager.PressButton(MouseButton.Left);
|
|
});
|
|
|
|
AddUntilStep("wait for fetch", () => scores.Any());
|
|
AddUntilStep("score removed from leaderboard", () => scores.All(s => s.OnlineID != scoreBeingDeleted.OnlineID));
|
|
|
|
// "Clean up"
|
|
AddStep("release left mouse button", () => InputManager.ReleaseButton(MouseButton.Left));
|
|
}
|
|
|
|
[Test]
|
|
public void TestDeleteViaDatabase()
|
|
{
|
|
AddStep("delete top score", () => scoreManager.Delete(importedScores[0]));
|
|
AddUntilStep("wait for fetch", () => scores.Any());
|
|
AddUntilStep("score removed from leaderboard", () => scores.All(s => s.OnlineID != importedScores[0].OnlineID));
|
|
}
|
|
|
|
protected override void Dispose(bool isDisposing)
|
|
{
|
|
base.Dispose(isDisposing);
|
|
|
|
if (rulesets.IsNotNull())
|
|
rulesets.Dispose();
|
|
}
|
|
}
|
|
}
|