diff --git a/osu.Game.Tests/Visual/Collections/TestSceneCollectionDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneCollectionDialog.cs deleted file mode 100644 index 5782e627ba..0000000000 --- a/osu.Game.Tests/Visual/Collections/TestSceneCollectionDialog.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Collections; -using osu.Game.Overlays; - -namespace osu.Game.Tests.Visual.Collections -{ - public class TestSceneCollectionDialog : OsuTestScene - { - [Cached] - private DialogOverlay dialogOverlay; - - public TestSceneCollectionDialog() - { - Children = new Drawable[] - { - new ManageCollectionsDialog { State = { Value = Visibility.Visible } }, - dialogOverlay = new DialogOverlay() - }; - } - } -} diff --git a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs new file mode 100644 index 0000000000..2d6f8abd8b --- /dev/null +++ b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs @@ -0,0 +1,198 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Testing; +using osu.Game.Collections; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; +using osu.Game.Overlays.Dialog; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Collections +{ + public class TestSceneManageCollectionsDialog : OsuManualInputManagerTestScene + { + [Cached] + private readonly DialogOverlay dialogOverlay; + + protected override Container Content => content; + + private readonly Container content; + + private BeatmapCollectionManager manager; + private ManageCollectionsDialog dialog; + + public TestSceneManageCollectionsDialog() + { + base.Content.AddRange(new Drawable[] + { + content = new Container { RelativeSizeAxes = Axes.Both }, + dialogOverlay = new DialogOverlay() + }); + } + + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(manager = new BeatmapCollectionManager(LocalStorage)); + Add(manager); + } + + [SetUp] + public void SetUp() => Schedule(() => + { + manager.Collections.Clear(); + Child = dialog = new ManageCollectionsDialog(); + }); + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("show dialog", () => dialog.Show()); + } + + [Test] + public void TestHideDialog() + { + AddWaitStep("wait for animation", 3); + AddStep("hide dialog", () => dialog.Hide()); + } + + [Test] + public void TestAddCollectionExternal() + { + AddStep("add collection", () => manager.Collections.Add(new BeatmapCollection { Name = { Value = "First collection" } })); + assertCollectionCount(1); + assertCollectionName(0, "First collection"); + + AddStep("add another collection", () => manager.Collections.Add(new BeatmapCollection { Name = { Value = "Second collection" } })); + assertCollectionCount(2); + assertCollectionName(1, "Second collection"); + } + + [Test] + public void TestAddCollectionViaButton() + { + AddStep("press new collection button", () => + { + InputManager.MoveMouseTo(dialog.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + assertCollectionCount(1); + + AddStep("press again", () => + { + InputManager.MoveMouseTo(dialog.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + assertCollectionCount(2); + } + + [Test] + public void TestRemoveCollectionExternal() + { + AddStep("add two collections", () => manager.Collections.AddRange(new[] + { + new BeatmapCollection { Name = { Value = "1" } }, + new BeatmapCollection { Name = { Value = "2" } }, + })); + + AddStep("remove first collection", () => manager.Collections.RemoveAt(0)); + assertCollectionCount(1); + assertCollectionName(0, "2"); + } + + [Test] + public void TestRemoveCollectionViaButton() + { + AddStep("add two collections", () => manager.Collections.AddRange(new[] + { + new BeatmapCollection { Name = { Value = "1" } }, + new BeatmapCollection { Name = { Value = "2" } }, + })); + + AddStep("click first delete button", () => + { + InputManager.MoveMouseTo(dialog.ChildrenOfType().First(), new Vector2(5, 0)); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is DeleteCollectionDialog); + AddStep("click confirmation", () => + { + InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + + assertCollectionCount(1); + assertCollectionName(0, "2"); + } + + [Test] + public void TestCollectionNotRemovedWhenDialogCancelled() + { + AddStep("add two collections", () => manager.Collections.AddRange(new[] + { + new BeatmapCollection { Name = { Value = "1" } }, + new BeatmapCollection { Name = { Value = "2" } }, + })); + + AddStep("click first delete button", () => + { + InputManager.MoveMouseTo(dialog.ChildrenOfType().First(), new Vector2(5, 0)); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is DeleteCollectionDialog); + AddStep("click confirmation", () => + { + InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().Last()); + InputManager.Click(MouseButton.Left); + }); + + assertCollectionCount(2); + } + + [Test] + public void TestCollectionRenamedExternal() + { + AddStep("add two collections", () => manager.Collections.AddRange(new[] + { + new BeatmapCollection { Name = { Value = "1" } }, + new BeatmapCollection { Name = { Value = "2" } }, + })); + + AddStep("change first collection name", () => manager.Collections[0].Name.Value = "First"); + + assertCollectionName(0, "First"); + } + + [Test] + public void TestCollectionRenamedOnTextChange() + { + AddStep("add two collections", () => manager.Collections.AddRange(new[] + { + new BeatmapCollection { Name = { Value = "1" } }, + new BeatmapCollection { Name = { Value = "2" } }, + })); + + AddStep("change first collection name", () => dialog.ChildrenOfType().First().Text = "First"); + AddAssert("collection has new name", () => manager.Collections[0].Name.Value == "First"); + } + + private void assertCollectionCount(int count) + => AddAssert($"{count} collections shown", () => dialog.ChildrenOfType().Count() == count); + + private void assertCollectionName(int index, string name) + => AddAssert($"item {index + 1} has correct name", () => dialog.ChildrenOfType().ElementAt(index).ChildrenOfType().First().Text == name); + } +} diff --git a/osu.Game/Collections/BeatmapCollectionManager.cs b/osu.Game/Collections/BeatmapCollectionManager.cs index 3d3e9e0e07..a553ac632e 100644 --- a/osu.Game/Collections/BeatmapCollectionManager.cs +++ b/osu.Game/Collections/BeatmapCollectionManager.cs @@ -37,12 +37,19 @@ namespace osu.Game.Collections [Resolved] private BeatmapManager beatmaps { get; set; } + private readonly Storage storage; + + public BeatmapCollectionManager(Storage storage) + { + this.storage = storage; + } + [BackgroundDependencyLoader] private void load() { - if (host.Storage.Exists(database_name)) + if (storage.Exists(database_name)) { - using (var stream = host.Storage.GetStream(database_name)) + using (var stream = storage.GetStream(database_name)) importCollections(readCollections(stream)); } @@ -78,11 +85,9 @@ namespace osu.Game.Collections return Task.Run(async () => { - var storage = GetStableStorage(); - - if (storage.Exists(database_name)) + if (stable.Exists(database_name)) { - using (var stream = storage.GetStream(database_name)) + using (var stream = stable.GetStream(database_name)) await Import(stream); } }); @@ -188,7 +193,7 @@ namespace osu.Game.Collections { // This is NOT thread-safe!! - using (var sw = new SerializationWriter(host.Storage.GetStream(database_name, FileAccess.Write))) + using (var sw = new SerializationWriter(storage.GetStream(database_name, FileAccess.Write))) { sw.Write(database_version); sw.Write(Collections.Count); diff --git a/osu.Game/Collections/DrawableCollectionListItem.cs b/osu.Game/Collections/DrawableCollectionListItem.cs index 7c1a2e1287..c7abf58d10 100644 --- a/osu.Game/Collections/DrawableCollectionListItem.cs +++ b/osu.Game/Collections/DrawableCollectionListItem.cs @@ -87,7 +87,7 @@ namespace osu.Game.Collections } } - private class DeleteButton : CompositeDrawable + public class DeleteButton : CompositeDrawable { public Func IsTextBoxHovered; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 30494d18fb..3114727d54 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -228,7 +228,7 @@ namespace osu.Game dependencies.Cache(difficultyManager); AddInternal(difficultyManager); - dependencies.Cache(CollectionManager = new BeatmapCollectionManager()); + dependencies.Cache(CollectionManager = new BeatmapCollectionManager(Storage)); AddInternal(CollectionManager); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));