Merge branch 'master' of github.com:ppy/osu into #7146

This commit is contained in:
Willy Tu
2020-01-03 11:32:06 -08:00
163 changed files with 3017 additions and 1511 deletions

View File

@ -4,6 +4,8 @@
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose;
namespace osu.Game.Tests.Visual.Editor
@ -11,10 +13,21 @@ namespace osu.Game.Tests.Visual.Editor
[TestFixture]
public class TestSceneComposeScreen : EditorClockTestScene
{
[Cached(typeof(EditorBeatmap))]
private readonly EditorBeatmap editorBeatmap =
new EditorBeatmap(new OsuBeatmap
{
BeatmapInfo =
{
Ruleset = new OsuRuleset().RulesetInfo
}
});
[BackgroundDependencyLoader]
private void load()
{
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap);
Child = new ComposeScreen();
}
}

View File

@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
@ -21,15 +20,15 @@ namespace osu.Game.Tests.Visual.Editor
private const double beat_length = 100;
private static readonly Vector2 grid_position = new Vector2(512, 384);
[Cached(typeof(IEditorBeatmap))]
private readonly EditorBeatmap<OsuHitObject> editorBeatmap;
[Cached(typeof(EditorBeatmap))]
private readonly EditorBeatmap editorBeatmap;
[Cached(typeof(IDistanceSnapProvider))]
private readonly SnapProvider snapProvider = new SnapProvider();
public TestSceneDistanceSnapGrid()
{
editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap());
editorBeatmap = new EditorBeatmap(new OsuBeatmap());
editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length });
}

View File

@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Editor
{
Beatmap.Value = new WaveformTestBeatmap(audio);
var editorBeatmap = new EditorBeatmap<HitObject>((Beatmap<HitObject>)Beatmap.Value.Beatmap);
var editorBeatmap = new EditorBeatmap((Beatmap<HitObject>)Beatmap.Value.Beatmap);
Children = new Drawable[]
{

View File

@ -16,6 +16,7 @@ using osu.Game.Rulesets.Osu.Edit;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
@ -59,9 +60,12 @@ namespace osu.Game.Tests.Visual.Editor
},
});
var editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(new OsuRuleset().RulesetInfo));
var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
Dependencies.CacheAs<IAdjustableClock>(clock);
Dependencies.CacheAs<IFrameBasedClock>(clock);
Dependencies.CacheAs(editorBeatmap);
Child = new OsuHitObjectComposer(new OsuRuleset());
}

View File

@ -5,7 +5,8 @@ using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Timing;
namespace osu.Game.Tests.Visual.Editor
@ -25,10 +26,13 @@ namespace osu.Game.Tests.Visual.Editor
typeof(RowAttribute)
};
[Cached(typeof(EditorBeatmap))]
private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap());
[BackgroundDependencyLoader]
private void load()
{
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap);
Child = new TimingScreen();
}
}

View File

@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => new TestDrawableScrollingRuleset(this, beatmap, mods);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap, null);
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException();
@ -268,12 +268,12 @@ namespace osu.Game.Tests.Visual.Gameplay
private class TestBeatmapConverter : BeatmapConverter<TestHitObject>
{
public TestBeatmapConverter(IBeatmap beatmap)
: base(beatmap)
public TestBeatmapConverter(IBeatmap beatmap, Ruleset ruleset)
: base(beatmap, ruleset)
{
}
protected override IEnumerable<Type> ValidConversionTypes => new[] { typeof(HitObject) };
public override bool CanConvert() => true;
protected override IEnumerable<TestHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap)
{

View File

@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override void LoadComplete()
{
base.LoadComplete();
ScoreProcessor.FailConditions += (_, __) => true;
HealthProcessor.FailConditions += (_, __) => true;
}
}
}

View File

@ -22,12 +22,12 @@ namespace osu.Game.Tests.Visual.Gameplay
{
AddUntilStep("wait for fail", () => Player.HasFailed);
AddUntilStep("wait for multiple judged objects", () => ((FailPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.Count(h => h.AllJudged) > 1);
AddAssert("total judgements == 1", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits == 1);
AddAssert("total judgements == 1", () => ((FailPlayer)Player).HealthProcessor.JudgedHits >= 1);
}
private class FailPlayer : TestPlayer
{
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
public new HealthProcessor HealthProcessor => base.HealthProcessor;
public FailPlayer()
: base(false, false)
@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override void LoadComplete()
{
base.LoadComplete();
ScoreProcessor.FailConditions += (_, __) => true;
HealthProcessor.FailConditions += (_, __) => true;
}
}
}

View File

@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
AddStep("create overlay", () =>
{
Child = hudOverlay = new HUDOverlay(null, null, Array.Empty<Mod>());
Child = hudOverlay = new HUDOverlay(null, null, null, Array.Empty<Mod>());
action?.Invoke(hudOverlay);
});

View File

@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public void TestResumeWithResumeOverlay()
{
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1);
AddUntilStep("wait for hitobjects", () => Player.HealthProcessor.Health.Value < 1);
pauseAndConfirm();
resume();
@ -73,7 +73,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public void TestPauseWithResumeOverlay()
{
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1);
AddUntilStep("wait for hitobjects", () => Player.HealthProcessor.Health.Value < 1);
pauseAndConfirm();
@ -92,7 +92,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
AddStep("move cursor to button", () =>
InputManager.MoveMouseTo(Player.HUDOverlay.HoldToQuit.Children.OfType<HoldToConfirmContainer>().First().ScreenSpaceDrawQuad.Centre));
AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1);
AddUntilStep("wait for hitobjects", () => Player.HealthProcessor.Health.Value < 1);
pauseAndConfirm();
resumeAndConfirm();
@ -285,7 +285,7 @@ namespace osu.Game.Tests.Visual.Gameplay
protected class PausePlayer : TestPlayer
{
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
public new HealthProcessor HealthProcessor => base.HealthProcessor;
public new HUDOverlay HUDOverlay => base.HUDOverlay;

View File

@ -3,12 +3,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Threading;
using osu.Game.Configuration;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
@ -28,12 +30,16 @@ namespace osu.Game.Tests.Visual.Gameplay
[Cached(typeof(IReadOnlyList<Mod>))]
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
private const int spawn_interval = 5000;
private readonly ScrollingTestContainer[] scrollContainers = new ScrollingTestContainer[4];
private readonly TestPlayfield[] playfields = new TestPlayfield[4];
private ScheduledDelegate hitObjectSpawnDelegate;
public TestSceneScrollingHitObjects()
[SetUp]
public void Setup() => Schedule(() =>
{
Add(new GridContainer
Child = new GridContainer
{
RelativeSizeAxes = Axes.Both,
Content = new[]
@ -43,48 +49,66 @@ namespace osu.Game.Tests.Visual.Gameplay
scrollContainers[0] = new ScrollingTestContainer(ScrollingDirection.Up)
{
RelativeSizeAxes = Axes.Both,
Child = playfields[0] = new TestPlayfield()
Child = playfields[0] = new TestPlayfield(),
TimeRange = spawn_interval
},
scrollContainers[1] = new ScrollingTestContainer(ScrollingDirection.Up)
scrollContainers[1] = new ScrollingTestContainer(ScrollingDirection.Down)
{
RelativeSizeAxes = Axes.Both,
Child = playfields[1] = new TestPlayfield()
Child = playfields[1] = new TestPlayfield(),
TimeRange = spawn_interval
},
},
new Drawable[]
{
scrollContainers[2] = new ScrollingTestContainer(ScrollingDirection.Up)
scrollContainers[2] = new ScrollingTestContainer(ScrollingDirection.Left)
{
RelativeSizeAxes = Axes.Both,
Child = playfields[2] = new TestPlayfield()
Child = playfields[2] = new TestPlayfield(),
TimeRange = spawn_interval
},
scrollContainers[3] = new ScrollingTestContainer(ScrollingDirection.Up)
scrollContainers[3] = new ScrollingTestContainer(ScrollingDirection.Right)
{
RelativeSizeAxes = Axes.Both,
Child = playfields[3] = new TestPlayfield()
Child = playfields[3] = new TestPlayfield(),
TimeRange = spawn_interval
}
}
}
});
};
setUpHitObjects();
});
private void setUpHitObjects()
{
scrollContainers.ForEach(c => c.ControlPoints.Add(new MultiplierControlPoint(0)));
for (int i = 0; i <= spawn_interval; i += 1000)
addHitObject(Time.Current + i);
hitObjectSpawnDelegate?.Cancel();
hitObjectSpawnDelegate = Scheduler.AddDelayed(() => addHitObject(Time.Current + spawn_interval), 1000, true);
}
[Test]
public void TestScrollAlgorithms()
{
AddStep("Constant scroll", () => setScrollAlgorithm(ScrollVisualisationMethod.Constant));
AddStep("Overlapping scroll", () => setScrollAlgorithm(ScrollVisualisationMethod.Overlapping));
AddStep("Sequential scroll", () => setScrollAlgorithm(ScrollVisualisationMethod.Sequential));
AddSliderStep("Time range", 100, 10000, 5000, v => scrollContainers.ForEach(c => c.TimeRange = v));
AddStep("Add control point", () => addControlPoint(Time.Current + 5000));
AddSliderStep("Time range", 100, 10000, spawn_interval, v => scrollContainers.Where(c => c != null).ForEach(c => c.TimeRange = v));
AddStep("Add control point", () => addControlPoint(Time.Current + spawn_interval));
}
protected override void LoadComplete()
[Test]
public void TestScrollLifetime()
{
base.LoadComplete();
scrollContainers.ForEach(c => c.ControlPoints.Add(new MultiplierControlPoint(0)));
for (int i = 0; i <= 5000; i += 1000)
addHitObject(Time.Current + i);
Scheduler.AddDelayed(() => addHitObject(Time.Current + 5000), 1000, true);
AddStep("Set constant scroll", () => setScrollAlgorithm(ScrollVisualisationMethod.Constant));
// scroll container time range must be less than the rate of spawning hitobjects
// otherwise the hitobjects will spawn already partly visible on screen and look wrong
AddStep("Set time range", () => scrollContainers.ForEach(c => c.TimeRange = spawn_interval / 2.0));
}
private void addHitObject(double time)
@ -207,7 +231,9 @@ namespace osu.Game.Tests.Visual.Gameplay
public TestDrawableHitObject(double time)
: base(new HitObject { StartTime = time })
{
Origin = Anchor.Centre;
Origin = Anchor.Custom;
OriginPosition = new Vector2(75 / 4.0f);
AutoSizeAxes = Axes.Both;
AddInternal(new Box { Size = new Vector2(75) });

View File

@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online
typeof(ProfileHeader),
typeof(RankGraph),
typeof(LineGraph),
typeof(OverlayHeaderTabControl),
typeof(TabControlOverlayHeader.OverlayHeaderTabControl),
typeof(CentreHeaderContainer),
typeof(BottomHeaderContainer),
typeof(DetailHeaderContainer),

View File

@ -1,237 +0,0 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Play.HUD;
using osu.Game.Screens.Select;
using osu.Game.Tests.Beatmaps;
using osuTK;
namespace osu.Game.Tests.Visual.SongSelect
{
[TestFixture]
[System.ComponentModel.Description("PlaySongSelect leaderboard/details area")]
public class TestSceneBeatmapDetailArea : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(BeatmapDetails) };
private ModDisplay modDisplay;
[BackgroundDependencyLoader]
private void load(OsuGameBase game, RulesetStore rulesets)
{
BeatmapDetailArea detailsArea;
Add(detailsArea = new BeatmapDetailArea
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(550f, 450f),
});
Add(modDisplay = new ModDisplay
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Position = new Vector2(0, 25),
});
modDisplay.Current.BindTo(SelectedMods);
AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
Version = "All Metrics",
Metadata = new BeatmapMetadata
{
Source = "osu!lazer",
Tags = "this beatmap has all the metrics",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 7,
DrainRate = 1,
OverallDifficulty = 5.7f,
ApproachRate = 3.5f,
},
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
}));
AddStep("all except source", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
Version = "All Metrics",
Metadata = new BeatmapMetadata
{
Tags = "this beatmap has all the metrics",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 7,
DrainRate = 1,
OverallDifficulty = 5.7f,
ApproachRate = 3.5f,
},
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
}));
AddStep("ratings", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
BeatmapSet = new BeatmapSetInfo
{
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }
},
Version = "Only Ratings",
Metadata = new BeatmapMetadata
{
Source = "osu!lazer",
Tags = "this beatmap has ratings metrics but not retries or fails",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 6,
DrainRate = 9,
OverallDifficulty = 6,
ApproachRate = 6,
},
StarDifficulty = 4.8f
}
}));
AddStep("fails+retries", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
Version = "Only Retries and Fails",
Metadata = new BeatmapMetadata
{
Source = "osu!lazer",
Tags = "this beatmap has retries and fails but no ratings",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 3.7f,
DrainRate = 6,
OverallDifficulty = 6,
ApproachRate = 7,
},
StarDifficulty = 2.91f,
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
}
}));
AddStep("null metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
Version = "No Metrics",
Metadata = new BeatmapMetadata
{
Source = "osu!lazer",
Tags = "this beatmap has no metrics",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 5,
DrainRate = 5,
OverallDifficulty = 5.5f,
ApproachRate = 6.5f,
},
StarDifficulty = 1.97f,
}
}));
AddStep("null beatmap", () => detailsArea.Beatmap = null);
Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance();
AddStep("with EZ mod", () =>
{
detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
Version = "Has Easy Mod",
Metadata = new BeatmapMetadata
{
Source = "osu!lazer",
Tags = "this beatmap has the easy mod enabled",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 3,
DrainRate = 3,
OverallDifficulty = 3,
ApproachRate = 3,
},
StarDifficulty = 1f,
}
});
SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) };
});
AddStep("with HR mod", () =>
{
detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap
{
BeatmapInfo =
{
Version = "Has Hard Rock Mod",
Metadata = new BeatmapMetadata
{
Source = "osu!lazer",
Tags = "this beatmap has the hard rock mod enabled",
},
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 3,
DrainRate = 3,
OverallDifficulty = 3,
ApproachRate = 3,
},
StarDifficulty = 1f,
}
});
SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) };
});
}
}
}

