Skip to content

Commit a433003

Browse files
finnurbrekiDevtools-frontend LUCI CQ
authored andcommitted
[RPP]: Add a test for the nuances in TimelineUIUtils url regex.
Bug: 436356278 Change-Id: I1f3ad2abe5f4be8636f0f8d82846739a892bc961 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6922732 Commit-Queue: Finnur Thorarinsson <[email protected]> Reviewed-by: Paul Irish <[email protected]>
1 parent 97f4e16 commit a433003

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

front_end/panels/timeline/TimelineUIUtils.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,4 +1872,55 @@ in the middle or at the end: <button class="devtools-link text-button link-style
18721872
'so data:text/html,%3Cscript%3Ealert%28%27hi%27%29%3B%3C%2Fscript%3E and www.site.com remain plain');
18731873
});
18741874
});
1875+
1876+
describe('URL regex in parseStringForLinks', () => {
1877+
const urlRegex = Timeline.TimelineUIUtils.URL_REGEX;
1878+
1879+
const testCases: Array<{url: string, matches: boolean}> = [
1880+
// Matching URLs:
1881+
{url: 'http://example.com', matches: true},
1882+
{url: 'https://example.com', matches: true},
1883+
{url: 'https://www.xn--examl-gsa.com', matches: true},
1884+
{url: 'https://example.com/path/to/resource', matches: true},
1885+
{url: 'https://example.com?query=param&another=param', matches: true},
1886+
{url: 'https://example.com#fragment', matches: true},
1887+
{url: 'ftp://files.example.com', matches: true},
1888+
{url: 'custom-scheme://resource/123', matches: true},
1889+
{url: 'ext://node/123', matches: true},
1890+
{url: 'http://a.z', matches: true},
1891+
{url: '9http://example.com', matches: true},
1892+
// URLs with trailing punctuation should still match the URL part.
1893+
{url: 'https://example.com(', matches: true},
1894+
{url: 'https://example.com)', matches: true},
1895+
{url: 'https://example.com[', matches: true},
1896+
{url: 'https://example.com]', matches: true},
1897+
{url: 'https://example.com{', matches: true},
1898+
{url: 'https://example.com}', matches: true},
1899+
{url: 'https://example.com,', matches: true},
1900+
{url: 'https://example.com:', matches: true},
1901+
{url: 'https://example.com;', matches: true},
1902+
{url: 'https://example.com.', matches: true},
1903+
{url: 'https://example.com!', matches: true},
1904+
{url: 'https://example.com?', matches: true},
1905+
1906+
// Non-matching strings:
1907+
{url: 'www.example.com', matches: false},
1908+
{url: 'example.com', matches: false},
1909+
{url: 'data:text/html,hello', matches: false},
1910+
{url: 'mailto:[email protected]', matches: false},
1911+
{url: 'javascript:void(0)', matches: false},
1912+
{url: 'not a url', matches: false},
1913+
{url: 'http://', matches: false},
1914+
{url: 'https://a', matches: false},
1915+
{url: 'http://a .com', matches: false},
1916+
{url: 'http://a".com', matches: false},
1917+
{url: 'ht://example.com)', matches: false}, // protocol must be 3 or more letters.
1918+
];
1919+
1920+
for (const {url, matches} of testCases) {
1921+
it(`correctly validates "${url}" as ${matches ? 'matching' : 'not matching'}`, () => {
1922+
assert.strictEqual(urlRegex.test(url), matches);
1923+
});
1924+
}
1925+
});
18751926
});

front_end/panels/timeline/TimelineUIUtils.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ const UIStrings = {
476476
const str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineUIUtils.ts', UIStrings);
477477
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
478478

479+
// Look for scheme:// plus text and exclude any punctuation at the end.
480+
export const URL_REGEX = /(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\/\/)[^\s"]{2,}[^\s"'\)\}\],:;.!?]/u;
481+
479482
let eventDispatchDesciptors: EventDispatchTypeDescriptor[];
480483

481484
let colorGenerator: Common.Color.Generator;
@@ -897,9 +900,7 @@ export class TimelineUIUtils {
897900
* of the link is the URL, so the visible string to the user is unchanged.
898901
*/
899902
static parseStringForLinks(rawString: string): DocumentFragment {
900-
// Look for scheme:// plus text and exclude any punctuation at the end.
901-
const urlRegex = /(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\/\/)[^\s"]{2,}[^\s"'\)\}\],:;.!?]/u;
902-
const results = TextUtils.TextUtils.Utils.splitStringByRegexes(rawString, [urlRegex]);
903+
const results = TextUtils.TextUtils.Utils.splitStringByRegexes(rawString, [URL_REGEX]);
903904
const nodes = results.map(result => {
904905
if (result.regexIndex === -1) {
905906
return result.value;

0 commit comments

Comments
 (0)