Files
Terminal.Gui/Tests/UnitTestsParallelizable/Drivers/UrlHyperlinkerTests.cs

171 lines
6.2 KiB
C#

#nullable enable
using System.Text;
using Xunit.Abstractions;
namespace UnitTests_Parallelizable.DriverTests;
public class Osc8UrlLinkerTests (ITestOutputHelper output)
{
private readonly ITestOutputHelper _output = output;
[Theory]
[InlineData ("<https://example.com>", "<", "https://example.com", ">")]
[InlineData ("\"https://example.com\"", "\"", "https://example.com", "\"")]
public void WrapOsc8_Does_Not_Cross_Delimiters (string input, string prefix, string url, string suffix)
{
string actual = Wrap (input);
string expected = prefix + LinkWrappedWithOSCs (url) + suffix;
Assert.Equal (expected, actual);
}
[Theory]
[InlineData ("No url here")]
[InlineData ("http://")]
[InlineData ("://missing-scheme.com")]
public void WrapOsc8_Leaves_Text_Unchanged_Without_Urls (string input)
{
StringBuilder sb = new (input);
StringBuilder result = Osc8UrlLinker.WrapOsc8 (sb);
Assert.Same (sb, result);
Assert.Equal (input, result.ToString ());
}
[Fact]
public void WrapOsc8_Stops_At_Ansi_Escape_Sequence ()
{
var esc = "\x1B[38;2;173m";
string input = "https://example.com" + esc + "/more";
string wrapped = Wrap (input);
string expected = LinkWrappedWithOSCs ("https://example.com") + esc + "/more";
Assert.Equal (expected, wrapped);
// Verify that the hyperlinked visible content contains no ESC
string start = EscSeqUtils.OSC_StartHyperlink ("https://example.com");
string end = EscSeqUtils.OSC_EndHyperlink ();
int s = wrapped.IndexOf (start, StringComparison.Ordinal);
Assert.True (s >= 0);
int e = wrapped.IndexOf (end, s + start.Length, StringComparison.Ordinal);
Assert.True (e > s);
int contentStart = s + start.Length;
int contentLength = e - contentStart;
string visible = wrapped.Substring (contentStart, contentLength);
Assert.DoesNotContain ('\x1B', visible);
Assert.Equal ("https://example.com", visible);
}
[Theory]
[InlineData ("See https://example.com/path.", "See ", "https://example.com/path", ".")]
[InlineData ("See https://example.com/file.tar.gz,", "See ", "https://example.com/file.tar.gz", ",")]
[InlineData ("See https://example.com/path_(with)_parens)", "See ", "https://example.com/path_(with)_parens", ")")]
public void WrapOsc8_Trims_Trailing_Punctuation (string input, string prefix, string url, string suffix)
{
string actual = Wrap (input);
string expected = prefix + LinkWrappedWithOSCs (url) + suffix;
Assert.Equal (expected, actual);
}
[Theory]
[InlineData (
"Multiple: https://a.com, https://b.com!",
"Multiple: ",
"https://a.com",
", ",
"https://b.com",
"!")]
[InlineData (
"List https://one.com https://two.com https://three.com",
"List ",
"https://one.com",
" ",
"https://two.com",
" ",
"https://three.com",
"")]
public void WrapOsc8_Wraps_Multiple_Urls (string input, params string [] segments)
{
// segments: text0, url1, text1, [url2, text2]...
string expected = BuildExpected (segments);
string actual = Wrap (input);
Assert.Equal (expected, actual);
}
[Theory]
[InlineData ("https://github.com", "https://github.com")]
[InlineData ("http://example.com", "http://example.com")]
[InlineData ("ftp://ftp.example.com/file.zip", "ftp://ftp.example.com/file.zip")]
[InlineData ("https://example.com:8080/path", "https://example.com:8080/path")]
[InlineData ("https://example.com/path#anchor", "https://example.com/path#anchor")]
[InlineData ("https://example.com/path?query=value&other=123", "https://example.com/path?query=value&other=123")]
[InlineData ("https://commons.wikimedia.org/wiki/File:Spinning_globe.gif", "https://commons.wikimedia.org/wiki/File:Spinning_globe.gif")]
public void WrapOsc8_Wraps_Standalone_Url (string input, string expectedUrl)
{
string actual = Wrap (input);
string expected = LinkWrappedWithOSCs (expectedUrl);
Assert.Equal (expected, actual);
}
[Theory]
[InlineData (
"Visit https://github.com for more info",
"Visit ",
"https://github.com",
" for more info")]
[InlineData (
"Check out https://commons.wikimedia.org/wiki/File:Spinning_globe.gif!",
"Check out ",
"https://commons.wikimedia.org/wiki/File:Spinning_globe.gif",
"!")]
[InlineData (
"URLs: https://example.com and http://other.com",
"URLs: ",
"https://example.com",
" and ",
"http://other.com",
"")]
public void WrapOsc8_Wraps_Urls_In_Text (string input, params string [] segments)
{
// segments: text0, url1, text1, [url2, text2]...
string expected = BuildExpected (segments);
string actual = Wrap (input);
Assert.Equal (expected, actual);
}
private static string BuildExpected (string [] segments)
{
// segments must be: text0, url1, text1, url2, text2, ...
string expected = segments.Length > 0 ? segments [0] : string.Empty;
for (var i = 1; i + 1 < segments.Length; i += 2)
{
string url = segments [i];
string textAfter = segments [i + 1];
expected += LinkWrappedWithOSCs (url);
expected += textAfter;
}
return expected;
}
private static string LinkWrappedWithOSCs (string url, string? display = null)
{
display ??= url;
return EscSeqUtils.OSC_StartHyperlink (url) + display + EscSeqUtils.OSC_EndHyperlink ();
}
private static string Wrap (string input)
{
StringBuilder sb = new (input);
return Osc8UrlLinker.WrapOsc8 (sb).ToString ();
}
}