| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- #nullable enable
- using System.Text;
- using Xunit.Abstractions;
- namespace Terminal.Gui.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 ();
- }
- }
|