Merge branch 'master' into ruleset-resources-skin

This commit is contained in:
Salman Ahmed
2021-06-22 20:36:49 +03:00
269 changed files with 5653 additions and 1787 deletions

View File

@ -28,6 +28,8 @@ namespace osu.Game.Tests.Chat
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123")]
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123/whatever")]
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc", "https://dev.ppy.sh/beatmapsets/abc")]
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/discussions", "https://dev.ppy.sh/beatmapsets/discussions")]
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/discussions/123", "https://dev.ppy.sh/beatmapsets/discussions/123")]
public void TestBeatmapLinks(LinkAction expectedAction, string expectedArg, string link)
{
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";

View File

@ -113,7 +113,6 @@ namespace osu.Game.Tests.Collections.IO
await importCollectionsFromStream(osu, ms);
}
Assert.That(host.UpdateThread.Running, Is.True);
Assert.That(exceptionThrown, Is.False);
Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(0));
}

View File

@ -0,0 +1,101 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Input.Bindings;
using osu.Framework.Platform;
using osu.Game.Database;
using osu.Game.Input;
using osu.Game.Input.Bindings;
using Realms;
namespace osu.Game.Tests.Database
{
[TestFixture]
public class TestRealmKeyBindingStore
{
private NativeStorage storage;
private RealmKeyBindingStore keyBindingStore;
private RealmContextFactory realmContextFactory;
[SetUp]
public void SetUp()
{
var directory = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
storage = new NativeStorage(directory.FullName);
realmContextFactory = new RealmContextFactory(storage);
keyBindingStore = new RealmKeyBindingStore(realmContextFactory);
}
[Test]
public void TestDefaultsPopulationAndQuery()
{
Assert.That(query().Count, Is.EqualTo(0));
KeyBindingContainer testContainer = new TestKeyBindingContainer();
keyBindingStore.Register(testContainer);
Assert.That(query().Count, Is.EqualTo(3));
Assert.That(query().Where(k => k.ActionInt == (int)GlobalAction.Back).Count, Is.EqualTo(1));
Assert.That(query().Where(k => k.ActionInt == (int)GlobalAction.Select).Count, Is.EqualTo(2));
}
private IQueryable<RealmKeyBinding> query() => realmContextFactory.Context.All<RealmKeyBinding>();
[Test]
public void TestUpdateViaQueriedReference()
{
KeyBindingContainer testContainer = new TestKeyBindingContainer();
keyBindingStore.Register(testContainer);
var backBinding = query().Single(k => k.ActionInt == (int)GlobalAction.Back);
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.Escape }));
var tsr = ThreadSafeReference.Create(backBinding);
using (var usage = realmContextFactory.GetForWrite())
{
var binding = usage.Realm.ResolveReference(tsr);
binding.KeyCombination = new KeyCombination(InputKey.BackSpace);
usage.Commit();
}
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.BackSpace }));
// check still correct after re-query.
backBinding = query().Single(k => k.ActionInt == (int)GlobalAction.Back);
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.BackSpace }));
}
[TearDown]
public void TearDown()
{
realmContextFactory.Dispose();
storage.DeleteDirectory(string.Empty);
}
public class TestKeyBindingContainer : KeyBindingContainer
{
public override IEnumerable<IKeyBinding> DefaultKeyBindings =>
new[]
{
new KeyBinding(InputKey.Escape, GlobalAction.Back),
new KeyBinding(InputKey.Enter, GlobalAction.Select),
new KeyBinding(InputKey.Space, GlobalAction.Select),
};
}
}
}

View File

