mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 23:24:04 +09:00
Merge branch 'master' into page-selector
This commit is contained in:
@ -209,9 +209,10 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public void TransitionTest()
|
||||
{
|
||||
performFullSetup();
|
||||
var results = new FadeAccessibleResults(new ScoreInfo { User = new User { Username = "osu!" } });
|
||||
AddStep("Transition to Results", () => player.Push(results));
|
||||
AddUntilStep("Wait for results is current", results.IsCurrentScreen);
|
||||
FadeAccessibleResults results = null;
|
||||
AddStep("Transition to Results", () => player.Push(results =
|
||||
new FadeAccessibleResults(new ScoreInfo { User = new User { Username = "osu!" } })));
|
||||
AddUntilStep("Wait for results is current", () => results.IsCurrentScreen());
|
||||
waitForDim();
|
||||
AddAssert("Screen is undimmed, original background retained", () =>
|
||||
songSelect.IsBackgroundUndimmed() && songSelect.IsBackgroundCurrent() && results.IsBlurCorrect());
|
||||
@ -285,6 +286,12 @@ namespace osu.Game.Tests.Visual.Background
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
rulesets?.Dispose();
|
||||
}
|
||||
|
||||
private class DummySongSelect : PlaySongSelect
|
||||
{
|
||||
protected override BackgroundScreen CreateBackground()
|
||||
|
@ -3,16 +3,20 @@
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using static osu.Game.Tests.Visual.Components.TestScenePreviewTrackManager.TestPreviewTrackManager;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Components
|
||||
{
|
||||
public class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner
|
||||
{
|
||||
private readonly PreviewTrackManager trackManager = new TestPreviewTrackManager();
|
||||
private readonly TestPreviewTrackManager trackManager = new TestPreviewTrackManager();
|
||||
|
||||
private AudioManager audio;
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
@ -23,8 +27,10 @@ namespace osu.Game.Tests.Visual.Components
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
this.audio = audio;
|
||||
|
||||
Add(trackManager);
|
||||
}
|
||||
|
||||
@ -34,6 +40,7 @@ namespace osu.Game.Tests.Visual.Components
|
||||
PreviewTrack track = null;
|
||||
|
||||
AddStep("get track", () => track = getOwnedTrack());
|
||||
AddUntilStep("wait loaded", () => track.IsLoaded);
|
||||
AddStep("start", () => track.Start());
|
||||
AddAssert("started", () => track.IsRunning);
|
||||
AddStep("stop", () => track.Stop());
|
||||
@ -52,10 +59,15 @@ namespace osu.Game.Tests.Visual.Components
|
||||
track2 = getOwnedTrack();
|
||||
});
|
||||
|
||||
AddUntilStep("wait loaded", () => track1.IsLoaded && track2.IsLoaded);
|
||||
|
||||
AddStep("start track 1", () => track1.Start());
|
||||
AddStep("start track 2", () => track2.Start());
|
||||
AddAssert("track 1 stopped", () => !track1.IsRunning);
|
||||
AddAssert("track 2 started", () => track2.IsRunning);
|
||||
AddStep("start track 1", () => track1.Start());
|
||||
AddAssert("track 2 stopped", () => !track2.IsRunning);
|
||||
AddAssert("track 1 started", () => track1.IsRunning);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -64,6 +76,7 @@ namespace osu.Game.Tests.Visual.Components
|
||||
PreviewTrack track = null;
|
||||
|
||||
AddStep("get track", () => track = getOwnedTrack());
|
||||
AddUntilStep("wait loaded", () => track.IsLoaded);
|
||||
AddStep("start", () => track.Start());
|
||||
AddStep("stop by owner", () => trackManager.StopAnyPlaying(this));
|
||||
AddAssert("stopped", () => !track.IsRunning);
|
||||
@ -76,6 +89,7 @@ namespace osu.Game.Tests.Visual.Components
|
||||
PreviewTrack track = null;
|
||||
|
||||
AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack())));
|
||||
AddUntilStep("wait loaded", () => track.IsLoaded);
|
||||
AddStep("start", () => track.Start());
|
||||
AddStep("attempt stop", () => trackManager.StopAnyPlaying(this));
|
||||
AddAssert("not stopped", () => track.IsRunning);
|
||||
@ -83,22 +97,100 @@ namespace osu.Game.Tests.Visual.Components
|
||||
AddAssert("stopped", () => !track.IsRunning);
|
||||
}
|
||||
|
||||
private PreviewTrack getTrack() => trackManager.Get(null);
|
||||
[Test]
|
||||
public void TestNonPresentTrack()
|
||||
{
|
||||
TestPreviewTrack track = null;
|
||||
|
||||
private PreviewTrack getOwnedTrack()
|
||||
AddStep("get non-present track", () =>
|
||||
{
|
||||
Add(new TestTrackOwner(track = getTrack()));
|
||||
track.Alpha = 0;
|
||||
});
|
||||
AddUntilStep("wait loaded", () => track.IsLoaded);
|
||||
AddStep("start", () => track.Start());
|
||||
AddStep("seek to end", () => track.Track.Seek(track.Track.Length));
|
||||
AddAssert("track stopped", () => !track.IsRunning);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that <see cref="PreviewTrackManager.CurrentTrack"/> changes correctly.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCurrentTrackChanges()
|
||||
{
|
||||
PreviewTrack track = null;
|
||||
TestTrackOwner owner = null;
|
||||
|
||||
AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack())));
|
||||
AddUntilStep("wait loaded", () => track.IsLoaded);
|
||||
AddStep("start track", () => track.Start());
|
||||
AddAssert("current is track", () => trackManager.CurrentTrack == track);
|
||||
AddStep("pause manager updates", () => trackManager.AllowUpdate = false);
|
||||
AddStep("stop any playing", () => trackManager.StopAnyPlaying(owner));
|
||||
AddAssert("current not changed", () => trackManager.CurrentTrack == track);
|
||||
AddStep("resume manager updates", () => trackManager.AllowUpdate = true);
|
||||
AddAssert("current is null", () => trackManager.CurrentTrack == null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that <see cref="PreviewTrackManager"/> mutes game-wide audio tracks correctly.
|
||||
/// </summary>
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestEnsureMutingCorrectly(bool stopAnyPlaying)
|
||||
{
|
||||
PreviewTrack track = null;
|
||||
TestTrackOwner owner = null;
|
||||
|
||||
AddStep("ensure volume not zero", () =>
|
||||
{
|
||||
if (audio.Volume.Value == 0)
|
||||
audio.Volume.Value = 1;
|
||||
|
||||
if (audio.VolumeTrack.Value == 0)
|
||||
audio.VolumeTrack.Value = 1;
|
||||
});
|
||||
|
||||
AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0);
|
||||
|
||||
AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack())));
|
||||
AddUntilStep("wait loaded", () => track.IsLoaded);
|
||||
AddStep("start track", () => track.Start());
|
||||
AddAssert("game is muted", () => audio.Tracks.AggregateVolume.Value == 0);
|
||||
|
||||
if (stopAnyPlaying)
|
||||
AddStep("stop any playing", () => trackManager.StopAnyPlaying(owner));
|
||||
else
|
||||
AddStep("stop track", () => track.Stop());
|
||||
|
||||
AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0);
|
||||
}
|
||||
|
||||
private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null);
|
||||
|
||||
private TestPreviewTrack getOwnedTrack()
|
||||
{
|
||||
var track = getTrack();
|
||||
|
||||
Add(track);
|
||||
LoadComponentAsync(track, Add);
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
private class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner
|
||||
{
|
||||
private readonly PreviewTrack track;
|
||||
|
||||
public TestTrackOwner(PreviewTrack track)
|
||||
{
|
||||
AddInternal(track);
|
||||
this.track = track;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LoadComponentAsync(track, AddInternal);
|
||||
}
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
@ -109,14 +201,28 @@ namespace osu.Game.Tests.Visual.Components
|
||||
}
|
||||
}
|
||||
|
||||
private class TestPreviewTrackManager : PreviewTrackManager
|
||||
public class TestPreviewTrackManager : PreviewTrackManager
|
||||
{
|
||||
public bool AllowUpdate = true;
|
||||
|
||||
public new PreviewTrack CurrentTrack => base.CurrentTrack;
|
||||
|
||||
protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore);
|
||||
|
||||
protected class TestPreviewTrack : TrackManagerPreviewTrack
|
||||
public override bool UpdateSubTree()
|
||||
{
|
||||
if (!AllowUpdate)
|
||||
return true;
|
||||
|
||||
return base.UpdateSubTree();
|
||||
}
|
||||
|
||||
public class TestPreviewTrack : TrackManagerPreviewTrack
|
||||
{
|
||||
private readonly ITrackStore trackManager;
|
||||
|
||||
public new Track Track => base.Track;
|
||||
|
||||
public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager)
|
||||
: base(beatmapSetInfo, trackManager)
|
||||
{
|
||||
|
@ -1,8 +1,6 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
@ -11,10 +9,8 @@ using osu.Game.Screens.Edit.Compose;
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneEditorCompose : EditorClockTestScene
|
||||
public class TestSceneComposeScreen : EditorClockTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ComposeScreen) };
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
171
osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs
Normal file
171
osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs
Normal file
@ -0,0 +1,171 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
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;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
public class TestSceneDistanceSnapGrid : EditorClockTestScene
|
||||
{
|
||||
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(IDistanceSnapProvider))]
|
||||
private readonly SnapProvider snapProvider = new SnapProvider();
|
||||
|
||||
public TestSceneDistanceSnapGrid()
|
||||
{
|
||||
editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap());
|
||||
editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length });
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.SlateGray
|
||||
},
|
||||
new TestDistanceSnapGrid(new HitObject(), grid_position)
|
||||
};
|
||||
});
|
||||
|
||||
[TestCase(1)]
|
||||
[TestCase(2)]
|
||||
[TestCase(3)]
|
||||
[TestCase(4)]
|
||||
[TestCase(6)]
|
||||
[TestCase(8)]
|
||||
[TestCase(12)]
|
||||
[TestCase(16)]
|
||||
public void TestBeatDivisor(int divisor)
|
||||
{
|
||||
AddStep($"set beat divisor = {divisor}", () => BeatDivisor.Value = divisor);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLimitedDistance()
|
||||
{
|
||||
AddStep("create limited grid", () =>
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.SlateGray
|
||||
},
|
||||
new TestDistanceSnapGrid(new HitObject(), grid_position, new HitObject { StartTime = 100 })
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private class TestDistanceSnapGrid : DistanceSnapGrid
|
||||
{
|
||||
public new float DistanceSpacing => base.DistanceSpacing;
|
||||
|
||||
public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition, HitObject nextHitObject = null)
|
||||
: base(hitObject, nextHitObject, centrePosition)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CreateContent(Vector2 centrePosition)
|
||||
{
|
||||
AddInternal(new Circle
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(5),
|
||||
Position = centrePosition
|
||||
});
|
||||
|
||||
int beatIndex = 0;
|
||||
|
||||
for (float s = centrePosition.X + DistanceSpacing; s <= DrawWidth && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++)
|
||||
{
|
||||
AddInternal(new Circle
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(5, 10),
|
||||
Position = new Vector2(s, centrePosition.Y),
|
||||
Colour = GetColourForBeatIndex(beatIndex)
|
||||
});
|
||||
}
|
||||
|
||||
beatIndex = 0;
|
||||
|
||||
for (float s = centrePosition.X - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++)
|
||||
{
|
||||
AddInternal(new Circle
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(5, 10),
|
||||
Position = new Vector2(s, centrePosition.Y),
|
||||
Colour = GetColourForBeatIndex(beatIndex)
|
||||
});
|
||||
}
|
||||
|
||||
beatIndex = 0;
|
||||
|
||||
for (float s = centrePosition.Y + DistanceSpacing; s <= DrawHeight && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++)
|
||||
{
|
||||
AddInternal(new Circle
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(10, 5),
|
||||
Position = new Vector2(centrePosition.X, s),
|
||||
Colour = GetColourForBeatIndex(beatIndex)
|
||||
});
|
||||
}
|
||||
|
||||
beatIndex = 0;
|
||||
|
||||
for (float s = centrePosition.Y - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++)
|
||||
{
|
||||
AddInternal(new Circle
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(10, 5),
|
||||
Position = new Vector2(centrePosition.X, s),
|
||||
Colour = GetColourForBeatIndex(beatIndex)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override (Vector2 position, double time) GetSnappedPosition(Vector2 screenSpacePosition)
|
||||
=> (Vector2.Zero, 0);
|
||||
}
|
||||
|
||||
private class SnapProvider : IDistanceSnapProvider
|
||||
{
|
||||
public (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) => (position, time);
|
||||
|
||||
public float GetBeatSnapDistanceAt(double referenceTime) => 10;
|
||||
|
||||
public float DurationToDistance(double referenceTime, double duration) => (float)duration;
|
||||
|
||||
public double DistanceToDuration(double referenceTime, float distance) => distance;
|
||||
|
||||
public double GetSnappedDurationFromDistance(double referenceTime, float distance) => 0;
|
||||
|
||||
public float GetSnappedDistanceFromDistance(double referenceTime, float distance) => 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,9 +10,9 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
}
|
||||
}
|
||||
|
||||
private class StartStopButton : Button
|
||||
private class StartStopButton : OsuButton
|
||||
{
|
||||
private IAdjustableClock adjustableClock;
|
||||
private bool started;
|
||||
|
@ -28,18 +28,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
var testBeatmap = new Beatmap
|
||||
{
|
||||
ControlPointInfo = new ControlPointInfo
|
||||
{
|
||||
TimingPoints =
|
||||
{
|
||||
new TimingControlPoint { Time = 0, BeatLength = 200 },
|
||||
new TimingControlPoint { Time = 100, BeatLength = 400 },
|
||||
new TimingControlPoint { Time = 175, BeatLength = 800 },
|
||||
new TimingControlPoint { Time = 350, BeatLength = 200 },
|
||||
new TimingControlPoint { Time = 450, BeatLength = 100 },
|
||||
new TimingControlPoint { Time = 500, BeatLength = 307.69230769230802 }
|
||||
}
|
||||
},
|
||||
ControlPointInfo = new ControlPointInfo(),
|
||||
HitObjects =
|
||||
{
|
||||
new HitCircle { StartTime = 0 },
|
||||
@ -47,6 +36,13 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
}
|
||||
};
|
||||
|
||||
testBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 200 });
|
||||
testBeatmap.ControlPointInfo.Add(100, new TimingControlPoint { BeatLength = 400 });
|
||||
testBeatmap.ControlPointInfo.Add(175, new TimingControlPoint { BeatLength = 800 });
|
||||
testBeatmap.ControlPointInfo.Add(350, new TimingControlPoint { BeatLength = 200 });
|
||||
testBeatmap.ControlPointInfo.Add(450, new TimingControlPoint { BeatLength = 100 });
|
||||
testBeatmap.ControlPointInfo.Add(500, new TimingControlPoint { BeatLength = 307.69230769230802 });
|
||||
|
||||
Beatmap.Value = CreateWorkingBeatmap(testBeatmap);
|
||||
|
||||
Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock };
|
||||
|
@ -22,7 +22,7 @@ using osuTK;
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneHitObjectComposer : OsuTestScene
|
||||
public class TestSceneHitObjectComposer : EditorClockTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
|
35
osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs
Normal file
35
osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Edit.Timing;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneTimingScreen : EditorClockTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ControlPointTable),
|
||||
typeof(ControlPointSettings),
|
||||
typeof(Section<>),
|
||||
typeof(TimingSection),
|
||||
typeof(EffectSection),
|
||||
typeof(SampleSection),
|
||||
typeof(DifficultySection),
|
||||
typeof(RowAttribute)
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
Child = new TimingScreen();
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Storyboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
@ -29,9 +30,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
}
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap)
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||
{
|
||||
var working = base.CreateWorkingBeatmap(beatmap);
|
||||
var working = base.CreateWorkingBeatmap(beatmap, storyboard);
|
||||
|
||||
track = (ClockBackedTestWorkingBeatmap.TrackVirtualManual)working.Track;
|
||||
|
||||
|
@ -9,7 +9,7 @@ using osu.Game.Rulesets.Judgements;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Catch.Scoring;
|
||||
using osu.Game.Rulesets.Mania.Scoring;
|
||||
using osu.Game.Rulesets.Osu.Scoring;
|
||||
@ -85,9 +85,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
new SpriteText { Text = $@"Great: {hitWindows?.WindowFor(HitResult.Great)}" },
|
||||
new SpriteText { Text = $@"Good: {hitWindows?.WindowFor(HitResult.Good)}" },
|
||||
new SpriteText { Text = $@"Meh: {hitWindows?.WindowFor(HitResult.Meh)}" },
|
||||
new OsuSpriteText { Text = $@"Great: {hitWindows?.WindowFor(HitResult.Great)}" },
|
||||
new OsuSpriteText { Text = $@"Good: {hitWindows?.WindowFor(HitResult.Good)}" },
|
||||
new OsuSpriteText { Text = $@"Meh: {hitWindows?.WindowFor(HitResult.Meh)}" },
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -95,6 +95,19 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
seekAndAssertBreak("seek to break after end", testBreaks[1].EndTime + 500, false);
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void TestBeforeGameplayStart(bool withBreaks)
|
||||
{
|
||||
setClock(true);
|
||||
|
||||
if (withBreaks)
|
||||
loadBreaksStep("multiple breaks", testBreaks);
|
||||
|
||||
seekAndAssertBreak("seek to break intro time", -100, true);
|
||||
seekAndAssertBreak("seek to break intro time", 0, false);
|
||||
}
|
||||
|
||||
private void addShowBreakStep(double seconds)
|
||||
{
|
||||
AddStep($"show '{seconds}s' break", () => breakOverlay.Breaks = new List<BreakPeriod>
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -46,7 +47,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestRelativeBeatLengthScaleSingleTimingPoint()
|
||||
{
|
||||
var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range / 2 });
|
||||
var beatmap = createBeatmap();
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range / 2 });
|
||||
|
||||
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
||||
|
||||
@ -60,10 +62,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestRelativeBeatLengthScaleTimingPointBeyondEndDoesNotBecomeDominant()
|
||||
{
|
||||
var beatmap = createBeatmap(
|
||||
new TimingControlPoint { BeatLength = time_range / 2 },
|
||||
new TimingControlPoint { Time = 12000, BeatLength = time_range },
|
||||
new TimingControlPoint { Time = 100000, BeatLength = time_range });
|
||||
var beatmap = createBeatmap();
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range / 2 });
|
||||
beatmap.ControlPointInfo.Add(12000, new TimingControlPoint { BeatLength = time_range });
|
||||
beatmap.ControlPointInfo.Add(100000, new TimingControlPoint { BeatLength = time_range });
|
||||
|
||||
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
||||
|
||||
@ -74,9 +76,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestRelativeBeatLengthScaleFromSecondTimingPoint()
|
||||
{
|
||||
var beatmap = createBeatmap(
|
||||
new TimingControlPoint { BeatLength = time_range },
|
||||
new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 });
|
||||
var beatmap = createBeatmap();
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range });
|
||||
beatmap.ControlPointInfo.Add(3 * time_range, new TimingControlPoint { BeatLength = time_range / 2 });
|
||||
|
||||
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
||||
|
||||
@ -96,9 +98,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestNonRelativeScale()
|
||||
{
|
||||
var beatmap = createBeatmap(
|
||||
new TimingControlPoint { BeatLength = time_range },
|
||||
new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 });
|
||||
var beatmap = createBeatmap();
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range });
|
||||
beatmap.ControlPointInfo.Add(3 * time_range, new TimingControlPoint { BeatLength = time_range / 2 });
|
||||
|
||||
createTest(beatmap);
|
||||
|
||||
@ -115,6 +117,34 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
assertPosition(4, 1f);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSliderMultiplierDoesNotAffectRelativeBeatLength()
|
||||
{
|
||||
var beatmap = createBeatmap();
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range });
|
||||
beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2;
|
||||
|
||||
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
||||
AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 5000);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
assertPosition(i, i / 5f);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSliderMultiplierAffectsNonRelativeBeatLength()
|
||||
{
|
||||
var beatmap = createBeatmap();
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range });
|
||||
beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2;
|
||||
|
||||
createTest(beatmap);
|
||||
AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 2000);
|
||||
|
||||
assertPosition(0, 0);
|
||||
assertPosition(1, 1);
|
||||
}
|
||||
|
||||
private void assertPosition(int index, float relativeY) => AddAssert($"hitobject {index} at {relativeY}",
|
||||
() => Precision.AlmostEquals(drawableRuleset.Playfield.AllHitObjects.ElementAt(index).DrawPosition.Y, drawableRuleset.Playfield.HitObjectContainer.DrawHeight * relativeY));
|
||||
|
||||
@ -127,14 +157,11 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
/// Creates an <see cref="IBeatmap"/>, containing 10 hitobjects and user-provided timing points.
|
||||
/// The hitobjects are spaced <see cref="time_range"/> milliseconds apart.
|
||||
/// </summary>
|
||||
/// <param name="timingControlPoints">The timing points to add to the beatmap.</param>
|
||||
/// <returns>The <see cref="IBeatmap"/>.</returns>
|
||||
private IBeatmap createBeatmap(params TimingControlPoint[] timingControlPoints)
|
||||
private IBeatmap createBeatmap()
|
||||
{
|
||||
var beatmap = new Beatmap<HitObject> { BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo } };
|
||||
|
||||
beatmap.ControlPointInfo.TimingPoints.AddRange(timingControlPoints);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
beatmap.HitObjects.Add(new HitObject { StartTime = i * time_range });
|
||||
|
||||
@ -193,6 +220,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping;
|
||||
|
||||
public new Bindable<double> TimeRange => base.TimeRange;
|
||||
|
||||
public TestDrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Storyboards;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
@ -35,9 +36,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
private Track track;
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap)
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||
{
|
||||
var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager);
|
||||
var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager);
|
||||
track = working.Track;
|
||||
return working;
|
||||
}
|
||||
|
113
osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs
Normal file
113
osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs
Normal file
@ -0,0 +1,113 @@
|
||||
// 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.Diagnostics;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Storyboards;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneLeadIn : RateAdjustedBeatmapTestScene
|
||||
{
|
||||
private LeadInPlayer player;
|
||||
|
||||
private const double lenience_ms = 10;
|
||||
|
||||
private const double first_hit_object = 2170;
|
||||
|
||||
[TestCase(1000, 0)]
|
||||
[TestCase(2000, 0)]
|
||||
[TestCase(3000, first_hit_object - 3000)]
|
||||
[TestCase(10000, first_hit_object - 10000)]
|
||||
public void TestLeadInProducesCorrectStartTime(double leadIn, double expectedStartTime)
|
||||
{
|
||||
loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo)
|
||||
{
|
||||
BeatmapInfo = { AudioLeadIn = leadIn }
|
||||
});
|
||||
|
||||
AddAssert($"first frame is {expectedStartTime}", () =>
|
||||
{
|
||||
Debug.Assert(player.FirstFrameClockTime != null);
|
||||
return Precision.AlmostEquals(player.FirstFrameClockTime.Value, expectedStartTime, lenience_ms);
|
||||
});
|
||||
}
|
||||
|
||||
[TestCase(1000, 0)]
|
||||
[TestCase(0, 0)]
|
||||
[TestCase(-1000, -1000)]
|
||||
[TestCase(-10000, -10000)]
|
||||
public void TestStoryboardProducesCorrectStartTime(double firstStoryboardEvent, double expectedStartTime)
|
||||
{
|
||||
var storyboard = new Storyboard();
|
||||
|
||||
var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero);
|
||||
sprite.TimelineGroup.Alpha.Add(Easing.None, firstStoryboardEvent, firstStoryboardEvent + 500, 0, 1);
|
||||
|
||||
storyboard.GetLayer("Background").Add(sprite);
|
||||
|
||||
loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo), storyboard);
|
||||
|
||||
AddAssert($"first frame is {expectedStartTime}", () =>
|
||||
{
|
||||
Debug.Assert(player.FirstFrameClockTime != null);
|
||||
return Precision.AlmostEquals(player.FirstFrameClockTime.Value, expectedStartTime, lenience_ms);
|
||||
});
|
||||
}
|
||||
|
||||
private void loadPlayerWithBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||
{
|
||||
AddStep("create player", () =>
|
||||
{
|
||||
Beatmap.Value = CreateWorkingBeatmap(beatmap, storyboard);
|
||||
LoadScreen(player = new LeadInPlayer());
|
||||
});
|
||||
|
||||
AddUntilStep("player loaded", () => player.IsLoaded && player.Alpha == 1);
|
||||
}
|
||||
|
||||
private class LeadInPlayer : TestPlayer
|
||||
{
|
||||
public LeadInPlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
public double? FirstFrameClockTime;
|
||||
|
||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
||||
|
||||
public double GameplayStartTime => DrawableRuleset.GameplayStartTime;
|
||||
|
||||
public double FirstHitObjectTime => DrawableRuleset.Objects.First().StartTime;
|
||||
|
||||
public double GameplayClockTime => GameplayClockContainer.GameplayClock.CurrentTime;
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
if (!FirstFrameClockTime.HasValue)
|
||||
{
|
||||
FirstFrameClockTime = GameplayClockContainer.GameplayClock.CurrentTime;
|
||||
AddInternal(new OsuSpriteText
|
||||
{
|
||||
Text = $"GameplayStartTime: {DrawableRuleset.GameplayStartTime} "
|
||||
+ $"FirstHitObjectTime: {FirstHitObjectTime} "
|
||||
+ $"LeadInTime: {Beatmap.Value.BeatmapInfo.AudioLeadIn} "
|
||||
+ $"FirstFrameClockTime: {FirstFrameClockTime}"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -69,6 +69,24 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
confirmClockRunning(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPauseWithResumeOverlay()
|
||||
{
|
||||
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||
AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1);
|
||||
|
||||
pauseAndConfirm();
|
||||
|
||||
resume();
|
||||
confirmClockRunning(false);
|
||||
confirmPauseOverlayShown(false);
|
||||
|
||||
pauseAndConfirm();
|
||||
|
||||
AddUntilStep("resume overlay is not active", () => Player.DrawableRuleset.ResumeOverlay.State.Value == Visibility.Hidden);
|
||||
confirmPaused();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestResumeWithResumeOverlaySkipped()
|
||||
{
|
||||
@ -97,8 +115,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestExitTooSoon()
|
||||
{
|
||||
pauseAndConfirm();
|
||||
AddStep("seek before gameplay", () => Player.GameplayClockContainer.Seek(-5000));
|
||||
|
||||
pauseAndConfirm();
|
||||
resume();
|
||||
|
||||
AddStep("exit too soon", () => Player.Exit());
|
||||
@ -127,14 +146,49 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
exitAndConfirm();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExitFromFailedGameplay()
|
||||
{
|
||||
AddUntilStep("wait for fail", () => Player.HasFailed);
|
||||
AddStep("exit", () => Player.Exit());
|
||||
|
||||
confirmExited();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestQuickRetryFromFailedGameplay()
|
||||
{
|
||||
AddUntilStep("wait for fail", () => Player.HasFailed);
|
||||
AddStep("quick retry", () => Player.GameplayClockContainer.OfType<HotkeyRetryOverlay>().First().Action?.Invoke());
|
||||
|
||||
confirmExited();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestQuickExitFromFailedGameplay()
|
||||
{
|
||||
AddUntilStep("wait for fail", () => Player.HasFailed);
|
||||
AddStep("quick exit", () => Player.GameplayClockContainer.OfType<HotkeyExitOverlay>().First().Action?.Invoke());
|
||||
|
||||
confirmExited();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExitFromGameplay()
|
||||
{
|
||||
AddStep("exit", () => Player.Exit());
|
||||
|
||||
confirmPaused();
|
||||
|
||||
exitAndConfirm();
|
||||
AddStep("exit", () => Player.Exit());
|
||||
confirmExited();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestQuickExitFromGameplay()
|
||||
{
|
||||
AddStep("quick exit", () => Player.GameplayClockContainer.OfType<HotkeyExitOverlay>().First().Action?.Invoke());
|
||||
|
||||
confirmExited();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -163,6 +217,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestRestartAfterResume()
|
||||
{
|
||||
AddStep("seek before gameplay", () => Player.GameplayClockContainer.Seek(-5000));
|
||||
|
||||
pauseAndConfirm();
|
||||
resumeAndConfirm();
|
||||
restart();
|
||||
@ -186,6 +242,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddUntilStep("player not exited", () => Player.IsCurrentScreen());
|
||||
AddStep("exit", () => Player.Exit());
|
||||
confirmExited();
|
||||
confirmNoTrackAdjustments();
|
||||
}
|
||||
|
||||
private void confirmPaused()
|
||||
@ -207,6 +264,11 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddUntilStep("player exited", () => !Player.IsCurrentScreen());
|
||||
}
|
||||
|
||||
private void confirmNoTrackAdjustments()
|
||||
{
|
||||
AddAssert("track has no adjustments", () => Beatmap.Value.Track.AggregateFrequency.Value == 1);
|
||||
}
|
||||
|
||||
private void restart() => AddStep("restart", () => Player.Restart());
|
||||
private void pause() => AddStep("pause", () => Player.Pause());
|
||||
private void resume() => AddStep("resume", () => Player.Resume());
|
||||
|
@ -7,10 +7,16 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
@ -18,25 +24,49 @@ using osu.Game.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestScenePlayerLoader : ManualInputManagerTestScene
|
||||
{
|
||||
private TestPlayerLoader loader;
|
||||
private OsuScreenStack stack;
|
||||
private TestPlayerLoaderContainer container;
|
||||
private TestPlayer player;
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
[Resolved]
|
||||
private AudioManager audioManager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private SessionStatics sessionStatics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the input manager child to a new test player loader container instance.
|
||||
/// </summary>
|
||||
/// <param name="interactive">If the test player should behave like the production one.</param>
|
||||
/// <param name="beforeLoadAction">An action to run before player load but after bindable leases are returned.</param>
|
||||
/// <param name="afterLoadAction">An action to run after container load.</param>
|
||||
public void ResetPlayer(bool interactive, Action beforeLoadAction = null, Action afterLoadAction = null)
|
||||
{
|
||||
InputManager.Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both };
|
||||
audioManager.Volume.SetDefault();
|
||||
|
||||
InputManager.Clear();
|
||||
|
||||
beforeLoadAction?.Invoke();
|
||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
});
|
||||
|
||||
InputManager.Child = container = new TestPlayerLoaderContainer(
|
||||
loader = new TestPlayerLoader(() =>
|
||||
{
|
||||
afterLoadAction?.Invoke();
|
||||
return player = new TestPlayer(interactive, interactive);
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBlockLoadViaMouseMovement()
|
||||
{
|
||||
AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => new TestPlayer(false, false))));
|
||||
AddStep("load dummy beatmap", () => ResetPlayer(false));
|
||||
AddUntilStep("wait for current", () => loader.IsCurrentScreen());
|
||||
AddRepeatStep("move mouse", () => InputManager.MoveMouseTo(loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft + (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft) * RNG.NextSingle()), 20);
|
||||
AddAssert("loader still active", () => loader.IsCurrentScreen());
|
||||
@ -46,16 +76,17 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestLoadContinuation()
|
||||
{
|
||||
Player player = null;
|
||||
SlowLoadPlayer slowPlayer = null;
|
||||
|
||||
AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer(false, false))));
|
||||
AddStep("load dummy beatmap", () => ResetPlayer(false));
|
||||
AddUntilStep("wait for current", () => loader.IsCurrentScreen());
|
||||
AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre));
|
||||
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen());
|
||||
AddStep("load slow dummy beatmap", () =>
|
||||
{
|
||||
stack.Push(loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false)));
|
||||
InputManager.Child = container = new TestPlayerLoaderContainer(
|
||||
loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false)));
|
||||
|
||||
Scheduler.AddDelayed(() => slowPlayer.AllowLoad.Set(), 5000);
|
||||
});
|
||||
|
||||
@ -65,16 +96,11 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestModReinstantiation()
|
||||
{
|
||||
TestPlayer player = null;
|
||||
TestMod gameMod = null;
|
||||
TestMod playerMod1 = null;
|
||||
TestMod playerMod2 = null;
|
||||
|
||||
AddStep("load player", () =>
|
||||
{
|
||||
Mods.Value = new[] { gameMod = new TestMod() };
|
||||
stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer()));
|
||||
});
|
||||
AddStep("load player", () => { ResetPlayer(true, () => Mods.Value = new[] { gameMod = new TestMod() }); });
|
||||
|
||||
AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen());
|
||||
AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre));
|
||||
@ -97,6 +123,75 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddAssert("player mods applied", () => playerMod2.Applied);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMutedNotificationMasterVolume() => addVolumeSteps("master volume", () => audioManager.Volume.Value = 0, null, () => audioManager.Volume.IsDefault);
|
||||
|
||||
[Test]
|
||||
public void TestMutedNotificationTrackVolume() => addVolumeSteps("music volume", () => audioManager.VolumeTrack.Value = 0, null, () => audioManager.VolumeTrack.IsDefault);
|
||||
|
||||
[Test]
|
||||
public void TestMutedNotificationMuteButton() => addVolumeSteps("mute button", null, () => container.VolumeOverlay.IsMuted.Value = true, () => !container.VolumeOverlay.IsMuted.Value);
|
||||
|
||||
/// <remarks>
|
||||
/// Created for avoiding copy pasting code for the same steps.
|
||||
/// </remarks>
|
||||
/// <param name="volumeName">What part of the volume system is checked</param>
|
||||
/// <param name="beforeLoad">The action to be invoked to set the volume before loading</param>
|
||||
/// <param name="afterLoad">The action to be invoked to set the volume after loading</param>
|
||||
/// <param name="assert">The function to be invoked and checked</param>
|
||||
private void addVolumeSteps(string volumeName, Action beforeLoad, Action afterLoad, Func<bool> assert)
|
||||
{
|
||||
AddStep("reset notification lock", () => sessionStatics.GetBindable<bool>(Static.MutedAudioNotificationShownOnce).Value = false);
|
||||
|
||||
AddStep("load player", () => ResetPlayer(false, beforeLoad, afterLoad));
|
||||
AddUntilStep("wait for player", () => player.IsLoaded);
|
||||
|
||||
AddAssert("check for notification", () => container.NotificationOverlay.UnreadCount.Value == 1);
|
||||
AddStep("click notification", () =>
|
||||
{
|
||||
var scrollContainer = (OsuScrollContainer)container.NotificationOverlay.Children.Last();
|
||||
var flowContainer = scrollContainer.Children.OfType<FillFlowContainer<NotificationSection>>().First();
|
||||
var notification = flowContainer.First();
|
||||
|
||||
InputManager.MoveMouseTo(notification);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddAssert("check " + volumeName, assert);
|
||||
}
|
||||
|
||||
private class TestPlayerLoaderContainer : Container
|
||||
{
|
||||
[Cached]
|
||||
public readonly NotificationOverlay NotificationOverlay;
|
||||
|
||||
[Cached]
|
||||
public readonly VolumeOverlay VolumeOverlay;
|
||||
|
||||
public TestPlayerLoaderContainer(IScreen screen)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new OsuScreenStack(screen)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
NotificationOverlay = new NotificationOverlay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
VolumeOverlay = new VolumeOverlay
|
||||
{
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TestPlayerLoader : PlayerLoader
|
||||
{
|
||||
public new VisualSettings VisualSettings => base.VisualSettings;
|
||||
|
@ -6,6 +6,7 @@ using osu.Framework.Lists;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Storyboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
@ -42,9 +43,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
});
|
||||
}
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap)
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||
{
|
||||
var working = base.CreateWorkingBeatmap(beatmap);
|
||||
var working = base.CreateWorkingBeatmap(beatmap, storyboard);
|
||||
workingWeakReferences.Add(working);
|
||||
return working;
|
||||
}
|
||||
|
@ -5,19 +5,22 @@ using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Ranking.Pages;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneReplayDownloadButton : OsuTestScene
|
||||
{
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ReplayDownloadButton)
|
||||
@ -42,7 +45,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(80, 40),
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -51,16 +53,15 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
return new APILegacyScoreInfo
|
||||
{
|
||||
ID = 1,
|
||||
OnlineScoreID = 2553163309,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
OnlineRulesetID = 0,
|
||||
Replay = replayAvailable,
|
||||
User = new User
|
||||
{
|
||||
Id = 39828,
|
||||
Username = @"WubWoofWolf",
|
||||
}
|
||||
};
|
||||
}.CreateScoreInfo(rulesets);
|
||||
}
|
||||
|
||||
private class TestReplayDownloadButton : ReplayDownloadButton
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
@ -20,6 +21,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
State = { Value = Visibility.Visible }
|
||||
});
|
||||
|
||||
Add(container = new ExampleContainer());
|
||||
|
@ -3,11 +3,16 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.Ranking.Pages;
|
||||
@ -22,11 +27,13 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ScoreInfo),
|
||||
typeof(Results),
|
||||
typeof(ResultsPage),
|
||||
typeof(ScoreResultsPage),
|
||||
typeof(LocalLeaderboardPage)
|
||||
typeof(RetryButton),
|
||||
typeof(ReplayDownloadButton),
|
||||
typeof(LocalLeaderboardPage),
|
||||
typeof(TestPlayer)
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -42,26 +49,82 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
var beatmapInfo = beatmaps.QueryBeatmap(b => b.RulesetID == 0);
|
||||
if (beatmapInfo != null)
|
||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo);
|
||||
}
|
||||
|
||||
LoadScreen(new SoloResults(new ScoreInfo
|
||||
private TestSoloResults createResultsScreen() => new TestSoloResults(new ScoreInfo
|
||||
{
|
||||
TotalScore = 2845370,
|
||||
Accuracy = 0.98,
|
||||
MaxCombo = 123,
|
||||
Rank = ScoreRank.A,
|
||||
Date = DateTimeOffset.Now,
|
||||
Statistics = new Dictionary<HitResult, int>
|
||||
{
|
||||
TotalScore = 2845370,
|
||||
Accuracy = 0.98,
|
||||
MaxCombo = 123,
|
||||
Rank = ScoreRank.A,
|
||||
Date = DateTimeOffset.Now,
|
||||
Statistics = new Dictionary<HitResult, int>
|
||||
{ HitResult.Great, 50 },
|
||||
{ HitResult.Good, 20 },
|
||||
{ HitResult.Meh, 50 },
|
||||
{ HitResult.Miss, 1 }
|
||||
},
|
||||
User = new User
|
||||
{
|
||||
Username = "peppy",
|
||||
}
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void ResultsWithoutPlayer()
|
||||
{
|
||||
TestSoloResults screen = null;
|
||||
|
||||
AddStep("load results", () => Child = new OsuScreenStack(screen = createResultsScreen())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
});
|
||||
AddUntilStep("wait for loaded", () => screen.IsLoaded);
|
||||
AddAssert("retry overlay not present", () => screen.RetryOverlay == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResultsWithPlayer()
|
||||
{
|
||||
TestSoloResults screen = null;
|
||||
|
||||
AddStep("load results", () => Child = new TestResultsContainer(screen = createResultsScreen()));
|
||||
AddUntilStep("wait for loaded", () => screen.IsLoaded);
|
||||
AddAssert("retry overlay present", () => screen.RetryOverlay != null);
|
||||
}
|
||||
|
||||
private class TestResultsContainer : Container
|
||||
{
|
||||
[Cached(typeof(Player))]
|
||||
private readonly Player player = new TestPlayer();
|
||||
|
||||
public TestResultsContainer(IScreen screen)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChild = new OsuScreenStack(screen)
|
||||
{
|
||||
{ HitResult.Great, 50 },
|
||||
{ HitResult.Good, 20 },
|
||||
{ HitResult.Meh, 50 },
|
||||
{ HitResult.Miss, 1 }
|
||||
},
|
||||
User = new User
|
||||
{
|
||||
Username = "peppy",
|
||||
}
|
||||
}));
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TestSoloResults : SoloResults
|
||||
{
|
||||
public HotkeyRetryOverlay RetryOverlay;
|
||||
|
||||
public TestSoloResults(ScoreInfo score)
|
||||
: base(score)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
RetryOverlay = InternalChildren.OfType<HotkeyRetryOverlay>().SingleOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -326,21 +326,23 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => throw new NotImplementedException();
|
||||
|
||||
public event Action SourceChanged;
|
||||
public event Action SourceChanged
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
}
|
||||
|
||||
private class TestSkinComponent : ISkinComponent
|
||||
{
|
||||
private readonly string name;
|
||||
|
||||
public TestSkinComponent(string name)
|
||||
{
|
||||
this.name = name;
|
||||
LookupName = name;
|
||||
}
|
||||
|
||||
public string ComponentGroup => string.Empty;
|
||||
|
||||
public string LookupName => name;
|
||||
public string LookupName { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
@ -18,25 +18,37 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
private SkipOverlay skip;
|
||||
private int requestCount;
|
||||
|
||||
private double increment;
|
||||
|
||||
private GameplayClockContainer gameplayClockContainer;
|
||||
private GameplayClock gameplayClock;
|
||||
|
||||
private const double skip_time = 6000;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
requestCount = 0;
|
||||
Child = new Container
|
||||
increment = skip_time;
|
||||
|
||||
Child = gameplayClockContainer = new GameplayClockContainer(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), new Mod[] { }, 0)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = new FramedOffsetClock(Clock)
|
||||
{
|
||||
Offset = -Clock.CurrentTime,
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
skip = new SkipOverlay(6000)
|
||||
skip = new SkipOverlay(skip_time)
|
||||
{
|
||||
RequestSeek = _ => requestCount++
|
||||
RequestSkip = () =>
|
||||
{
|
||||
requestCount++;
|
||||
gameplayClockContainer.Seek(gameplayClock.CurrentTime + increment);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
gameplayClockContainer.Start();
|
||||
gameplayClock = gameplayClockContainer.GameplayClock;
|
||||
});
|
||||
|
||||
[Test]
|
||||
@ -64,19 +76,35 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
public void TestClickOnlyActuatesOnce()
|
||||
{
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("click", () =>
|
||||
{
|
||||
increment = skip_time - gameplayClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2;
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
checkRequestCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClickOnlyActuatesMultipleTimes()
|
||||
{
|
||||
AddStep("set increment lower", () => increment = 3000);
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
checkRequestCount(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDoesntFadeOnMouseDown()
|
||||
{
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("button down", () => InputManager.PressButton(MouseButton.Left));
|
||||
AddUntilStep("wait for overlay disapper", () => !skip.IsAlive);
|
||||
AddUntilStep("wait for overlay disappear", () => !skip.IsPresent);
|
||||
AddAssert("ensure button didn't disappear", () => skip.Children.First().Alpha > 0);
|
||||
AddStep("button up", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
checkRequestCount(0);
|
||||
|
@ -33,23 +33,15 @@ namespace osu.Game.Tests.Visual.Menus
|
||||
[Test]
|
||||
public void TestInstantLoad()
|
||||
{
|
||||
bool logoVisible = false;
|
||||
// visual only, very impossible to test this using asserts.
|
||||
|
||||
AddStep("begin loading", () =>
|
||||
AddStep("load immediately", () =>
|
||||
{
|
||||
loader = new TestLoader();
|
||||
loader.AllowLoad.Set();
|
||||
|
||||
LoadScreen(loader);
|
||||
});
|
||||
|
||||
AddUntilStep("loaded", () =>
|
||||
{
|
||||
logoVisible = loader.Logo?.Alpha > 0;
|
||||
return loader.Logo != null && loader.ScreenLoaded;
|
||||
});
|
||||
|
||||
AddAssert("logo was not visible", () => !logoVisible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -58,7 +50,7 @@ namespace osu.Game.Tests.Visual.Menus
|
||||
AddStep("begin loading", () => LoadScreen(loader = new TestLoader()));
|
||||
AddUntilStep("wait for logo visible", () => loader.Logo?.Alpha > 0);
|
||||
AddStep("finish loading", () => loader.AllowLoad.Set());
|
||||
AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded);
|
||||
AddUntilStep("loaded", () => loader.Logo != null && loader.ScreenLoaded);
|
||||
AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0);
|
||||
}
|
||||
|
||||
|
244
osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs
Normal file
244
osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs
Normal file
@ -0,0 +1,244 @@
|
||||
// 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.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
using IntroSequence = osu.Game.Configuration.IntroSequence;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Menus
|
||||
{
|
||||
public class TestSceneScreenNavigation : ManualInputManagerTestScene
|
||||
{
|
||||
private const float click_padding = 25;
|
||||
|
||||
private GameHost host;
|
||||
private TestOsuGame game;
|
||||
|
||||
private Vector2 backButtonPosition => game.ToScreenSpace(new Vector2(click_padding, game.LayoutRectangle.Bottom - click_padding));
|
||||
|
||||
private Vector2 optionsButtonPosition => game.ToScreenSpace(new Vector2(click_padding, click_padding));
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(GameHost host)
|
||||
{
|
||||
this.host = host;
|
||||
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
};
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("Create new game instance", () =>
|
||||
{
|
||||
if (game != null)
|
||||
{
|
||||
Remove(game);
|
||||
game.Dispose();
|
||||
}
|
||||
|
||||
game = new TestOsuGame(LocalStorage, API);
|
||||
game.SetHost(host);
|
||||
|
||||
// todo: this can be removed once we can run audio trakcs without a device present
|
||||
// see https://github.com/ppy/osu/issues/1302
|
||||
game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
||||
|
||||
Add(game);
|
||||
});
|
||||
AddUntilStep("Wait for load", () => game.IsLoaded);
|
||||
AddUntilStep("Wait for intro", () => game.ScreenStack.CurrentScreen is IntroScreen);
|
||||
confirmAtMainMenu();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExitSongSelectWithEscape()
|
||||
{
|
||||
TestSongSelect songSelect = null;
|
||||
|
||||
pushAndConfirm(() => songSelect = new TestSongSelect());
|
||||
AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show());
|
||||
AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
|
||||
pushEscape();
|
||||
AddAssert("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
||||
exitViaEscapeAndConfirm();
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void TestSongContinuesAfterExitPlayer(bool withUserPause)
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
WorkingBeatmap beatmap() => game.Beatmap.Value;
|
||||
Track track() => beatmap().Track;
|
||||
|
||||
pushAndConfirm(() => new TestSongSelect());
|
||||
|
||||
AddStep("import beatmap", () => ImportBeatmapTest.LoadOszIntoOsu(game, virtualTrack: true).Wait());
|
||||
|
||||
AddUntilStep("wait for selected", () => !game.Beatmap.IsDefault);
|
||||
|
||||
if (withUserPause)
|
||||
AddStep("pause", () => game.Dependencies.Get<MusicController>().Stop());
|
||||
|
||||
AddStep("press enter", () => pressAndRelease(Key.Enter));
|
||||
|
||||
AddUntilStep("wait for player", () => (player = game.ScreenStack.CurrentScreen as Player) != null);
|
||||
AddUntilStep("wait for fail", () => player.HasFailed);
|
||||
|
||||
AddUntilStep("wait for track stop", () => !track().IsRunning);
|
||||
AddAssert("Ensure time before preview point", () => track().CurrentTime < beatmap().Metadata.PreviewTime);
|
||||
|
||||
pushEscape();
|
||||
|
||||
AddUntilStep("wait for track playing", () => track().IsRunning);
|
||||
AddAssert("Ensure time wasn't reset to preview point", () => track().CurrentTime < beatmap().Metadata.PreviewTime);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExitSongSelectWithClick()
|
||||
{
|
||||
TestSongSelect songSelect = null;
|
||||
|
||||
pushAndConfirm(() => songSelect = new TestSongSelect());
|
||||
AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show());
|
||||
AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
|
||||
AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition));
|
||||
|
||||
// BackButton handles hover using its child button, so this checks whether or not any of BackButton's children are hovered.
|
||||
AddUntilStep("Back button is hovered", () => InputManager.HoveredDrawables.Any(d => d.Parent == game.BackButton));
|
||||
|
||||
AddStep("Click back button", () => InputManager.Click(MouseButton.Left));
|
||||
AddUntilStep("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
||||
exitViaBackButtonAndConfirm();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExitMultiWithEscape()
|
||||
{
|
||||
pushAndConfirm(() => new Screens.Multi.Multiplayer());
|
||||
exitViaEscapeAndConfirm();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExitMultiWithBackButton()
|
||||
{
|
||||
pushAndConfirm(() => new Screens.Multi.Multiplayer());
|
||||
exitViaBackButtonAndConfirm();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOpenOptionsAndExitWithEscape()
|
||||
{
|
||||
AddUntilStep("Wait for options to load", () => game.Settings.IsLoaded);
|
||||
AddStep("Enter menu", () => pressAndRelease(Key.Enter));
|
||||
AddStep("Move mouse to options overlay", () => InputManager.MoveMouseTo(optionsButtonPosition));
|
||||
AddStep("Click options overlay", () => InputManager.Click(MouseButton.Left));
|
||||
AddAssert("Options overlay was opened", () => game.Settings.State.Value == Visibility.Visible);
|
||||
AddStep("Hide options overlay using escape", () => pressAndRelease(Key.Escape));
|
||||
AddAssert("Options overlay was closed", () => game.Settings.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
private void pushAndConfirm(Func<Screen> newScreen)
|
||||
{
|
||||
Screen screen = null;
|
||||
AddStep("Push new screen", () => game.ScreenStack.Push(screen = newScreen()));
|
||||
AddUntilStep("Wait for new screen", () => game.ScreenStack.CurrentScreen == screen && screen.IsLoaded);
|
||||
}
|
||||
|
||||
private void pushEscape() =>
|
||||
AddStep("Press escape", () => pressAndRelease(Key.Escape));
|
||||
|
||||
private void exitViaEscapeAndConfirm()
|
||||
{
|
||||
pushEscape();
|
||||
confirmAtMainMenu();
|
||||
}
|
||||
|
||||
private void exitViaBackButtonAndConfirm()
|
||||
{
|
||||
AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition));
|
||||
AddStep("Click back button", () => InputManager.Click(MouseButton.Left));
|
||||
confirmAtMainMenu();
|
||||
}
|
||||
|
||||
private void confirmAtMainMenu() => AddUntilStep("Wait for main menu", () => game.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded);
|
||||
|
||||
private void pressAndRelease(Key key)
|
||||
{
|
||||
InputManager.PressKey(key);
|
||||
InputManager.ReleaseKey(key);
|
||||
}
|
||||
|
||||
private class TestOsuGame : OsuGame
|
||||
{
|
||||
public new ScreenStack ScreenStack => base.ScreenStack;
|
||||
|
||||
public new BackButton BackButton => base.BackButton;
|
||||
|
||||
public new SettingsPanel Settings => base.Settings;
|
||||
|
||||
public new OsuConfigManager LocalConfig => base.LocalConfig;
|
||||
|
||||
public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;
|
||||
|
||||
protected override Loader CreateLoader() => new TestLoader();
|
||||
|
||||
public TestOsuGame(Storage storage, IAPIProvider api)
|
||||
{
|
||||
Storage = storage;
|
||||
API = api;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
API.Login("Rhythm Champion", "osu!");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestSongSelect : PlaySongSelect
|
||||
{
|
||||
public ModSelectOverlay ModSelectOverlay => ModSelect;
|
||||
}
|
||||
|
||||
private class TestLoader : Loader
|
||||
{
|
||||
protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler();
|
||||
|
||||
private class TestShaderPrecompiler : ShaderPrecompiler
|
||||
{
|
||||
protected override bool AllLoaded => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
102
osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs
Normal file
102
osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs
Normal file
@ -0,0 +1,102 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
using osu.Game.Rulesets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneBeatmapRulesetSelector : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(BeatmapRulesetSelector),
|
||||
typeof(BeatmapRulesetTabItem),
|
||||
};
|
||||
|
||||
private readonly TestRulesetSelector selector;
|
||||
|
||||
public TestSceneBeatmapRulesetSelector()
|
||||
{
|
||||
Add(selector = new TestRulesetSelector());
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
[Test]
|
||||
public void TestMultipleRulesetsBeatmapSet()
|
||||
{
|
||||
var enabledRulesets = rulesets.AvailableRulesets.Skip(1).Take(2);
|
||||
|
||||
AddStep("load multiple rulesets beatmapset", () =>
|
||||
{
|
||||
selector.BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
Beatmaps = enabledRulesets.Select(r => new BeatmapInfo { Ruleset = r }).ToList()
|
||||
};
|
||||
});
|
||||
|
||||
var tabItems = selector.TabContainer.TabItems;
|
||||
AddAssert("other rulesets disabled", () => tabItems.Except(tabItems.Where(t => enabledRulesets.Any(r => r.Equals(t.Value)))).All(t => !t.Enabled.Value));
|
||||
AddAssert("left-most ruleset selected", () => tabItems.First(t => t.Enabled.Value).Active.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSingleRulesetBeatmapSet()
|
||||
{
|
||||
var enabledRuleset = rulesets.AvailableRulesets.Last();
|
||||
|
||||
AddStep("load single ruleset beatmapset", () =>
|
||||
{
|
||||
selector.BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = enabledRuleset
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
AddAssert("single ruleset selected", () => selector.SelectedTab.Value.Equals(enabledRuleset));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmptyBeatmapSet()
|
||||
{
|
||||
AddStep("load empty beatmapset", () => selector.BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
Beatmaps = new List<BeatmapInfo>()
|
||||
});
|
||||
|
||||
AddAssert("no ruleset selected", () => selector.SelectedTab == null);
|
||||
AddAssert("all rulesets disabled", () => selector.TabContainer.TabItems.All(t => !t.Enabled.Value));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNullBeatmapSet()
|
||||
{
|
||||
AddStep("load null beatmapset", () => selector.BeatmapSet = null);
|
||||
|
||||
AddAssert("no ruleset selected", () => selector.SelectedTab == null);
|
||||
AddAssert("all rulesets disabled", () => selector.TabContainer.TabItems.All(t => !t.Enabled.Value));
|
||||
}
|
||||
|
||||
private class TestRulesetSelector : BeatmapRulesetSelector
|
||||
{
|
||||
public new TabItem<RulesetInfo> SelectedTab => base.SelectedTab;
|
||||
|
||||
public new TabFillFlowContainer TabContainer => base.TabContainer;
|
||||
}
|
||||
}
|
||||
}
|
@ -40,24 +40,20 @@ namespace osu.Game.Tests.Visual.Online
|
||||
typeof(PreviewButton),
|
||||
typeof(SuccessRate),
|
||||
typeof(BeatmapAvailability),
|
||||
typeof(BeatmapRulesetSelector),
|
||||
typeof(BeatmapRulesetTabItem),
|
||||
typeof(NotSupporterPlaceholder)
|
||||
};
|
||||
|
||||
protected override bool UseOnlineAPI => true;
|
||||
|
||||
private RulesetInfo taikoRuleset;
|
||||
private RulesetInfo maniaRuleset;
|
||||
|
||||
public TestSceneBeatmapSetOverlay()
|
||||
{
|
||||
Add(overlay = new TestBeatmapSetOverlay());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
taikoRuleset = rulesets.GetRuleset(1);
|
||||
maniaRuleset = rulesets.GetRuleset(3);
|
||||
}
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
[Test]
|
||||
public void TestLoading()
|
||||
@ -111,7 +107,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
StarDifficulty = 9.99,
|
||||
Version = @"TEST",
|
||||
Length = 456000,
|
||||
Ruleset = maniaRuleset,
|
||||
Ruleset = rulesets.GetRuleset(3),
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 1,
|
||||
@ -189,7 +185,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
StarDifficulty = 5.67,
|
||||
Version = @"ANOTHER TEST",
|
||||
Length = 123000,
|
||||
Ruleset = taikoRuleset,
|
||||
Ruleset = rulesets.GetRuleset(1),
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 9,
|
||||
@ -217,6 +213,54 @@ namespace osu.Game.Tests.Visual.Online
|
||||
downloadAssert(false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleRulesets()
|
||||
{
|
||||
AddStep("show multiple rulesets beatmap", () =>
|
||||
{
|
||||
var beatmaps = new List<BeatmapInfo>();
|
||||
|
||||
foreach (var ruleset in rulesets.AvailableRulesets.Skip(1))
|
||||
{
|
||||
beatmaps.Add(new BeatmapInfo
|
||||
{
|
||||
Version = ruleset.Name,
|
||||
Ruleset = ruleset,
|
||||
BaseDifficulty = new BeatmapDifficulty(),
|
||||
OnlineInfo = new BeatmapOnlineInfo(),
|
||||
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(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
overlay.ShowBeatmapSet(new BeatmapSetInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"multiple rulesets beatmap",
|
||||
Artist = @"none",
|
||||
Author = new User
|
||||
{
|
||||
Username = "BanchoBot",
|
||||
Id = 3,
|
||||
}
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = new BeatmapSetOnlineCovers(),
|
||||
},
|
||||
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
|
||||
Beatmaps = beatmaps
|
||||
});
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHide()
|
||||
{
|
||||
@ -281,12 +325,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private void downloadAssert(bool shown)
|
||||
{
|
||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.DownloadButtonsVisible == shown);
|
||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.DownloadButtonsVisible == shown);
|
||||
}
|
||||
|
||||
private class TestBeatmapSetOverlay : BeatmapSetOverlay
|
||||
{
|
||||
public bool DownloadButtonsVisible => Header.DownloadButtonsVisible;
|
||||
public new Header Header => base.Header;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddStep("set second set", () => successRate.Beatmap = secondBeatmap);
|
||||
AddAssert("ratings set", () => successRate.Graph.Metrics == secondBeatmap.Metrics);
|
||||
|
||||
BeatmapInfo createBeatmap() => new BeatmapInfo
|
||||
static BeatmapInfo createBeatmap() => new BeatmapInfo
|
||||
{
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
|
@ -68,6 +68,34 @@ namespace osu.Game.Tests.Visual.Online
|
||||
changelog.ShowListing();
|
||||
changelog.Show();
|
||||
});
|
||||
|
||||
AddStep(@"Ensure HTML string unescaping", () =>
|
||||
{
|
||||
changelog.ShowBuild(new APIChangelogBuild
|
||||
{
|
||||
Version = "2019.920.0",
|
||||
DisplayVersion = "2019.920.0",
|
||||
UpdateStream = new APIUpdateStream
|
||||
{
|
||||
Name = "Test",
|
||||
DisplayName = "Test"
|
||||
},
|
||||
ChangelogEntries = new List<APIChangelogEntry>
|
||||
{
|
||||
new APIChangelogEntry
|
||||
{
|
||||
Category = "Testing HTML strings unescaping",
|
||||
Title = "Ensuring HTML strings are being unescaped",
|
||||
MessageHtml = """"This text should appear triple-quoted""" >_<",
|
||||
GithubUser = new APIChangelogUser
|
||||
{
|
||||
DisplayName = "Dummy",
|
||||
OsuUsername = "Dummy",
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
59
osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs
Normal file
59
osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs
Normal file
@ -0,0 +1,59 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays.Comments;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneCommentsContainer : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(CommentsContainer),
|
||||
typeof(CommentsHeader),
|
||||
typeof(DrawableComment),
|
||||
typeof(HeaderButton),
|
||||
typeof(SortTabControl),
|
||||
typeof(ShowChildrenButton),
|
||||
typeof(DeletedChildrenPlaceholder),
|
||||
typeof(VotePill)
|
||||
};
|
||||
|
||||
protected override bool UseOnlineAPI => true;
|
||||
|
||||
public TestSceneCommentsContainer()
|
||||
{
|
||||
BasicScrollContainer scrollFlow;
|
||||
|
||||
Add(scrollFlow = new BasicScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
|
||||
AddStep("Big Black comments", () =>
|
||||
{
|
||||
scrollFlow.Clear();
|
||||
scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 41823));
|
||||
});
|
||||
|
||||
AddStep("Airman comments", () =>
|
||||
{
|
||||
scrollFlow.Clear();
|
||||
scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 24313));
|
||||
});
|
||||
|
||||
AddStep("lazer build comments", () =>
|
||||
{
|
||||
scrollFlow.Clear();
|
||||
scrollFlow.Add(new CommentsContainer(CommentableType.Build, 4772));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
39
osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs
Normal file
39
osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs
Normal file
@ -0,0 +1,39 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Overlays.Comments;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneCommentsHeader : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(CommentsHeader),
|
||||
typeof(HeaderButton),
|
||||
typeof(SortTabControl),
|
||||
};
|
||||
|
||||
private readonly Bindable<CommentsSortCriteria> sort = new Bindable<CommentsSortCriteria>();
|
||||
private readonly BindableBool showDeleted = new BindableBool();
|
||||
|
||||
public TestSceneCommentsHeader()
|
||||
{
|
||||
Add(new CommentsHeader
|
||||
{
|
||||
Sort = { BindTarget = sort },
|
||||
ShowDeleted = { BindTarget = showDeleted }
|
||||
});
|
||||
|
||||
AddStep("Trigger ShowDeleted", () => showDeleted.Value = !showDeleted.Value);
|
||||
AddStep("Select old", () => sort.Value = CommentsSortCriteria.Old);
|
||||
AddStep("Select new", () => sort.Value = CommentsSortCriteria.New);
|
||||
AddStep("Select top", () => sort.Value = CommentsSortCriteria.Top);
|
||||
}
|
||||
}
|
||||
}
|
54
osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs
Normal file
54
osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// 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;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.BeatmapSet.Buttons;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneFavouriteButton : OsuTestScene
|
||||
{
|
||||
private FavouriteButton favourite;
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("create button", () => Child = favourite = new FavouriteButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Size = new Vector2(50),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLoggedOutIn()
|
||||
{
|
||||
AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo { OnlineBeatmapSetID = 88 });
|
||||
AddStep("log out", () => API.Logout());
|
||||
checkEnabled(false);
|
||||
AddStep("log in", () => API.Login("test", "test"));
|
||||
checkEnabled(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBeatmapChange()
|
||||
{
|
||||
AddStep("log in", () => API.Login("test", "test"));
|
||||
AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo { OnlineBeatmapSetID = 88 });
|
||||
checkEnabled(true);
|
||||
AddStep("set invalid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo());
|
||||
checkEnabled(false);
|
||||
}
|
||||
|
||||
private void checkEnabled(bool expected)
|
||||
{
|
||||
AddAssert("is " + (expected ? "enabled" : "disabled"), () => favourite.Enabled.Value == expected);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
// 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.BeatmapSet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneLeaderboardModSelector : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(LeaderboardModSelector),
|
||||
};
|
||||
|
||||
public TestSceneLeaderboardModSelector()
|
||||
{
|
||||
LeaderboardModSelector modSelector;
|
||||
FillFlowContainer<SpriteText> selectedMods;
|
||||
var ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
Add(selectedMods = new FillFlowContainer<SpriteText>
|
||||
{
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
});
|
||||
|
||||
Add(modSelector = new LeaderboardModSelector
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Ruleset = { BindTarget = ruleset }
|
||||
});
|
||||
|
||||
modSelector.SelectedMods.ItemsAdded += mods =>
|
||||
{
|
||||
mods.ForEach(mod => selectedMods.Add(new OsuSpriteText
|
||||
{
|
||||
Text = mod.Acronym,
|
||||
}));
|
||||
};
|
||||
|
||||
modSelector.SelectedMods.ItemsRemoved += mods =>
|
||||
{
|
||||
mods.ForEach(mod =>
|
||||
{
|
||||
foreach (var selected in selectedMods)
|
||||
{
|
||||
if (selected.Text == mod.Acronym)
|
||||
{
|
||||
selectedMods.Remove(selected);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo);
|
||||
AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo);
|
||||
AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo);
|
||||
AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo);
|
||||
AddStep("Deselect all", () => modSelector.DeselectAll());
|
||||
AddStep("null ruleset", () => ruleset.Value = null);
|
||||
}
|
||||
}
|
||||
}
|
23
osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs
Normal file
23
osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneNewsOverlay : OsuTestScene
|
||||
{
|
||||
private NewsOverlay news;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Add(news = new NewsOverlay());
|
||||
AddStep(@"Show", news.Show);
|
||||
AddStep(@"Hide", news.Hide);
|
||||
|
||||
AddStep(@"Show front page", () => news.ShowFrontPage());
|
||||
AddStep(@"Custom article", () => news.Current.Value = "Test Article 101");
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays.Rankings;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Size = new Vector2(30, 20),
|
||||
Country = countryA,
|
||||
},
|
||||
text = new SpriteText
|
||||
text = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
|
129
osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs
Normal file
129
osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs
Normal file
@ -0,0 +1,129 @@
|
||||
// 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 osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays.Rankings.Tables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using System.Threading;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneRankingsTables : OsuTestScene
|
||||
{
|
||||
protected override bool UseOnlineAPI => true;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(PerformanceTable),
|
||||
typeof(ScoresTable),
|
||||
typeof(CountriesTable),
|
||||
typeof(TableRowBackground),
|
||||
typeof(UserBasedTable),
|
||||
typeof(RankingsTable<>)
|
||||
};
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
private readonly BasicScrollContainer scrollFlow;
|
||||
private readonly DimmedLoadingLayer loading;
|
||||
private CancellationTokenSource cancellationToken;
|
||||
private APIRequest request;
|
||||
|
||||
public TestSceneRankingsTables()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
scrollFlow = new BasicScrollContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.8f,
|
||||
},
|
||||
loading = new DimmedLoadingLayer(),
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
AddStep("Osu performance", () => createPerformanceTable(new OsuRuleset().RulesetInfo, null));
|
||||
AddStep("Mania scores", () => createScoreTable(new ManiaRuleset().RulesetInfo));
|
||||
AddStep("Taiko country scores", () => createCountryTable(new TaikoRuleset().RulesetInfo));
|
||||
AddStep("Catch US performance page 10", () => createPerformanceTable(new CatchRuleset().RulesetInfo, "US", 10));
|
||||
}
|
||||
|
||||
private void createCountryTable(RulesetInfo ruleset, int page = 1)
|
||||
{
|
||||
onLoadStarted();
|
||||
|
||||
request = new GetCountryRankingsRequest(ruleset, page);
|
||||
((GetCountryRankingsRequest)request).Success += rankings => Schedule(() =>
|
||||
{
|
||||
var table = new CountriesTable(page, rankings.Countries);
|
||||
loadTable(table);
|
||||
});
|
||||
|
||||
api.Queue(request);
|
||||
}
|
||||
|
||||
private void createPerformanceTable(RulesetInfo ruleset, string country, int page = 1)
|
||||
{
|
||||
onLoadStarted();
|
||||
|
||||
request = new GetUserRankingsRequest(ruleset, country: country, page: page);
|
||||
((GetUserRankingsRequest)request).Success += rankings => Schedule(() =>
|
||||
{
|
||||
var table = new PerformanceTable(page, rankings.Users);
|
||||
loadTable(table);
|
||||
});
|
||||
|
||||
api.Queue(request);
|
||||
}
|
||||
|
||||
private void createScoreTable(RulesetInfo ruleset, int page = 1)
|
||||
{
|
||||
onLoadStarted();
|
||||
|
||||
request = new GetUserRankingsRequest(ruleset, UserRankingsType.Score, page);
|
||||
((GetUserRankingsRequest)request).Success += rankings => Schedule(() =>
|
||||
{
|
||||
var table = new ScoresTable(page, rankings.Users);
|
||||
loadTable(table);
|
||||
});
|
||||
|
||||
api.Queue(request);
|
||||
}
|
||||
|
||||
private void onLoadStarted()
|
||||
{
|
||||
loading.Show();
|
||||
request?.Cancel();
|
||||
cancellationToken?.Cancel();
|
||||
cancellationToken = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
private void loadTable(Drawable table)
|
||||
{
|
||||
LoadComponentAsync(table, t =>
|
||||
{
|
||||
scrollFlow.Clear();
|
||||
scrollFlow.Add(t);
|
||||
loading.Hide();
|
||||
}, cancellationToken.Token);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// 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 System;
|
||||
@ -9,9 +9,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays.BeatmapSet.Scores;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Graphics;
|
||||
@ -66,12 +64,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
FlagName = @"ES",
|
||||
},
|
||||
},
|
||||
Mods = new Mod[]
|
||||
Mods = new[]
|
||||
{
|
||||
new OsuModDoubleTime(),
|
||||
new OsuModHidden(),
|
||||
new OsuModFlashlight(),
|
||||
new OsuModHardRock(),
|
||||
new OsuModDoubleTime().Acronym,
|
||||
new OsuModHidden().Acronym,
|
||||
new OsuModFlashlight().Acronym,
|
||||
new OsuModHardRock().Acronym,
|
||||
},
|
||||
Rank = ScoreRank.XH,
|
||||
PP = 200,
|
||||
@ -91,11 +89,11 @@ namespace osu.Game.Tests.Visual.Online
|
||||
FlagName = @"BR",
|
||||
},
|
||||
},
|
||||
Mods = new Mod[]
|
||||
Mods = new[]
|
||||
{
|
||||
new OsuModDoubleTime(),
|
||||
new OsuModHidden(),
|
||||
new OsuModFlashlight(),
|
||||
new OsuModDoubleTime().Acronym,
|
||||
new OsuModHidden().Acronym,
|
||||
new OsuModFlashlight().Acronym,
|
||||
},
|
||||
Rank = ScoreRank.S,
|
||||
PP = 190,
|
||||
@ -115,10 +113,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
FlagName = @"JP",
|
||||
},
|
||||
},
|
||||
Mods = new Mod[]
|
||||
Mods = new[]
|
||||
{
|
||||
new OsuModDoubleTime(),
|
||||
new OsuModHidden(),
|
||||
new OsuModDoubleTime().Acronym,
|
||||
new OsuModHidden().Acronym,
|
||||
},
|
||||
Rank = ScoreRank.B,
|
||||
PP = 180,
|
||||
@ -138,9 +136,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
FlagName = @"CA",
|
||||
},
|
||||
},
|
||||
Mods = new Mod[]
|
||||
Mods = new[]
|
||||
{
|
||||
new OsuModDoubleTime(),
|
||||
new OsuModDoubleTime().Acronym,
|
||||
},
|
||||
Rank = ScoreRank.C,
|
||||
PP = 170,
|
||||
@ -208,12 +206,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
FlagName = @"ES",
|
||||
},
|
||||
},
|
||||
Mods = new Mod[]
|
||||
Mods = new[]
|
||||
{
|
||||
new OsuModDoubleTime(),
|
||||
new OsuModHidden(),
|
||||
new OsuModFlashlight(),
|
||||
new OsuModHardRock(),
|
||||
new OsuModDoubleTime().Acronym,
|
||||
new OsuModHidden().Acronym,
|
||||
new OsuModFlashlight().Acronym,
|
||||
new OsuModHardRock().Acronym,
|
||||
},
|
||||
Rank = ScoreRank.XH,
|
||||
PP = 200,
|
||||
@ -226,10 +224,13 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
foreach (var s in allScores.Scores)
|
||||
{
|
||||
s.Statistics.Add(HitResult.Great, RNG.Next(2000));
|
||||
s.Statistics.Add(HitResult.Good, RNG.Next(2000));
|
||||
s.Statistics.Add(HitResult.Meh, RNG.Next(2000));
|
||||
s.Statistics.Add(HitResult.Miss, RNG.Next(2000));
|
||||
s.Statistics = new Dictionary<string, int>
|
||||
{
|
||||
{ "count_300", RNG.Next(2000) },
|
||||
{ "count_100", RNG.Next(2000) },
|
||||
{ "count_50", RNG.Next(2000) },
|
||||
{ "count_miss", RNG.Next(2000) }
|
||||
};
|
||||
}
|
||||
|
||||
AddStep("Load all scores", () =>
|
||||
|
@ -1,10 +1,12 @@
|
||||
// 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.Profile.Sections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
@ -17,11 +19,11 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
public TestSceneShowMoreButton()
|
||||
{
|
||||
ShowMoreButton button = null;
|
||||
TestButton button = null;
|
||||
|
||||
int fireCount = 0;
|
||||
|
||||
Add(button = new ShowMoreButton
|
||||
Add(button = new TestButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -51,5 +53,16 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddAssert("action fired twice", () => fireCount == 2);
|
||||
AddAssert("is in loading state", () => button.IsLoading);
|
||||
}
|
||||
|
||||
private class TestButton : ShowMoreButton
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colors)
|
||||
{
|
||||
IdleColour = colors.YellowDark;
|
||||
HoverColour = colors.Yellow;
|
||||
ChevronIconColour = colors.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,11 @@ using osu.Framework.Graphics;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Overlays.Chat;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
@ -32,17 +37,23 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Id = 4,
|
||||
};
|
||||
|
||||
private readonly User longUsernameUser = new User
|
||||
{
|
||||
Username = "Very Long Long Username",
|
||||
Id = 5,
|
||||
};
|
||||
|
||||
[Cached]
|
||||
private ChannelManager channelManager = new ChannelManager();
|
||||
|
||||
private readonly StandAloneChatDisplay chatDisplay;
|
||||
private readonly StandAloneChatDisplay chatDisplay2;
|
||||
private readonly TestStandAloneChatDisplay chatDisplay;
|
||||
private readonly TestStandAloneChatDisplay chatDisplay2;
|
||||
|
||||
public TestSceneStandAloneChatDisplay()
|
||||
{
|
||||
Add(channelManager);
|
||||
|
||||
Add(chatDisplay = new StandAloneChatDisplay
|
||||
Add(chatDisplay = new TestStandAloneChatDisplay
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
@ -50,7 +61,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Size = new Vector2(400, 80)
|
||||
});
|
||||
|
||||
Add(chatDisplay2 = new StandAloneChatDisplay(true)
|
||||
Add(chatDisplay2 = new TestStandAloneChatDisplay(true)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
@ -99,6 +110,66 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Sender = admin,
|
||||
Content = "Okay okay, calm down guys. Let's do this!"
|
||||
}));
|
||||
|
||||
AddStep("message from long username", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Hi guys, my new username is lit!"
|
||||
}));
|
||||
|
||||
AddStep("message with new date", () => testChannel.AddNewMessages(new Message(sequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Message from the future!",
|
||||
Timestamp = DateTimeOffset.Now
|
||||
}));
|
||||
|
||||
AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom);
|
||||
|
||||
const int messages_per_call = 10;
|
||||
AddRepeatStep("add many messages", () =>
|
||||
{
|
||||
for (int i = 0; i < messages_per_call; i++)
|
||||
{
|
||||
testChannel.AddNewMessages(new Message(sequence++)
|
||||
{
|
||||
Sender = longUsernameUser,
|
||||
Content = "Many messages! " + Guid.NewGuid(),
|
||||
Timestamp = DateTimeOffset.Now
|
||||
});
|
||||
}
|
||||
}, Channel.MAX_HISTORY / messages_per_call + 5);
|
||||
|
||||
AddAssert("Ensure no adjacent day separators", () =>
|
||||
{
|
||||
var indices = chatDisplay.FillFlow.OfType<DrawableChannel.DaySeparator>().Select(ds => chatDisplay.FillFlow.IndexOf(ds));
|
||||
|
||||
foreach (var i in indices)
|
||||
{
|
||||
if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom);
|
||||
}
|
||||
|
||||
private class TestStandAloneChatDisplay : StandAloneChatDisplay
|
||||
{
|
||||
public TestStandAloneChatDisplay(bool textbox = false)
|
||||
: base(textbox)
|
||||
{
|
||||
}
|
||||
|
||||
protected DrawableChannel DrawableChannel => InternalChildren.OfType<DrawableChannel>().First();
|
||||
|
||||
protected OsuScrollContainer ScrollContainer => (OsuScrollContainer)((Container)DrawableChannel.Child).Child;
|
||||
|
||||
public FillFlowContainer FillFlow => (FillFlowContainer)ScrollContainer.Child;
|
||||
|
||||
public bool ScrolledToBottom => ScrollContainer.IsScrolledToEnd(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
// 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 osu.Framework.Graphics;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Overlays.Comments;
|
||||
using osu.Framework.MathUtils;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneTotalCommentsCounter : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(TotalCommentsCounter),
|
||||
};
|
||||
|
||||
public TestSceneTotalCommentsCounter()
|
||||
{
|
||||
var count = new BindableInt();
|
||||
|
||||
Add(new TotalCommentsCounter
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Current = { BindTarget = count }
|
||||
});
|
||||
|
||||
AddStep(@"Set 100", () => count.Value = 100);
|
||||
AddStep(@"Set 0", () => count.Value = 0);
|
||||
AddStep(@"Set random", () => count.Value = RNG.Next(0, int.MaxValue));
|
||||
}
|
||||
}
|
||||
}
|
@ -107,6 +107,15 @@ namespace osu.Game.Tests.Visual.Online
|
||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
|
||||
}, api.IsLoggedIn));
|
||||
|
||||
AddStep("Show bancho", () => profile.ShowUser(new User
|
||||
{
|
||||
Username = @"BanchoBot",
|
||||
Id = 3,
|
||||
IsBot = true,
|
||||
Country = new Country { FullName = @"Saint Helena", FlagName = @"SH" },
|
||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c4.jpg"
|
||||
}, api.IsLoggedIn));
|
||||
|
||||
AddStep("Hide", profile.Hide);
|
||||
AddStep("Show without reload", profile.Show);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Users;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
@ -94,11 +94,11 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
new SpriteText
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = $@"Username: {user.NewValue?.Username}"
|
||||
},
|
||||
new SpriteText
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = $@"RankedScore: {user.NewValue?.Statistics.RankedScore}"
|
||||
},
|
||||
|
76
osu.Game.Tests/Visual/Online/TestSceneVotePill.cs
Normal file
76
osu.Game.Tests/Visual/Online/TestSceneVotePill.cs
Normal file
@ -0,0 +1,76 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays.Comments;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneVotePill : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(VotePill)
|
||||
};
|
||||
|
||||
private VotePill votePill;
|
||||
|
||||
[Test]
|
||||
public void TestUserCommentPill()
|
||||
{
|
||||
AddStep("Log in", logIn);
|
||||
AddStep("User comment", () => addVotePill(getUserComment()));
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Not loading", () => !votePill.IsLoading);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRandomCommentPill()
|
||||
{
|
||||
AddStep("Log in", logIn);
|
||||
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Loading", () => votePill.IsLoading);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOfflineRandomCommentPill()
|
||||
{
|
||||
AddStep("Log out", API.Logout);
|
||||
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
||||
AddStep("Click", () => votePill.Click());
|
||||
AddAssert("Not loading", () => !votePill.IsLoading);
|
||||
}
|
||||
|
||||
private void logIn() => API.Login("localUser", "password");
|
||||
|
||||
private Comment getUserComment() => new Comment
|
||||
{
|
||||
IsVoted = false,
|
||||
UserId = API.LocalUser.Value.Id,
|
||||
VotesCount = 10,
|
||||
};
|
||||
|
||||
private Comment getRandomComment() => new Comment
|
||||
{
|
||||
IsVoted = false,
|
||||
UserId = 4444,
|
||||
VotesCount = 2,
|
||||
};
|
||||
|
||||
private void addVotePill(Comment comment)
|
||||
{
|
||||
Clear();
|
||||
Add(votePill = new VotePill(comment)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
@ -43,7 +44,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private readonly Stack<BeatmapSetInfo> selectedSets = new Stack<BeatmapSetInfo>();
|
||||
private readonly HashSet<int> eagerSelectedIDs = new HashSet<int>();
|
||||
|
||||
private BeatmapInfo currentSelection;
|
||||
private BeatmapInfo currentSelection => carousel.SelectedBeatmap;
|
||||
|
||||
private const int set_count = 5;
|
||||
|
||||
@ -51,50 +52,433 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
this.rulesets = rulesets;
|
||||
|
||||
Add(carousel = new TestBeatmapCarousel
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
|
||||
List<BeatmapSetInfo> beatmapSets = new List<BeatmapSetInfo>();
|
||||
|
||||
for (int i = 1; i <= set_count; i++)
|
||||
beatmapSets.Add(createTestBeatmapSet(i));
|
||||
|
||||
carousel.SelectionChanged = s => currentSelection = s;
|
||||
|
||||
loadBeatmaps(beatmapSets);
|
||||
|
||||
testTraversal();
|
||||
testFiltering();
|
||||
testRandom();
|
||||
testAddRemove();
|
||||
testSorting();
|
||||
|
||||
testRemoveAll();
|
||||
testEmptyTraversal();
|
||||
testHiding();
|
||||
testSelectingFilteredRuleset();
|
||||
testCarouselRootIsRandom();
|
||||
}
|
||||
|
||||
private void loadBeatmaps(List<BeatmapSetInfo> beatmapSets)
|
||||
/// <summary>
|
||||
/// Test keyboard traversal
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTraversal()
|
||||
{
|
||||
loadBeatmaps();
|
||||
|
||||
advanceSelection(direction: 1, diff: false);
|
||||
waitForSelection(1, 1);
|
||||
|
||||
advanceSelection(direction: 1, diff: true);
|
||||
waitForSelection(1, 2);
|
||||
|
||||
advanceSelection(direction: -1, diff: false);
|
||||
waitForSelection(set_count, 1);
|
||||
|
||||
advanceSelection(direction: -1, diff: true);
|
||||
waitForSelection(set_count - 1, 3);
|
||||
|
||||
advanceSelection(diff: false);
|
||||
advanceSelection(diff: false);
|
||||
waitForSelection(1, 2);
|
||||
|
||||
advanceSelection(direction: -1, diff: true);
|
||||
advanceSelection(direction: -1, diff: true);
|
||||
waitForSelection(set_count, 3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test filtering
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestFiltering()
|
||||
{
|
||||
loadBeatmaps();
|
||||
|
||||
// basic filtering
|
||||
|
||||
setSelected(1, 1);
|
||||
|
||||
AddStep("Filter", () => carousel.Filter(new FilterCriteria { SearchText = "set #3!" }, false));
|
||||
checkVisibleItemCount(diff: false, count: 1);
|
||||
checkVisibleItemCount(diff: true, count: 3);
|
||||
waitForSelection(3, 1);
|
||||
|
||||
advanceSelection(diff: true, count: 4);
|
||||
waitForSelection(3, 2);
|
||||
|
||||
AddStep("Un-filter (debounce)", () => carousel.Filter(new FilterCriteria()));
|
||||
AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask);
|
||||
checkVisibleItemCount(diff: false, count: set_count);
|
||||
checkVisibleItemCount(diff: true, count: 3);
|
||||
|
||||
// test filtering some difficulties (and keeping current beatmap set selected).
|
||||
|
||||
setSelected(1, 2);
|
||||
AddStep("Filter some difficulties", () => carousel.Filter(new FilterCriteria { SearchText = "Normal" }, false));
|
||||
waitForSelection(1, 1);
|
||||
|
||||
AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false));
|
||||
waitForSelection(1, 1);
|
||||
|
||||
AddStep("Filter all", () => carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false));
|
||||
|
||||
checkVisibleItemCount(false, 0);
|
||||
checkVisibleItemCount(true, 0);
|
||||
AddAssert("Selection is null", () => currentSelection == null);
|
||||
|
||||
advanceSelection(true);
|
||||
AddAssert("Selection is null", () => currentSelection == null);
|
||||
|
||||
advanceSelection(false);
|
||||
AddAssert("Selection is null", () => currentSelection == null);
|
||||
|
||||
AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false));
|
||||
|
||||
AddAssert("Selection is non-null", () => currentSelection != null);
|
||||
|
||||
setSelected(1, 3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFilterRange()
|
||||
{
|
||||
loadBeatmaps();
|
||||
|
||||
// buffer the selection
|
||||
setSelected(3, 2);
|
||||
|
||||
setSelected(1, 3);
|
||||
|
||||
AddStep("Apply a range filter", () => carousel.Filter(new FilterCriteria
|
||||
{
|
||||
SearchText = "#3",
|
||||
StarDifficulty = new FilterCriteria.OptionalRange<double>
|
||||
{
|
||||
Min = 2,
|
||||
Max = 5.5,
|
||||
IsLowerInclusive = true
|
||||
}
|
||||
}, false));
|
||||
|
||||
// should reselect the buffered selection.
|
||||
waitForSelection(3, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test random non-repeating algorithm
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRandom()
|
||||
{
|
||||
loadBeatmaps();
|
||||
|
||||
setSelected(1, 1);
|
||||
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
|
||||
prevRandom();
|
||||
ensureRandomFetchSuccess();
|
||||
prevRandom();
|
||||
ensureRandomFetchSuccess();
|
||||
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
|
||||
nextRandom();
|
||||
AddAssert("ensure repeat", () => selectedSets.Contains(carousel.SelectedBeatmapSet));
|
||||
|
||||
AddStep("Add set with 100 difficulties", () => carousel.UpdateBeatmapSet(createTestBeatmapSetWithManyDifficulties(set_count + 1)));
|
||||
AddStep("Filter Extra", () => carousel.Filter(new FilterCriteria { SearchText = "Extra 10" }, false));
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test adding and removing beatmap sets
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddRemove()
|
||||
{
|
||||
loadBeatmaps();
|
||||
|
||||
AddStep("Add new set", () => carousel.UpdateBeatmapSet(createTestBeatmapSet(set_count + 1)));
|
||||
AddStep("Add new set", () => carousel.UpdateBeatmapSet(createTestBeatmapSet(set_count + 2)));
|
||||
|
||||
checkVisibleItemCount(false, set_count + 2);
|
||||
|
||||
AddStep("Remove set", () => carousel.RemoveBeatmapSet(createTestBeatmapSet(set_count + 2)));
|
||||
|
||||
checkVisibleItemCount(false, set_count + 1);
|
||||
|
||||
setSelected(set_count + 1, 1);
|
||||
|
||||
AddStep("Remove set", () => carousel.RemoveBeatmapSet(createTestBeatmapSet(set_count + 1)));
|
||||
|
||||
checkVisibleItemCount(false, set_count);
|
||||
|
||||
waitForSelection(set_count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test sorting
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSorting()
|
||||
{
|
||||
loadBeatmaps();
|
||||
|
||||
AddStep("Sort by author", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Author }, false));
|
||||
AddAssert("Check zzzzz is at bottom", () => carousel.BeatmapSets.Last().Metadata.AuthorString == "zzzzz");
|
||||
AddStep("Sort by artist", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Artist }, false));
|
||||
AddAssert($"Check #{set_count} is at bottom", () => carousel.BeatmapSets.Last().Metadata.Title.EndsWith($"#{set_count}!"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSortingStability()
|
||||
{
|
||||
var sets = new List<BeatmapSetInfo>();
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
var set = createTestBeatmapSet(i);
|
||||
set.Metadata.Artist = "same artist";
|
||||
set.Metadata.Title = "same title";
|
||||
sets.Add(set);
|
||||
}
|
||||
|
||||
loadBeatmaps(sets);
|
||||
|
||||
AddStep("Sort by artist", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Artist }, false));
|
||||
AddAssert("Items remain in original order", () => carousel.BeatmapSets.Select((set, index) => set.ID == index).All(b => b));
|
||||
|
||||
AddStep("Sort by title", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Title }, false));
|
||||
AddAssert("Items remain in original order", () => carousel.BeatmapSets.Select((set, index) => set.ID == index).All(b => b));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSortingWithFiltered()
|
||||
{
|
||||
List<BeatmapSetInfo> sets = new List<BeatmapSetInfo>();
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var set = createTestBeatmapSet(i);
|
||||
set.Beatmaps[0].StarDifficulty = 3 - i;
|
||||
set.Beatmaps[2].StarDifficulty = 6 + i;
|
||||
sets.Add(set);
|
||||
}
|
||||
|
||||
loadBeatmaps(sets);
|
||||
|
||||
AddStep("Filter to normal", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Difficulty, SearchText = "Normal" }, false));
|
||||
AddAssert("Check first set at end", () => carousel.BeatmapSets.First() == sets.Last());
|
||||
AddAssert("Check last set at start", () => carousel.BeatmapSets.Last() == sets.First());
|
||||
|
||||
AddStep("Filter to insane", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Difficulty, SearchText = "Insane" }, false));
|
||||
AddAssert("Check first set at start", () => carousel.BeatmapSets.First() == sets.First());
|
||||
AddAssert("Check last set at end", () => carousel.BeatmapSets.Last() == sets.Last());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRemoveAll()
|
||||
{
|
||||
loadBeatmaps();
|
||||
|
||||
setSelected(2, 1);
|
||||
AddAssert("Selection is non-null", () => currentSelection != null);
|
||||
|
||||
AddStep("Remove selected", () => carousel.RemoveBeatmapSet(carousel.SelectedBeatmapSet));
|
||||
waitForSelection(2);
|
||||
|
||||
AddStep("Remove first", () => carousel.RemoveBeatmapSet(carousel.BeatmapSets.First()));
|
||||
AddStep("Remove first", () => carousel.RemoveBeatmapSet(carousel.BeatmapSets.First()));
|
||||
waitForSelection(1);
|
||||
|
||||
AddUntilStep("Remove all", () =>
|
||||
{
|
||||
if (!carousel.BeatmapSets.Any()) return true;
|
||||
|
||||
carousel.RemoveBeatmapSet(carousel.BeatmapSets.Last());
|
||||
return false;
|
||||
});
|
||||
|
||||
checkNoSelection();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmptyTraversal()
|
||||
{
|
||||
loadBeatmaps(new List<BeatmapSetInfo>());
|
||||
|
||||
advanceSelection(direction: 1, diff: false);
|
||||
checkNoSelection();
|
||||
|
||||
advanceSelection(direction: 1, diff: true);
|
||||
checkNoSelection();
|
||||
|
||||
advanceSelection(direction: -1, diff: false);
|
||||
checkNoSelection();
|
||||
|
||||
advanceSelection(direction: -1, diff: true);
|
||||
checkNoSelection();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHiding()
|
||||
{
|
||||
BeatmapSetInfo hidingSet = null;
|
||||
List<BeatmapSetInfo> hiddenList = new List<BeatmapSetInfo>();
|
||||
|
||||
AddStep("create hidden set", () =>
|
||||
{
|
||||
hidingSet = createTestBeatmapSet(1);
|
||||
hidingSet.Beatmaps[1].Hidden = true;
|
||||
|
||||
hiddenList.Clear();
|
||||
hiddenList.Add(hidingSet);
|
||||
});
|
||||
|
||||
loadBeatmaps(hiddenList);
|
||||
|
||||
setSelected(1, 1);
|
||||
|
||||
checkVisibleItemCount(true, 2);
|
||||
advanceSelection(true);
|
||||
waitForSelection(1, 3);
|
||||
|
||||
setHidden(3);
|
||||
waitForSelection(1, 1);
|
||||
|
||||
setHidden(2, false);
|
||||
advanceSelection(true);
|
||||
waitForSelection(1, 2);
|
||||
|
||||
setHidden(1);
|
||||
waitForSelection(1, 2);
|
||||
|
||||
setHidden(2);
|
||||
checkNoSelection();
|
||||
|
||||
void setHidden(int diff, bool hidden = true)
|
||||
{
|
||||
AddStep((hidden ? "" : "un") + $"hide diff {diff}", () =>
|
||||
{
|
||||
hidingSet.Beatmaps[diff - 1].Hidden = hidden;
|
||||
carousel.UpdateBeatmapSet(hidingSet);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSelectingFilteredRuleset()
|
||||
{
|
||||
BeatmapSetInfo testMixed = null;
|
||||
|
||||
createCarousel();
|
||||
|
||||
AddStep("add mixed ruleset beatmapset", () =>
|
||||
{
|
||||
testMixed = createTestBeatmapSet(set_count + 1);
|
||||
|
||||
for (int i = 0; i <= 2; i++)
|
||||
{
|
||||
testMixed.Beatmaps[i].Ruleset = rulesets.AvailableRulesets.ElementAt(i);
|
||||
testMixed.Beatmaps[i].RulesetID = i;
|
||||
}
|
||||
|
||||
carousel.UpdateBeatmapSet(testMixed);
|
||||
});
|
||||
AddStep("filter to ruleset 0", () =>
|
||||
carousel.Filter(new FilterCriteria { Ruleset = rulesets.AvailableRulesets.ElementAt(0) }, false));
|
||||
AddStep("select filtered map skipping filtered", () => carousel.SelectBeatmap(testMixed.Beatmaps[1], false));
|
||||
AddAssert("unfiltered beatmap selected", () => carousel.SelectedBeatmap.Equals(testMixed.Beatmaps[0]));
|
||||
|
||||
AddStep("remove mixed set", () =>
|
||||
{
|
||||
carousel.RemoveBeatmapSet(testMixed);
|
||||
testMixed = null;
|
||||
});
|
||||
var testSingle = createTestBeatmapSet(set_count + 2);
|
||||
testSingle.Beatmaps.ForEach(b =>
|
||||
{
|
||||
b.Ruleset = rulesets.AvailableRulesets.ElementAt(1);
|
||||
b.RulesetID = b.Ruleset.ID ?? 1;
|
||||
});
|
||||
AddStep("add single ruleset beatmapset", () => carousel.UpdateBeatmapSet(testSingle));
|
||||
AddStep("select filtered map skipping filtered", () => carousel.SelectBeatmap(testSingle.Beatmaps[0], false));
|
||||
checkNoSelection();
|
||||
AddStep("remove single ruleset set", () => carousel.RemoveBeatmapSet(testSingle));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCarouselRootIsRandom()
|
||||
{
|
||||
List<BeatmapSetInfo> manySets = new List<BeatmapSetInfo>();
|
||||
|
||||
for (int i = 1; i <= 50; i++)
|
||||
manySets.Add(createTestBeatmapSet(i));
|
||||
|
||||
loadBeatmaps(manySets);
|
||||
|
||||
advanceSelection(direction: 1, diff: false);
|
||||
checkNonmatchingFilter();
|
||||
checkNonmatchingFilter();
|
||||
checkNonmatchingFilter();
|
||||
checkNonmatchingFilter();
|
||||
checkNonmatchingFilter();
|
||||
AddAssert("Selection was random", () => eagerSelectedIDs.Count > 1);
|
||||
}
|
||||
|
||||
private void loadBeatmaps(List<BeatmapSetInfo> beatmapSets = null)
|
||||
{
|
||||
createCarousel();
|
||||
|
||||
if (beatmapSets == null)
|
||||
{
|
||||
beatmapSets = new List<BeatmapSetInfo>();
|
||||
|
||||
for (int i = 1; i <= set_count; i++)
|
||||
beatmapSets.Add(createTestBeatmapSet(i));
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
AddStep($"Load {beatmapSets.Count} Beatmaps", () =>
|
||||
{
|
||||
carousel.Filter(new FilterCriteria());
|
||||
carousel.BeatmapSetsChanged = () => changed = true;
|
||||
carousel.BeatmapSets = beatmapSets;
|
||||
});
|
||||
|
||||
AddUntilStep("Wait for load", () => changed);
|
||||
}
|
||||
|
||||
private void createCarousel(Container target = null)
|
||||
{
|
||||
AddStep("Create carousel", () =>
|
||||
{
|
||||
selectedSets.Clear();
|
||||
eagerSelectedIDs.Clear();
|
||||
|
||||
(target ?? this).Child = carousel = new TestBeatmapCarousel
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private void ensureRandomFetchSuccess() =>
|
||||
AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet);
|
||||
|
||||
private void checkSelected(int set, int? diff = null) =>
|
||||
AddAssert($"selected is set{set}{(diff.HasValue ? $" diff{diff.Value}" : "")}", () =>
|
||||
private void waitForSelection(int set, int? diff = null) =>
|
||||
AddUntilStep($"selected is set{set}{(diff.HasValue ? $" diff{diff.Value}" : "")}", () =>
|
||||
{
|
||||
if (diff != null)
|
||||
return carousel.SelectedBeatmap == carousel.BeatmapSets.Skip(set - 1).First().Beatmaps.Skip(diff.Value - 1).First();
|
||||
@ -109,8 +493,10 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private void advanceSelection(bool diff, int direction = 1, int count = 1)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
AddStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () =>
|
||||
carousel.SelectNext(direction, !diff));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRepeatStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () =>
|
||||
@ -170,275 +556,6 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test keyboard traversal
|
||||
/// </summary>
|
||||
private void testTraversal()
|
||||
{
|
||||
advanceSelection(direction: 1, diff: false);
|
||||
checkSelected(1, 1);
|
||||
|
||||
advanceSelection(direction: 1, diff: true);
|
||||
checkSelected(1, 2);
|
||||
|
||||
advanceSelection(direction: -1, diff: false);
|
||||
checkSelected(set_count, 1);
|
||||
|
||||
advanceSelection(direction: -1, diff: true);
|
||||
checkSelected(set_count - 1, 3);
|
||||
|
||||
advanceSelection(diff: false);
|
||||
advanceSelection(diff: false);
|
||||
checkSelected(1, 2);
|
||||
|
||||
advanceSelection(direction: -1, diff: true);
|
||||
advanceSelection(direction: -1, diff: true);
|
||||
checkSelected(set_count, 3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test filtering
|
||||
/// </summary>
|
||||
private void testFiltering()
|
||||
{
|
||||
// basic filtering
|
||||
|
||||
setSelected(1, 1);
|
||||
|
||||
AddStep("Filter", () => carousel.Filter(new FilterCriteria { SearchText = "set #3!" }, false));
|
||||
checkVisibleItemCount(diff: false, count: 1);
|
||||
checkVisibleItemCount(diff: true, count: 3);
|
||||
checkSelected(3, 1);
|
||||
|
||||
advanceSelection(diff: true, count: 4);
|
||||
checkSelected(3, 2);
|
||||
|
||||
AddStep("Un-filter (debounce)", () => carousel.Filter(new FilterCriteria()));
|
||||
AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask);
|
||||
checkVisibleItemCount(diff: false, count: set_count);
|
||||
checkVisibleItemCount(diff: true, count: 3);
|
||||
|
||||
// test filtering some difficulties (and keeping current beatmap set selected).
|
||||
|
||||
setSelected(1, 2);
|
||||
AddStep("Filter some difficulties", () => carousel.Filter(new FilterCriteria { SearchText = "Normal" }, false));
|
||||
checkSelected(1, 1);
|
||||
|
||||
AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false));
|
||||
checkSelected(1, 1);
|
||||
|
||||
AddStep("Filter all", () => carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false));
|
||||
|
||||
checkVisibleItemCount(false, 0);
|
||||
checkVisibleItemCount(true, 0);
|
||||
AddAssert("Selection is null", () => currentSelection == null);
|
||||
|
||||
advanceSelection(true);
|
||||
AddAssert("Selection is null", () => currentSelection == null);
|
||||
|
||||
advanceSelection(false);
|
||||
AddAssert("Selection is null", () => currentSelection == null);
|
||||
|
||||
AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false));
|
||||
|
||||
AddAssert("Selection is non-null", () => currentSelection != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test random non-repeating algorithm
|
||||
/// </summary>
|
||||
private void testRandom()
|
||||
{
|
||||
setSelected(1, 1);
|
||||
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
|
||||
prevRandom();
|
||||
ensureRandomFetchSuccess();
|
||||
prevRandom();
|
||||
ensureRandomFetchSuccess();
|
||||
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
nextRandom();
|
||||
ensureRandomDidntRepeat();
|
||||
|
||||
nextRandom();
|
||||
AddAssert("ensure repeat", () => selectedSets.Contains(carousel.SelectedBeatmapSet));
|
||||
|
||||
AddStep("Add set with 100 difficulties", () => carousel.UpdateBeatmapSet(createTestBeatmapSetWithManyDifficulties(set_count + 1)));
|
||||
AddStep("Filter Extra", () => carousel.Filter(new FilterCriteria { SearchText = "Extra 10" }, false));
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
checkInvisibleDifficultiesUnselectable();
|
||||
AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test adding and removing beatmap sets
|
||||
/// </summary>
|
||||
private void testAddRemove()
|
||||
{
|
||||
AddStep("Add new set", () => carousel.UpdateBeatmapSet(createTestBeatmapSet(set_count + 1)));
|
||||
AddStep("Add new set", () => carousel.UpdateBeatmapSet(createTestBeatmapSet(set_count + 2)));
|
||||
|
||||
checkVisibleItemCount(false, set_count + 2);
|
||||
|
||||
AddStep("Remove set", () => carousel.RemoveBeatmapSet(createTestBeatmapSet(set_count + 2)));
|
||||
|
||||
checkVisibleItemCount(false, set_count + 1);
|
||||
|
||||
setSelected(set_count + 1, 1);
|
||||
|
||||
AddStep("Remove set", () => carousel.RemoveBeatmapSet(createTestBeatmapSet(set_count + 1)));
|
||||
|
||||
checkVisibleItemCount(false, set_count);
|
||||
|
||||
checkSelected(set_count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test sorting
|
||||
/// </summary>
|
||||
private void testSorting()
|
||||
{
|
||||
AddStep("Sort by author", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Author }, false));
|
||||
AddAssert("Check zzzzz is at bottom", () => carousel.BeatmapSets.Last().Metadata.AuthorString == "zzzzz");
|
||||
AddStep("Sort by artist", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Artist }, false));
|
||||
AddAssert($"Check #{set_count} is at bottom", () => carousel.BeatmapSets.Last().Metadata.Title.EndsWith($"#{set_count}!"));
|
||||
}
|
||||
|
||||
private void testRemoveAll()
|
||||
{
|
||||
setSelected(2, 1);
|
||||
AddAssert("Selection is non-null", () => currentSelection != null);
|
||||
|
||||
AddStep("Remove selected", () => carousel.RemoveBeatmapSet(carousel.SelectedBeatmapSet));
|
||||
checkSelected(2);
|
||||
|
||||
AddStep("Remove first", () => carousel.RemoveBeatmapSet(carousel.BeatmapSets.First()));
|
||||
AddStep("Remove first", () => carousel.RemoveBeatmapSet(carousel.BeatmapSets.First()));
|
||||
checkSelected(1);
|
||||
|
||||
AddUntilStep("Remove all", () =>
|
||||
{
|
||||
if (!carousel.BeatmapSets.Any()) return true;
|
||||
|
||||
carousel.RemoveBeatmapSet(carousel.BeatmapSets.Last());
|
||||
return false;
|
||||
});
|
||||
|
||||
checkNoSelection();
|
||||
}
|
||||
|
||||
private void testEmptyTraversal()
|
||||
{
|
||||
advanceSelection(direction: 1, diff: false);
|
||||
checkNoSelection();
|
||||
|
||||
advanceSelection(direction: 1, diff: true);
|
||||
checkNoSelection();
|
||||
|
||||
advanceSelection(direction: -1, diff: false);
|
||||
checkNoSelection();
|
||||
|
||||
advanceSelection(direction: -1, diff: true);
|
||||
checkNoSelection();
|
||||
}
|
||||
|
||||
private void testHiding()
|
||||
{
|
||||
var hidingSet = createTestBeatmapSet(1);
|
||||
hidingSet.Beatmaps[1].Hidden = true;
|
||||
AddStep("Add set with diff 2 hidden", () => carousel.UpdateBeatmapSet(hidingSet));
|
||||
setSelected(1, 1);
|
||||
|
||||
checkVisibleItemCount(true, 2);
|
||||
advanceSelection(true);
|
||||
checkSelected(1, 3);
|
||||
|
||||
setHidden(3);
|
||||
checkSelected(1, 1);
|
||||
|
||||
setHidden(2, false);
|
||||
advanceSelection(true);
|
||||
checkSelected(1, 2);
|
||||
|
||||
setHidden(1);
|
||||
checkSelected(1, 2);
|
||||
|
||||
setHidden(2);
|
||||
checkNoSelection();
|
||||
|
||||
void setHidden(int diff, bool hidden = true)
|
||||
{
|
||||
AddStep((hidden ? "" : "un") + $"hide diff {diff}", () =>
|
||||
{
|
||||
hidingSet.Beatmaps[diff - 1].Hidden = hidden;
|
||||
carousel.UpdateBeatmapSet(hidingSet);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void testSelectingFilteredRuleset()
|
||||
{
|
||||
var testMixed = createTestBeatmapSet(set_count + 1);
|
||||
AddStep("add mixed ruleset beatmapset", () =>
|
||||
{
|
||||
for (int i = 0; i <= 2; i++)
|
||||
{
|
||||
testMixed.Beatmaps[i].Ruleset = rulesets.AvailableRulesets.ElementAt(i);
|
||||
testMixed.Beatmaps[i].RulesetID = i;
|
||||
}
|
||||
|
||||
carousel.UpdateBeatmapSet(testMixed);
|
||||
});
|
||||
AddStep("filter to ruleset 0", () =>
|
||||
carousel.Filter(new FilterCriteria { Ruleset = rulesets.AvailableRulesets.ElementAt(0) }, false));
|
||||
AddStep("select filtered map skipping filtered", () => carousel.SelectBeatmap(testMixed.Beatmaps[1], false));
|
||||
AddAssert("unfiltered beatmap selected", () => carousel.SelectedBeatmap.Equals(testMixed.Beatmaps[0]));
|
||||
|
||||
AddStep("remove mixed set", () =>
|
||||
{
|
||||
carousel.RemoveBeatmapSet(testMixed);
|
||||
testMixed = null;
|
||||
});
|
||||
var testSingle = createTestBeatmapSet(set_count + 2);
|
||||
testSingle.Beatmaps.ForEach(b =>
|
||||
{
|
||||
b.Ruleset = rulesets.AvailableRulesets.ElementAt(1);
|
||||
b.RulesetID = b.Ruleset.ID ?? 1;
|
||||
});
|
||||
AddStep("add single ruleset beatmapset", () => carousel.UpdateBeatmapSet(testSingle));
|
||||
AddStep("select filtered map skipping filtered", () => carousel.SelectBeatmap(testSingle.Beatmaps[0], false));
|
||||
checkNoSelection();
|
||||
AddStep("remove single ruleset set", () => carousel.RemoveBeatmapSet(testSingle));
|
||||
}
|
||||
|
||||
private void testCarouselRootIsRandom()
|
||||
{
|
||||
List<BeatmapSetInfo> beatmapSets = new List<BeatmapSetInfo>();
|
||||
|
||||
for (int i = 1; i <= 50; i++)
|
||||
beatmapSets.Add(createTestBeatmapSet(i));
|
||||
|
||||
loadBeatmaps(beatmapSets);
|
||||
advanceSelection(direction: 1, diff: false);
|
||||
checkNonmatchingFilter();
|
||||
checkNonmatchingFilter();
|
||||
checkNonmatchingFilter();
|
||||
checkNonmatchingFilter();
|
||||
checkNonmatchingFilter();
|
||||
AddAssert("Selection was random", () => eagerSelectedIDs.Count > 1);
|
||||
}
|
||||
|
||||
private BeatmapSetInfo createTestBeatmapSet(int id)
|
||||
{
|
||||
return new BeatmapSetInfo
|
||||
|
@ -75,7 +75,6 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
testBeatmapLabels(instance);
|
||||
|
||||
// TODO: adjust cases once more info is shown for other gamemodes
|
||||
switch (instance)
|
||||
{
|
||||
case OsuRuleset _:
|
||||
@ -99,8 +98,6 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
testNullBeatmap();
|
||||
}
|
||||
|
||||
private void testBeatmapLabels(Ruleset ruleset)
|
||||
@ -117,7 +114,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
AddAssert("check info labels count", () => infoWedge.Info.InfoLabelContainer.Children.Count == expectedCount);
|
||||
}
|
||||
|
||||
private void testNullBeatmap()
|
||||
[Test]
|
||||
public void TestNullBeatmap()
|
||||
{
|
||||
selectBeatmap(null);
|
||||
AddAssert("check empty version", () => string.IsNullOrEmpty(infoWedge.Info.VersionLabel.Text));
|
||||
@ -127,6 +125,12 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
AddAssert("check no info labels", () => !infoWedge.Info.InfoLabelContainer.Children.Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTruncation()
|
||||
{
|
||||
selectBeatmap(createLongMetadata());
|
||||
}
|
||||
|
||||
private void selectBeatmap([CanBeNull] IBeatmap b)
|
||||
{
|
||||
BeatmapInfoWedge.BufferedWedgeInfo infoBefore = null;
|
||||
@ -166,6 +170,25 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
};
|
||||
}
|
||||
|
||||
private IBeatmap createLongMetadata()
|
||||
{
|
||||
return new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
AuthorString = "WWWWWWWWWWWWWWW",
|
||||
Artist = "Verrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Artist",
|
||||
Source = "Verrrrry long Source",
|
||||
Title = "Verrrrry long Title"
|
||||
},
|
||||
Version = "Verrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Version",
|
||||
Status = BeatmapSetOnlineStatus.Graveyard,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private class TestBeatmapInfoWedge : BeatmapInfoWedge
|
||||
{
|
||||
public new BufferedWedgeInfo Info => base.Info;
|
||||
|
@ -7,7 +7,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
@ -62,7 +61,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
Mods = new[] { new OsuModHidden().Acronym, new OsuModHardRock().Acronym, },
|
||||
User = new User
|
||||
{
|
||||
Id = 6602580,
|
||||
|
@ -18,8 +18,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
overlay.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, Color4.Purple, null, Key.Number1);
|
||||
overlay.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, Color4.Purple, null, Key.Number2);
|
||||
overlay.AddButton(@"Edit", @"Beatmap", FontAwesome.Solid.PencilAlt, Color4.Yellow, null, Key.Number3);
|
||||
overlay.AddButton(@"Delete", @"Beatmap", FontAwesome.Solid.Trash, Color4.Pink, null, Key.Number4, float.MaxValue);
|
||||
overlay.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, Color4.Pink, null, Key.Number3);
|
||||
overlay.AddButton(@"Edit", @"beatmap", FontAwesome.Solid.PencilAlt, Color4.Yellow, null, Key.Number4);
|
||||
|
||||
Add(overlay);
|
||||
|
||||
|
@ -16,6 +16,7 @@ using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
@ -34,6 +35,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
private RulesetStore rulesets;
|
||||
|
||||
private MusicController music;
|
||||
|
||||
private WorkingBeatmap defaultBeatmap;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
@ -54,23 +57,6 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
typeof(DrawableCarouselBeatmapSet),
|
||||
};
|
||||
|
||||
private class TestSongSelect : PlaySongSelect
|
||||
{
|
||||
public Action StartRequested;
|
||||
|
||||
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
|
||||
|
||||
public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
|
||||
public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
|
||||
public new BeatmapCarousel Carousel => base.Carousel;
|
||||
|
||||
protected override bool OnStart()
|
||||
{
|
||||
StartRequested?.Invoke();
|
||||
return base.OnStart();
|
||||
}
|
||||
}
|
||||
|
||||
private TestSongSelect songSelect;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -79,6 +65,11 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default));
|
||||
|
||||
Dependencies.Cache(music = new MusicController());
|
||||
|
||||
// required to get bindables attached
|
||||
Add(music);
|
||||
|
||||
Beatmap.SetDefault();
|
||||
|
||||
Dependencies.Cache(config = new OsuConfigManager(LocalStorage));
|
||||
@ -93,6 +84,70 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
manager?.Delete(manager.GetAllUsableBeatmapSets());
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestSingleFilterOnEnter()
|
||||
{
|
||||
addRulesetImportStep(0);
|
||||
addRulesetImportStep(0);
|
||||
|
||||
createSongSelect();
|
||||
|
||||
AddAssert("filter count is 1", () => songSelect.FilterCount == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAudioResuming()
|
||||
{
|
||||
createSongSelect();
|
||||
|
||||
addRulesetImportStep(0);
|
||||
addRulesetImportStep(0);
|
||||
|
||||
checkMusicPlaying(true);
|
||||
AddStep("select first", () => songSelect.Carousel.SelectBeatmap(songSelect.Carousel.BeatmapSets.First().Beatmaps.First()));
|
||||
checkMusicPlaying(true);
|
||||
|
||||
AddStep("manual pause", () => music.TogglePause());
|
||||
checkMusicPlaying(false);
|
||||
AddStep("select next difficulty", () => songSelect.Carousel.SelectNext(skipDifficulties: false));
|
||||
checkMusicPlaying(false);
|
||||
|
||||
AddStep("select next set", () => songSelect.Carousel.SelectNext());
|
||||
checkMusicPlaying(true);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestAudioRemainsCorrectOnRulesetChange(bool rulesetsInSameBeatmap)
|
||||
{
|
||||
createSongSelect();
|
||||
|
||||
// start with non-osu! to avoid convert confusion
|
||||
changeRuleset(1);
|
||||
|
||||
if (rulesetsInSameBeatmap)
|
||||
{
|
||||
AddStep("import multi-ruleset map", () =>
|
||||
{
|
||||
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
|
||||
manager.Import(createTestBeatmapSet(0, usableRulesets)).Wait();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
addRulesetImportStep(1);
|
||||
addRulesetImportStep(0);
|
||||
}
|
||||
|
||||
checkMusicPlaying(true);
|
||||
|
||||
AddStep("manual pause", () => music.TogglePause());
|
||||
checkMusicPlaying(false);
|
||||
|
||||
changeRuleset(0);
|
||||
checkMusicPlaying(!rulesetsInSameBeatmap);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDummy()
|
||||
{
|
||||
@ -128,12 +183,10 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("needs fixing")]
|
||||
public void TestImportUnderDifferentRuleset()
|
||||
{
|
||||
createSongSelect();
|
||||
changeRuleset(2);
|
||||
addRulesetImportStep(0);
|
||||
addRulesetImportStep(2);
|
||||
AddUntilStep("no selection", () => songSelect.Carousel.SelectedBeatmap == null);
|
||||
}
|
||||
|
||||
@ -183,6 +236,22 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
void onRulesetChange(ValueChangedEvent<RulesetInfo> e) => rulesetChangeIndex = actionIndex++;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestModsRetainedBetweenSongSelect()
|
||||
{
|
||||
AddAssert("empty mods", () => !Mods.Value.Any());
|
||||
|
||||
createSongSelect();
|
||||
|
||||
addRulesetImportStep(0);
|
||||
|
||||
changeMods(new OsuModHardRock());
|
||||
|
||||
createSongSelect();
|
||||
|
||||
AddAssert("mods retained", () => Mods.Value.Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStartAfterUnMatchingFilterDoesNotStart()
|
||||
{
|
||||
@ -224,6 +293,9 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private static int importId;
|
||||
private int getImportId() => ++importId;
|
||||
|
||||
private void checkMusicPlaying(bool playing) =>
|
||||
AddUntilStep($"music {(playing ? "" : "not ")}playing", () => music.IsPlaying == playing);
|
||||
|
||||
private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => Mods.Value = mods);
|
||||
|
||||
private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id));
|
||||
@ -289,5 +361,36 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
DateAdded = DateTimeOffset.UtcNow,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
rulesets?.Dispose();
|
||||
}
|
||||
|
||||
private class TestSongSelect : PlaySongSelect
|
||||
{
|
||||
public Action StartRequested;
|
||||
|
||||
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
|
||||
|
||||
public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
|
||||
public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
|
||||
public new BeatmapCarousel Carousel => base.Carousel;
|
||||
|
||||
protected override bool OnStart()
|
||||
{
|
||||
StartRequested?.Invoke();
|
||||
return base.OnStart();
|
||||
}
|
||||
|
||||
public int FilterCount;
|
||||
|
||||
protected override void ApplyFilterToCarousel(FilterCriteria criteria)
|
||||
{
|
||||
FilterCount++;
|
||||
base.ApplyFilterToCarousel(criteria);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osuTK.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Users;
|
||||
@ -52,7 +51,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
Mods = new[] { new OsuModHidden().Acronym, new OsuModHardRock().Acronym, },
|
||||
User = new User
|
||||
{
|
||||
Id = 6602580,
|
||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual
|
||||
private IReadOnlyList<Type> requiredGameDependencies => new[]
|
||||
{
|
||||
typeof(OsuGame),
|
||||
typeof(RavenLogger),
|
||||
typeof(SentryLogger),
|
||||
typeof(OsuLogo),
|
||||
typeof(IdleTracker),
|
||||
typeof(OnScreenDisplay),
|
||||
@ -109,16 +109,20 @@ namespace osu.Game.Tests.Visual
|
||||
AddAssert("check OsuGame DI members", () =>
|
||||
{
|
||||
foreach (var type in requiredGameDependencies)
|
||||
{
|
||||
if (game.Dependencies.Get(type) == null)
|
||||
throw new Exception($"{type} has not been cached");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
AddAssert("check OsuGameBase DI members", () =>
|
||||
{
|
||||
foreach (var type in requiredGameBaseDependencies)
|
||||
{
|
||||
if (gameBase.Dependencies.Get(type) == null)
|
||||
throw new Exception($"{type} has not been cached");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
@ -22,6 +22,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
public TestSceneBackButton()
|
||||
{
|
||||
BackButton button;
|
||||
BackButton.Receptor receptor = new BackButton.Receptor();
|
||||
|
||||
Child = new Container
|
||||
{
|
||||
@ -31,12 +32,13 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
receptor,
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.SlateGray
|
||||
},
|
||||
button = new BackButton
|
||||
button = new BackButton(receptor)
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
@ -10,7 +11,6 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Lists;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
@ -153,7 +153,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
};
|
||||
}
|
||||
|
||||
private SortedList<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints;
|
||||
private List<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ToList();
|
||||
|
||||
private TimingControlPoint getNextTimingPoint(TimingControlPoint current)
|
||||
{
|
||||
|
@ -52,19 +52,23 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("start confirming", () => overlay.Begin());
|
||||
AddStep("abort confirming", () => overlay.Abort());
|
||||
|
||||
AddAssert("ensure not fired internally", () => !overlay.Fired);
|
||||
AddAssert("ensure aborted", () => !fired);
|
||||
|
||||
AddStep("start confirming", () => overlay.Begin());
|
||||
|
||||
AddUntilStep("wait until confirmed", () => fired);
|
||||
AddAssert("ensure fired internally", () => overlay.Fired);
|
||||
|
||||
AddStep("abort after fire", () => overlay.Abort());
|
||||
AddAssert("ensure not fired internally", () => !overlay.Fired);
|
||||
AddStep("start confirming", () => overlay.Begin());
|
||||
AddUntilStep("wait until fired again", () => overlay.Fired);
|
||||
}
|
||||
|
||||
private class TestHoldToConfirmOverlay : ExitConfirmOverlay
|
||||
{
|
||||
protected override bool AllowMultipleFires => true;
|
||||
|
||||
public void Begin() => BeginConfirm();
|
||||
public void Abort() => AbortConfirm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
// 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;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneLabelledDrawable : OsuTestScene
|
||||
{
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestPadded(bool hasDescription) => createPaddedComponent(hasDescription);
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestNonPadded(bool hasDescription) => createPaddedComponent(hasDescription, false);
|
||||
|
||||
private void createPaddedComponent(bool hasDescription = false, bool padded = true)
|
||||
{
|
||||
AddStep("create component", () =>
|
||||
{
|
||||
LabelledDrawable<Drawable> component;
|
||||
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Width = 500,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = component = padded ? (LabelledDrawable<Drawable>)new PaddedLabelledDrawable() : new NonPaddedLabelledDrawable(),
|
||||
};
|
||||
|
||||
component.Label = "a sample component";
|
||||
component.Description = hasDescription ? "this text describes the component" : string.Empty;
|
||||
});
|
||||
}
|
||||
|
||||
private class PaddedLabelledDrawable : LabelledDrawable<Drawable>
|
||||
{
|
||||
public PaddedLabelledDrawable()
|
||||
: base(true)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Drawable CreateComponent() => new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Colour = Color4.Red,
|
||||
Text = @"(( Component ))"
|
||||
};
|
||||
}
|
||||
|
||||
private class NonPaddedLabelledDrawable : LabelledDrawable<Drawable>
|
||||
{
|
||||
public NonPaddedLabelledDrawable()
|
||||
: base(false)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Drawable CreateComponent() => new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 40,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.SlateGray
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Colour = Color4.Red,
|
||||
Text = @"(( Component ))"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneLabelledSwitchButton : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(LabelledSwitchButton),
|
||||
typeof(SwitchButton)
|
||||
};
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestSwitchButton(bool hasDescription) => createSwitchButton(hasDescription);
|
||||
|
||||
private void createSwitchButton(bool hasDescription = false)
|
||||
{
|
||||
AddStep("create component", () =>
|
||||
{
|
||||
LabelledSwitchButton component;
|
||||
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Width = 500,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = component = new LabelledSwitchButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
};
|
||||
|
||||
component.Label = "a sample component";
|
||||
component.Description = hasDescription ? "this text describes the component" : string.Empty;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Screens.Edit.Setup.Components.LabelledComponents;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
@ -19,6 +19,36 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
typeof(LabelledTextBox),
|
||||
};
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestTextBox(bool hasDescription) => createTextBox(hasDescription);
|
||||
|
||||
private void createTextBox(bool hasDescription = false)
|
||||
{
|
||||
AddStep("create component", () =>
|
||||
{
|
||||
LabelledTextBox component;
|
||||
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Width = 500,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = component = new LabelledTextBox
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Label = "Testing text",
|
||||
PlaceholderText = "This is definitely working as intended",
|
||||
}
|
||||
};
|
||||
|
||||
component.Label = "a sample component";
|
||||
component.Description = hasDescription ? "this text describes the component" : string.Empty;
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -32,7 +62,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
LabelText = "Testing text",
|
||||
Label = "Testing text",
|
||||
PlaceholderText = "This is definitely working as intended",
|
||||
}
|
||||
};
|
||||
|
145
osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs
Normal file
145
osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs
Normal file
@ -0,0 +1,145 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneStatefulMenuItem : ManualInputManagerTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(OsuMenu),
|
||||
typeof(StatefulMenuItem),
|
||||
typeof(TernaryStateMenuItem),
|
||||
typeof(DrawableStatefulMenuItem),
|
||||
};
|
||||
|
||||
[Test]
|
||||
public void TestTernaryMenuItem()
|
||||
{
|
||||
OsuMenu menu = null;
|
||||
|
||||
Bindable<TernaryState> state = new Bindable<TernaryState>(TernaryState.Indeterminate);
|
||||
|
||||
AddStep("create menu", () =>
|
||||
{
|
||||
state.Value = TernaryState.Indeterminate;
|
||||
|
||||
Child = menu = new OsuMenu(Direction.Vertical, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Items = new[]
|
||||
{
|
||||
new TernaryStateMenuItem("First"),
|
||||
new TernaryStateMenuItem("Second") { State = { BindTarget = state } },
|
||||
new TernaryStateMenuItem("Third") { State = { Value = TernaryState.True } },
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
checkState(TernaryState.Indeterminate);
|
||||
|
||||
click();
|
||||
checkState(TernaryState.True);
|
||||
|
||||
click();
|
||||
checkState(TernaryState.False);
|
||||
|
||||
click();
|
||||
checkState(TernaryState.True);
|
||||
|
||||
click();
|
||||
checkState(TernaryState.False);
|
||||
|
||||
AddStep("change state via bindable", () => state.Value = TernaryState.True);
|
||||
|
||||
void click() =>
|
||||
AddStep("click", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(menu.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
void checkState(TernaryState expected)
|
||||
=> AddAssert($"state is {expected}", () => state.Value == expected);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCustomState()
|
||||
{
|
||||
AddStep("create menu", () =>
|
||||
{
|
||||
Child = new OsuMenu(Direction.Vertical, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Items = new[]
|
||||
{
|
||||
new TestMenuItem("First", MenuItemType.Standard, getNextState),
|
||||
new TestMenuItem("Second", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State2 } },
|
||||
new TestMenuItem("Third", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State3 } },
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private TestStates getNextState(TestStates state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case TestStates.State1:
|
||||
return TestStates.State2;
|
||||
|
||||
case TestStates.State2:
|
||||
return TestStates.State3;
|
||||
|
||||
case TestStates.State3:
|
||||
return TestStates.State1;
|
||||
}
|
||||
|
||||
return TestStates.State1;
|
||||
}
|
||||
|
||||
private class TestMenuItem : StatefulMenuItem<TestStates>
|
||||
{
|
||||
public TestMenuItem(string text, MenuItemType type, Func<TestStates, TestStates> changeStateFunc)
|
||||
: base(text, changeStateFunc, type)
|
||||
{
|
||||
}
|
||||
|
||||
public override IconUsage? GetIconForState(TestStates state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case TestStates.State1:
|
||||
return FontAwesome.Solid.DiceOne;
|
||||
|
||||
case TestStates.State2:
|
||||
return FontAwesome.Solid.DiceTwo;
|
||||
|
||||
case TestStates.State3:
|
||||
return FontAwesome.Solid.DiceThree;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(state), state, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum TestStates
|
||||
{
|
||||
State1,
|
||||
State2,
|
||||
State3
|
||||
}
|
||||
}
|
||||
}
|
44
osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs
Normal file
44
osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs
Normal file
@ -0,0 +1,44 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneSwitchButton : ManualInputManagerTestScene
|
||||
{
|
||||
private SwitchButton switchButton;
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
Child = switchButton = new SwitchButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestChangeThroughInput()
|
||||
{
|
||||
AddStep("move to switch button", () => InputManager.MoveMouseTo(switchButton));
|
||||
AddStep("click on", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("click off", () => InputManager.Click(MouseButton.Left));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangeThroughBindable()
|
||||
{
|
||||
BindableBool bindable = null;
|
||||
|
||||
AddStep("bind bindable", () => switchButton.Current.BindTo(bindable = new BindableBool()));
|
||||
AddStep("toggle bindable", () => bindable.Toggle());
|
||||
AddStep("toggle bindable", () => bindable.Toggle());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
// 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 osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneToggleMenuItem : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(OsuMenu),
|
||||
typeof(ToggleMenuItem),
|
||||
typeof(DrawableStatefulMenuItem)
|
||||
};
|
||||
|
||||
public TestSceneToggleMenuItem()
|
||||
{
|
||||
Add(new OsuMenu(Direction.Vertical, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Items = new[]
|
||||
{
|
||||
new ToggleMenuItem("First"),
|
||||
new ToggleMenuItem("Second") { State = { Value = true } }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneWaveContainer : OsuTestScene
|
Reference in New Issue
Block a user