From eba3cfc96e0e812a764cf70103905f4d7aff0874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 Nov 2021 12:37:12 +0100 Subject: [PATCH 1/8] Move `ScoreInfo` string representation to extension method --- osu.Game/Scoring/ScoreInfo.cs | 2 +- osu.Game/Scoring/ScoreInfoExtensions.cs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Scoring/ScoreInfoExtensions.cs diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index e5b050fc01..736a939a59 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -225,7 +225,7 @@ namespace osu.Game.Scoring return clone; } - public override string ToString() => $"{User} playing {BeatmapInfo}"; + public override string ToString() => this.GetDisplayTitle(); public bool Equals(ScoreInfo other) { diff --git a/osu.Game/Scoring/ScoreInfoExtensions.cs b/osu.Game/Scoring/ScoreInfoExtensions.cs new file mode 100644 index 0000000000..2279337fef --- /dev/null +++ b/osu.Game/Scoring/ScoreInfoExtensions.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; + +namespace osu.Game.Scoring +{ + public static class ScoreInfoExtensions + { + /// + /// A user-presentable display title representing this score. + /// + public static string GetDisplayTitle(this IScoreInfo scoreInfo) => $"{scoreInfo.User.Username} playing {scoreInfo.Beatmap.GetDisplayTitle()}"; + } +} From a1b55d6490cd103b9d3eb0238305df7a38234a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 Nov 2021 13:34:36 +0100 Subject: [PATCH 2/8] Add failing test case --- .../Online/TestSceneBeatmapManager.cs | 52 ++++++++++++++++--- .../Notifications/ProgressNotification.cs | 9 +++- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Online/TestSceneBeatmapManager.cs b/osu.Game.Tests/Online/TestSceneBeatmapManager.cs index 0ae0186770..4d5bee13f2 100644 --- a/osu.Game.Tests/Online/TestSceneBeatmapManager.cs +++ b/osu.Game.Tests/Online/TestSceneBeatmapManager.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Tests.Visual; @@ -16,7 +17,30 @@ namespace osu.Game.Tests.Online private BeatmapManager beatmaps; private ProgressNotification recentNotification; - private static readonly BeatmapSetInfo test_model = new BeatmapSetInfo { OnlineBeatmapSetID = 1 }; + private static readonly BeatmapSetInfo test_db_model = new BeatmapSetInfo + { + OnlineBeatmapSetID = 1, + Metadata = new BeatmapMetadata + { + Artist = "test author", + Title = "test title", + Author = new APIUser + { + Username = "mapper" + } + } + }; + + private static readonly APIBeatmapSet test_online_model = new APIBeatmapSet + { + OnlineID = 2, + Artist = "test author", + Title = "test title", + Author = new APIUser + { + Username = "mapper" + } + }; [BackgroundDependencyLoader] private void load(BeatmapManager beatmaps) @@ -26,25 +50,41 @@ namespace osu.Game.Tests.Online beatmaps.PostNotification = n => recentNotification = n as ProgressNotification; } + private static readonly object[][] notification_test_cases = + { + new object[] { test_db_model }, + new object[] { test_online_model } + }; + + [TestCaseSource(nameof(notification_test_cases))] + public void TestNotificationMessage(IBeatmapSetInfo model) + { + AddStep("clear recent notification", () => recentNotification = null); + AddStep("download beatmap", () => beatmaps.Download(model)); + + AddUntilStep("wait for notification", () => recentNotification != null); + AddUntilStep("notification text correct", () => recentNotification.Text.ToString() == "Downloading test author - test title (mapper)"); + } + [Test] public void TestCancelDownloadFromRequest() { - AddStep("download beatmap", () => beatmaps.Download(test_model)); + AddStep("download beatmap", () => beatmaps.Download(test_db_model)); - AddStep("cancel download from request", () => beatmaps.GetExistingDownload(test_model).Cancel()); + AddStep("cancel download from request", () => beatmaps.GetExistingDownload(test_db_model).Cancel()); - AddUntilStep("is removed from download list", () => beatmaps.GetExistingDownload(test_model) == null); + AddUntilStep("is removed from download list", () => beatmaps.GetExistingDownload(test_db_model) == null); AddAssert("is notification cancelled", () => recentNotification.State == ProgressNotificationState.Cancelled); } [Test] public void TestCancelDownloadFromNotification() { - AddStep("download beatmap", () => beatmaps.Download(test_model)); + AddStep("download beatmap", () => beatmaps.Download(test_db_model)); AddStep("cancel download from notification", () => recentNotification.Close()); - AddUntilStep("is removed from download list", () => beatmaps.GetExistingDownload(test_model) == null); + AddUntilStep("is removed from download list", () => beatmaps.GetExistingDownload(test_db_model) == null); AddAssert("is notification cancelled", () => recentNotification.State == ProgressNotificationState.Cancelled); } } diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index c44b88ad29..5b74bff817 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -23,9 +23,16 @@ namespace osu.Game.Overlays.Notifications { private const float loading_spinner_size = 22; + private LocalisableString text; + public LocalisableString Text { - set => Schedule(() => textDrawable.Text = value); + get => text; + set + { + text = value; + Schedule(() => textDrawable.Text = text); + } } public string CompletionText { get; set; } = "Task has completed!"; From 5ec8288508876dff6b6af1717b4a9fb6866792f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 Nov 2021 13:34:56 +0100 Subject: [PATCH 3/8] Add `GetDisplayString()` extension to handle all model interface types globally --- osu.Game/Database/ArchiveModelManager.cs | 3 +- osu.Game/Database/ModelDownloader.cs | 3 +- osu.Game/Extensions/ModelExtensions.cs | 61 ++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Extensions/ModelExtensions.cs diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 019749760f..320f108886 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -15,6 +15,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Threading; +using osu.Game.Extensions; using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.IPC; @@ -192,7 +193,7 @@ namespace osu.Game.Database else { notification.CompletionText = imported.Count == 1 - ? $"Imported {imported.First().Value}!" + ? $"Imported {imported.First().Value.GetDisplayString()}!" : $"Imported {imported.Count} {HumanisedModelName}s!"; if (imported.Count > 0 && PostImport != null) diff --git a/osu.Game/Database/ModelDownloader.cs b/osu.Game/Database/ModelDownloader.cs index 3c1f181f24..43ba62dfe0 100644 --- a/osu.Game/Database/ModelDownloader.cs +++ b/osu.Game/Database/ModelDownloader.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Humanizer; using osu.Framework.Logging; using osu.Framework.Platform; +using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Overlays.Notifications; @@ -50,7 +51,7 @@ namespace osu.Game.Database DownloadNotification notification = new DownloadNotification { - Text = $"Downloading {request.Model}", + Text = $"Downloading {request.Model.GetDisplayString()}", }; request.DownloadProgressed += progress => diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs new file mode 100644 index 0000000000..5c96add076 --- /dev/null +++ b/osu.Game/Extensions/ModelExtensions.cs @@ -0,0 +1,61 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Extensions +{ + public static class ModelExtensions + { + /// + /// Returns a user-facing string representing the . + /// + /// + /// + /// Non-interface types without special handling will fall back to . + /// + /// + /// Warning: This method is _purposefully_ not called GetDisplayTitle() like the others, because otherwise + /// extension method type inference rules cause this method to call itself and cause a stack overflow. + /// + /// + public static string GetDisplayString(this object model) + { + string result = null; + + switch (model) + { + case IBeatmapSetInfo beatmapSetInfo: + result = beatmapSetInfo.Metadata?.GetDisplayTitle(); + break; + + case IBeatmapInfo beatmapInfo: + result = beatmapInfo.GetDisplayTitle(); + break; + + case IBeatmapMetadataInfo metadataInfo: + result = metadataInfo.GetDisplayTitle(); + break; + + case IScoreInfo scoreInfo: + result = scoreInfo.GetDisplayTitle(); + break; + + case IRulesetInfo rulesetInfo: + result = rulesetInfo.Name; + break; + + case IUser user: + result = user.Username; + break; + } + + // fallback in case none of the above happens to match. + result ??= model.ToString(); + return result; + } + } +} From 9686bf507d7b49419e802f44d841579a954536b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 Nov 2021 13:48:05 +0100 Subject: [PATCH 4/8] Add failing tests for coverage of `GetDisplayString()` --- osu.Game.Tests/Models/DisplayStringTest.cs | 95 ++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 osu.Game.Tests/Models/DisplayStringTest.cs diff --git a/osu.Game.Tests/Models/DisplayStringTest.cs b/osu.Game.Tests/Models/DisplayStringTest.cs new file mode 100644 index 0000000000..9a3c32bfb2 --- /dev/null +++ b/osu.Game.Tests/Models/DisplayStringTest.cs @@ -0,0 +1,95 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Moq; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Extensions; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Tests.Models +{ + [TestFixture] + public class DisplayStringTest + { + private static readonly object[][] test_cases = + { + new object[] { makeMockBeatmapSet(), "artist - title (author)" }, + new object[] { makeMockBeatmap(), "artist - title (author) [difficulty]" }, + new object[] { makeMockMetadata(), "artist - title (author)" }, + new object[] { makeMockScore(), "user playing artist - title (author) [difficulty]" }, + new object[] { makeMockRuleset(), "ruleset" }, + new object[] { makeMockUser(), "user" }, + new object[] { new Fallback(), "fallback" } + }; + + [TestCaseSource(nameof(test_cases))] + public void TestDisplayString(object model, string expected) => Assert.That(model.GetDisplayString(), Is.EqualTo(expected)); + + private static IBeatmapSetInfo makeMockBeatmapSet() + { + var mock = new Mock(); + + mock.Setup(m => m.Metadata).Returns(makeMockMetadata); + + return mock.Object; + } + + private static IBeatmapInfo makeMockBeatmap() + { + var mock = new Mock(); + + mock.Setup(m => m.Metadata).Returns(makeMockMetadata); + mock.Setup(m => m.DifficultyName).Returns("difficulty"); + + return mock.Object; + } + + private static IBeatmapMetadataInfo makeMockMetadata() + { + var mock = new Mock(); + + mock.Setup(m => m.Artist).Returns("artist"); + mock.Setup(m => m.Title).Returns("title"); + mock.Setup(m => m.Author.Username).Returns("author"); + + return mock.Object; + } + + private static IScoreInfo makeMockScore() + { + var mock = new Mock(); + + mock.Setup(m => m.User).Returns(new APIUser { Username = "user" }); // TODO: temporary. + mock.Setup(m => m.Beatmap).Returns(makeMockBeatmap); + + return mock.Object; + } + + private static IRulesetInfo makeMockRuleset() + { + var mock = new Mock(); + + mock.Setup(m => m.Name).Returns("ruleset"); + + return mock.Object; + } + + private static IUser makeMockUser() + { + var mock = new Mock(); + + mock.Setup(m => m.Username).Returns("user"); + + return mock.Object; + } + + private class Fallback + { + public override string ToString() => "fallback"; + } + } +} From 3d148aea4040615fa8250a2de890b6e318783633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 Nov 2021 13:51:18 +0100 Subject: [PATCH 5/8] Fix `GetDisplayTitle()` implementations relying on `ToString()` themselves --- osu.Game/Beatmaps/BeatmapInfoExtensions.cs | 2 +- osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs index 707b588063..eab66b9857 100644 --- a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps /// /// A user-presentable display title representing this beatmap. /// - public static string GetDisplayTitle(this IBeatmapInfo beatmapInfo) => $"{beatmapInfo.Metadata} {getVersionString(beatmapInfo)}".Trim(); + public static string GetDisplayTitle(this IBeatmapInfo beatmapInfo) => $"{beatmapInfo.Metadata.GetDisplayTitle()} {getVersionString(beatmapInfo)}".Trim(); /// /// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields. diff --git a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs index 27cd7f8d9a..32fb389e9a 100644 --- a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs @@ -27,7 +27,7 @@ namespace osu.Game.Beatmaps /// public static string GetDisplayTitle(this IBeatmapMetadataInfo metadataInfo) { - string author = string.IsNullOrEmpty(metadataInfo.Author.Username) ? string.Empty : $"({metadataInfo.Author})"; + string author = string.IsNullOrEmpty(metadataInfo.Author.Username) ? string.Empty : $"({metadataInfo.Author.Username})"; return $"{metadataInfo.Artist} - {metadataInfo.Title} {author}".Trim(); } From 03a315b9f54595446861e5cd6377efd44f17ffb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 Nov 2021 14:33:06 +0100 Subject: [PATCH 6/8] Fix missing beatmap in replay download test scene Was causing nullrefs in `GetDisplayTitle()`. --- osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index d4036fefc0..f47fae33ca 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -175,7 +175,7 @@ namespace osu.Game.Tests.Visual.Gameplay Id = 39828, Username = @"WubWoofWolf", } - }.CreateScoreInfo(rulesets); + }.CreateScoreInfo(rulesets, CreateBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo); } private class TestReplayDownloadButton : ReplayDownloadButton From f4ef8419729f4c80ccd8b1a666c180b2267a73f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Nov 2021 18:27:23 +0900 Subject: [PATCH 7/8] Add fallback for cases where beatmap has no author/title/artist specified --- osu.Game.Tests/Models/DisplayStringTest.cs | 22 +++++++++++++++++++ .../Beatmaps/BeatmapMetadataInfoExtensions.cs | 8 +++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Models/DisplayStringTest.cs b/osu.Game.Tests/Models/DisplayStringTest.cs index 9a3c32bfb2..754a849ac8 100644 --- a/osu.Game.Tests/Models/DisplayStringTest.cs +++ b/osu.Game.Tests/Models/DisplayStringTest.cs @@ -17,6 +17,8 @@ namespace osu.Game.Tests.Models { private static readonly object[][] test_cases = { + new object[] { makeNoMetadataMockBeatmapSet(), "unknown artist - unknown title" }, + new object[] { makeNoAuthorMockBeatmapSet(), "artist - title" }, new object[] { makeMockBeatmapSet(), "artist - title (author)" }, new object[] { makeMockBeatmap(), "artist - title (author) [difficulty]" }, new object[] { makeMockMetadata(), "artist - title (author)" }, @@ -29,6 +31,26 @@ namespace osu.Game.Tests.Models [TestCaseSource(nameof(test_cases))] public void TestDisplayString(object model, string expected) => Assert.That(model.GetDisplayString(), Is.EqualTo(expected)); + private static IBeatmapSetInfo makeNoAuthorMockBeatmapSet() + { + var mock = new Mock(); + + mock.Setup(m => m.Metadata.Artist).Returns("artist"); + mock.Setup(m => m.Metadata.Title).Returns("title"); + mock.Setup(m => m.Metadata.Author.Username).Returns(string.Empty); + + return mock.Object; + } + + private static IBeatmapSetInfo makeNoMetadataMockBeatmapSet() + { + var mock = new Mock(); + + mock.Setup(m => m.Metadata).Returns(new BeatmapMetadata()); + + return mock.Object; + } + private static IBeatmapSetInfo makeMockBeatmapSet() { var mock = new Mock(); diff --git a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs index 32fb389e9a..7aab6a7a9b 100644 --- a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs @@ -27,8 +27,12 @@ namespace osu.Game.Beatmaps /// public static string GetDisplayTitle(this IBeatmapMetadataInfo metadataInfo) { - string author = string.IsNullOrEmpty(metadataInfo.Author.Username) ? string.Empty : $"({metadataInfo.Author.Username})"; - return $"{metadataInfo.Artist} - {metadataInfo.Title} {author}".Trim(); + string author = string.IsNullOrEmpty(metadataInfo.Author.Username) ? string.Empty : $" ({metadataInfo.Author.Username})"; + + string artist = string.IsNullOrEmpty(metadataInfo.Artist) ? "unknown artist" : metadataInfo.Artist; + string title = string.IsNullOrEmpty(metadataInfo.Title) ? "unknown title" : metadataInfo.Title; + + return $"{artist} - {title}{author}".Trim(); } /// From a52d9363f9a3a7dc8fe6e9b6d9e83a97f20985e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 10 Nov 2021 11:09:09 +0100 Subject: [PATCH 8/8] Rewrite tests to be easier to follow --- osu.Game.Tests/Models/DisplayStringTest.cs | 83 ++++++++++++---------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/osu.Game.Tests/Models/DisplayStringTest.cs b/osu.Game.Tests/Models/DisplayStringTest.cs index 754a849ac8..cac5dd1aaa 100644 --- a/osu.Game.Tests/Models/DisplayStringTest.cs +++ b/osu.Game.Tests/Models/DisplayStringTest.cs @@ -15,23 +15,20 @@ namespace osu.Game.Tests.Models [TestFixture] public class DisplayStringTest { - private static readonly object[][] test_cases = + [Test] + public void TestBeatmapSet() { - new object[] { makeNoMetadataMockBeatmapSet(), "unknown artist - unknown title" }, - new object[] { makeNoAuthorMockBeatmapSet(), "artist - title" }, - new object[] { makeMockBeatmapSet(), "artist - title (author)" }, - new object[] { makeMockBeatmap(), "artist - title (author) [difficulty]" }, - new object[] { makeMockMetadata(), "artist - title (author)" }, - new object[] { makeMockScore(), "user playing artist - title (author) [difficulty]" }, - new object[] { makeMockRuleset(), "ruleset" }, - new object[] { makeMockUser(), "user" }, - new object[] { new Fallback(), "fallback" } - }; + var mock = new Mock(); - [TestCaseSource(nameof(test_cases))] - public void TestDisplayString(object model, string expected) => Assert.That(model.GetDisplayString(), Is.EqualTo(expected)); + mock.Setup(m => m.Metadata.Artist).Returns("artist"); + mock.Setup(m => m.Metadata.Title).Returns("title"); + mock.Setup(m => m.Metadata.Author.Username).Returns("author"); - private static IBeatmapSetInfo makeNoAuthorMockBeatmapSet() + Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("artist - title (author)")); + } + + [Test] + public void TestBeatmapSetWithNoAuthor() { var mock = new Mock(); @@ -39,38 +36,34 @@ namespace osu.Game.Tests.Models mock.Setup(m => m.Metadata.Title).Returns("title"); mock.Setup(m => m.Metadata.Author.Username).Returns(string.Empty); - return mock.Object; + Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("artist - title")); } - private static IBeatmapSetInfo makeNoMetadataMockBeatmapSet() + [Test] + public void TestBeatmapSetWithNoMetadata() { var mock = new Mock(); mock.Setup(m => m.Metadata).Returns(new BeatmapMetadata()); - return mock.Object; + Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("unknown artist - unknown title")); } - private static IBeatmapSetInfo makeMockBeatmapSet() - { - var mock = new Mock(); - - mock.Setup(m => m.Metadata).Returns(makeMockMetadata); - - return mock.Object; - } - - private static IBeatmapInfo makeMockBeatmap() + [Test] + public void TestBeatmap() { var mock = new Mock(); - mock.Setup(m => m.Metadata).Returns(makeMockMetadata); + mock.Setup(m => m.Metadata.Artist).Returns("artist"); + mock.Setup(m => m.Metadata.Title).Returns("title"); + mock.Setup(m => m.Metadata.Author.Username).Returns("author"); mock.Setup(m => m.DifficultyName).Returns("difficulty"); - return mock.Object; + Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("artist - title (author) [difficulty]")); } - private static IBeatmapMetadataInfo makeMockMetadata() + [Test] + public void TestMetadata() { var mock = new Mock(); @@ -78,35 +71,49 @@ namespace osu.Game.Tests.Models mock.Setup(m => m.Title).Returns("title"); mock.Setup(m => m.Author.Username).Returns("author"); - return mock.Object; + Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("artist - title (author)")); } - private static IScoreInfo makeMockScore() + [Test] + public void TestScore() { var mock = new Mock(); mock.Setup(m => m.User).Returns(new APIUser { Username = "user" }); // TODO: temporary. - mock.Setup(m => m.Beatmap).Returns(makeMockBeatmap); + mock.Setup(m => m.Beatmap.Metadata.Artist).Returns("artist"); + mock.Setup(m => m.Beatmap.Metadata.Title).Returns("title"); + mock.Setup(m => m.Beatmap.Metadata.Author.Username).Returns("author"); + mock.Setup(m => m.Beatmap.DifficultyName).Returns("difficulty"); - return mock.Object; + Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("user playing artist - title (author) [difficulty]")); } - private static IRulesetInfo makeMockRuleset() + [Test] + public void TestRuleset() { var mock = new Mock(); mock.Setup(m => m.Name).Returns("ruleset"); - return mock.Object; + Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("ruleset")); } - private static IUser makeMockUser() + [Test] + public void TestUser() { var mock = new Mock(); mock.Setup(m => m.Username).Returns("user"); - return mock.Object; + Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("user")); + } + + [Test] + public void TestFallback() + { + var fallback = new Fallback(); + + Assert.That(fallback.GetDisplayString(), Is.EqualTo("fallback")); } private class Fallback