osukey/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
Dean Herbert b0d14526ea Move test ScoreInfo creation to TestResources
The main goal here is to remove the inheritance, since realm doesn't
like that. Unfortunate that we can't use object initialisers in a few of
these places, but no real way around that.
2021-12-13 16:34:50 +09:00

385 lines
14 KiB
C#

// 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.Net;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Screens.Ranking;
using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Visual.Playlists
{
public class TestScenePlaylistsResultsScreen : ScreenTestScene
{
private const int scores_per_result = 10;
private const int real_user_position = 200;
private TestResultsScreen resultsScreen;
private int currentScoreId;
private bool requestComplete;
private int totalCount;
[SetUp]
public void Setup() => Schedule(() =>
{
currentScoreId = 1;
requestComplete = false;
totalCount = 0;
bindHandler();
});
[Test]
public void TestShowWithUserScore()
{
ScoreInfo userScore = null;
AddStep("bind user score info handler", () =>
{
userScore = TestResources.CreateTestScoreInfo(new OsuRuleset().RulesetInfo);
userScore.OnlineID = currentScoreId++;
bindHandler(userScore: userScore);
});
createResults(() => userScore);
AddAssert("user score selected", () => this.ChildrenOfType<ScorePanel>().Single(p => p.Score.OnlineID == userScore.OnlineID).State == PanelState.Expanded);
AddAssert($"score panel position is {real_user_position}",
() => this.ChildrenOfType<ScorePanel>().Single(p => p.Score.OnlineID == userScore.OnlineID).ScorePosition.Value == real_user_position);
}
[Test]
public void TestShowNullUserScore()
{
createResults();
AddAssert("top score selected", () => this.ChildrenOfType<ScorePanel>().OrderByDescending(p => p.Score.TotalScore).First().State == PanelState.Expanded);
}
[Test]
public void TestShowUserScoreWithDelay()
{
ScoreInfo userScore = null;
AddStep("bind user score info handler", () =>
{
userScore = TestResources.CreateTestScoreInfo(new OsuRuleset().RulesetInfo);
userScore.OnlineID = currentScoreId++;
bindHandler(true, userScore);
});
createResults(() => userScore);
AddAssert("more than 1 panel displayed", () => this.ChildrenOfType<ScorePanel>().Count() > 1);
AddAssert("user score selected", () => this.ChildrenOfType<ScorePanel>().Single(p => p.Score.OnlineID == userScore.OnlineID).State == PanelState.Expanded);
}
[Test]
public void TestShowNullUserScoreWithDelay()
{
AddStep("bind delayed handler", () => bindHandler(true));
createResults();
AddAssert("top score selected", () => this.ChildrenOfType<ScorePanel>().OrderByDescending(p => p.Score.TotalScore).First().State == PanelState.Expanded);
}
[Test]
public void TestFetchWhenScrolledToTheRight()
{
createResults();
AddStep("bind delayed handler", () => bindHandler(true));
for (int i = 0; i < 2; i++)
{
int beforePanelCount = 0;
AddStep("get panel count", () => beforePanelCount = this.ChildrenOfType<ScorePanel>().Count());
AddStep("scroll to right", () => resultsScreen.ScorePanelList.ChildrenOfType<OsuScrollContainer>().Single().ScrollToEnd(false));
AddAssert("right loading spinner shown", () => resultsScreen.RightSpinner.State.Value == Visibility.Visible);
waitForDisplay();
AddAssert($"count increased by {scores_per_result}", () => this.ChildrenOfType<ScorePanel>().Count() == beforePanelCount + scores_per_result);
AddAssert("right loading spinner hidden", () => resultsScreen.RightSpinner.State.Value == Visibility.Hidden);
}
}
[Test]
public void TestFetchWhenScrolledToTheLeft()
{
ScoreInfo userScore = null;
AddStep("bind user score info handler", () =>
{
userScore = TestResources.CreateTestScoreInfo(new OsuRuleset().RulesetInfo);
userScore.OnlineID = currentScoreId++;
bindHandler(userScore: userScore);
});
createResults(() => userScore);
AddStep("bind delayed handler", () => bindHandler(true));
for (int i = 0; i < 2; i++)
{
int beforePanelCount = 0;
AddStep("get panel count", () => beforePanelCount = this.ChildrenOfType<ScorePanel>().Count());
AddStep("scroll to left", () => resultsScreen.ScorePanelList.ChildrenOfType<OsuScrollContainer>().Single().ScrollToStart(false));
AddAssert("left loading spinner shown", () => resultsScreen.LeftSpinner.State.Value == Visibility.Visible);
waitForDisplay();
AddAssert($"count increased by {scores_per_result}", () => this.ChildrenOfType<ScorePanel>().Count() == beforePanelCount + scores_per_result);
AddAssert("left loading spinner hidden", () => resultsScreen.LeftSpinner.State.Value == Visibility.Hidden);
}
}
private void createResults(Func<ScoreInfo> getScore = null)
{
AddStep("load results", () =>
{
LoadScreen(resultsScreen = new TestResultsScreen(getScore?.Invoke(), 1, new PlaylistItem
{
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
Ruleset = { Value = new OsuRuleset().RulesetInfo }
}));
});
waitForDisplay();
}
private void waitForDisplay()
{
AddUntilStep("wait for load to complete", () =>
requestComplete
&& resultsScreen.ScorePanelList.GetScorePanels().Count() == totalCount
&& resultsScreen.ScorePanelList.AllPanelsVisible);
AddWaitStep("wait for display", 5);
}
private void bindHandler(bool delayed = false, ScoreInfo userScore = null, bool failRequests = false) => ((DummyAPIAccess)API).HandleRequest = request =>
{
// pre-check for requests we should be handling (as they are scheduled below).
switch (request)
{
case ShowPlaylistUserScoreRequest _:
case IndexPlaylistScoresRequest _:
break;
default:
return false;
}
requestComplete = false;
double delay = delayed ? 3000 : 0;
Scheduler.AddDelayed(() =>
{
if (failRequests)
{
triggerFail(request);
return;
}
switch (request)
{
case ShowPlaylistUserScoreRequest s:
if (userScore == null)
triggerFail(s);
else
triggerSuccess(s, createUserResponse(userScore));
break;
case IndexPlaylistScoresRequest i:
triggerSuccess(i, createIndexResponse(i));
break;
}
}, delay);
return true;
};
private void triggerSuccess<T>(APIRequest<T> req, T result)
where T : class
{
requestComplete = true;
req.TriggerSuccess(result);
}
private void triggerFail(APIRequest req)
{
requestComplete = true;
req.TriggerFailure(new WebException("Failed."));
}
private MultiplayerScore createUserResponse([NotNull] ScoreInfo userScore)
{
var multiplayerUserScore = new MultiplayerScore
{
ID = (int)(userScore.OnlineID > 0 ? userScore.OnlineID : currentScoreId++),
Accuracy = userScore.Accuracy,
EndedAt = userScore.Date,
Passed = userScore.Passed,
Rank = userScore.Rank,
Position = real_user_position,
MaxCombo = userScore.MaxCombo,
TotalScore = userScore.TotalScore,
User = userScore.User,
Statistics = userScore.Statistics,
ScoresAround = new MultiplayerScoresAround
{
Higher = new MultiplayerScores(),
Lower = new MultiplayerScores()
}
};
totalCount++;
for (int i = 1; i <= scores_per_result; i++)
{
multiplayerUserScore.ScoresAround.Lower.Scores.Add(new MultiplayerScore
{
ID = currentScoreId++,
Accuracy = userScore.Accuracy,
EndedAt = userScore.Date,
Passed = true,
Rank = userScore.Rank,
MaxCombo = userScore.MaxCombo,
TotalScore = userScore.TotalScore - i,
User = new APIUser
{
Id = 2,
Username = $"peppy{i}",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
},
Statistics = userScore.Statistics
});
multiplayerUserScore.ScoresAround.Higher.Scores.Add(new MultiplayerScore
{
ID = currentScoreId++,
Accuracy = userScore.Accuracy,
EndedAt = userScore.Date,
Passed = true,
Rank = userScore.Rank,
MaxCombo = userScore.MaxCombo,
TotalScore = userScore.TotalScore + i,
User = new APIUser
{
Id = 2,
Username = $"peppy{i}",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
},
Statistics = userScore.Statistics
});
totalCount += 2;
}
addCursor(multiplayerUserScore.ScoresAround.Lower);
addCursor(multiplayerUserScore.ScoresAround.Higher);
return multiplayerUserScore;
}
private IndexedMultiplayerScores createIndexResponse(IndexPlaylistScoresRequest req)
{
var result = new IndexedMultiplayerScores();
long startTotalScore = req.Cursor?.Properties["total_score"].ToObject<long>() ?? 1000000;
string sort = req.IndexParams?.Properties["sort"].ToObject<string>() ?? "score_desc";
for (int i = 1; i <= scores_per_result; i++)
{
result.Scores.Add(new MultiplayerScore
{
ID = currentScoreId++,
Accuracy = 1,
EndedAt = DateTimeOffset.Now,
Passed = true,
Rank = ScoreRank.X,
MaxCombo = 1000,
TotalScore = startTotalScore + (sort == "score_asc" ? i : -i),
User = new APIUser
{
Id = 2,
Username = $"peppy{i}",
CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
},
Statistics = new Dictionary<HitResult, int>
{
{ HitResult.Miss, 1 },
{ HitResult.Meh, 50 },
{ HitResult.Good, 100 },
{ HitResult.Great, 300 }
}
});
totalCount++;
}
addCursor(result);
return result;
}
private void addCursor(MultiplayerScores scores)
{
scores.Cursor = new Cursor
{
Properties = new Dictionary<string, JToken>
{
{ "total_score", JToken.FromObject(scores.Scores[^1].TotalScore) },
{ "score_id", JToken.FromObject(scores.Scores[^1].ID) },
}
};
scores.Params = new IndexScoresParams
{
Properties = new Dictionary<string, JToken>
{
{ "sort", JToken.FromObject(scores.Scores[^1].TotalScore > scores.Scores[^2].TotalScore ? "score_asc" : "score_desc") }
}
};
}
private class TestResultsScreen : PlaylistsResultsScreen
{
public new LoadingSpinner LeftSpinner => base.LeftSpinner;
public new LoadingSpinner CentreSpinner => base.CentreSpinner;
public new LoadingSpinner RightSpinner => base.RightSpinner;
public new ScorePanelList ScorePanelList => base.ScorePanelList;
public TestResultsScreen(ScoreInfo score, int roomId, PlaylistItem playlistItem, bool allowRetry = true)
: base(score, roomId, playlistItem, allowRetry)
{
}
}
}
}