@ -44,11 +44,9 @@ namespace osu.Game.Tests.Gameplay
{
TestDrawableHitObject dho = null;
TestLifetimeEntry entry = null;
AddStep("Create DHO", () =>
AddStep("Create DHO", () => Child = dho = new TestDrawableHitObject
{
dho = new TestDrawableHitObject(null);
dho.Apply(entry = new TestLifetimeEntry(new HitObject()));
Child = dho;
Entry = entry = new TestLifetimeEntry(new HitObject())
});
AddStep("KeepAlive = true", () =>
@ -81,12 +79,10 @@ namespace osu.Game.Tests.Gameplay
AddAssert("Lifetime is updated", () => entry.LifetimeStart == -TestLifetimeEntry.INITIAL_LIFETIME_OFFSET);
TestDrawableHitObject dho = null;
AddStep("Create DHO", () =>
AddStep("Create DHO", () => Child = dho = new TestDrawableHitObject
{
dho = new TestDrawableHitObject(null);
dho.Apply(entry);
Child = dho;
dho.SetLifetimeStartOnApply = true;
Entry = entry,
SetLifetimeStartOnApply = true
});
AddStep("ApplyDefaults", () => entry.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()));
AddAssert("Lifetime is correct", () => dho.LifetimeStart == TestDrawableHitObject.LIFETIME_ON_APPLY && entry.LifetimeStart == TestDrawableHitObject.LIFETIME_ON_APPLY);
@ -97,11 +93,9 @@ namespace osu.Game.Tests.Gameplay
{
TestDrawableHitObject dho = null;
TestLifetimeEntry entry = null;
AddStep("Create DHO", () =>
AddStep("Create DHO", () => Child = dho = new TestDrawableHitObject
{
dho = new TestDrawableHitObject(null);
dho.Apply(entry = new TestLifetimeEntry(new HitObject()));
Child = dho;
Entry = entry = new TestLifetimeEntry(new HitObject())
});
AddStep("Set entry lifetime", () =>
@ -135,7 +129,7 @@ namespace osu.Game.Tests.Gameplay
public bool SetLifetimeStartOnApply;
public TestDrawableHitObject(HitObject hitObject)
public TestDrawableHitObject(HitObject hitObject = null)
: base(hitObject)
{
}

View File

@ -14,6 +14,14 @@ namespace osu.Game.Tests.Mods
[TestFixture]
public class ModUtilsTest
{
[Test]
public void TestModIsNotCompatibleWithItself()
{
var mod = new Mock<CustomMod1>();
Assert.That(ModUtils.CheckCompatibleSet(new[] { mod.Object, mod.Object }, out var invalid), Is.False);
Assert.That(invalid, Is.EquivalentTo(new[] { mod.Object }));
}
[Test]
public void TestModIsCompatibleByItself()
{
@ -21,6 +29,14 @@ namespace osu.Game.Tests.Mods
Assert.That(ModUtils.CheckCompatibleSet(new[] { mod.Object }));
}
[Test]
public void TestModIsCompatibleByItselfWithIncompatibleInterface()
{
var mod = new Mock<CustomMod1>();
mod.Setup(m => m.IncompatibleMods).Returns(new[] { typeof(IModCompatibilitySpecification) });
Assert.That(ModUtils.CheckCompatibleSet(new[] { mod.Object }));
}
[Test]
public void TestIncompatibleThroughTopLevel()
{
@ -34,6 +50,20 @@ namespace osu.Game.Tests.Mods
Assert.That(ModUtils.CheckCompatibleSet(new Mod[] { mod2.Object, mod1.Object }), Is.False);
}
[Test]
public void TestIncompatibleThroughInterface()
{
var mod1 = new Mock<CustomMod1>();
var mod2 = new Mock<CustomMod2>();
mod1.Setup(m => m.IncompatibleMods).Returns(new[] { typeof(IModCompatibilitySpecification) });
mod2.Setup(m => m.IncompatibleMods).Returns(new[] { typeof(IModCompatibilitySpecification) });
// Test both orderings.
Assert.That(ModUtils.CheckCompatibleSet(new Mod[] { mod1.Object, mod2.Object }), Is.False);
Assert.That(ModUtils.CheckCompatibleSet(new Mod[] { mod2.Object, mod1.Object }), Is.False);
}
[Test]
public void TestMultiModIncompatibleWithTopLevel()
{
@ -125,7 +155,7 @@ namespace osu.Game.Tests.Mods
// multi mod.
new object[]
{
new Mod[] { new MultiMod(new OsuModHalfTime()), new OsuModHalfTime() },
new Mod[] { new MultiMod(new OsuModHalfTime()), new OsuModDaycore() },
new[] { typeof(MultiMod) }
},
// valid pair.
@ -149,11 +179,15 @@ namespace osu.Game.Tests.Mods
Assert.That(invalid.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid));
}
public abstract class CustomMod1 : Mod
public abstract class CustomMod1 : Mod, IModCompatibilitySpecification
{
}
public abstract class CustomMod2 : Mod
public abstract class CustomMod2 : Mod, IModCompatibilitySpecification
{
}
public interface IModCompatibilitySpecification
{
}
}

View File

@ -142,7 +142,10 @@ namespace osu.Game.Tests.NonVisual
foreach (var file in osuStorage.IgnoreFiles)
{
Assert.That(File.Exists(Path.Combine(originalDirectory, file)));
// avoid touching realm files which may be a pipe and break everything.
// this is also done locally inside OsuStorage via the IgnoreFiles list.
if (file.EndsWith(".ini", StringComparison.Ordinal))
Assert.That(File.Exists(Path.Combine(originalDirectory, file)));
Assert.That(storage.Exists(file), Is.False);
}

View File

@ -33,10 +33,11 @@ namespace osu.Game.Tests.NonVisual.Filtering
* outside of the range.
*/
[Test]
public void TestApplyStarQueries()
[TestCase("star")]
[TestCase("stars")]
public void TestApplyStarQueries(string variant)
{
const string query = "stars<4 easy";
string query = $"{variant}<4 easy";
var filterCriteria = new FilterCriteria();
FilterQueryParser.ApplyQueries(filterCriteria, query);
Assert.AreEqual("easy", filterCriteria.SearchText.Trim());

View File

@ -1,2 +1,2 @@
[General]
Version: 1.0
// no version specified means v1

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

View File

@ -161,15 +161,18 @@ namespace osu.Game.Tests.Visual.Background
private void loadNextBackground()
{
SeasonalBackground previousBackground = null;
SeasonalBackground background = null;
AddStep("create next background", () =>
{
previousBackground = (SeasonalBackground)backgroundContainer.SingleOrDefault();
background = backgroundLoader.LoadNextBackground();
LoadComponentAsync(background, bg => backgroundContainer.Child = bg);
});
AddUntilStep("background loaded", () => background.IsLoaded);
AddAssert("background is different", () => !background.Equals(previousBackground));
}
private void assertAnyBackground()

View File

@ -0,0 +1,144 @@
// 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.Game.Beatmaps;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Setup;
namespace osu.Game.Tests.Visual.Editing
{
public class TestSceneMetadataSection : OsuTestScene
{
[Cached]
private EditorBeatmap editorBeatmap = new EditorBeatmap(new Beatmap());
private TestMetadataSection metadataSection;
[Test]
public void TestMinimalMetadata()
{
AddStep("set metadata", () =>
{
editorBeatmap.Metadata.Artist = "Example Artist";
editorBeatmap.Metadata.ArtistUnicode = null;
editorBeatmap.Metadata.Title = "Example Title";
editorBeatmap.Metadata.TitleUnicode = null;
});
createSection();
assertArtist("Example Artist");
assertRomanisedArtist("Example Artist", false);
assertTitle("Example Title");
assertRomanisedTitle("Example Title", false);
}
[Test]
public void TestInitialisationFromNonRomanisedVariant()
{
AddStep("set metadata", () =>
{
editorBeatmap.Metadata.ArtistUnicode = "*なみりん";
editorBeatmap.Metadata.Artist = null;
editorBeatmap.Metadata.TitleUnicode = "コイシテイク・プラネット";
editorBeatmap.Metadata.Title = null;
});
createSection();
assertArtist("*なみりん");
assertRomanisedArtist(string.Empty, true);
assertTitle("コイシテイク・プラネット");
assertRomanisedTitle(string.Empty, true);
}
[Test]
public void TestInitialisationPreservesOriginalValues()
{
AddStep("set metadata", () =>
{
editorBeatmap.Metadata.ArtistUnicode = "*なみりん";
editorBeatmap.Metadata.Artist = "*namirin";
editorBeatmap.Metadata.TitleUnicode = "コイシテイク・プラネット";
editorBeatmap.Metadata.Title = "Koishiteiku Planet";
});
createSection();
assertArtist("*なみりん");
assertRomanisedArtist("*namirin", true);
assertTitle("コイシテイク・プラネット");
assertRomanisedTitle("Koishiteiku Planet", true);
}
[Test]
public void TestValueTransfer()
{
AddStep("set metadata", () =>
{
editorBeatmap.Metadata.ArtistUnicode = "*なみりん";
editorBeatmap.Metadata.Artist = null;
editorBeatmap.Metadata.TitleUnicode = "コイシテイク・プラネット";
editorBeatmap.Metadata.Title = null;
});
createSection();
AddStep("set romanised artist name", () => metadataSection.ArtistTextBox.Current.Value = "*namirin");
assertArtist("*namirin");
assertRomanisedArtist("*namirin", false);
AddStep("set native artist name", () => metadataSection.ArtistTextBox.Current.Value = "*なみりん");
assertArtist("*なみりん");
assertRomanisedArtist("*namirin", true);
AddStep("set romanised title", () => metadataSection.TitleTextBox.Current.Value = "Hitokoto no kyori");
assertTitle("Hitokoto no kyori");
assertRomanisedTitle("Hitokoto no kyori", false);
AddStep("set native title", () => metadataSection.TitleTextBox.Current.Value = "ヒトコトの距離");
assertTitle("ヒトコトの距離");
assertRomanisedTitle("Hitokoto no kyori", true);
}
private void createSection()
=> AddStep("create metadata section", () => Child = metadataSection = new TestMetadataSection());
private void assertArtist(string expected)
=> AddAssert($"artist is {expected}", () => metadataSection.ArtistTextBox.Current.Value == expected);
private void assertRomanisedArtist(string expected, bool editable)
{
AddAssert($"romanised artist is {expected}", () => metadataSection.RomanisedArtistTextBox.Current.Value == expected);
AddAssert($"romanised artist is {(editable ? "" : "not ")}editable", () => metadataSection.RomanisedArtistTextBox.ReadOnly == !editable);
}
private void assertTitle(string expected)
=> AddAssert($"title is {expected}", () => metadataSection.TitleTextBox.Current.Value == expected);
private void assertRomanisedTitle(string expected, bool editable)
{
AddAssert($"romanised title is {expected}", () => metadataSection.RomanisedTitleTextBox.Current.Value == expected);
AddAssert($"romanised title is {(editable ? "" : "not ")}editable", () => metadataSection.RomanisedTitleTextBox.ReadOnly == !editable);
}
private class TestMetadataSection : MetadataSection
{
public new LabelledTextBox ArtistTextBox => base.ArtistTextBox;
public new LabelledTextBox RomanisedArtistTextBox => base.RomanisedArtistTextBox;
public new LabelledTextBox TitleTextBox => base.TitleTextBox;
public new LabelledTextBox RomanisedTitleTextBox => base.RomanisedTitleTextBox;
}
}
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using NUnit.Framework;
@ -330,6 +331,8 @@ namespace osu.Game.Tests.Visual.Gameplay
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => throw new NotImplementedException();
public IEnumerable<ISkin> AllSources => throw new NotImplementedException();
public event Action SourceChanged
{
add { }

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
@ -146,7 +147,8 @@ namespace osu.Game.Tests.Visual.Gameplay
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => source?.GetTexture(componentName, wrapModeS, wrapModeT);
public ISample GetSample(ISampleInfo sampleInfo) => source?.GetSample(sampleInfo);
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => source?.GetConfig<TLookup, TValue>(lookup);
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => source?.FindProvider(lookupFunction);
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => lookupFunction(this) ? this : source?.FindProvider(lookupFunction);
public IEnumerable<ISkin> AllSources => new[] { this }.Concat(source?.AllSources ?? Enumerable.Empty<ISkin>());
public void TriggerSourceChanged()
{

View File

@ -66,12 +66,12 @@ namespace osu.Game.Tests.Visual.Gameplay
}
[Test]
public void TestStoryboardExitToSkipOutro()
public void TestStoryboardExitDuringOutroStillExits()
{
CreateTest(null);
AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value);
AddStep("exit via pause", () => Player.ExitViaPause());
AddAssert("score shown", () => Player.IsScoreShown);
AddAssert("player exited", () => !Player.IsCurrentScreen() && Player.GetChildScreen() == null);
}
[TestCase(false)]

View File

@ -0,0 +1,240 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Chat;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Users;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneMessageNotifier : OsuManualInputManagerTestScene
{
private User friend;
private Channel publicChannel;
private Channel privateMessageChannel;
private TestContainer testContainer;
private int messageIdCounter;
[SetUp]
public void Setup()
{
if (API is DummyAPIAccess daa)
{
daa.HandleRequest = dummyAPIHandleRequest;
}
friend = new User { Id = 0, Username = "Friend" };
publicChannel = new Channel { Id = 1, Name = "osu" };
privateMessageChannel = new Channel(friend) { Id = 2, Name = friend.Username, Type = ChannelType.PM };
Schedule(() =>
{
Child = testContainer = new TestContainer(new[] { publicChannel, privateMessageChannel })
{
RelativeSizeAxes = Axes.Both,
};
testContainer.ChatOverlay.Show();
});
}
private bool dummyAPIHandleRequest(APIRequest request)
{
switch (request)
{
case GetMessagesRequest messagesRequest:
messagesRequest.TriggerSuccess(new List<Message>(0));
return true;
case CreateChannelRequest createChannelRequest:
var apiChatChannel = new APIChatChannel
{
RecentMessages = new List<Message>(0),
ChannelID = (int)createChannelRequest.Channel.Id
};
createChannelRequest.TriggerSuccess(apiChatChannel);
return true;
case ListChannelsRequest listChannelsRequest:
listChannelsRequest.TriggerSuccess(new List<Channel>(1) { publicChannel });
return true;
case GetUpdatesRequest updatesRequest:
updatesRequest.TriggerSuccess(new GetUpdatesResponse
{
Messages = new List<Message>(0),
Presence = new List<Channel>(0)
});
return true;
case JoinChannelRequest joinChannelRequest:
joinChannelRequest.TriggerSuccess();
return true;
default:
return false;
}
}
[Test]
public void TestPublicChannelMention()
{
AddStep("switch to PMs", () => testContainer.ChannelManager.CurrentChannel.Value = privateMessageChannel);
AddStep("receive public message", () => receiveMessage(friend, publicChannel, "Hello everyone"));
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
AddStep("receive message containing mention", () => receiveMessage(friend, publicChannel, $"Hello {API.LocalUser.Value.Username.ToLowerInvariant()}!"));
AddAssert("1 notification fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 1);
AddStep("open notification overlay", () => testContainer.NotificationOverlay.Show());
AddStep("click notification", clickNotification<MessageNotifier.MentionNotification>);
AddAssert("chat overlay is open", () => testContainer.ChatOverlay.State.Value == Visibility.Visible);
AddAssert("public channel is selected", () => testContainer.ChannelManager.CurrentChannel.Value == publicChannel);
}
[Test]
public void TestPrivateMessageNotification()
{
AddStep("switch to public channel", () => testContainer.ChannelManager.CurrentChannel.Value = publicChannel);
AddStep("receive PM", () => receiveMessage(friend, privateMessageChannel, $"Hello {API.LocalUser.Value.Username}"));
AddAssert("1 notification fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 1);
AddStep("open notification overlay", () => testContainer.NotificationOverlay.Show());
AddStep("click notification", clickNotification<MessageNotifier.PrivateMessageNotification>);
AddAssert("chat overlay is open", () => testContainer.ChatOverlay.State.Value == Visibility.Visible);
AddAssert("PM channel is selected", () => testContainer.ChannelManager.CurrentChannel.Value == privateMessageChannel);
}
[Test]
public void TestNoNotificationWhenPMChannelOpen()
{
AddStep("switch to PMs", () => testContainer.ChannelManager.CurrentChannel.Value = privateMessageChannel);
AddStep("receive PM", () => receiveMessage(friend, privateMessageChannel, "you're reading this, right?"));
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
}
[Test]
public void TestNoNotificationWhenMentionedInOpenPublicChannel()
{
AddStep("switch to public channel", () => testContainer.ChannelManager.CurrentChannel.Value = publicChannel);
AddStep("receive mention", () => receiveMessage(friend, publicChannel, $"{API.LocalUser.Value.Username.ToUpperInvariant()} has been reading this"));
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
}
[Test]
public void TestNoNotificationOnSelfMention()
{
AddStep("switch to PM channel", () => testContainer.ChannelManager.CurrentChannel.Value = privateMessageChannel);
AddStep("receive self-mention", () => receiveMessage(API.LocalUser.Value, publicChannel, $"my name is {API.LocalUser.Value.Username}"));
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
}
[Test]
public void TestNoNotificationOnPMFromSelf()
{
AddStep("switch to public channel", () => testContainer.ChannelManager.CurrentChannel.Value = publicChannel);
AddStep("receive PM from self", () => receiveMessage(API.LocalUser.Value, privateMessageChannel, "hey hey"));
AddAssert("no notifications fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 0);
}
[Test]
public void TestNotificationsNotFiredTwice()
{
AddStep("switch to public channel", () => testContainer.ChannelManager.CurrentChannel.Value = publicChannel);
AddStep("receive same PM twice", () =>
{
var message = createMessage(friend, privateMessageChannel, "hey hey");
privateMessageChannel.AddNewMessages(message, message);
});
AddStep("open notification overlay", () => testContainer.NotificationOverlay.Show());
AddAssert("1 notification fired", () => testContainer.NotificationOverlay.UnreadCount.Value == 1);
}
private void receiveMessage(User sender, Channel channel, string content) => channel.AddNewMessages(createMessage(sender, channel, content));
private Message createMessage(User sender, Channel channel, string content) => new Message(messageIdCounter++)
{
Content = content,
Sender = sender,
ChannelId = channel.Id
};
private void clickNotification<T>() where T : Notification
{
var notification = testContainer.NotificationOverlay.ChildrenOfType<T>().Single();
InputManager.MoveMouseTo(notification);
InputManager.Click(MouseButton.Left);
}
private class TestContainer : Container
{
[Cached]
public ChannelManager ChannelManager { get; } = new ChannelManager();
[Cached]
public NotificationOverlay NotificationOverlay { get; } = new NotificationOverlay
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
};
[Cached]
public ChatOverlay ChatOverlay { get; } = new ChatOverlay();
private readonly MessageNotifier messageNotifier = new MessageNotifier();
private readonly Channel[] channels;
public TestContainer(Channel[] channels)
{
this.channels = channels;
}
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
ChannelManager,
ChatOverlay,
NotificationOverlay,
messageNotifier,
};
((BindableList<Channel>)ChannelManager.AvailableChannels).AddRange(channels);
foreach (var channel in channels)
ChannelManager.JoinChannel(channel);
}
}
}
}

View File

@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Ranking
}
}
},
new AccuracyCircle(score)
new AccuracyCircle(score, true)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,

View File

@ -2,15 +2,22 @@
// 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;
using osu.Framework.Graphics;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Online.Leaderboards;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Scoring;
using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Tests.Resources;
using osu.Game.Users;
using osuTK;
@ -23,32 +30,98 @@ namespace osu.Game.Tests.Visual.SongSelect
[Cached]
private readonly DialogOverlay dialogOverlay;
private ScoreManager scoreManager;
private RulesetStore rulesetStore;
private BeatmapManager beatmapManager;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
dependencies.Cache(rulesetStore = new RulesetStore(ContextFactory));
dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesetStore, null, dependencies.Get<AudioManager>(), Resources, dependencies.Get<GameHost>(), Beatmap.Default));
dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, null, ContextFactory));
return dependencies;
}
public TestSceneBeatmapLeaderboard()
{
Add(dialogOverlay = new DialogOverlay
AddRange(new Drawable[]
{
Depth = -1
dialogOverlay = new DialogOverlay
{
Depth = -1
},
leaderboard = new FailableLeaderboard
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(550f, 450f),
Scope = BeatmapLeaderboardScope.Global,
}
});
}
[Test]
public void TestLocalScoresDisplay()
{
BeatmapInfo beatmapInfo = null;
AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Local);
AddStep(@"Set beatmap", () =>
{
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First();
leaderboard.Beatmap = beatmapInfo;
});
Add(leaderboard = new FailableLeaderboard
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(550f, 450f),
Scope = BeatmapLeaderboardScope.Global,
});
clearScores();
checkCount(0);
AddStep(@"New Scores", newScores);
loadMoreScores(() => beatmapInfo);
checkCount(10);
loadMoreScores(() => beatmapInfo);
checkCount(20);
clearScores();
checkCount(0);
}
[Test]
public void TestGlobalScoresDisplay()
{
AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Global);
AddStep(@"New Scores", () => leaderboard.Scores = generateSampleScores(null));
}
[Test]
public void TestPersonalBest()
{
AddStep(@"Show personal best", showPersonalBest);
AddStep("null personal best position", showPersonalBestWithNullPosition);
}
[Test]
public void TestPlaceholderStates()
{
AddStep(@"Empty Scores", () => leaderboard.SetRetrievalState(PlaceholderState.NoScores));
AddStep(@"Network failure", () => leaderboard.SetRetrievalState(PlaceholderState.NetworkFailure));
AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter));
AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn));
AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable));
AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected));
}
[Test]
public void TestBeatmapStates()
{
foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus)))
AddStep($"{status} beatmap", () => showBeatmapWithStatus(status));
AddStep("null personal best position", showPersonalBestWithNullPosition);
}
private void showPersonalBestWithNullPosition()
@ -96,9 +169,26 @@ namespace osu.Game.Tests.Visual.SongSelect
};
}
private void newScores()
private void loadMoreScores(Func<BeatmapInfo> beatmapInfo)
{
var scores = new[]
AddStep(@"Load new scores via manager", () =>
{
foreach (var score in generateSampleScores(beatmapInfo()))
scoreManager.Import(score).Wait();
});
}
private void clearScores()
{
AddStep("Clear all scores", () => scoreManager.Delete(scoreManager.GetAllUsableScores()));
}
private void checkCount(int expected) =>
AddUntilStep("Correct count displayed", () => leaderboard.ChildrenOfType<LeaderboardScore>().Count() == expected);
private static ScoreInfo[] generateSampleScores(BeatmapInfo beatmap)
{
return new[]
{
new ScoreInfo
{
@ -107,6 +197,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 6602580,
@ -125,6 +216,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 4608074,
@ -143,6 +235,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 1014222,
@ -161,6 +254,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 1541390,
@ -179,6 +273,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 2243452,
@ -197,6 +292,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 2705430,
@ -215,6 +311,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 7151382,
@ -233,6 +330,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 2051389,
@ -251,6 +349,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 6169483,
@ -269,6 +368,7 @@ namespace osu.Game.Tests.Visual.SongSelect
MaxCombo = 244,
TotalScore = 1707827,
//Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
Beatmap = beatmap,
User = new User
{
Id = 6702666,
@ -281,8 +381,6 @@ namespace osu.Game.Tests.Visual.SongSelect
},
},
};
leaderboard.Scores = scores;
}
private void showBeatmapWithStatus(BeatmapSetOnlineStatus status)

View File

@ -74,7 +74,6 @@ namespace osu.Game.Tests.Visual
typeof(FileStore),
typeof(ScoreManager),
typeof(BeatmapManager),
typeof(KeyBindingStore),
typeof(SettingsStore),
typeof(RulesetConfigCache),
typeof(OsuColour),