mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 07:06:35 +09:00
Merge branch 'master' into non-concurrent-sample-playback
This commit is contained in:
@ -5,6 +5,8 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||
using osuTK;
|
||||
|
||||
@ -13,6 +15,9 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
[TestFixture]
|
||||
public class TestSceneEditorSummaryTimeline : EditorClockTestScene
|
||||
{
|
||||
[Cached(typeof(EditorBeatmap))]
|
||||
private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap());
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
|
@ -0,0 +1,55 @@
|
||||
// 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.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
using static osu.Game.Screens.Edit.Compose.Components.Timeline.TimelineHitObjectBlueprint;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
public class TestSceneTimelineHitObjectBlueprint : TimelineTestScene
|
||||
{
|
||||
public override Drawable CreateTestComponent() => new TimelineBlueprintContainer(Composer);
|
||||
|
||||
[Test]
|
||||
public void TestDisallowZeroDurationObjects()
|
||||
{
|
||||
DragBar dragBar;
|
||||
|
||||
AddStep("add spinner", () =>
|
||||
{
|
||||
EditorBeatmap.Clear();
|
||||
EditorBeatmap.Add(new Spinner
|
||||
{
|
||||
Position = new Vector2(256, 256),
|
||||
StartTime = 150,
|
||||
Duration = 500
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("hold down drag bar", () =>
|
||||
{
|
||||
// distinguishes between the actual drag bar and its "underlay shadow".
|
||||
dragBar = this.ChildrenOfType<DragBar>().Single(bar => bar.HandlePositionalInput);
|
||||
InputManager.MoveMouseTo(dragBar);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddStep("try to drag bar past start", () =>
|
||||
{
|
||||
var blueprint = this.ChildrenOfType<TimelineHitObjectBlueprint>().Single();
|
||||
InputManager.MoveMouseTo(blueprint.SelectionQuad.TopLeft - new Vector2(100, 0));
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddAssert("object has non-zero duration", () => EditorBeatmap.HitObjects.OfType<IHasDuration>().Single().Duration > 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -23,22 +23,24 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
protected HitObjectComposer Composer { get; private set; }
|
||||
|
||||
protected EditorBeatmap EditorBeatmap { get; private set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
Beatmap.Value = new WaveformTestBeatmap(audio);
|
||||
|
||||
var playable = Beatmap.Value.GetPlayableBeatmap(Beatmap.Value.BeatmapInfo.Ruleset);
|
||||
var editorBeatmap = new EditorBeatmap(playable);
|
||||
EditorBeatmap = new EditorBeatmap(playable);
|
||||
|
||||
Dependencies.Cache(editorBeatmap);
|
||||
Dependencies.CacheAs<IBeatSnapProvider>(editorBeatmap);
|
||||
Dependencies.Cache(EditorBeatmap);
|
||||
Dependencies.CacheAs<IBeatSnapProvider>(EditorBeatmap);
|
||||
|
||||
Composer = playable.BeatmapInfo.Ruleset.CreateInstance().CreateHitObjectComposer().With(d => d.Alpha = 0);
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
editorBeatmap,
|
||||
EditorBeatmap,
|
||||
Composer,
|
||||
new FillFlowContainer
|
||||
{
|
||||
|
@ -17,10 +17,12 @@ using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Legacy;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -129,6 +131,31 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddUntilStep("no DHOs shown", () => !this.ChildrenOfType<DrawableTestHitObject>().Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestApplyHitResultOnKilled()
|
||||
{
|
||||
ManualClock clock = null;
|
||||
bool anyJudged = false;
|
||||
|
||||
void onNewResult(JudgementResult _) => anyJudged = true;
|
||||
|
||||
var beatmap = new Beatmap();
|
||||
beatmap.HitObjects.Add(new TestKilledHitObject { Duration = 20 });
|
||||
|
||||
createTest(beatmap, 10, () => new FramedClock(clock = new ManualClock()));
|
||||
|
||||
AddStep("subscribe to new result", () =>
|
||||
{
|
||||
anyJudged = false;
|
||||
drawableRuleset.NewResult += onNewResult;
|
||||
});
|
||||
AddStep("skip past object", () => clock.CurrentTime = beatmap.HitObjects[0].GetEndTime() + 1000);
|
||||
|
||||
AddAssert("object judged", () => anyJudged);
|
||||
|
||||
AddStep("clean up", () => drawableRuleset.NewResult -= onNewResult);
|
||||
}
|
||||
|
||||
private void createTest(IBeatmap beatmap, int poolSize, Func<IFrameBasedClock> createClock = null) => AddStep("create test", () =>
|
||||
{
|
||||
var ruleset = new TestPoolingRuleset();
|
||||
@ -192,6 +219,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
private void load()
|
||||
{
|
||||
RegisterPool<TestHitObject, DrawableTestHitObject>(poolSize);
|
||||
RegisterPool<TestKilledHitObject, DrawableTestKilledHitObject>(poolSize);
|
||||
}
|
||||
|
||||
protected override HitObjectLifetimeEntry CreateLifetimeEntry(HitObject hitObject) => new TestHitObjectLifetimeEntry(hitObject);
|
||||
@ -220,19 +248,30 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
protected override IEnumerable<TestHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap, CancellationToken cancellationToken)
|
||||
{
|
||||
yield return new TestHitObject
|
||||
switch (original)
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Duration = 250
|
||||
};
|
||||
case TestKilledHitObject h:
|
||||
yield return h;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
yield return new TestHitObject
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
Duration = 250
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HitObject
|
||||
#region HitObjects
|
||||
|
||||
private class TestHitObject : ConvertHitObject
|
||||
private class TestHitObject : ConvertHitObject, IHasDuration
|
||||
{
|
||||
public double EndTime => StartTime + Duration;
|
||||
|
||||
@ -287,6 +326,30 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
}
|
||||
}
|
||||
|
||||
private class TestKilledHitObject : TestHitObject
|
||||
{
|
||||
}
|
||||
|
||||
private class DrawableTestKilledHitObject : DrawableHitObject<TestKilledHitObject>
|
||||
{
|
||||
public DrawableTestKilledHitObject()
|
||||
: base(null)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateHitStateTransforms(ArmedState state)
|
||||
{
|
||||
base.UpdateHitStateTransforms(state);
|
||||
Expire();
|
||||
}
|
||||
|
||||
public override void OnKilled()
|
||||
{
|
||||
base.OnKilled();
|
||||
ApplyResult(r => r.Type = r.Judgement.MinResult);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Array.Empty<Mod>());
|
||||
|
||||
return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod()?.CreateReplayScore(beatmap));
|
||||
return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod()?.CreateReplayScore(beatmap, Array.Empty<Mod>()));
|
||||
}
|
||||
|
||||
protected override void AddCheckSteps()
|
||||
|
@ -0,0 +1,74 @@
|
||||
// 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.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Storyboards;
|
||||
using osu.Game.Storyboards.Drawables;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneStoryboardSamplePlayback : PlayerTestScene
|
||||
{
|
||||
private Storyboard storyboard;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
config.Set(OsuSetting.ShowStoryboard, true);
|
||||
|
||||
storyboard = new Storyboard();
|
||||
var backgroundLayer = storyboard.GetLayer("Background");
|
||||
backgroundLayer.Add(new StoryboardSampleInfo("Intro/welcome.mp3", time: -7000, volume: 20));
|
||||
backgroundLayer.Add(new StoryboardSampleInfo("Intro/welcome.mp3", time: -5000, volume: 20));
|
||||
backgroundLayer.Add(new StoryboardSampleInfo("Intro/welcome.mp3", time: 0, volume: 20));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStoryboardSamplesStopDuringPause()
|
||||
{
|
||||
checkForFirstSamplePlayback();
|
||||
|
||||
AddStep("player paused", () => Player.Pause());
|
||||
AddAssert("player is currently paused", () => Player.GameplayClockContainer.IsPaused.Value);
|
||||
AddAssert("all storyboard samples stopped immediately", () => allStoryboardSamples.All(sound => !sound.IsPlaying));
|
||||
|
||||
AddStep("player resume", () => Player.Resume());
|
||||
AddUntilStep("any storyboard samples playing after resume", () => allStoryboardSamples.Any(sound => sound.IsPlaying));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStoryboardSamplesStopOnSkip()
|
||||
{
|
||||
checkForFirstSamplePlayback();
|
||||
|
||||
AddStep("skip intro", () => InputManager.Key(osuTK.Input.Key.Space));
|
||||
AddAssert("all storyboard samples stopped immediately", () => allStoryboardSamples.All(sound => !sound.IsPlaying));
|
||||
|
||||
AddUntilStep("any storyboard samples playing after skip", () => allStoryboardSamples.Any(sound => sound.IsPlaying));
|
||||
}
|
||||
|
||||
private void checkForFirstSamplePlayback()
|
||||
{
|
||||
AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded);
|
||||
AddUntilStep("any storyboard samples playing", () => allStoryboardSamples.Any(sound => sound.IsPlaying));
|
||||
}
|
||||
|
||||
private IEnumerable<DrawableStoryboardSample> allStoryboardSamples => Player.ChildrenOfType<DrawableStoryboardSample>();
|
||||
|
||||
protected override bool AllowFail => false;
|
||||
|
||||
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, false);
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) =>
|
||||
new ClockBackedTestWorkingBeatmap(beatmap, storyboard ?? this.storyboard, Clock, Audio);
|
||||
}
|
||||
}
|
@ -11,8 +11,8 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
@ -20,6 +20,7 @@ using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
@ -241,7 +242,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
}
|
||||
|
||||
private void moveToItem(int index, Vector2? offset = null)
|
||||
=> AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<OsuRearrangeableListItem<PlaylistItem>>().ElementAt(index), offset));
|
||||
=> AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<DifficultyIcon>().ElementAt(index), offset));
|
||||
|
||||
private void moveToDragger(int index, Vector2? offset = null) => AddStep($"move mouse to dragger {index}", () =>
|
||||
{
|
||||
@ -252,7 +253,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
private void moveToDeleteButton(int index, Vector2? offset = null) => AddStep($"move mouse to delete button {index}", () =>
|
||||
{
|
||||
var item = playlist.ChildrenOfType<OsuRearrangeableListItem<PlaylistItem>>().ElementAt(index);
|
||||
InputManager.MoveMouseTo(item.ChildrenOfType<IconButton>().ElementAt(0), offset);
|
||||
InputManager.MoveMouseTo(item.ChildrenOfType<DrawableRoomPlaylistItem.PlaylistRemoveButton>().ElementAt(0), offset);
|
||||
});
|
||||
|
||||
private void assertHandleVisibility(int index, bool visible)
|
||||
@ -260,7 +261,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
() => (playlist.ChildrenOfType<OsuRearrangeableListItem<PlaylistItem>.PlaylistItemHandle>().ElementAt(index).Alpha > 0) == visible);
|
||||
|
||||
private void assertDeleteButtonVisibility(int index, bool visible)
|
||||
=> AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType<IconButton>().ElementAt(2 + index * 2).Alpha > 0) == visible);
|
||||
=> AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType<DrawableRoomPlaylistItem.PlaylistRemoveButton>().ElementAt(2 + index * 2).Alpha > 0) == visible);
|
||||
|
||||
private void createPlaylist(bool allowEdit, bool allowSelection)
|
||||
{
|
||||
@ -278,7 +279,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
playlist.Items.Add(new PlaylistItem
|
||||
{
|
||||
ID = i,
|
||||
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
|
||||
Beatmap =
|
||||
{
|
||||
Value = i % 2 == 1
|
||||
? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
|
||||
: new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Artist = "Artist",
|
||||
Author = new User { Username = "Creator name here" },
|
||||
Title = "Long title used to check background colour",
|
||||
},
|
||||
BeatmapSet = new BeatmapSetInfo()
|
||||
}
|
||||
},
|
||||
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
||||
RequiredMods =
|
||||
{
|
||||
|
@ -0,0 +1,21 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
public class TestSceneFreeModSelectOverlay : MultiplayerTestScene
|
||||
{
|
||||
[SetUp]
|
||||
public new void Setup() => Schedule(() =>
|
||||
{
|
||||
Child = new FreeModSelectOverlay
|
||||
{
|
||||
State = { Value = Visibility.Visible }
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
@ -7,7 +7,12 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Participants;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
@ -17,16 +22,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
public class TestSceneMultiplayerParticipantsList : MultiplayerTestScene
|
||||
{
|
||||
[SetUp]
|
||||
public new void Setup() => Schedule(() =>
|
||||
{
|
||||
Child = new ParticipantsList
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Size = new Vector2(380, 0.7f)
|
||||
};
|
||||
});
|
||||
public new void Setup() => Schedule(createNewParticipantsList);
|
||||
|
||||
[Test]
|
||||
public void TestAddUser()
|
||||
@ -73,6 +69,50 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddAssert("single panel is for second user", () => this.ChildrenOfType<ParticipantPanel>().Single().User.User == secondUser);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGameStateHasPriorityOverDownloadState()
|
||||
{
|
||||
AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
||||
checkProgressBarVisibility(true);
|
||||
|
||||
AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Results));
|
||||
checkProgressBarVisibility(false);
|
||||
AddUntilStep("ready mark visible", () => this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
||||
|
||||
AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Idle));
|
||||
checkProgressBarVisibility(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCorrectInitialState()
|
||||
{
|
||||
AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
||||
AddStep("recreate list", createNewParticipantsList);
|
||||
checkProgressBarVisibility(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBeatmapDownloadingStates()
|
||||
{
|
||||
AddStep("set to no map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded()));
|
||||
AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
||||
|
||||
checkProgressBarVisibility(true);
|
||||
|
||||
AddRepeatStep("increment progress", () =>
|
||||
{
|
||||
var progress = this.ChildrenOfType<ParticipantPanel>().Single().User.BeatmapAvailability.DownloadProgress ?? 0;
|
||||
Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f)));
|
||||
}, 25);
|
||||
|
||||
AddAssert("progress bar increased", () => this.ChildrenOfType<ProgressBar>().Single().Current.Value > 0);
|
||||
|
||||
AddStep("set to importing map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Importing()));
|
||||
checkProgressBarVisibility(false);
|
||||
|
||||
AddStep("set to available", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestToggleReadyState()
|
||||
{
|
||||
@ -120,8 +160,64 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
});
|
||||
|
||||
Client.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results + 1));
|
||||
|
||||
if (RNG.NextBool())
|
||||
{
|
||||
var beatmapState = (DownloadState)RNG.Next(0, (int)DownloadState.LocallyAvailable + 1);
|
||||
|
||||
switch (beatmapState)
|
||||
{
|
||||
case DownloadState.NotDownloaded:
|
||||
Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.NotDownloaded());
|
||||
break;
|
||||
|
||||
case DownloadState.Downloading:
|
||||
Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Downloading(RNG.NextSingle()));
|
||||
break;
|
||||
|
||||
case DownloadState.Importing:
|
||||
Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Importing());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserWithMods()
|
||||
{
|
||||
AddStep("add user", () =>
|
||||
{
|
||||
Client.AddUser(new User
|
||||
{
|
||||
Id = 0,
|
||||
Username = "User 0",
|
||||
CurrentModeRank = RNG.Next(1, 100000),
|
||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
||||
});
|
||||
|
||||
Client.ChangeUserMods(0, new Mod[]
|
||||
{
|
||||
new OsuModHardRock(),
|
||||
new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } }
|
||||
});
|
||||
});
|
||||
|
||||
for (var i = MultiplayerUserState.Idle; i < MultiplayerUserState.Results; i++)
|
||||
{
|
||||
var state = i;
|
||||
AddStep($"set state: {state}", () => Client.ChangeUserState(0, state));
|
||||
}
|
||||
}
|
||||
|
||||
private void createNewParticipantsList()
|
||||
{
|
||||
Child = new ParticipantsList { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Y, Size = new Vector2(380, 0.7f) };
|
||||
}
|
||||
|
||||
private void checkProgressBarVisibility(bool visible) =>
|
||||
AddUntilStep($"progress bar {(visible ? "is" : "is not")}visible", () =>
|
||||
this.ChildrenOfType<ProgressBar>().Single().IsPresent == visible);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
@ -26,8 +27,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
public class TestSceneMultiplayerReadyButton : MultiplayerTestScene
|
||||
{
|
||||
private MultiplayerReadyButton button;
|
||||
private OnlinePlayBeatmapAvailablilityTracker beatmapTracker;
|
||||
private BeatmapSetInfo importedSet;
|
||||
|
||||
private readonly Bindable<PlaylistItem> selectedItem = new Bindable<PlaylistItem>();
|
||||
|
||||
private BeatmapManager beatmaps;
|
||||
private RulesetStore rulesets;
|
||||
|
||||
@ -39,6 +43,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default));
|
||||
beatmaps.Import(TestResources.GetTestBeatmapForImport(true)).Wait();
|
||||
|
||||
Add(beatmapTracker = new OnlinePlayBeatmapAvailablilityTracker
|
||||
{
|
||||
SelectedItem = { BindTarget = selectedItem }
|
||||
});
|
||||
|
||||
Dependencies.Cache(beatmapTracker);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
@ -46,20 +57,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
|
||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
|
||||
selectedItem.Value = new PlaylistItem
|
||||
{
|
||||
Beatmap = { Value = Beatmap.Value.BeatmapInfo },
|
||||
Ruleset = { Value = Beatmap.Value.BeatmapInfo.Ruleset },
|
||||
};
|
||||
|
||||
Child = button = new MultiplayerReadyButton
|
||||
if (button != null)
|
||||
Remove(button);
|
||||
|
||||
Add(button = new MultiplayerReadyButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(200, 50),
|
||||
SelectedItem =
|
||||
{
|
||||
Value = new PlaylistItem
|
||||
{
|
||||
Beatmap = { Value = Beatmap.Value.BeatmapInfo },
|
||||
Ruleset = { Value = Beatmap.Value.BeatmapInfo.Ruleset }
|
||||
}
|
||||
},
|
||||
OnReadyClick = async () =>
|
||||
{
|
||||
readyClickOperation = OngoingOperationTracker.BeginOperation();
|
||||
@ -73,7 +84,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
await Client.ToggleReady();
|
||||
readyClickOperation.Dispose();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
[Test]
|
||||
|
@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
});
|
||||
});
|
||||
|
||||
AddAssert("multiplayer room joined", () => roomContainer.Client.Room != null);
|
||||
AddUntilStep("multiplayer room joined", () => roomContainer.Client.Room != null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -133,7 +133,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
});
|
||||
});
|
||||
|
||||
AddAssert("multiplayer room joined", () => roomContainer.Client.Room != null);
|
||||
AddUntilStep("multiplayer room joined", () => roomContainer.Client.Room != null);
|
||||
}
|
||||
|
||||
private TestMultiplayerRoomManager createRoomManager()
|
||||
|
@ -19,11 +19,11 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
public class TestSceneMatchSongSelect : RoomTestScene
|
||||
public class TestScenePlaylistsSongSelect : RoomTestScene
|
||||
{
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
private RulesetStore rulesets;
|
||||
|
||||
private TestMatchSongSelect songSelect;
|
||||
private TestPlaylistsSongSelect songSelect;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(GameHost host, AudioManager audio)
|
||||
@ -87,9 +87,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
Ruleset.Value = new OsuRuleset().RulesetInfo;
|
||||
Beatmap.SetDefault();
|
||||
SelectedMods.Value = Array.Empty<Mod>();
|
||||
});
|
||||
|
||||
AddStep("create song select", () => LoadScreen(songSelect = new TestMatchSongSelect()));
|
||||
AddStep("create song select", () => LoadScreen(songSelect = new TestPlaylistsSongSelect()));
|
||||
AddUntilStep("wait for present", () => songSelect.IsCurrentScreen());
|
||||
}
|
||||
|
||||
@ -176,7 +177,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddAssert("item has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)Room.Playlist.First().RequiredMods[0]).SpeedChange.Value));
|
||||
}
|
||||
|
||||
private class TestMatchSongSelect : MatchSongSelect
|
||||
private class TestPlaylistsSongSelect : PlaylistsSongSelect
|
||||
{
|
||||
public new MatchBeatmapDetailArea BeatmapDetails => (MatchBeatmapDetailArea)base.BeatmapDetails;
|
||||
}
|
@ -1,32 +1,81 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// 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 osu.Game.Overlays;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.BeatmapListing;
|
||||
using osu.Game.Rulesets;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneBeatmapListingOverlay : OsuTestScene
|
||||
{
|
||||
protected override bool UseOnlineAPI => true;
|
||||
private readonly List<APIBeatmapSet> setsForResponse = new List<APIBeatmapSet>();
|
||||
|
||||
private readonly BeatmapListingOverlay overlay;
|
||||
private BeatmapListingOverlay overlay;
|
||||
|
||||
public TestSceneBeatmapListingOverlay()
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(overlay = new BeatmapListingOverlay());
|
||||
Child = overlay = new BeatmapListingOverlay { State = { Value = Visibility.Visible } };
|
||||
|
||||
((DummyAPIAccess)API).HandleRequest = req =>
|
||||
{
|
||||
if (req is SearchBeatmapSetsRequest searchBeatmapSetsRequest)
|
||||
{
|
||||
searchBeatmapSetsRequest.TriggerSuccess(new SearchBeatmapSetsResponse
|
||||
{
|
||||
BeatmapSets = setsForResponse,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestShow()
|
||||
public void TestNoBeatmapsPlaceholder()
|
||||
{
|
||||
AddStep("Show", overlay.Show);
|
||||
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||
|
||||
AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet));
|
||||
AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().Any());
|
||||
|
||||
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||
|
||||
// fetch once more to ensure nothing happens in displaying placeholder again when it already is present.
|
||||
AddStep("fetch for 0 beatmaps again", () => fetchFor());
|
||||
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHide()
|
||||
private void fetchFor(params BeatmapSetInfo[] beatmaps)
|
||||
{
|
||||
AddStep("Hide", overlay.Hide);
|
||||
setsForResponse.Clear();
|
||||
setsForResponse.AddRange(beatmaps.Select(b => new TestAPIBeatmapSet(b)));
|
||||
|
||||
// trigger arbitrary change for fetching.
|
||||
overlay.ChildrenOfType<BeatmapListingSearchControl>().Single().Query.TriggerChange();
|
||||
}
|
||||
|
||||
private class TestAPIBeatmapSet : APIBeatmapSet
|
||||
{
|
||||
private readonly BeatmapSetInfo beatmapSet;
|
||||
|
||||
public TestAPIBeatmapSet(BeatmapSetInfo beatmapSet)
|
||||
{
|
||||
this.beatmapSet = beatmapSet;
|
||||
}
|
||||
|
||||
public override BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) => beatmapSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,8 +231,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
});
|
||||
|
||||
AddAssert("shown beatmaps of current ruleset", () => overlay.Header.Picker.Difficulties.All(b => b.Beatmap.Ruleset.Equals(overlay.Header.RulesetSelector.Current.Value)));
|
||||
AddAssert("left-most beatmap selected", () => overlay.Header.Picker.Difficulties.First().State == BeatmapPicker.DifficultySelectorState.Selected);
|
||||
AddAssert("shown beatmaps of current ruleset", () => overlay.Header.HeaderContent.Picker.Difficulties.All(b => b.Beatmap.Ruleset.Equals(overlay.Header.RulesetSelector.Current.Value)));
|
||||
AddAssert("left-most beatmap selected", () => overlay.Header.HeaderContent.Picker.Difficulties.First().State == BeatmapPicker.DifficultySelectorState.Selected);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -310,12 +310,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private void downloadAssert(bool shown)
|
||||
{
|
||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.DownloadButtonsVisible == shown);
|
||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.HeaderContent.DownloadButtonsVisible == shown);
|
||||
}
|
||||
|
||||
private class TestBeatmapSetOverlay : BeatmapSetOverlay
|
||||
{
|
||||
public new Header Header => base.Header;
|
||||
public new BeatmapSetHeader Header => base.Header;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,26 +103,26 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private void testLinksGeneral()
|
||||
{
|
||||
addMessageWithChecks("test!");
|
||||
addMessageWithChecks("osu.ppy.sh!");
|
||||
addMessageWithChecks("https://osu.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("dev.ppy.sh!");
|
||||
addMessageWithChecks("https://dev.ppy.sh!", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("00:12:345 (1,2) - Test?", 1, expectedActions: LinkAction.OpenEditorTimestamp);
|
||||
addMessageWithChecks("Wiki link for tasty [[Performance Points]]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(osu forums)[https://osu.ppy.sh/forum] (old link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://osu.ppy.sh/home New site] (new link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[osu forums](https://osu.ppy.sh/forum) (new link format 2)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://osu.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("is now listening to [https://osu.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmapSet);
|
||||
addMessageWithChecks("is now playing [https://osu.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmap);
|
||||
addMessageWithChecks("Let's (try)[https://osu.ppy.sh/home] [https://osu.ppy.sh/b/252238 multiple links] https://osu.ppy.sh/home", 3,
|
||||
addMessageWithChecks("(osu forums)[https://dev.ppy.sh/forum] (old link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home New site] (new link format)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[osu forums](https://dev.ppy.sh/forum) (new link format 2)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("is now listening to [https://dev.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmapSet);
|
||||
addMessageWithChecks("is now playing [https://dev.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmap);
|
||||
addMessageWithChecks("Let's (try)[https://dev.ppy.sh/home] [https://dev.ppy.sh/b/252238 multiple links] https://dev.ppy.sh/home", 3,
|
||||
expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External });
|
||||
addMessageWithChecks("[https://osu.ppy.sh/home New link format with escaped [and \\[ paired] braces]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://osu.ppy.sh/home)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://osu.ppy.sh/home] and [[also a rogue wiki link]]", 2, expectedActions: new[] { LinkAction.External, LinkAction.External });
|
||||
addMessageWithChecks("[https://dev.ppy.sh/home New link format with escaped [and \\[ paired] braces]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://dev.ppy.sh/home)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]", 2, expectedActions: new[] { LinkAction.External, LinkAction.External });
|
||||
// note that there's 0 links here (they get removed if a channel is not found)
|
||||
addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present).");
|
||||
addMessageWithChecks("I am important!", 0, false, true);
|
||||
addMessageWithChecks("feels important", 0, true, true);
|
||||
addMessageWithChecks("likes to post this [https://osu.ppy.sh/home link].", 1, true, true, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("likes to post this [https://dev.ppy.sh/home link].", 1, true, true, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("Join my multiplayer game osump://12346.", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
|
||||
addMessageWithChecks("Join my [multiplayer game](osump://12346).", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
|
||||
addMessageWithChecks("Join my [#english](osu://chan/#english).", 1, expectedActions: LinkAction.OpenChannel);
|
||||
@ -136,9 +136,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
int echoCounter = 0;
|
||||
|
||||
addEchoWithWait("sent!", "received!");
|
||||
addEchoWithWait("https://osu.ppy.sh/home", null, 500);
|
||||
addEchoWithWait("[https://osu.ppy.sh/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://osu.ppy.sh/home]", null, 5000);
|
||||
addEchoWithWait("https://dev.ppy.sh/home", null, 500);
|
||||
addEchoWithWait("[https://dev.ppy.sh/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://dev.ppy.sh/home]", null, 5000);
|
||||
|
||||
void addEchoWithWait(string text, string completeText = null, double delay = 250)
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private class TestFullscreenOverlay : FullscreenOverlay<OverlayHeader>
|
||||
{
|
||||
public TestFullscreenOverlay()
|
||||
: base(OverlayColourScheme.Pink, null)
|
||||
: base(OverlayColourScheme.Pink)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@ -52,6 +52,17 @@ namespace osu.Game.Tests.Visual.Online
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override OverlayHeader CreateHeader() => new TestHeader();
|
||||
|
||||
internal class TestHeader : OverlayHeader
|
||||
{
|
||||
protected override OverlayTitle CreateTitle() => new TestTitle();
|
||||
|
||||
internal class TestTitle : OverlayTitle
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
// 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 osu.Game.Overlays;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[Description("uses online API")]
|
||||
public class TestSceneOnlineBeatmapListingOverlay : OsuTestScene
|
||||
{
|
||||
protected override bool UseOnlineAPI => true;
|
||||
|
||||
private readonly BeatmapListingOverlay overlay;
|
||||
|
||||
public TestSceneOnlineBeatmapListingOverlay()
|
||||
{
|
||||
Add(overlay = new BeatmapListingOverlay());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestShow()
|
||||
{
|
||||
AddStep("Show", overlay.Show);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHide()
|
||||
{
|
||||
AddStep("Hide", overlay.Hide);
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Add(rankingsOverlay = new TestRankingsOverlay
|
||||
{
|
||||
Country = { BindTarget = countryBindable },
|
||||
Scope = { BindTarget = scope },
|
||||
Header = { Current = { BindTarget = scope } },
|
||||
});
|
||||
}
|
||||
|
||||
@ -65,8 +65,6 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private class TestRankingsOverlay : RankingsOverlay
|
||||
{
|
||||
public new Bindable<Country> Country => base.Country;
|
||||
|
||||
public new Bindable<RankingsScope> Scope => base.Scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,16 +8,16 @@ using osu.Game.Users;
|
||||
using osuTK;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays.Chat;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneStandAloneChatDisplay : OsuTestScene
|
||||
public class TestSceneStandAloneChatDisplay : OsuManualInputManagerTestScene
|
||||
{
|
||||
private readonly Channel testChannel = new Channel();
|
||||
|
||||
private readonly User admin = new User
|
||||
{
|
||||
Username = "HappyStick",
|
||||
@ -46,92 +46,97 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Cached]
|
||||
private ChannelManager channelManager = new ChannelManager();
|
||||
|
||||
private readonly TestStandAloneChatDisplay chatDisplay;
|
||||
private readonly TestStandAloneChatDisplay chatDisplay2;
|
||||
private TestStandAloneChatDisplay chatDisplay;
|
||||
private int messageIdSequence;
|
||||
|
||||
private Channel testChannel;
|
||||
|
||||
public TestSceneStandAloneChatDisplay()
|
||||
{
|
||||
Add(channelManager);
|
||||
|
||||
Add(chatDisplay = new TestStandAloneChatDisplay
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding(20),
|
||||
Size = new Vector2(400, 80)
|
||||
});
|
||||
|
||||
Add(chatDisplay2 = new TestStandAloneChatDisplay(true)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Margin = new MarginPadding(20),
|
||||
Size = new Vector2(400, 150)
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
base.LoadComplete();
|
||||
messageIdSequence = 0;
|
||||
channelManager.CurrentChannel.Value = testChannel = new Channel();
|
||||
|
||||
channelManager.CurrentChannel.Value = testChannel;
|
||||
Children = new[]
|
||||
{
|
||||
chatDisplay = new TestStandAloneChatDisplay
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding(20),
|
||||
Size = new Vector2(400, 80),
|
||||
Channel = { Value = testChannel },
|
||||
},
|
||||
new TestStandAloneChatDisplay(true)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Margin = new MarginPadding(20),
|
||||
Size = new Vector2(400, 150),
|
||||
Channel = { Value = testChannel },
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
chatDisplay.Channel.Value = testChannel;
|
||||
chatDisplay2.Channel.Value = testChannel;
|
||||
|
||||
int sequence = 0;
|
||||
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
[Test]
|
||||
public void TestManyMessages()
|
||||
{
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "I am a wang!"
|
||||
}));
|
||||
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = redUser,
|
||||
Content = "I am team red."
|
||||
}));
|
||||
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = redUser,
|
||||
Content = "I plan to win!"
|
||||
}));
|
||||
|
||||
AddStep("message from team blue", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from team blue", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = blueUser,
|
||||
Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand."
|
||||
}));
|
||||
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "Okay okay, calm down guys. Let's do this!"
|
||||
}));
|
||||
|
||||
AddStep("message from long username", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message from long username", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Hi guys, my new username is lit!"
|
||||
}));
|
||||
|
||||
AddStep("message with new date", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
AddStep("message with new date", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Message from the future!",
|
||||
Timestamp = DateTimeOffset.Now
|
||||
}));
|
||||
|
||||
AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom);
|
||||
checkScrolledToBottom();
|
||||
|
||||
const int messages_per_call = 10;
|
||||
AddRepeatStep("add many messages", () =>
|
||||
{
|
||||
for (int i = 0; i < messages_per_call; i++)
|
||||
{
|
||||
testChannel.AddNewMessages(new Message(sequence++)
|
||||
testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Many messages! " + Guid.NewGuid(),
|
||||
@ -153,9 +158,133 @@ namespace osu.Game.Tests.Visual.Online
|
||||
return true;
|
||||
});
|
||||
|
||||
AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom);
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that when a message gets wrapped by the chat display getting contracted while scrolled to bottom, the chat will still keep scrolling down.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestMessageWrappingKeepsAutoScrolling()
|
||||
{
|
||||
fillChat();
|
||||
|
||||
// send message with short words for text wrapping to occur when contracting chat.
|
||||
sendMessage();
|
||||
|
||||
AddStep("contract chat", () => chatDisplay.Width -= 100);
|
||||
checkScrolledToBottom();
|
||||
|
||||
AddStep("send another message", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "As we were saying...",
|
||||
}));
|
||||
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserScrollOverride()
|
||||
{
|
||||
fillChat();
|
||||
|
||||
sendMessage();
|
||||
checkScrolledToBottom();
|
||||
|
||||
AddStep("User scroll up", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre + new Vector2(0, chatDisplay.ScreenSpaceDrawQuad.Height));
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
});
|
||||
|
||||
checkNotScrolledToBottom();
|
||||
sendMessage();
|
||||
checkNotScrolledToBottom();
|
||||
|
||||
AddRepeatStep("User scroll to bottom", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre - new Vector2(0, chatDisplay.ScreenSpaceDrawQuad.Height));
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
}, 5);
|
||||
|
||||
checkScrolledToBottom();
|
||||
sendMessage();
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLocalEchoMessageResetsScroll()
|
||||
{
|
||||
fillChat();
|
||||
|
||||
sendMessage();
|
||||
checkScrolledToBottom();
|
||||
|
||||
AddStep("User scroll up", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
InputManager.MoveMouseTo(chatDisplay.ScreenSpaceDrawQuad.Centre + new Vector2(0, chatDisplay.ScreenSpaceDrawQuad.Height));
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
});
|
||||
|
||||
checkNotScrolledToBottom();
|
||||
sendMessage();
|
||||
checkNotScrolledToBottom();
|
||||
|
||||
sendLocalMessage();
|
||||
checkScrolledToBottom();
|
||||
|
||||
sendMessage();
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
private void fillChat()
|
||||
{
|
||||
AddStep("fill chat", () =>
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = $"some stuff {Guid.NewGuid()}",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
checkScrolledToBottom();
|
||||
}
|
||||
|
||||
private void sendMessage()
|
||||
{
|
||||
AddStep("send lorem ipsum", () => testChannel.AddNewMessages(new Message(messageIdSequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce et bibendum velit.",
|
||||
}));
|
||||
}
|
||||
|
||||
private void sendLocalMessage()
|
||||
{
|
||||
AddStep("send local echo", () => testChannel.AddLocalEcho(new LocalEchoMessage
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "This is a local echo message.",
|
||||
}));
|
||||
}
|
||||
|
||||
private void checkScrolledToBottom() =>
|
||||
AddUntilStep("is scrolled to bottom", () => chatDisplay.ScrolledToBottom);
|
||||
|
||||
private void checkNotScrolledToBottom() =>
|
||||
AddUntilStep("not scrolled to bottom", () => !chatDisplay.ScrolledToBottom);
|
||||
|
||||
private class TestStandAloneChatDisplay : StandAloneChatDisplay
|
||||
{
|
||||
public TestStandAloneChatDisplay(bool textbox = false)
|
||||
@ -165,7 +294,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
protected DrawableChannel DrawableChannel => InternalChildren.OfType<DrawableChannel>().First();
|
||||
|
||||
protected OsuScrollContainer ScrollContainer => (OsuScrollContainer)((Container)DrawableChannel.Child).Child;
|
||||
protected UserTrackingScrollContainer ScrollContainer => (UserTrackingScrollContainer)((Container)DrawableChannel.Child).Child;
|
||||
|
||||
public FillFlowContainer FillFlow => (FillFlowContainer)ScrollContainer.Child;
|
||||
|
||||
|
@ -7,6 +7,8 @@ using osu.Game.Overlays.Comments;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
@ -16,13 +18,33 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
private VotePill votePill;
|
||||
[Cached]
|
||||
private LoginOverlay login;
|
||||
|
||||
private TestPill votePill;
|
||||
private readonly Container pillContainer;
|
||||
|
||||
public TestSceneVotePill()
|
||||
{
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
pillContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both
|
||||
},
|
||||
login = new LoginOverlay()
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserCommentPill()
|
||||
{
|
||||
AddStep("Hide login overlay", () => login.Hide());
|
||||
AddStep("Log in", logIn);
|
||||
AddStep("User comment", () => addVotePill(getUserComment()));
|
||||
AddAssert("Background is transparent", () => votePill.Background.Alpha == 0);
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Not loading", () => !votePill.IsLoading);
|
||||
}
|
||||
@ -30,8 +52,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestRandomCommentPill()
|
||||
{
|
||||
AddStep("Hide login overlay", () => login.Hide());
|
||||
AddStep("Log in", logIn);
|
||||
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
||||
AddAssert("Background is visible", () => votePill.Background.Alpha == 1);
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Loading", () => votePill.IsLoading);
|
||||
}
|
||||
@ -39,10 +63,11 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Test]
|
||||
public void TestOfflineRandomCommentPill()
|
||||
{
|
||||
AddStep("Hide login overlay", () => login.Hide());
|
||||
AddStep("Log out", API.Logout);
|
||||
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Not loading", () => !votePill.IsLoading);
|
||||
AddAssert("Login overlay is visible", () => login.State.Value == Visibility.Visible);
|
||||
}
|
||||
|
||||
private void logIn() => API.Login("localUser", "password");
|
||||
@ -63,12 +88,22 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private void addVotePill(Comment comment)
|
||||
{
|
||||
Clear();
|
||||
Add(votePill = new VotePill(comment)
|
||||
pillContainer.Clear();
|
||||
pillContainer.Child = votePill = new TestPill(comment)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private class TestPill : VotePill
|
||||
{
|
||||
public new Box Background => base.Background;
|
||||
|
||||
public TestPill(Comment comment)
|
||||
: base(comment)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@ -28,12 +27,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("push screen", () => LoadScreen(loungeScreen = new PlaylistsLoungeSubScreen
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Width = 0.5f,
|
||||
}));
|
||||
AddStep("push screen", () => LoadScreen(loungeScreen = new PlaylistsLoungeSubScreen()));
|
||||
|
||||
AddUntilStep("wait for present", () => loungeScreen.IsCurrentScreen());
|
||||
}
|
||||
|
@ -11,12 +11,10 @@ using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Users;
|
||||
@ -85,8 +83,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
|
||||
AddStep("move mouse to create button", () =>
|
||||
{
|
||||
var footer = match.ChildrenOfType<Footer>().Single();
|
||||
InputManager.MoveMouseTo(footer.ChildrenOfType<OsuButton>().Single());
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<PlaylistsMatchSettingsOverlay.CreateRoomButton>().Single());
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
21
osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs
Normal file
21
osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneModIcon : OsuTestScene
|
||||
{
|
||||
[Test]
|
||||
public void TestChangeModType()
|
||||
{
|
||||
ModIcon icon = null;
|
||||
|
||||
AddStep("create mod icon", () => Child = icon = new ModIcon(new OsuModDoubleTime()));
|
||||
AddStep("change mod", () => icon.Mod = new OsuModEasy());
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
@ -40,24 +41,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
modSelect = new TestModSelectOverlay
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
SelectedMods = { BindTarget = SelectedMods }
|
||||
},
|
||||
|
||||
modDisplay = new ModDisplay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Position = new Vector2(-5, 25),
|
||||
Current = { BindTarget = modSelect.SelectedMods }
|
||||
}
|
||||
};
|
||||
SelectedMods.Value = Array.Empty<Mod>();
|
||||
createDisplay(() => new TestModSelectOverlay());
|
||||
});
|
||||
|
||||
[SetUpSteps]
|
||||
@ -66,6 +51,50 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("show", () => modSelect.Show());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSettingsResetOnDeselection()
|
||||
{
|
||||
var osuModDoubleTime = new OsuModDoubleTime { SpeedChange = { Value = 1.2 } };
|
||||
|
||||
changeRuleset(0);
|
||||
|
||||
AddStep("set dt mod with custom rate", () => { SelectedMods.Value = new[] { osuModDoubleTime }; });
|
||||
|
||||
AddAssert("selected mod matches", () => (SelectedMods.Value.Single() as OsuModDoubleTime)?.SpeedChange.Value == 1.2);
|
||||
|
||||
AddStep("deselect", () => modSelect.DeselectAllButton.Click());
|
||||
AddAssert("selected mods empty", () => SelectedMods.Value.Count == 0);
|
||||
|
||||
AddStep("reselect", () => modSelect.GetModButton(osuModDoubleTime).Click());
|
||||
AddAssert("selected mod has default value", () => (SelectedMods.Value.Single() as OsuModDoubleTime)?.SpeedChange.IsDefault == true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAnimationFlushOnClose()
|
||||
{
|
||||
changeRuleset(0);
|
||||
|
||||
AddStep("Select all fun mods", () =>
|
||||
{
|
||||
modSelect.ModSectionsContainer
|
||||
.Single(c => c.ModType == ModType.DifficultyIncrease)
|
||||
.SelectAll();
|
||||
});
|
||||
|
||||
AddUntilStep("many mods selected", () => modDisplay.Current.Value.Count >= 5);
|
||||
|
||||
AddStep("trigger deselect and close overlay", () =>
|
||||
{
|
||||
modSelect.ModSectionsContainer
|
||||
.Single(c => c.ModType == ModType.DifficultyIncrease)
|
||||
.DeselectAll();
|
||||
|
||||
modSelect.Hide();
|
||||
});
|
||||
|
||||
AddAssert("all mods deselected", () => modDisplay.Current.Value.Count == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOsuMods()
|
||||
{
|
||||
@ -134,6 +163,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
[Test]
|
||||
public void TestExternallySetCustomizedMod()
|
||||
{
|
||||
changeRuleset(0);
|
||||
|
||||
AddStep("set customized mod externally", () => SelectedMods.Value = new[] { new OsuModDoubleTime { SpeedChange = { Value = 1.01 } } });
|
||||
|
||||
AddAssert("ensure button is selected and customized accordingly", () =>
|
||||
@ -143,6 +174,85 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSettingsAreRetainedOnReload()
|
||||
{
|
||||
changeRuleset(0);
|
||||
|
||||
AddStep("set customized mod externally", () => SelectedMods.Value = new[] { new OsuModDoubleTime { SpeedChange = { Value = 1.01 } } });
|
||||
|
||||
AddAssert("setting remains", () => (SelectedMods.Value.SingleOrDefault() as OsuModDoubleTime)?.SpeedChange.Value == 1.01);
|
||||
|
||||
AddStep("create overlay", () => createDisplay(() => new TestNonStackedModSelectOverlay()));
|
||||
|
||||
AddAssert("setting remains", () => (SelectedMods.Value.SingleOrDefault() as OsuModDoubleTime)?.SpeedChange.Value == 1.01);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExternallySetModIsReplacedByOverlayInstance()
|
||||
{
|
||||
Mod external = new OsuModDoubleTime();
|
||||
Mod overlayButtonMod = null;
|
||||
|
||||
changeRuleset(0);
|
||||
|
||||
AddStep("set mod externally", () => { SelectedMods.Value = new[] { external }; });
|
||||
|
||||
AddAssert("ensure button is selected", () =>
|
||||
{
|
||||
var button = modSelect.GetModButton(SelectedMods.Value.Single());
|
||||
overlayButtonMod = button.SelectedMod;
|
||||
return overlayButtonMod.GetType() == external.GetType();
|
||||
});
|
||||
|
||||
// Right now, when an external change occurs, the ModSelectOverlay will replace the global instance with its own
|
||||
AddAssert("mod instance doesn't match", () => external != overlayButtonMod);
|
||||
|
||||
AddAssert("one mod present in global selected", () => SelectedMods.Value.Count == 1);
|
||||
AddAssert("globally selected matches button's mod instance", () => SelectedMods.Value.Contains(overlayButtonMod));
|
||||
AddAssert("globally selected doesn't contain original external change", () => !SelectedMods.Value.Contains(external));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNonStacked()
|
||||
{
|
||||
changeRuleset(0);
|
||||
|
||||
AddStep("create overlay", () => createDisplay(() => new TestNonStackedModSelectOverlay()));
|
||||
|
||||
AddStep("show", () => modSelect.Show());
|
||||
|
||||
AddAssert("ensure all buttons are spread out", () => modSelect.ChildrenOfType<ModButton>().All(m => m.Mods.Length <= 1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangeIsValidChangesButtonVisibility()
|
||||
{
|
||||
changeRuleset(0);
|
||||
|
||||
AddAssert("double time visible", () => modSelect.ChildrenOfType<ModButton>().Any(b => b.Mods.Any(m => m is OsuModDoubleTime)));
|
||||
|
||||
AddStep("make double time invalid", () => modSelect.IsValidMod = m => !(m is OsuModDoubleTime));
|
||||
AddUntilStep("double time not visible", () => modSelect.ChildrenOfType<ModButton>().All(b => !b.Mods.Any(m => m is OsuModDoubleTime)));
|
||||
AddAssert("nightcore still visible", () => modSelect.ChildrenOfType<ModButton>().Any(b => b.Mods.Any(m => m is OsuModNightcore)));
|
||||
|
||||
AddStep("make double time valid again", () => modSelect.IsValidMod = m => true);
|
||||
AddUntilStep("double time visible", () => modSelect.ChildrenOfType<ModButton>().Any(b => b.Mods.Any(m => m is OsuModDoubleTime)));
|
||||
AddAssert("nightcore still visible", () => modSelect.ChildrenOfType<ModButton>().Any(b => b.Mods.Any(m => m is OsuModNightcore)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangeIsValidPreservesSelection()
|
||||
{
|
||||
changeRuleset(0);
|
||||
|
||||
AddStep("select DT + HD", () => SelectedMods.Value = new Mod[] { new OsuModDoubleTime(), new OsuModHidden() });
|
||||
AddAssert("DT + HD selected", () => modSelect.ChildrenOfType<ModButton>().Count(b => b.Selected) == 2);
|
||||
|
||||
AddStep("make NF invalid", () => modSelect.IsValidMod = m => !(m is ModNoFail));
|
||||
AddAssert("DT + HD still selected", () => modSelect.ChildrenOfType<ModButton>().Count(b => b.Selected) == 2);
|
||||
}
|
||||
|
||||
private void testSingleMod(Mod mod)
|
||||
{
|
||||
selectNext(mod);
|
||||
@ -262,12 +372,36 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
private void checkLabelColor(Func<Color4> getColour) => AddAssert("check label has expected colour", () => modSelect.MultiplierLabel.Colour.AverageColour == getColour());
|
||||
|
||||
private class TestModSelectOverlay : ModSelectOverlay
|
||||
private void createDisplay(Func<TestModSelectOverlay> createOverlayFunc)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
modSelect = createOverlayFunc().With(d =>
|
||||
{
|
||||
d.Origin = Anchor.BottomCentre;
|
||||
d.Anchor = Anchor.BottomCentre;
|
||||
d.SelectedMods.BindTarget = SelectedMods;
|
||||
}),
|
||||
modDisplay = new ModDisplay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Position = new Vector2(-5, 25),
|
||||
Current = { BindTarget = modSelect.SelectedMods }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class TestModSelectOverlay : LocalPlayerModSelectOverlay
|
||||
{
|
||||
public new Bindable<IReadOnlyList<Mod>> SelectedMods => base.SelectedMods;
|
||||
|
||||
public bool AllLoaded => ModSectionsContainer.Children.All(c => c.ModIconsLoaded);
|
||||
|
||||
public new FillFlowContainer<ModSection> ModSectionsContainer =>
|
||||
base.ModSectionsContainer;
|
||||
|
||||
public ModButton GetModButton(Mod mod)
|
||||
{
|
||||
var section = ModSectionsContainer.Children.Single(s => s.ModType == mod.Type);
|
||||
@ -280,5 +414,10 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
public new Color4 LowMultiplierColour => base.LowMultiplierColour;
|
||||
public new Color4 HighMultiplierColour => base.HighMultiplierColour;
|
||||
}
|
||||
|
||||
private class TestNonStackedModSelectOverlay : TestModSelectOverlay
|
||||
{
|
||||
protected override bool Stacked => false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddUntilStep("wait for ready", () => modSelect.State.Value == Visibility.Visible && modSelect.ButtonsLoaded);
|
||||
}
|
||||
|
||||
private class TestModSelectOverlay : ModSelectOverlay
|
||||
private class TestModSelectOverlay : LocalPlayerModSelectOverlay
|
||||
{
|
||||
public new VisibilityContainer ModSettingsContainer => base.ModSettingsContainer;
|
||||
public new TriangleButton CustomiseButton => base.CustomiseButton;
|
||||
|
@ -105,6 +105,15 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
checkDisplayedCount(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestError()
|
||||
{
|
||||
setState(Visibility.Visible);
|
||||
AddStep(@"error #1", sendErrorNotification);
|
||||
AddAssert("Is visible", () => notificationOverlay.State.Value == Visibility.Visible);
|
||||
checkDisplayedCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSpam()
|
||||
{
|
||||
@ -179,7 +188,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
private void sendBarrage()
|
||||
{
|
||||
switch (RNG.Next(0, 4))
|
||||
switch (RNG.Next(0, 5))
|
||||
{
|
||||
case 0:
|
||||
sendHelloNotification();
|
||||
@ -196,6 +205,10 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
case 3:
|
||||
sendDownloadProgress();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
sendErrorNotification();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,6 +227,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
notificationOverlay.Post(new BackgroundNotification { Text = @"Welcome to osu!. Enjoy your stay!" });
|
||||
}
|
||||
|
||||
private void sendErrorNotification()
|
||||
{
|
||||
notificationOverlay.Post(new SimpleErrorNotification { Text = @"Rut roh!. Something went wrong!" });
|
||||
}
|
||||
|
||||
private void sendManyNotifications()
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
|
@ -0,0 +1,122 @@
|
||||
// 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.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneSectionsContainer : OsuManualInputManagerTestScene
|
||||
{
|
||||
private readonly SectionsContainer<TestSection> container;
|
||||
private float custom;
|
||||
private const float header_height = 100;
|
||||
|
||||
public TestSceneSectionsContainer()
|
||||
{
|
||||
container = new SectionsContainer<TestSection>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 300,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
FixedHeader = new Box
|
||||
{
|
||||
Alpha = 0.5f,
|
||||
Width = 300,
|
||||
Height = header_height,
|
||||
Colour = Color4.Red
|
||||
}
|
||||
};
|
||||
container.SelectedSection.ValueChanged += section =>
|
||||
{
|
||||
if (section.OldValue != null)
|
||||
section.OldValue.Selected = false;
|
||||
if (section.NewValue != null)
|
||||
section.NewValue.Selected = true;
|
||||
};
|
||||
Add(container);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSelection()
|
||||
{
|
||||
AddStep("clear", () => container.Clear());
|
||||
AddStep("add 1/8th", () => append(1 / 8.0f));
|
||||
AddStep("add third", () => append(1 / 3.0f));
|
||||
AddStep("add half", () => append(1 / 2.0f));
|
||||
AddStep("add full", () => append(1));
|
||||
AddSliderStep("set custom", 0.1f, 1.1f, 0.5f, i => custom = i);
|
||||
AddStep("add custom", () => append(custom));
|
||||
AddStep("scroll to previous", () => container.ScrollTo(
|
||||
container.Children.Reverse().SkipWhile(s => s != container.SelectedSection.Value).Skip(1).FirstOrDefault() ?? container.Children.First()
|
||||
));
|
||||
AddStep("scroll to next", () => container.ScrollTo(
|
||||
container.Children.SkipWhile(s => s != container.SelectedSection.Value).Skip(1).FirstOrDefault() ?? container.Children.Last()
|
||||
));
|
||||
AddStep("scroll up", () => triggerUserScroll(1));
|
||||
AddStep("scroll down", () => triggerUserScroll(-1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCorrectSectionSelected()
|
||||
{
|
||||
const int sections_count = 11;
|
||||
float[] alternating = { 0.07f, 0.33f, 0.16f, 0.33f };
|
||||
AddStep("clear", () => container.Clear());
|
||||
AddStep("fill with sections", () =>
|
||||
{
|
||||
for (int i = 0; i < sections_count; i++)
|
||||
append(alternating[i % alternating.Length]);
|
||||
});
|
||||
|
||||
void step(int scrollIndex)
|
||||
{
|
||||
AddStep($"scroll to section {scrollIndex + 1}", () => container.ScrollTo(container.Children[scrollIndex]));
|
||||
AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[scrollIndex]);
|
||||
}
|
||||
|
||||
for (int i = 1; i < sections_count; i++)
|
||||
step(i);
|
||||
for (int i = sections_count - 2; i >= 0; i--)
|
||||
step(i);
|
||||
|
||||
AddStep("scroll almost to end", () => container.ScrollTo(container.Children[sections_count - 2]));
|
||||
AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[sections_count - 2]);
|
||||
AddStep("scroll down", () => triggerUserScroll(-1));
|
||||
AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[sections_count - 1]);
|
||||
}
|
||||
|
||||
private static readonly ColourInfo selected_colour = ColourInfo.GradientVertical(Color4.Yellow, Color4.Gold);
|
||||
private static readonly ColourInfo default_colour = ColourInfo.GradientVertical(Color4.White, Color4.DarkGray);
|
||||
|
||||
private void append(float multiplier)
|
||||
{
|
||||
container.Add(new TestSection
|
||||
{
|
||||
Width = 300,
|
||||
Height = (container.ChildSize.Y - header_height) * multiplier,
|
||||
Colour = default_colour
|
||||
});
|
||||
}
|
||||
|
||||
private void triggerUserScroll(float direction)
|
||||
{
|
||||
InputManager.MoveMouseTo(container);
|
||||
InputManager.ScrollVerticalBy(direction);
|
||||
}
|
||||
|
||||
private class TestSection : Box
|
||||
{
|
||||
public bool Selected
|
||||
{
|
||||
set => Colour = value ? selected_colour : default_colour;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user