diff --git a/osu.Android.props b/osu.Android.props index 5497a82a7a..e5a1ec2f4e 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -54,6 +54,6 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 4676f14655..bbb50c287b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -7,12 +7,10 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Graphics; using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Screens; using osu.Game.Screens.Play; using osu.Game.Skinning; using osu.Game.Tests.Visual; @@ -21,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneLegacyBeatmapSkin : OsuTestScene + public class TestSceneLegacyBeatmapSkin : ScreenTestScene { [Resolved] private AudioManager audio { get; set; } @@ -65,7 +63,8 @@ namespace osu.Game.Rulesets.Osu.Tests ExposedPlayer player; Beatmap.Value = new CustomSkinWorkingBeatmap(audio, beatmapHasColours); - Child = new OsuScreenStack(player = new ExposedPlayer(userHasCustomColours)) { RelativeSizeAxes = Axes.Both }; + + LoadScreen(player = new ExposedPlayer(userHasCustomColours)); return player; } diff --git a/osu.Game/Tests/Visual/AllPlayersTestScene.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs similarity index 59% rename from osu.Game/Tests/Visual/AllPlayersTestScene.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs index dd65c8c382..83a7b896d2 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestScene.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs @@ -2,49 +2,66 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Configuration; using osu.Game.Rulesets; +using osu.Game.Rulesets.Catch; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Play; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { /// /// A base class which runs test for all available rulesets. /// Steps to be run for each ruleset should be added via . /// - public abstract class AllPlayersTestScene : RateAdjustedBeatmapTestScene + public abstract class TestSceneAllRulesetPlayers : RateAdjustedBeatmapTestScene { protected Player Player; [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - foreach (var r in rulesets.AvailableRulesets) - { - Player p = null; - AddStep(r.Name, () => p = loadPlayerFor(r)); - AddUntilStep("player loaded", () => - { - if (p?.IsLoaded == true) - { - p = null; - return true; - } - - return false; - }); - - AddCheckSteps(); - } - OsuConfigManager manager; Dependencies.Cache(manager = new OsuConfigManager(LocalStorage)); manager.GetBindable(OsuSetting.DimLevel).Value = 1.0; } + [Test] + public void TestOsu() => runForRuleset(new OsuRuleset().RulesetInfo); + + [Test] + public void TestTaiko() => runForRuleset(new TaikoRuleset().RulesetInfo); + + [Test] + public void TestCatch() => runForRuleset(new CatchRuleset().RulesetInfo); + + [Test] + public void TestMania() => runForRuleset(new ManiaRuleset().RulesetInfo); + + private void runForRuleset(RulesetInfo ruleset) + { + Player p = null; + AddStep($"load {ruleset.Name} player", () => p = loadPlayerFor(ruleset)); + AddUntilStep("player loaded", () => + { + if (p?.IsLoaded == true) + { + p = null; + return true; + } + + return false; + }); + + AddCheckSteps(); + } + protected abstract void AddCheckSteps(); private Player loadPlayerFor(RulesetInfo rulesetInfo) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 069b965d9b..4daab8d137 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -12,7 +12,7 @@ using osu.Game.Storyboards; namespace osu.Game.Tests.Visual.Gameplay { [Description("Player instantiated with an autoplay mod.")] - public class TestSceneAutoplay : AllPlayersTestScene + public class TestSceneAutoplay : TestSceneAllRulesetPlayers { private ClockBackedTestWorkingBeatmap.TrackVirtualManual track; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index 81050b1637..de257c9e53 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneFailAnimation : AllPlayersTestScene + public class TestSceneFailAnimation : TestSceneAllRulesetPlayers { protected override Player CreatePlayer(Ruleset ruleset) { @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override IReadOnlyList RequiredTypes => new[] { - typeof(AllPlayersTestScene), + typeof(TestSceneAllRulesetPlayers), typeof(TestPlayer), typeof(Player), }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index 2045072c79..d80efb2c6e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneFailJudgement : AllPlayersTestScene + public class TestSceneFailJudgement : TestSceneAllRulesetPlayers { protected override Player CreatePlayer(Ruleset ruleset) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 1a83e35e4f..ad5bab4681 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -36,6 +36,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override void SetUpSteps() { base.SetUpSteps(); + AddStep("resume player", () => Player.GameplayClockContainer.Start()); confirmClockRunning(true); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index 4d701f56a9..8f767659c6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -10,7 +10,7 @@ using osu.Game.Storyboards; namespace osu.Game.Tests.Visual.Gameplay { - public class TestScenePlayerReferenceLeaking : AllPlayersTestScene + public class TestScenePlayerReferenceLeaking : TestSceneAllRulesetPlayers { private readonly WeakList workingWeakReferences = new WeakList(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index 36335bc54a..e82722e7a2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { [Description("Player instantiated with a replay.")] - public class TestSceneReplay : AllPlayersTestScene + public class TestSceneReplay : TestSceneAllRulesetPlayers { protected override Player CreatePlayer(Ruleset ruleset) { diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 1561d0d11d..19bdaff6ff 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -38,9 +38,21 @@ namespace osu.Game.Tests.Visual.Online private TestChatOverlay chatOverlay; private ChannelManager channelManager; - private readonly Channel channel1 = new Channel(new User()) { Name = "test really long username", Topic = "Topic for channel 1" }; - private readonly Channel channel2 = new Channel(new User()) { Name = "test2", Topic = "Topic for channel 2" }; - private readonly Channel channel3 = new Channel(new User()) { Name = "channel with no topic" }; + private readonly List channels; + + private Channel channel1 => channels[0]; + private Channel channel2 => channels[1]; + + public TestSceneChatOverlay() + { + channels = Enumerable.Range(1, 10) + .Select(index => new Channel(new User()) + { + Name = $"Channel no. {index}", + Topic = index == 3 ? null : $"We talk about the number {index} here" + }) + .ToList(); + } [SetUp] public void Setup() @@ -49,7 +61,7 @@ namespace osu.Game.Tests.Visual.Online { ChannelManagerContainer container; - Child = container = new ChannelManagerContainer(new List { channel1, channel2, channel3 }) + Child = container = new ChannelManagerContainer(channels) { RelativeSizeAxes = Axes.Both, }; @@ -103,7 +115,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestSearchInSelector() { - AddStep("search for 'test2'", () => chatOverlay.ChildrenOfType().First().Text = "test2"); + AddStep("search for 'no. 2'", () => chatOverlay.ChildrenOfType().First().Text = "no. 2"); AddUntilStep("only channel 2 visible", () => { var listItems = chatOverlay.ChildrenOfType().Where(c => c.IsPresent); @@ -111,6 +123,36 @@ namespace osu.Game.Tests.Visual.Online }); } + [Test] + public void TestChannelShortcutKeys() + { + AddStep("join 10 channels", () => channels.ForEach(channel => channelManager.JoinChannel(channel))); + AddStep("close channel selector", () => + { + InputManager.PressKey(Key.Escape); + InputManager.ReleaseKey(Key.Escape); + }); + AddUntilStep("wait for close", () => chatOverlay.SelectionOverlayState == Visibility.Hidden); + + for (int zeroBasedIndex = 0; zeroBasedIndex < 10; ++zeroBasedIndex) + { + var oneBasedIndex = zeroBasedIndex + 1; + var targetNumberKey = oneBasedIndex % 10; + var targetChannel = channels[zeroBasedIndex]; + AddStep($"press Alt+{targetNumberKey}", () => pressChannelHotkey(targetNumberKey)); + AddAssert($"channel #{oneBasedIndex} is selected", () => channelManager.CurrentChannel.Value == targetChannel); + } + } + + private void pressChannelHotkey(int number) + { + var channelKey = Key.Number0 + number; + InputManager.PressKey(Key.AltLeft); + InputManager.PressKey(channelKey); + InputManager.ReleaseKey(Key.AltLeft); + InputManager.ReleaseKey(channelKey); + } + private void clickDrawable(Drawable d) { InputManager.MoveMouseTo(d); diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index fc06780431..c01dee2959 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -72,19 +72,24 @@ namespace osu.Game.Tests.Visual.SongSelect // required to get bindables attached Add(music); - Beatmap.SetDefault(); - Dependencies.Cache(config = new OsuConfigManager(LocalStorage)); } private OsuConfigManager config; - [SetUp] - public virtual void SetUp() => Schedule(() => + [SetUpSteps] + public override void SetUpSteps() { - Ruleset.Value = new OsuRuleset().RulesetInfo; - manager?.Delete(manager.GetAllUsableBeatmapSets()); - }); + base.SetUpSteps(); + + AddStep("delete all beatmaps", () => + { + Ruleset.Value = new OsuRuleset().RulesetInfo; + manager?.Delete(manager.GetAllUsableBeatmapSets()); + + Beatmap.SetDefault(); + }); + } [Test] public void TestSingleFilterOnEnter() @@ -120,9 +125,6 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); AddAssert("ensure selection changed", () => selected != Beatmap.Value); - - AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen()); - AddUntilStep("bindable lease returned", () => !Beatmap.Disabled); } [Test] @@ -148,9 +150,6 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); AddAssert("ensure selection didn't change", () => selected == Beatmap.Value); - - AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen()); - AddUntilStep("bindable lease returned", () => !Beatmap.Disabled); } [Test] @@ -180,9 +179,6 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); AddAssert("ensure selection changed", () => selected != Beatmap.Value); - - AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen()); - AddUntilStep("bindable lease returned", () => !Beatmap.Disabled); } [Test] @@ -213,9 +209,6 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); AddAssert("ensure selection didn't change", () => selected == Beatmap.Value); - - AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen()); - AddUntilStep("bindable lease returned", () => !Beatmap.Disabled); } [Test] diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 2c0fa49b5d..f2aef0995f 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -321,8 +321,10 @@ namespace osu.Game.Overlays private void selectTab(int index) { - var channel = ChannelTabControl.Items.Skip(index).FirstOrDefault(); - if (channel != null && !(channel is ChannelSelectorTabItem.ChannelSelectorTabChannel)) + var channel = ChannelTabControl.Items + .Where(tab => !(tab is ChannelSelectorTabItem.ChannelSelectorTabChannel)) + .ElementAtOrDefault(index); + if (channel != null) ChannelTabControl.Current.Value = channel; } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index a16401a527..f9f015643d 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -345,8 +345,8 @@ namespace osu.Game.Screens.Select selectionChangedDebounce = null; } - if (performStartAction) - OnStart(); + if (performStartAction && OnStart()) + Carousel.AllowSelection = false; } /// @@ -500,6 +500,8 @@ namespace osu.Game.Screens.Select public override void OnResuming(IScreen last) { + Carousel.AllowSelection = true; + BeatmapDetails.Leaderboard.RefreshScores(); Beatmap.Value.Track.Looping = true; @@ -647,7 +649,6 @@ namespace osu.Game.Screens.Select decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; decoupledRuleset.DisabledChanged += r => Ruleset.Disabled = r; - Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true); Beatmap.BindValueChanged(workingBeatmapChanged); boundLocalBindables = true; diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 3ed65bee61..7c5ba7d30f 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -33,8 +33,10 @@ namespace osu.Game.Tests.Visual } [SetUpSteps] - public virtual void SetUpSteps() + public override void SetUpSteps() { + base.SetUpSteps(); + AddStep(ruleset.RulesetInfo.Name, loadPlayer); AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1); } diff --git a/osu.Game/Tests/Visual/ScreenTestScene.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs index 707aa61283..feca592049 100644 --- a/osu.Game/Tests/Visual/ScreenTestScene.cs +++ b/osu.Game/Tests/Visual/ScreenTestScene.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Game.Screens; namespace osu.Game.Tests.Visual @@ -27,11 +28,23 @@ namespace osu.Game.Tests.Visual }); } - protected void LoadScreen(OsuScreen screen) + protected void LoadScreen(OsuScreen screen) => Stack.Push(screen); + + [SetUpSteps] + public virtual void SetUpSteps() => addExitAllScreensStep(); + + [TearDownSteps] + public void TearDownSteps() => addExitAllScreensStep(); + + private void addExitAllScreensStep() { - if (Stack.CurrentScreen != null) + AddUntilStep("exit all screens", () => + { + if (Stack.CurrentScreen == null) return true; + Stack.Exit(); - Stack.Push(screen); + return false; + }); } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0ea558bbc7..b38b7ff9b1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a215bc65e8..6ab3c0f2d2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - +