2021-01-26 04:41:05 +08:00
// 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.
2021-06-27 02:24:12 +08:00
using System ;
2021-01-26 04:41:05 +08:00
using System.Collections.Generic ;
using System.Linq ;
using NUnit.Framework ;
using osu.Framework.Graphics.Containers ;
using osu.Framework.Testing ;
2021-12-22 22:02:59 +08:00
using osu.Game.Beatmaps.Drawables.Cards ;
2021-09-10 00:57:33 +08:00
using osu.Game.Graphics.UserInterface ;
2021-01-26 04:41:05 +08:00
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.BeatmapListing ;
2021-06-27 02:24:12 +08:00
using osu.Game.Scoring ;
2021-09-10 00:57:33 +08:00
using osuTK.Input ;
2021-11-04 17:02:44 +08:00
using APIUser = osu . Game . Online . API . Requests . Responses . APIUser ;
2021-01-26 04:41:05 +08:00
namespace osu.Game.Tests.Visual.Online
{
2021-09-10 00:57:33 +08:00
public class TestSceneBeatmapListingOverlay : OsuManualInputManagerTestScene
2021-01-26 04:41:05 +08:00
{
private readonly List < APIBeatmapSet > setsForResponse = new List < APIBeatmapSet > ( ) ;
private BeatmapListingOverlay overlay ;
2021-06-22 13:53:21 +08:00
private BeatmapListingSearchControl searchControl = > overlay . ChildrenOfType < BeatmapListingSearchControl > ( ) . Single ( ) ;
2021-09-10 00:57:33 +08:00
[SetUpSteps]
public void SetUpSteps ( )
2021-01-26 04:41:05 +08:00
{
2021-09-10 00:57:33 +08:00
AddStep ( "setup overlay" , ( ) = >
{
Child = overlay = new BeatmapListingOverlay { State = { Value = Visibility . Visible } } ;
setsForResponse . Clear ( ) ;
} ) ;
2021-01-26 04:41:05 +08:00
2021-09-10 00:57:33 +08:00
AddStep ( "initialize dummy" , ( ) = >
2021-01-26 04:41:05 +08:00
{
2021-09-10 00:57:33 +08:00
var api = ( DummyAPIAccess ) API ;
2021-03-23 17:08:32 +08:00
2021-09-10 00:57:33 +08:00
api . HandleRequest = req = >
2021-01-26 04:41:05 +08:00
{
2021-09-10 00:57:33 +08:00
if ( ! ( req is SearchBeatmapSetsRequest searchBeatmapSetsRequest ) ) return false ;
2021-03-23 17:08:32 +08:00
2021-09-10 00:57:33 +08:00
searchBeatmapSetsRequest . TriggerSuccess ( new SearchBeatmapSetsResponse
{
BeatmapSets = setsForResponse ,
} ) ;
return true ;
} ;
2021-06-20 18:28:43 +08:00
// non-supporter user
2021-11-04 17:02:44 +08:00
api . LocalUser . Value = new APIUser
2021-06-20 18:28:43 +08:00
{
Username = "TestBot" ,
Id = API . LocalUser . Value . Id + 1 ,
} ;
} ) ;
2021-01-26 04:41:05 +08:00
}
2021-09-10 00:57:33 +08:00
[Test]
public void TestHideViaBack ( )
{
AddAssert ( "is visible" , ( ) = > overlay . State . Value = = Visibility . Visible ) ;
AddStep ( "hide" , ( ) = > InputManager . Key ( Key . Escape ) ) ;
AddUntilStep ( "is hidden" , ( ) = > overlay . State . Value = = Visibility . Hidden ) ;
}
[Test]
public void TestHideViaBackWithSearch ( )
{
AddAssert ( "is visible" , ( ) = > overlay . State . Value = = Visibility . Visible ) ;
AddStep ( "search something" , ( ) = > overlay . ChildrenOfType < SearchTextBox > ( ) . First ( ) . Text = "search" ) ;
AddStep ( "kill search" , ( ) = > InputManager . Key ( Key . Escape ) ) ;
AddAssert ( "search textbox empty" , ( ) = > string . IsNullOrEmpty ( overlay . ChildrenOfType < SearchTextBox > ( ) . First ( ) . Text ) ) ;
AddAssert ( "is visible" , ( ) = > overlay . State . Value = = Visibility . Visible ) ;
AddStep ( "hide" , ( ) = > InputManager . Key ( Key . Escape ) ) ;
AddUntilStep ( "is hidden" , ( ) = > overlay . State . Value = = Visibility . Hidden ) ;
}
[Test]
public void TestHideViaBackWithScrolledSearch ( )
{
AddAssert ( "is visible" , ( ) = > overlay . State . Value = = Visibility . Visible ) ;
2021-10-25 12:47:12 +08:00
AddStep ( "show many results" , ( ) = > fetchFor ( Enumerable . Repeat ( CreateAPIBeatmapSet ( Ruleset . Value ) , 100 ) . ToArray ( ) ) ) ;
2021-09-10 00:57:33 +08:00
2021-09-10 03:33:02 +08:00
AddUntilStep ( "placeholder hidden" , ( ) = > ! overlay . ChildrenOfType < BeatmapListingOverlay . NotFoundDrawable > ( ) . Any ( d = > d . IsPresent ) ) ;
2021-09-10 00:57:33 +08:00
AddStep ( "scroll to bottom" , ( ) = > overlay . ChildrenOfType < OverlayScrollContainer > ( ) . First ( ) . ScrollToEnd ( ) ) ;
AddStep ( "kill search" , ( ) = > InputManager . Key ( Key . Escape ) ) ;
AddUntilStep ( "search textbox empty" , ( ) = > string . IsNullOrEmpty ( overlay . ChildrenOfType < SearchTextBox > ( ) . First ( ) . Text ) ) ;
AddUntilStep ( "is scrolled to top" , ( ) = > overlay . ChildrenOfType < OverlayScrollContainer > ( ) . First ( ) . Current = = 0 ) ;
AddAssert ( "is visible" , ( ) = > overlay . State . Value = = Visibility . Visible ) ;
AddStep ( "hide" , ( ) = > InputManager . Key ( Key . Escape ) ) ;
AddUntilStep ( "is hidden" , ( ) = > overlay . State . Value = = Visibility . Hidden ) ;
}
2022-01-04 02:27:46 +08:00
[Test]
public void TestCorrectOldContentExpiration ( )
{
AddAssert ( "is visible" , ( ) = > overlay . State . Value = = Visibility . Visible ) ;
AddStep ( "show many results" , ( ) = > fetchFor ( Enumerable . Repeat ( CreateAPIBeatmapSet ( Ruleset . Value ) , 100 ) . ToArray ( ) ) ) ;
assertAllCardsOfType < BeatmapCardNormal > ( 100 ) ;
AddStep ( "show more results" , ( ) = > fetchFor ( Enumerable . Repeat ( CreateAPIBeatmapSet ( Ruleset . Value ) , 30 ) . ToArray ( ) ) ) ;
assertAllCardsOfType < BeatmapCardNormal > ( 30 ) ;
}
2021-12-22 21:27:11 +08:00
[Test]
public void TestCardSizeSwitching ( )
{
AddAssert ( "is visible" , ( ) = > overlay . State . Value = = Visibility . Visible ) ;
AddStep ( "show many results" , ( ) = > fetchFor ( Enumerable . Repeat ( CreateAPIBeatmapSet ( Ruleset . Value ) , 100 ) . ToArray ( ) ) ) ;
2022-01-04 02:27:46 +08:00
assertAllCardsOfType < BeatmapCardNormal > ( 100 ) ;
2021-12-22 21:27:11 +08:00
setCardSize ( BeatmapCardSize . Extra ) ;
2022-01-04 02:27:46 +08:00
assertAllCardsOfType < BeatmapCardExtra > ( 100 ) ;
2021-12-22 21:27:11 +08:00
setCardSize ( BeatmapCardSize . Normal ) ;
2022-01-04 02:27:46 +08:00
assertAllCardsOfType < BeatmapCardNormal > ( 100 ) ;
2021-12-22 21:27:11 +08:00
AddStep ( "fetch for 0 beatmaps" , ( ) = > fetchFor ( ) ) ;
AddUntilStep ( "placeholder shown" , ( ) = > overlay . ChildrenOfType < BeatmapListingOverlay . NotFoundDrawable > ( ) . SingleOrDefault ( ) ? . IsPresent = = true ) ;
setCardSize ( BeatmapCardSize . Extra ) ;
AddAssert ( "placeholder shown" , ( ) = > overlay . ChildrenOfType < BeatmapListingOverlay . NotFoundDrawable > ( ) . SingleOrDefault ( ) ? . IsPresent = = true ) ;
}
2021-01-26 04:41:05 +08:00
[Test]
public void TestNoBeatmapsPlaceholder ( )
{
AddStep ( "fetch for 0 beatmaps" , ( ) = > fetchFor ( ) ) ;
2021-12-22 22:02:59 +08:00
placeholderShown ( ) ;
2021-01-26 04:41:05 +08:00
2021-12-22 22:02:59 +08:00
AddStep ( "show many results" , ( ) = > fetchFor ( Enumerable . Repeat ( CreateAPIBeatmapSet ( Ruleset . Value ) , 100 ) . ToArray ( ) ) ) ;
AddUntilStep ( "wait for loaded" , ( ) = > this . ChildrenOfType < BeatmapCard > ( ) . Count ( ) = = 100 ) ;
2021-09-10 03:33:02 +08:00
AddUntilStep ( "placeholder hidden" , ( ) = > ! overlay . ChildrenOfType < BeatmapListingOverlay . NotFoundDrawable > ( ) . Any ( d = > d . IsPresent ) ) ;
2021-01-26 04:41:05 +08:00
AddStep ( "fetch for 0 beatmaps" , ( ) = > fetchFor ( ) ) ;
2021-12-22 22:02:59 +08:00
placeholderShown ( ) ;
2021-01-26 04:41:05 +08:00
// fetch once more to ensure nothing happens in displaying placeholder again when it already is present.
AddStep ( "fetch for 0 beatmaps again" , ( ) = > fetchFor ( ) ) ;
2021-12-22 22:02:59 +08:00
placeholderShown ( ) ;
void placeholderShown ( ) = >
AddUntilStep ( "placeholder shown" , ( ) = >
{
var notFoundDrawable = overlay . ChildrenOfType < BeatmapListingOverlay . NotFoundDrawable > ( ) . SingleOrDefault ( ) ;
return notFoundDrawable ! = null & & notFoundDrawable . IsPresent & & notFoundDrawable . Parent . DrawHeight > 0 ;
} ) ;
2021-01-26 04:41:05 +08:00
}
2021-06-20 17:17:07 +08:00
[Test]
2021-06-27 01:27:34 +08:00
public void TestUserWithoutSupporterUsesSupporterOnlyFiltersWithoutResults ( )
2021-06-20 18:28:43 +08:00
{
2021-06-20 21:23:54 +08:00
AddStep ( "fetch for 0 beatmaps" , ( ) = > fetchFor ( ) ) ;
2021-12-21 13:10:38 +08:00
2021-06-20 18:28:43 +08:00
AddStep ( "set dummy as non-supporter" , ( ) = > ( ( DummyAPIAccess ) API ) . LocalUser . Value . IsSupporter = false ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
// only Rank Achieved filter
setRankAchievedFilter ( new [ ] { ScoreRank . XH } ) ;
2021-06-22 13:53:21 +08:00
supporterRequiredPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
setRankAchievedFilter ( Array . Empty < ScoreRank > ( ) ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
// only Played filter
setPlayedFilter ( SearchPlayed . Played ) ;
2021-06-22 13:53:21 +08:00
supporterRequiredPlaceholderShown ( ) ;
2021-06-20 21:23:54 +08:00
2021-06-27 02:24:12 +08:00
setPlayedFilter ( SearchPlayed . Any ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
2021-06-20 21:23:54 +08:00
2021-06-27 02:24:12 +08:00
// both RankAchieved and Played filters
setRankAchievedFilter ( new [ ] { ScoreRank . XH } ) ;
setPlayedFilter ( SearchPlayed . Played ) ;
2021-06-22 13:53:21 +08:00
supporterRequiredPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
setRankAchievedFilter ( Array . Empty < ScoreRank > ( ) ) ;
setPlayedFilter ( SearchPlayed . Any ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
}
2021-06-20 17:17:07 +08:00
2021-06-22 13:53:21 +08:00
[Test]
2021-06-27 01:27:34 +08:00
public void TestUserWithSupporterUsesSupporterOnlyFiltersWithoutResults ( )
2021-06-22 13:53:21 +08:00
{
AddStep ( "fetch for 0 beatmaps" , ( ) = > fetchFor ( ) ) ;
2021-06-20 18:28:43 +08:00
AddStep ( "set dummy as supporter" , ( ) = > ( ( DummyAPIAccess ) API ) . LocalUser . Value . IsSupporter = true ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
// only Rank Achieved filter
setRankAchievedFilter ( new [ ] { ScoreRank . XH } ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
setRankAchievedFilter ( Array . Empty < ScoreRank > ( ) ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
// only Played filter
setPlayedFilter ( SearchPlayed . Played ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
setPlayedFilter ( SearchPlayed . Any ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
2021-06-20 21:23:54 +08:00
2021-06-27 02:24:12 +08:00
// both Rank Achieved and Played filters
setRankAchievedFilter ( new [ ] { ScoreRank . XH } ) ;
setPlayedFilter ( SearchPlayed . Played ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
2021-06-20 21:23:54 +08:00
2021-06-27 02:24:12 +08:00
setRankAchievedFilter ( Array . Empty < ScoreRank > ( ) ) ;
setPlayedFilter ( SearchPlayed . Any ) ;
2021-06-22 13:53:21 +08:00
notFoundPlaceholderShown ( ) ;
2021-06-20 18:28:43 +08:00
}
[Test]
2021-06-27 01:27:34 +08:00
public void TestUserWithoutSupporterUsesSupporterOnlyFiltersWithResults ( )
2021-06-20 18:28:43 +08:00
{
2021-10-25 12:47:12 +08:00
AddStep ( "fetch for 1 beatmap" , ( ) = > fetchFor ( CreateAPIBeatmapSet ( Ruleset . Value ) ) ) ;
2021-12-21 13:10:38 +08:00
noPlaceholderShown ( ) ;
2021-06-20 18:28:43 +08:00
AddStep ( "set dummy as non-supporter" , ( ) = > ( ( DummyAPIAccess ) API ) . LocalUser . Value . IsSupporter = false ) ;
2021-06-27 02:24:12 +08:00
// only Rank Achieved filter
setRankAchievedFilter ( new [ ] { ScoreRank . XH } ) ;
2021-06-22 13:53:21 +08:00
supporterRequiredPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
setRankAchievedFilter ( Array . Empty < ScoreRank > ( ) ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
// only Played filter
setPlayedFilter ( SearchPlayed . Played ) ;
2021-06-22 13:53:21 +08:00
supporterRequiredPlaceholderShown ( ) ;
2021-06-20 21:23:54 +08:00
2021-06-27 02:24:12 +08:00
setPlayedFilter ( SearchPlayed . Any ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
2021-06-20 18:28:43 +08:00
2021-06-27 02:24:12 +08:00
// both Rank Achieved and Played filters
setRankAchievedFilter ( new [ ] { ScoreRank . XH } ) ;
setPlayedFilter ( SearchPlayed . Played ) ;
2021-06-22 13:53:21 +08:00
supporterRequiredPlaceholderShown ( ) ;
2021-06-20 21:23:54 +08:00
2021-06-27 02:24:12 +08:00
setRankAchievedFilter ( Array . Empty < ScoreRank > ( ) ) ;
setPlayedFilter ( SearchPlayed . Any ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
}
2021-06-20 17:17:07 +08:00
2021-06-22 13:53:21 +08:00
[Test]
2021-06-27 01:27:34 +08:00
public void TestUserWithSupporterUsesSupporterOnlyFiltersWithResults ( )
2021-06-22 13:53:21 +08:00
{
2021-10-25 12:47:12 +08:00
AddStep ( "fetch for 1 beatmap" , ( ) = > fetchFor ( CreateAPIBeatmapSet ( Ruleset . Value ) ) ) ;
2021-12-21 13:10:38 +08:00
noPlaceholderShown ( ) ;
2021-06-20 18:28:43 +08:00
AddStep ( "set dummy as supporter" , ( ) = > ( ( DummyAPIAccess ) API ) . LocalUser . Value . IsSupporter = true ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
// only Rank Achieved filter
setRankAchievedFilter ( new [ ] { ScoreRank . XH } ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
2021-06-27 02:24:12 +08:00
setRankAchievedFilter ( Array . Empty < ScoreRank > ( ) ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
2021-06-20 18:28:43 +08:00
2021-06-27 02:24:12 +08:00
// only Played filter
setPlayedFilter ( SearchPlayed . Played ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
2021-06-20 18:28:43 +08:00
2021-06-27 02:24:12 +08:00
setPlayedFilter ( SearchPlayed . Any ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
2021-06-20 21:23:54 +08:00
2021-06-27 02:24:12 +08:00
// both Rank Achieved and Played filters
setRankAchievedFilter ( new [ ] { ScoreRank . XH } ) ;
setPlayedFilter ( SearchPlayed . Played ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
2021-06-20 21:23:54 +08:00
2021-06-27 02:24:12 +08:00
setRankAchievedFilter ( Array . Empty < ScoreRank > ( ) ) ;
setPlayedFilter ( SearchPlayed . Any ) ;
2021-06-22 13:53:21 +08:00
noPlaceholderShown ( ) ;
2021-06-20 17:17:07 +08:00
}
2021-09-10 00:57:33 +08:00
private static int searchCount ;
2021-10-25 12:47:12 +08:00
private void fetchFor ( params APIBeatmapSet [ ] beatmaps )
2021-01-26 04:41:05 +08:00
{
setsForResponse . Clear ( ) ;
2021-10-25 12:47:12 +08:00
setsForResponse . AddRange ( beatmaps ) ;
2021-01-26 04:41:05 +08:00
// trigger arbitrary change for fetching.
2021-09-10 00:57:33 +08:00
searchControl . Query . Value = $"search {searchCount++}" ;
2021-01-26 04:41:05 +08:00
}
2021-06-27 02:24:12 +08:00
private void setRankAchievedFilter ( ScoreRank [ ] ranks )
2021-06-20 18:28:43 +08:00
{
2021-06-27 02:24:12 +08:00
AddStep ( $"set Rank Achieved filter to [{string.Join(',', ranks)}]" , ( ) = >
2021-06-20 18:28:43 +08:00
{
2021-06-22 13:53:21 +08:00
searchControl . Ranks . Clear ( ) ;
2021-06-27 02:24:12 +08:00
searchControl . Ranks . AddRange ( ranks ) ;
2021-06-20 18:28:43 +08:00
} ) ;
}
2021-06-27 02:24:12 +08:00
private void setPlayedFilter ( SearchPlayed played )
2021-06-20 18:28:43 +08:00
{
2021-06-27 02:24:12 +08:00
AddStep ( $"set Played filter to {played}" , ( ) = > searchControl . Played . Value = played ) ;
2021-06-20 18:28:43 +08:00
}
2021-06-22 13:53:21 +08:00
private void supporterRequiredPlaceholderShown ( )
2021-06-20 21:23:54 +08:00
{
2021-06-27 02:27:15 +08:00
AddUntilStep ( "\"supporter required\" placeholder shown" , ( ) = > overlay . ChildrenOfType < BeatmapListingOverlay . SupporterRequiredDrawable > ( ) . SingleOrDefault ( ) ? . IsPresent = = true ) ;
2021-06-22 13:53:21 +08:00
}
2021-06-20 21:23:54 +08:00
2021-06-22 13:53:21 +08:00
private void notFoundPlaceholderShown ( )
{
2021-06-27 02:27:15 +08:00
AddUntilStep ( "\"no maps found\" placeholder shown" , ( ) = > overlay . ChildrenOfType < BeatmapListingOverlay . NotFoundDrawable > ( ) . SingleOrDefault ( ) ? . IsPresent = = true ) ;
2021-06-22 13:53:21 +08:00
}
private void noPlaceholderShown ( )
{
2021-12-21 13:10:38 +08:00
AddUntilStep ( "\"supporter required\" placeholder not shown" , ( ) = > ! overlay . ChildrenOfType < BeatmapListingOverlay . SupporterRequiredDrawable > ( ) . Any ( d = > d . IsPresent ) ) ;
AddUntilStep ( "\"no maps found\" placeholder not shown" , ( ) = > ! overlay . ChildrenOfType < BeatmapListingOverlay . NotFoundDrawable > ( ) . Any ( d = > d . IsPresent ) ) ;
2021-06-20 21:23:54 +08:00
}
2021-12-22 21:27:11 +08:00
private void setCardSize ( BeatmapCardSize cardSize ) = > AddStep ( $"set card size to {cardSize}" , ( ) = > overlay . ChildrenOfType < BeatmapListingCardSizeTabControl > ( ) . Single ( ) . Current . Value = cardSize ) ;
2022-01-04 02:27:46 +08:00
private void assertAllCardsOfType < T > ( int expectedCount )
2021-12-22 21:27:11 +08:00
where T : BeatmapCard = >
AddUntilStep ( $"all loaded beatmap cards are {typeof(T)}" , ( ) = >
{
int loadedCorrectCount = this . ChildrenOfType < BeatmapCard > ( ) . Count ( card = > card . IsLoaded & & card . GetType ( ) = = typeof ( T ) ) ;
2022-01-04 02:27:46 +08:00
return loadedCorrectCount > 0 & & loadedCorrectCount = = expectedCount ;
2021-12-22 21:27:11 +08:00
} ) ;
2021-01-26 04:41:05 +08:00
}
}