View File

@ -3,8 +3,14 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Select;
namespace osu.Game.Tests.Visual.SongSelect
@ -174,5 +180,27 @@ namespace osu.Game.Tests.Visual.SongSelect
OnlineBeatmapID = 162,
});
}
[Resolved]
private RulesetStore rulesets { get; set; }
[Resolved]
private OsuColour colours { get; set; }
[Test]
public void TestModAdjustments()
{
TestAllMetrics();
Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance();
AddStep("with EZ mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) });
AddAssert("first bar coloured blue", () => details.ChildrenOfType<Bar>().Skip(1).First().AccentColour == colours.BlueDark);
AddStep("with HR mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) });
AddAssert("first bar coloured red", () => details.ChildrenOfType<Bar>().Skip(1).First().AccentColour == colours.Red);
}
}
}

View File

@ -10,11 +10,11 @@ using osu.Game.Graphics.UserInterface;
namespace osu.Game.Tests.Visual.UserInterface
{
[TestFixture]
public class TestSceneBreadcrumbs : OsuTestScene
public class TestSceneBreadcrumbControl : OsuTestScene
{
private readonly BreadcrumbControl<BreadcrumbTab> breadcrumbs;
public TestSceneBreadcrumbs()
public TestSceneBreadcrumbControl()
{
Add(breadcrumbs = new BreadcrumbControl<BreadcrumbTab>
{

View File

@ -67,9 +67,7 @@ namespace osu.Game.Tests.Visual.UserInterface
AddRepeatStep(@"add many simple", sendManyNotifications, 3);
AddWaitStep("wait some", 5);
checkProgressingCount(0);
waitForCompletion();
AddStep(@"progress #3", sendUploadProgress);
@ -77,9 +75,7 @@ namespace osu.Game.Tests.Visual.UserInterface
checkDisplayedCount(33);
AddWaitStep("wait some", 10);
checkProgressingCount(0);
waitForCompletion();
}
[Test]
@ -109,9 +105,9 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep(@"background progress #1", sendBackgroundUploadProgress);
AddWaitStep("wait some", 5);
checkProgressingCount(1);
checkProgressingCount(0);
waitForCompletion();
checkDisplayedCount(2);
@ -190,6 +186,8 @@ namespace osu.Game.Tests.Visual.UserInterface
private void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected);
private void waitForCompletion() => AddUntilStep("wait for notification progress completion", () => progressingNotifications.Count == 0);
private void sendBarrage()
{
switch (RNG.Next(0, 4))