mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 15:16:38 +09:00
Merge branch 'master' into NowPlaying
This commit is contained in:
@ -35,6 +35,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private OsuConfigManager localConfig;
|
||||
|
||||
private bool returnCursorOnResponse;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -61,6 +63,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
searchBeatmapSetsRequest.TriggerSuccess(new SearchBeatmapSetsResponse
|
||||
{
|
||||
BeatmapSets = setsForResponse,
|
||||
Cursor = returnCursorOnResponse ? new Cursor() : null,
|
||||
});
|
||||
|
||||
return true;
|
||||
@ -106,7 +109,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
AddAssert("is visible", () => overlay.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 100).ToArray()));
|
||||
AddStep("show many results", () => fetchFor(getManyBeatmaps(100).ToArray()));
|
||||
|
||||
AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().Any(d => d.IsPresent));
|
||||
|
||||
@ -127,10 +130,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
AddAssert("is visible", () => overlay.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 100).ToArray()));
|
||||
AddStep("show many results", () => fetchFor(getManyBeatmaps(100).ToArray()));
|
||||
assertAllCardsOfType<BeatmapCardNormal>(100);
|
||||
|
||||
AddStep("show more results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 30).ToArray()));
|
||||
AddStep("show more results", () => fetchFor(getManyBeatmaps(30).ToArray()));
|
||||
assertAllCardsOfType<BeatmapCardNormal>(30);
|
||||
}
|
||||
|
||||
@ -139,7 +142,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
AddAssert("is visible", () => overlay.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 100).ToArray()));
|
||||
AddStep("show many results", () => fetchFor(getManyBeatmaps(100).ToArray()));
|
||||
assertAllCardsOfType<BeatmapCardNormal>(100);
|
||||
|
||||
setCardSize(BeatmapCardSize.Extra, viaConfig);
|
||||
@ -161,7 +164,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||
placeholderShown();
|
||||
|
||||
AddStep("show many results", () => fetchFor(Enumerable.Repeat(CreateAPIBeatmapSet(Ruleset.Value), 100).ToArray()));
|
||||
AddStep("show many results", () => fetchFor(getManyBeatmaps(100).ToArray()));
|
||||
AddUntilStep("wait for loaded", () => this.ChildrenOfType<BeatmapCard>().Count() == 100);
|
||||
AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().Any(d => d.IsPresent));
|
||||
|
||||
@ -180,6 +183,32 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// During pagination, the first beatmap of the second page may be a duplicate of the last beatmap from the previous page.
|
||||
/// This is currently the case with osu!web API due to ES relevance score's presence in the response cursor.
|
||||
/// See: https://github.com/ppy/osu-web/issues/9270
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDuplicatedBeatmapOnlyShowsOnce()
|
||||
{
|
||||
APIBeatmapSet beatmapSet = null;
|
||||
|
||||
AddStep("show many results", () =>
|
||||
{
|
||||
beatmapSet = CreateAPIBeatmapSet(Ruleset.Value);
|
||||
beatmapSet.Title = "last beatmap of first page";
|
||||
|
||||
fetchFor(getManyBeatmaps(49).Append(new APIBeatmapSet { Title = "last beatmap of first page", OnlineID = beatmapSet.OnlineID }).ToArray(), true);
|
||||
});
|
||||
AddUntilStep("wait for loaded", () => this.ChildrenOfType<BeatmapCard>().Count() == 50);
|
||||
|
||||
AddStep("set next page", () => setSearchResponse(getManyBeatmaps(49).Prepend(new APIBeatmapSet { Title = "this shouldn't show up", OnlineID = beatmapSet.OnlineID }).ToArray(), false));
|
||||
AddStep("scroll to end", () => overlay.ChildrenOfType<OverlayScrollContainer>().Single().ScrollToEnd());
|
||||
AddUntilStep("wait for loaded", () => this.ChildrenOfType<BeatmapCard>().Count() >= 99);
|
||||
|
||||
AddAssert("beatmap not duplicated", () => overlay.ChildrenOfType<BeatmapCard>().Count(c => c.BeatmapSet.Equals(beatmapSet)) == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserWithoutSupporterUsesSupporterOnlyFiltersWithoutResults()
|
||||
{
|
||||
@ -336,15 +365,25 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private static int searchCount;
|
||||
|
||||
private void fetchFor(params APIBeatmapSet[] beatmaps)
|
||||
private APIBeatmapSet[] getManyBeatmaps(int count) => Enumerable.Range(0, count).Select(_ => CreateAPIBeatmapSet(Ruleset.Value)).ToArray();
|
||||
|
||||
private void fetchFor(params APIBeatmapSet[] beatmaps) => fetchFor(beatmaps, false);
|
||||
|
||||
private void fetchFor(APIBeatmapSet[] beatmaps, bool hasNextPage)
|
||||
{
|
||||
setsForResponse.Clear();
|
||||
setsForResponse.AddRange(beatmaps);
|
||||
setSearchResponse(beatmaps, hasNextPage);
|
||||
|
||||
// trigger arbitrary change for fetching.
|
||||
searchControl.Query.Value = $"search {searchCount++}";
|
||||
}
|
||||
|
||||
private void setSearchResponse(APIBeatmapSet[] beatmaps, bool hasNextPage)
|
||||
{
|
||||
setsForResponse.Clear();
|
||||
setsForResponse.AddRange(beatmaps);
|
||||
returnCursorOnResponse = hasNextPage;
|
||||
}
|
||||
|
||||
private void setRankAchievedFilter(ScoreRank[] ranks)
|
||||
{
|
||||
AddStep($"set Rank Achieved filter to [{string.Join(',', ranks)}]", () =>
|
||||
|
@ -46,6 +46,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
availableChannels.Add(new Channel { Name = "#english" });
|
||||
availableChannels.Add(new Channel { Name = "#japanese" });
|
||||
Dependencies.Cache(chatManager);
|
||||
|
||||
Add(chatManager);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
|
@ -40,8 +40,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private ChannelManager channelManager;
|
||||
|
||||
private readonly APIUser testUser = new APIUser { Username = "test user", Id = 5071479 };
|
||||
private readonly APIUser testUser1 = new APIUser { Username = "test user", Id = 5071480 };
|
||||
|
||||
private Channel[] testChannels;
|
||||
private Message[] initialMessages;
|
||||
|
||||
private Channel testChannel1 => testChannels[0];
|
||||
private Channel testChannel2 => testChannels[1];
|
||||
@ -49,10 +51,14 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Resolved]
|
||||
private OsuConfigManager config { get; set; } = null!;
|
||||
|
||||
private int currentMessageId;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
currentMessageId = 0;
|
||||
testChannels = Enumerable.Range(1, 10).Select(createPublicChannel).ToArray();
|
||||
initialMessages = testChannels.SelectMany(createChannelMessages).ToArray();
|
||||
|
||||
Child = new DependencyProvidingContainer
|
||||
{
|
||||
@ -99,7 +105,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
return true;
|
||||
|
||||
case GetMessagesRequest getMessages:
|
||||
getMessages.TriggerSuccess(createChannelMessages(getMessages.Channel));
|
||||
getMessages.TriggerSuccess(initialMessages.ToList());
|
||||
return true;
|
||||
|
||||
case GetUserRequest getUser:
|
||||
@ -495,6 +501,35 @@ namespace osu.Game.Tests.Visual.Online
|
||||
waitForChannel1Visible();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRemoveMessages()
|
||||
{
|
||||
AddStep("Show overlay with channel", () =>
|
||||
{
|
||||
chatOverlay.Show();
|
||||
channelManager.CurrentChannel.Value = channelManager.JoinChannel(testChannel1);
|
||||
});
|
||||
|
||||
AddAssert("Overlay is visible", () => chatOverlay.State.Value == Visibility.Visible);
|
||||
waitForChannel1Visible();
|
||||
|
||||
AddStep("Send message from another user", () =>
|
||||
{
|
||||
testChannel1.AddNewMessages(new Message
|
||||
{
|
||||
ChannelId = testChannel1.Id,
|
||||
Content = "Message from another user",
|
||||
Timestamp = DateTimeOffset.Now,
|
||||
Sender = testUser1,
|
||||
});
|
||||
});
|
||||
|
||||
AddStep("Remove messages from other user", () =>
|
||||
{
|
||||
testChannel1.RemoveMessagesFromUser(testUser.Id);
|
||||
});
|
||||
}
|
||||
|
||||
private void joinTestChannel(int i)
|
||||
{
|
||||
AddStep($"Join test channel {i}", () => channelManager.JoinChannel(testChannels[i]));
|
||||
@ -546,7 +581,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
private List<Message> createChannelMessages(Channel channel)
|
||||
{
|
||||
var message = new Message
|
||||
var message = new Message(currentMessageId++)
|
||||
{
|
||||
ChannelId = channel.Id,
|
||||
Content = $"Hello, this is a message in {channel.Name}",
|
||||
|
331
osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs
Normal file
331
osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs
Normal file
@ -0,0 +1,331 @@
|
||||
// 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.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Comments;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneCommentActions : OsuManualInputManagerTestScene
|
||||
{
|
||||
private Container<Drawable> content = null!;
|
||||
protected override Container<Drawable> Content => content;
|
||||
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
|
||||
|
||||
[Cached(typeof(IDialogOverlay))]
|
||||
private readonly DialogOverlay dialogOverlay = new DialogOverlay();
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
private CommentsContainer commentsContainer = null!;
|
||||
|
||||
private readonly ManualResetEventSlim requestLock = new ManualResetEventSlim();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
base.Content.AddRange(new Drawable[]
|
||||
{
|
||||
new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = content = new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
},
|
||||
dialogOverlay
|
||||
});
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUp()
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
API.Login("test", "test");
|
||||
Child = commentsContainer = new CommentsContainer();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNonOwnCommentCantBeDeleted()
|
||||
{
|
||||
addTestComments();
|
||||
|
||||
AddUntilStep("First comment has button", () =>
|
||||
{
|
||||
var comments = this.ChildrenOfType<DrawableComment>();
|
||||
var ourComment = comments.SingleOrDefault(x => x.Comment.Id == 1);
|
||||
return ourComment != null && ourComment.ChildrenOfType<OsuSpriteText>().Any(x => x.Text == "Delete");
|
||||
});
|
||||
|
||||
AddAssert("Second doesn't", () =>
|
||||
{
|
||||
var comments = this.ChildrenOfType<DrawableComment>();
|
||||
var ourComment = comments.Single(x => x.Comment.Id == 2);
|
||||
return ourComment.ChildrenOfType<OsuSpriteText>().All(x => x.Text != "Delete");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeletion()
|
||||
{
|
||||
DrawableComment? ourComment = null;
|
||||
|
||||
addTestComments();
|
||||
AddUntilStep("Comment exists", () =>
|
||||
{
|
||||
var comments = this.ChildrenOfType<DrawableComment>();
|
||||
ourComment = comments.SingleOrDefault(x => x.Comment.Id == 1);
|
||||
return ourComment != null;
|
||||
});
|
||||
AddStep("It has delete button", () =>
|
||||
{
|
||||
var btn = ourComment.ChildrenOfType<OsuSpriteText>().Single(x => x.Text == "Delete");
|
||||
InputManager.MoveMouseTo(btn);
|
||||
});
|
||||
AddStep("Click delete button", () =>
|
||||
{
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddStep("Setup request handling", () =>
|
||||
{
|
||||
requestLock.Reset();
|
||||
|
||||
dummyAPI.HandleRequest = request =>
|
||||
{
|
||||
if (!(request is CommentDeleteRequest req))
|
||||
return false;
|
||||
|
||||
if (req.CommentId != 1)
|
||||
return false;
|
||||
|
||||
CommentBundle cb = new CommentBundle
|
||||
{
|
||||
Comments = new List<Comment>
|
||||
{
|
||||
new Comment
|
||||
{
|
||||
Id = 2,
|
||||
Message = "This is a comment by another user",
|
||||
UserId = API.LocalUser.Value.Id + 1,
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
User = new APIUser
|
||||
{
|
||||
Id = API.LocalUser.Value.Id + 1,
|
||||
Username = "Another user"
|
||||
}
|
||||
},
|
||||
},
|
||||
IncludedComments = new List<Comment>(),
|
||||
PinnedComments = new List<Comment>(),
|
||||
};
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
requestLock.Wait(10000);
|
||||
req.TriggerSuccess(cb);
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
});
|
||||
AddStep("Confirm dialog", () => InputManager.Key(Key.Number1));
|
||||
|
||||
AddAssert("Loading spinner shown", () => commentsContainer.ChildrenOfType<LoadingSpinner>().Any(d => d.IsPresent));
|
||||
|
||||
AddStep("Complete request", () => requestLock.Set());
|
||||
|
||||
AddUntilStep("Comment is deleted locally", () => this.ChildrenOfType<DrawableComment>().Single(x => x.Comment.Id == 1).WasDeleted);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeletionFail()
|
||||
{
|
||||
DrawableComment? ourComment = null;
|
||||
bool delete = false;
|
||||
|
||||
addTestComments();
|
||||
AddUntilStep("Comment exists", () =>
|
||||
{
|
||||
var comments = this.ChildrenOfType<DrawableComment>();
|
||||
ourComment = comments.SingleOrDefault(x => x.Comment.Id == 1);
|
||||
return ourComment != null;
|
||||
});
|
||||
AddStep("It has delete button", () =>
|
||||
{
|
||||
var btn = ourComment.ChildrenOfType<OsuSpriteText>().Single(x => x.Text == "Delete");
|
||||
InputManager.MoveMouseTo(btn);
|
||||
});
|
||||
AddStep("Click delete button", () =>
|
||||
{
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddStep("Setup request handling", () =>
|
||||
{
|
||||
dummyAPI.HandleRequest = request =>
|
||||
{
|
||||
if (request is not CommentDeleteRequest req)
|
||||
return false;
|
||||
|
||||
req.TriggerFailure(new Exception());
|
||||
delete = true;
|
||||
return false;
|
||||
};
|
||||
});
|
||||
AddStep("Confirm dialog", () => InputManager.Key(Key.Number1));
|
||||
AddUntilStep("Deletion requested", () => delete);
|
||||
AddUntilStep("Comment is available", () =>
|
||||
{
|
||||
return !this.ChildrenOfType<DrawableComment>().Single(x => x.Comment.Id == 1).WasDeleted;
|
||||
});
|
||||
AddAssert("Loading spinner hidden", () =>
|
||||
{
|
||||
return ourComment.ChildrenOfType<LoadingSpinner>().All(d => !d.IsPresent);
|
||||
});
|
||||
AddAssert("Actions available", () =>
|
||||
{
|
||||
return ourComment.ChildrenOfType<LinkFlowContainer>().Single(x => x.Name == @"Actions buttons").IsPresent;
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestReport()
|
||||
{
|
||||
const string report_text = "I don't like this comment";
|
||||
DrawableComment? targetComment = null;
|
||||
CommentReportRequest? request = null;
|
||||
|
||||
addTestComments();
|
||||
AddUntilStep("Comment exists", () =>
|
||||
{
|
||||
var comments = this.ChildrenOfType<DrawableComment>();
|
||||
targetComment = comments.SingleOrDefault(x => x.Comment.Id == 2);
|
||||
return targetComment != null;
|
||||
});
|
||||
AddStep("Setup request handling", () =>
|
||||
{
|
||||
requestLock.Reset();
|
||||
|
||||
dummyAPI.HandleRequest = r =>
|
||||
{
|
||||
if (!(r is CommentReportRequest req))
|
||||
return false;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
request = req;
|
||||
requestLock.Wait(10000);
|
||||
req.TriggerSuccess();
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
});
|
||||
AddStep("Click the button", () =>
|
||||
{
|
||||
var btn = targetComment.ChildrenOfType<OsuSpriteText>().Single(x => x.Text == "Report");
|
||||
InputManager.MoveMouseTo(btn);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddStep("Try to report", () =>
|
||||
{
|
||||
var btn = this.ChildrenOfType<ReportCommentPopover>().Single().ChildrenOfType<RoundedButton>().Single();
|
||||
InputManager.MoveMouseTo(btn);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddWaitStep("Wait", 3);
|
||||
AddAssert("Nothing happened", () => this.ChildrenOfType<ReportCommentPopover>().Any());
|
||||
AddStep("Set report data", () =>
|
||||
{
|
||||
var field = this.ChildrenOfType<OsuTextBox>().Single();
|
||||
field.Current.Value = report_text;
|
||||
var reason = this.ChildrenOfType<OsuEnumDropdown<CommentReportReason>>().Single();
|
||||
reason.Current.Value = CommentReportReason.Other;
|
||||
});
|
||||
AddStep("Try to report", () =>
|
||||
{
|
||||
var btn = this.ChildrenOfType<ReportCommentPopover>().Single().ChildrenOfType<RoundedButton>().Single();
|
||||
InputManager.MoveMouseTo(btn);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddWaitStep("Wait", 3);
|
||||
AddAssert("Overlay closed", () => !this.ChildrenOfType<ReportCommentPopover>().Any());
|
||||
AddAssert("Loading spinner shown", () => targetComment.ChildrenOfType<LoadingSpinner>().Any(d => d.IsPresent));
|
||||
AddStep("Complete request", () => requestLock.Set());
|
||||
AddUntilStep("Request sent", () => request != null);
|
||||
AddAssert("Request is correct", () => request != null && request.CommentID == 2 && request.Comment == report_text && request.Reason == CommentReportReason.Other);
|
||||
}
|
||||
|
||||
private void addTestComments()
|
||||
{
|
||||
AddStep("set up response", () =>
|
||||
{
|
||||
CommentBundle cb = new CommentBundle
|
||||
{
|
||||
Comments = new List<Comment>
|
||||
{
|
||||
new Comment
|
||||
{
|
||||
Id = 1,
|
||||
Message = "This is our comment",
|
||||
UserId = API.LocalUser.Value.Id,
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
User = API.LocalUser.Value,
|
||||
},
|
||||
new Comment
|
||||
{
|
||||
Id = 2,
|
||||
Message = "This is a comment by another user",
|
||||
UserId = API.LocalUser.Value.Id + 1,
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
User = new APIUser
|
||||
{
|
||||
Id = API.LocalUser.Value.Id + 1,
|
||||
Username = "Another user"
|
||||
}
|
||||
},
|
||||
},
|
||||
IncludedComments = new List<Comment>(),
|
||||
PinnedComments = new List<Comment>(),
|
||||
};
|
||||
setUpCommentsResponse(cb);
|
||||
});
|
||||
|
||||
AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123));
|
||||
}
|
||||
|
||||
private void setUpCommentsResponse(CommentBundle commentBundle)
|
||||
{
|
||||
dummyAPI.HandleRequest = request =>
|
||||
{
|
||||
if (!(request is GetCommentsRequest getCommentsRequest))
|
||||
return false;
|
||||
|
||||
getCommentsRequest.TriggerSuccess(commentBundle);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
46
osu.Game.Tests/Visual/Online/TestSceneCommentReportButton.cs
Normal file
46
osu.Game.Tests/Visual/Online/TestSceneCommentReportButton.cs
Normal file
@ -0,0 +1,46 @@
|
||||
// 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.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
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.Overlays.Comments;
|
||||
using osu.Game.Tests.Visual.UserInterface;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneCommentReportButton : ThemeComparisonTestScene
|
||||
{
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("setup API", () => ((DummyAPIAccess)API).HandleRequest += req =>
|
||||
{
|
||||
switch (req)
|
||||
{
|
||||
case CommentReportRequest report:
|
||||
Scheduler.AddDelayed(report.TriggerSuccess, 1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
protected override Drawable CreateContent() => new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new CommentReportButton(new Comment { User = new APIUser { Username = "Someone" } })
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Scale = new Vector2(2f),
|
||||
}.With(b => Schedule(b.ShowPopover)),
|
||||
};
|
||||
}
|
||||
}
|
87
osu.Game.Tests/Visual/Online/TestSceneDrawableChannel.cs
Normal file
87
osu.Game.Tests/Visual/Online/TestSceneDrawableChannel.cs
Normal file
@ -0,0 +1,87 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Overlays.Chat;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneDrawableChannel : OsuTestScene
|
||||
{
|
||||
private Channel channel = null!;
|
||||
private DrawableChannel drawableChannel = null!;
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("create channel", () => channel = new Channel
|
||||
{
|
||||
Id = 1,
|
||||
Name = "Test channel"
|
||||
});
|
||||
AddStep("create drawable channel", () => Child = drawableChannel = new DrawableChannel(channel)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDaySeparators()
|
||||
{
|
||||
var localUser = new APIUser
|
||||
{
|
||||
Id = 3,
|
||||
Username = "LocalUser"
|
||||
};
|
||||
string uuid = Guid.NewGuid().ToString();
|
||||
AddStep("add local echo message", () => channel.AddLocalEcho(new LocalEchoMessage
|
||||
{
|
||||
Sender = localUser,
|
||||
Content = "Hi there all!",
|
||||
Timestamp = new DateTimeOffset(2022, 11, 21, 20, 11, 13, TimeSpan.Zero),
|
||||
Uuid = uuid
|
||||
}));
|
||||
AddUntilStep("one day separator present", () => drawableChannel.ChildrenOfType<DaySeparator>().Count() == 1);
|
||||
|
||||
AddStep("add two prior messages to channel", () => channel.AddNewMessages(
|
||||
new Message(1)
|
||||
{
|
||||
Sender = new APIUser
|
||||
{
|
||||
Id = 1,
|
||||
Username = "TestUser"
|
||||
},
|
||||
Content = "This is a message",
|
||||
Timestamp = new DateTimeOffset(2021, 10, 10, 13, 33, 23, TimeSpan.Zero),
|
||||
},
|
||||
new Message(2)
|
||||
{
|
||||
Sender = new APIUser
|
||||
{
|
||||
Id = 2,
|
||||
Username = "TestUser2"
|
||||
},
|
||||
Content = "This is another message",
|
||||
Timestamp = new DateTimeOffset(2021, 10, 11, 13, 33, 23, TimeSpan.Zero)
|
||||
}));
|
||||
AddUntilStep("three day separators present", () => drawableChannel.ChildrenOfType<DaySeparator>().Count() == 3);
|
||||
|
||||
AddStep("resolve pending message", () => channel.ReplaceMessage(channel.Messages.OfType<LocalEchoMessage>().Single(), new Message(3)
|
||||
{
|
||||
Sender = localUser,
|
||||
Content = "Hi there all!",
|
||||
Timestamp = new DateTimeOffset(2022, 11, 22, 20, 11, 16, TimeSpan.Zero),
|
||||
Uuid = uuid
|
||||
}));
|
||||
AddUntilStep("three day separators present", () => drawableChannel.ChildrenOfType<DaySeparator>().Count() == 3);
|
||||
AddAssert("last day separator is from correct day", () => drawableChannel.ChildrenOfType<DaySeparator>().Last().Date.Date == new DateTime(2022, 11, 22));
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
@ -32,6 +33,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddStep("values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Select(i => (float)i));
|
||||
AddStep("values from 1-100", () => graph.Values = Enumerable.Range(1, 100).Select(i => (float)i));
|
||||
AddStep("reversed values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Reverse().Select(i => (float)i));
|
||||
AddStep("empty values", () => graph.Values = Array.Empty<float>());
|
||||
AddStep("Bottom to top", () => graph.Direction = BarDirection.BottomToTop);
|
||||
AddStep("Top to bottom", () => graph.Direction = BarDirection.TopToBottom);
|
||||
AddStep("Left to right", () => graph.Direction = BarDirection.LeftToRight);
|
||||
|
@ -1,14 +1,15 @@
|
||||
// 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.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Profile.Header.Components;
|
||||
@ -23,33 +24,14 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
|
||||
|
||||
public TestSceneRankGraph()
|
||||
private RankGraph graph = null!;
|
||||
|
||||
private const int history_length = 89;
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
RankGraph graph;
|
||||
|
||||
int[] data = new int[89];
|
||||
int[] dataWithZeros = new int[89];
|
||||
int[] smallData = new int[89];
|
||||
int[] edgyData = new int[89];
|
||||
|
||||
for (int i = 0; i < 89; i++)
|
||||
data[i] = dataWithZeros[i] = (i + 1) * 1000;
|
||||
|
||||
for (int i = 20; i < 60; i++)
|
||||
dataWithZeros[i] = 0;
|
||||
|
||||
for (int i = 79; i < 89; i++)
|
||||
smallData[i] = 100000 - i * 1000;
|
||||
|
||||
bool edge = true;
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
edgyData[i] = 100000 + (edge ? 1000 : -1000) * (i + 1);
|
||||
edge = !edge;
|
||||
}
|
||||
|
||||
Add(new Container
|
||||
AddStep("create graph", () => Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -67,34 +49,70 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNullUser()
|
||||
{
|
||||
AddStep("null user", () => graph.Statistics.Value = null);
|
||||
AddAssert("line graph hidden", () => this.ChildrenOfType<LineGraph>().All(graph => graph.Alpha == 0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRankOnly()
|
||||
{
|
||||
AddStep("rank only", () =>
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
IsRanked = true,
|
||||
GlobalRank = 123456,
|
||||
PP = 12345,
|
||||
};
|
||||
});
|
||||
AddAssert("line graph hidden", () => this.ChildrenOfType<LineGraph>().All(graph => graph.Alpha == 0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestWithRankHistory()
|
||||
{
|
||||
int[] data = new int[history_length];
|
||||
|
||||
for (int i = 0; i < history_length; i++)
|
||||
data[i] = (i + 1) * 1000;
|
||||
|
||||
AddStep("with rank history", () =>
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
IsRanked = true,
|
||||
GlobalRank = 89000,
|
||||
PP = 12345,
|
||||
RankHistory = new APIRankHistory
|
||||
{
|
||||
Data = data,
|
||||
Data = data
|
||||
}
|
||||
};
|
||||
});
|
||||
AddAssert("line graph shown", () => this.ChildrenOfType<LineGraph>().All(graph => graph.Alpha == 1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRanksWithZeroValues()
|
||||
{
|
||||
int[] dataWithZeros = new int[history_length];
|
||||
|
||||
for (int i = 0; i < history_length; i++)
|
||||
{
|
||||
if (i < 20 || i >= 60)
|
||||
dataWithZeros[i] = (i + 1) * 1000;
|
||||
}
|
||||
|
||||
AddStep("with zero values", () =>
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
IsRanked = true,
|
||||
GlobalRank = 89000,
|
||||
PP = 12345,
|
||||
RankHistory = new APIRankHistory
|
||||
@ -103,11 +121,22 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
};
|
||||
});
|
||||
AddAssert("line graph shown", () => this.ChildrenOfType<LineGraph>().All(graph => graph.Alpha == 1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSmallAmountOfData()
|
||||
{
|
||||
int[] smallData = new int[history_length];
|
||||
|
||||
for (int i = history_length - 10; i < history_length; i++)
|
||||
smallData[i] = 100000 - i * 1000;
|
||||
|
||||
AddStep("small amount of data", () =>
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
IsRanked = true,
|
||||
GlobalRank = 12000,
|
||||
PP = 12345,
|
||||
RankHistory = new APIRankHistory
|
||||
@ -116,11 +145,27 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
};
|
||||
});
|
||||
AddAssert("line graph shown", () => this.ChildrenOfType<LineGraph>().All(graph => graph.Alpha == 1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHistoryWithEdges()
|
||||
{
|
||||
int[] edgyData = new int[89];
|
||||
|
||||
bool edge = true;
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
edgyData[i] = 100000 + (edge ? 1000 : -1000) * (i + 1);
|
||||
edge = !edge;
|
||||
}
|
||||
|
||||
AddStep("graph with edges", () =>
|
||||
{
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
IsRanked = true,
|
||||
GlobalRank = 12000,
|
||||
PP = 12345,
|
||||
RankHistory = new APIRankHistory
|
||||
@ -129,6 +174,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
};
|
||||
});
|
||||
AddAssert("line graph shown", () => this.ChildrenOfType<LineGraph>().All(graph => graph.Alpha == 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
}
|
||||
|
||||
private int onlineID = 1;
|
||||
private ulong onlineID = 1;
|
||||
|
||||
private APIScoresCollection createScores()
|
||||
{
|
||||
|
@ -56,7 +56,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
Add(channelManager = new ChannelManager(parent.Get<IAPIProvider>()));
|
||||
var api = parent.Get<IAPIProvider>();
|
||||
|
||||
Add(channelManager = new ChannelManager(api));
|
||||
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
|
||||
|
@ -52,8 +52,15 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
AwardedAt = DateTimeOffset.FromUnixTimeSeconds(1505741569),
|
||||
Description = "Outstanding help by being a voluntary test subject.",
|
||||
ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg"
|
||||
}
|
||||
ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg",
|
||||
Url = "https://osu.ppy.sh/wiki/en/People/Community_Contributors",
|
||||
},
|
||||
new Badge
|
||||
{
|
||||
AwardedAt = DateTimeOffset.FromUnixTimeSeconds(1505741569),
|
||||
Description = "Badge without a url.",
|
||||
ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg",
|
||||
},
|
||||
},
|
||||
Title = "osu!volunteer",
|
||||
Colour = "ff0000",
|
||||
|
@ -189,6 +189,16 @@ Line after image";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFlag()
|
||||
{
|
||||
AddStep("Add flag", () =>
|
||||
{
|
||||
markdownContainer.CurrentPath = @"https://dev.ppy.sh";
|
||||
markdownContainer.Text = "::{flag=\"AU\"}:: ::{flag=\"ZZ\"}::";
|
||||
});
|
||||
}
|
||||
|
||||
private class TestMarkdownContainer : WikiMarkdownContainer
|
||||
{
|
||||
public LinkInline Link;
|
||||
|
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user