2019-01-24 16:43:03 +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.
2018-04-13 17:19:50 +08:00
using System ;
using System.Linq ;
using NUnit.Framework ;
2019-03-25 00:02:36 +08:00
using osu.Framework.Allocation ;
2019-02-21 18:04:31 +08:00
using osu.Framework.Bindables ;
2020-03-11 09:18:41 +08:00
using osu.Framework.Extensions.Color4Extensions ;
2019-03-25 00:02:36 +08:00
using osu.Framework.Graphics ;
using osu.Framework.Graphics.Containers ;
using osu.Game.Graphics ;
2021-11-04 17:02:44 +08:00
using osu.Game.Online.API.Requests.Responses ;
2019-03-25 00:02:36 +08:00
using osu.Game.Online.Chat ;
using osu.Game.Overlays.Chat ;
using osuTK.Graphics ;
2018-04-13 17:19:50 +08:00
2019-03-25 00:02:36 +08:00
namespace osu.Game.Tests.Visual.Online
2018-04-13 17:19:50 +08:00
{
[TestFixture]
2019-05-15 03:37:25 +08:00
public class TestSceneChatLink : OsuTestScene
2018-04-13 17:19:50 +08:00
{
private readonly TestChatLineContainer textContainer ;
private Color4 linkColour ;
2019-05-15 03:37:25 +08:00
public TestSceneChatLink ( )
2018-04-13 17:19:50 +08:00
{
Add ( textContainer = new TestChatLineContainer
{
Padding = new MarginPadding { Left = 20 , Right = 20 } ,
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y ,
Direction = FillDirection . Vertical ,
} ) ;
}
[BackgroundDependencyLoader]
private void load ( OsuColour colours )
{
linkColour = colours . Blue ;
2018-04-14 19:31:03 +08:00
var chatManager = new ChannelManager ( ) ;
2019-01-07 17:50:27 +08:00
BindableList < Channel > availableChannels = ( BindableList < Channel > ) chatManager . AvailableChannels ;
2019-02-28 12:31:40 +08:00
availableChannels . Add ( new Channel { Name = "#english" } ) ;
2018-11-22 04:44:56 +08:00
availableChannels . Add ( new Channel { Name = "#japanese" } ) ;
2018-06-17 21:08:13 +08:00
Dependencies . Cache ( chatManager ) ;
2018-04-13 17:19:50 +08:00
}
2022-01-11 16:42:02 +08:00
[SetUp]
public void Setup ( ) = > Schedule ( ( ) = >
2018-04-13 17:19:50 +08:00
{
2022-01-11 16:42:02 +08:00
textContainer . Clear ( ) ;
} ) ;
2018-04-13 17:19:50 +08:00
2022-01-11 16:42:02 +08:00
[Test]
public void TestLinksGeneral ( )
2018-04-13 17:19:50 +08:00
{
2022-01-11 16:42:02 +08:00
int messageIndex = 0 ;
2018-04-13 17:19:50 +08:00
addMessageWithChecks ( "test!" ) ;
2021-02-12 14:29:21 +08:00
addMessageWithChecks ( "dev.ppy.sh!" ) ;
addMessageWithChecks ( "https://dev.ppy.sh!" , 1 , expectedActions : LinkAction . External ) ;
2018-04-13 17:19:50 +08:00
addMessageWithChecks ( "00:12:345 (1,2) - Test?" , 1 , expectedActions : LinkAction . OpenEditorTimestamp ) ;
2022-01-11 16:45:31 +08:00
addMessageWithChecks ( "Wiki link for tasty [[Performance Points]]" , 1 , expectedActions : LinkAction . OpenWiki ) ;
2021-02-12 14:29:21 +08:00
addMessageWithChecks ( "(osu forums)[https://dev.ppy.sh/forum] (old link format)" , 1 , expectedActions : LinkAction . External ) ;
addMessageWithChecks ( "[https://dev.ppy.sh/home New site] (new link format)" , 1 , expectedActions : LinkAction . External ) ;
addMessageWithChecks ( "[osu forums](https://dev.ppy.sh/forum) (new link format 2)" , 1 , expectedActions : LinkAction . External ) ;
addMessageWithChecks ( "[https://dev.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]" , 1 , expectedActions : LinkAction . External ) ;
addMessageWithChecks ( "is now listening to [https://dev.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]" , 1 , true , expectedActions : LinkAction . OpenBeatmapSet ) ;
addMessageWithChecks ( "is now playing [https://dev.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]" , 1 , true , expectedActions : LinkAction . OpenBeatmap ) ;
addMessageWithChecks ( "Let's (try)[https://dev.ppy.sh/home] [https://dev.ppy.sh/b/252238 multiple links] https://dev.ppy.sh/home" , 3 ,
2018-04-13 17:19:50 +08:00
expectedActions : new [ ] { LinkAction . External , LinkAction . OpenBeatmap , LinkAction . External } ) ;
2021-02-12 14:29:21 +08:00
addMessageWithChecks ( "[https://dev.ppy.sh/home New link format with escaped [and \\[ paired] braces]" , 1 , expectedActions : LinkAction . External ) ;
addMessageWithChecks ( "[Markdown link format with escaped [and \\[ paired] braces](https://dev.ppy.sh/home)" , 1 , expectedActions : LinkAction . External ) ;
2022-01-11 16:42:02 +08:00
addMessageWithChecks ( "(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]" , 2 ,
2022-01-11 16:45:31 +08:00
expectedActions : new [ ] { LinkAction . External , LinkAction . OpenWiki } ) ;
2018-04-13 17:19:50 +08:00
// note that there's 0 links here (they get removed if a channel is not found)
addMessageWithChecks ( "#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present)." ) ;
addMessageWithChecks ( "I am important!" , 0 , false , true ) ;
addMessageWithChecks ( "feels important" , 0 , true , true ) ;
2021-02-12 14:29:21 +08:00
addMessageWithChecks ( "likes to post this [https://dev.ppy.sh/home link]." , 1 , true , true , expectedActions : LinkAction . External ) ;
2018-04-13 17:19:50 +08:00
addMessageWithChecks ( "Join my multiplayer game osump://12346." , 1 , expectedActions : LinkAction . JoinMultiplayerMatch ) ;
addMessageWithChecks ( "Join my [multiplayer game](osump://12346)." , 1 , expectedActions : LinkAction . JoinMultiplayerMatch ) ;
2022-02-18 14:57:37 +08:00
addMessageWithChecks ( $"Join my [#english]({OsuGameBase.OSU_PROTOCOL}chan/#english)." , 1 , expectedActions : LinkAction . OpenChannel ) ;
addMessageWithChecks ( $"Join my {OsuGameBase.OSU_PROTOCOL}chan/#english." , 1 , expectedActions : LinkAction . OpenChannel ) ;
2018-04-13 17:19:50 +08:00
addMessageWithChecks ( "Join my #english or #japanese channels." , 2 , expectedActions : new [ ] { LinkAction . OpenChannel , LinkAction . OpenChannel } ) ;
addMessageWithChecks ( "Join my #english or #nonexistent #hashtag channels." , 1 , expectedActions : LinkAction . OpenChannel ) ;
2022-01-11 16:42:02 +08:00
void addMessageWithChecks ( string text , int linkAmount = 0 , bool isAction = false , bool isImportant = false , params LinkAction [ ] expectedActions )
{
ChatLine newLine = null ;
int index = messageIndex + + ;
AddStep ( "add message" , ( ) = >
{
newLine = new ChatLine ( new DummyMessage ( text , isAction , isImportant , index ) ) ;
textContainer . Add ( newLine ) ;
} ) ;
AddAssert ( $"msg #{index} has {linkAmount} link(s)" , ( ) = > newLine . Message . Links . Count = = linkAmount ) ;
AddAssert ( $"msg #{index} has the right action" , hasExpectedActions ) ;
//AddAssert($"msg #{index} is " + (isAction ? "italic" : "not italic"), () => newLine.ContentFlow.Any() && isAction == isItalic());
AddAssert ( $"msg #{index} shows {linkAmount} link(s)" , isShowingLinks ) ;
bool hasExpectedActions ( )
{
var expectedActionsList = expectedActions . ToList ( ) ;
if ( expectedActionsList . Count ! = newLine . Message . Links . Count )
return false ;
for ( int i = 0 ; i < newLine . Message . Links . Count ; i + + )
{
var action = newLine . Message . Links [ i ] . Action ;
if ( action ! = expectedActions [ i ] ) return false ;
}
return true ;
}
//bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast<OsuSpriteText>().All(sprite => sprite.Font.Italics);
bool isShowingLinks ( )
{
bool hasBackground = ! string . IsNullOrEmpty ( newLine . Message . Sender . Colour ) ;
Color4 textColour = isAction & & hasBackground ? Color4Extensions . FromHex ( newLine . Message . Sender . Colour ) : Color4 . White ;
var linkCompilers = newLine . ContentFlow . Where ( d = > d is DrawableLinkCompiler ) . ToList ( ) ;
var linkSprites = linkCompilers . SelectMany ( comp = > ( ( DrawableLinkCompiler ) comp ) . Parts ) ;
return linkSprites . All ( d = > d . Colour = = linkColour )
& & newLine . ContentFlow . Except ( linkSprites . Concat ( linkCompilers ) ) . All ( d = > d . Colour = = textColour ) ;
}
}
2018-04-13 17:19:50 +08:00
}
2022-01-11 16:42:02 +08:00
[Test]
public void TestEcho ( )
2018-04-13 17:19:50 +08:00
{
2022-01-11 16:42:02 +08:00
int messageIndex = 0 ;
2018-04-13 17:19:50 +08:00
addEchoWithWait ( "sent!" , "received!" ) ;
2021-02-12 14:29:21 +08:00
addEchoWithWait ( "https://dev.ppy.sh/home" , null , 500 ) ;
addEchoWithWait ( "[https://dev.ppy.sh/forum let's try multiple words too!]" ) ;
addEchoWithWait ( "(long loading times! clickable while loading?)[https://dev.ppy.sh/home]" , null , 5000 ) ;
2018-04-13 17:19:50 +08:00
void addEchoWithWait ( string text , string completeText = null , double delay = 250 )
{
2022-01-11 16:42:02 +08:00
int index = messageIndex + + ;
2018-04-13 17:19:50 +08:00
2022-01-11 16:42:02 +08:00
AddStep ( $"send msg #{index} after {delay}ms" , ( ) = >
2018-04-13 17:19:50 +08:00
{
2022-01-11 16:42:02 +08:00
ChatLine newLine = new ChatLine ( new DummyEchoMessage ( text ) ) ;
2018-04-13 17:19:50 +08:00
textContainer . Add ( newLine ) ;
Scheduler . AddDelayed ( ( ) = > newLine . Message = new DummyMessage ( completeText ? ? text ) , delay ) ;
} ) ;
2022-01-11 16:42:02 +08:00
AddUntilStep ( $"wait for msg #{index}" , ( ) = > textContainer . All ( line = > line . Message is DummyMessage ) ) ;
2018-04-13 17:19:50 +08:00
}
}
private class DummyEchoMessage : LocalEchoMessage
{
public DummyEchoMessage ( string text )
{
Content = text ;
Timestamp = DateTimeOffset . Now ;
Sender = DummyMessage . TEST_SENDER ;
}
}
private class DummyMessage : Message
{
private static long messageCounter ;
2021-11-04 17:02:44 +08:00
internal static readonly APIUser TEST_SENDER_BACKGROUND = new APIUser
2018-04-13 17:19:50 +08:00
{
Username = @"i-am-important" ,
Id = 42 ,
Colour = "#250cc9" ,
} ;
2021-11-04 17:02:44 +08:00
internal static readonly APIUser TEST_SENDER = new APIUser
2018-04-13 17:19:50 +08:00
{
Username = @"Somebody" ,
Id = 1 ,
} ;
public new DateTimeOffset Timestamp = DateTimeOffset . Now ;
public DummyMessage ( string text , bool isAction = false , bool isImportant = false , int number = 0 )
: base ( messageCounter + + )
{
Content = text ;
IsAction = isAction ;
2021-11-04 17:02:44 +08:00
Sender = new APIUser
2018-04-13 17:19:50 +08:00
{
Username = $"User {number}" ,
Id = number ,
Colour = isImportant ? "#250cc9" : null ,
} ;
}
}
private class TestChatLineContainer : FillFlowContainer < ChatLine >
{
protected override int Compare ( Drawable x , Drawable y )
{
var xC = ( ChatLine ) x ;
var yC = ( ChatLine ) y ;
return xC . Message . CompareTo ( yC . Message ) ;
}
}
}
}