Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/static_src/autolink.test.js b/static_src/autolink.test.js
new file mode 100644
index 0000000..fcb2af2
--- /dev/null
+++ b/static_src/autolink.test.js
@@ -0,0 +1,948 @@
+import sinon from 'sinon';
+import {assert} from 'chai';
+import {autolink} from './autolink.js';
+import {prpcClient} from 'prpc-client-instance.js';
+
+const components = autolink.Components;
+const markupAutolinks = autolink.markupAutolinks;
+
+describe('autolink', () => {
+ describe('crbug component functions', () => {
+ const {extractRefs, refRegs, replacer} = components.get('01-tracker-crbug');
+
+ it('Extract crbug project and local ids', () => {
+ const match = refRegs[0].exec('https://crbug.com/monorail/1234');
+ refRegs[0].lastIndex = 0;
+ const ref = extractRefs(match);
+ assert.deepEqual(ref, [{projectName: 'monorail', localId: '1234'}]);
+ });
+
+ it('Extract crbug default project name', () => {
+ const match = refRegs[0].exec('http://crbug.com/1234');
+ refRegs[0].lastIndex = 0;
+ const ref = extractRefs(match);
+ assert.deepEqual(ref, [{projectName: 'chromium', localId: '1234'}]);
+ });
+
+ it('Extract crbug passed project name is ignored', () => {
+ const match = refRegs[0].exec('https://crbug.com/1234');
+ refRegs[0].lastIndex = 0;
+ const ref = extractRefs(match, 'foo');
+ assert.deepEqual(ref, [{projectName: 'chromium', localId: '1234'}]);
+ });
+
+ it('Replace crbug with found components', () => {
+ const str = 'crbug.com/monorail/1234';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+ const components = {
+ closedRefs: [
+ {summary: 'Issue summary', localId: 1234, projectName: 'monorail'},
+ {},
+ ]};
+ const actualRun = replacer(match, components);
+ assert.deepEqual(
+ actualRun,
+ [{
+ tag: 'a',
+ css: 'strike-through',
+ href: '/p/monorail/issues/detail?id=1234',
+ title: 'Issue summary',
+ content: str,
+ }],
+ );
+ });
+
+ it('Replace crbug with found components, with comment', () => {
+ const str = 'crbug.com/monorail/1234#c1';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+ const components = {
+ closedRefs: [
+ {summary: 'Issue summary', localId: 1234, projectName: 'monorail'},
+ {},
+ ]};
+ const actualRun = replacer(match, components);
+ assert.deepEqual(
+ actualRun,
+ [{
+ tag: 'a',
+ css: 'strike-through',
+ href: '/p/monorail/issues/detail?id=1234#c1',
+ title: 'Issue summary',
+ content: str,
+ }],
+ );
+ });
+
+ it('Replace crbug with default project_name', () => {
+ const str = 'crbug.com/1234';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+ const components = {
+ openRefs: [
+ {localId: 134},
+ {summary: 'Issue 1234', localId: 1234, projectName: 'chromium'},
+ ],
+ };
+ const actualRun = replacer(match, components);
+ assert.deepEqual(
+ actualRun,
+ [{
+ tag: 'a',
+ href: '/p/chromium/issues/detail?id=1234',
+ css: '',
+ title: 'Issue 1234',
+ content: str,
+ }],
+ );
+ });
+
+ it('Replace crbug incomplete responses', () => {
+ const str = 'crbug.com/1234';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+ const components = {
+ openRefs: [{localId: 1234}, {projectName: 'chromium'}],
+ closedRefs: [{localId: 1234}, {projectName: 'chromium'}],
+ };
+ const actualRun = replacer(match, components);
+ assert.deepEqual(actualRun, [{content: str}]);
+ });
+
+ it('Replace crbug passed project name is ignored', () => {
+ const str = 'crbug.com/1234';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+ const components = {
+ openRefs: [
+ {localId: 134},
+ {summary: 'Issue 1234', localId: 1234, projectName: 'chromium'},
+ ],
+ };
+ const actualRun = replacer(match, components, 'foo');
+ assert.deepEqual(
+ actualRun,
+ [{
+ tag: 'a',
+ href: '/p/chromium/issues/detail?id=1234',
+ css: '',
+ title: 'Issue 1234',
+ content: str,
+ }],
+ );
+ });
+
+ it('Replace crbug with no found components', () => {
+ const str = 'crbug.com/1234';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+ const components = {};
+ const actualRun = replacer(match, components);
+ assert.deepEqual(actualRun, [{content: str}]);
+ });
+
+ it('Replace crbug with no issue summary', () => {
+ const str = 'crbug.com/monorail/1234';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+ const components = {
+ closedRefs: [
+ {localId: 1234, projectName: 'monorail'},
+ {},
+ ]};
+ const actualRun = replacer(match, components);
+ assert.deepEqual(
+ actualRun,
+ [{
+ tag: 'a',
+ css: 'strike-through',
+ href: '/p/monorail/issues/detail?id=1234',
+ title: '',
+ content: str,
+ }],
+ );
+ });
+ });
+
+ describe('regular tracker component functions', () => {
+ const {extractRefs, refRegs, replacer} =
+ components.get('04-tracker-regular');
+ const str = 'bugs=123, monorail:234 or #345 and PROJ:#456';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+
+ it('Extract tracker projects and local ids', () => {
+ const actualRefs = extractRefs(match, 'foo-project');
+ assert.deepEqual(
+ actualRefs,
+ [{projectName: 'foo-project', localId: '123'},
+ {projectName: 'monorail', localId: '234'},
+ {projectName: 'monorail', localId: '345'},
+ {projectName: 'PROJ', localId: '456'}]);
+ });
+
+ it('Replace tracker refs.', () => {
+ const components = {
+ openRefs: [
+ {summary: 'sum', projectName: 'monorail', localId: 888},
+ {summary: 'ma', projectName: 'chromium', localId: '123'},
+ ],
+ closedRefs: [
+ {summary: 'ry', projectName: 'proj', localId: 456},
+ ],
+ };
+ const actualTextRuns = replacer(match, components, 'chromium');
+ assert.deepEqual(
+ actualTextRuns,
+ [
+ {content: 'bugs='},
+ {
+ tag: 'a',
+ href: '/p/chromium/issues/detail?id=123',
+ css: '',
+ title: 'ma',
+ content: '123',
+ },
+ {content: ', '},
+ {content: 'monorail:234'},
+ {content: ' or '},
+ {content: '#345'},
+ {content: ' and '},
+ {
+ tag: 'a',
+ href: '/p/PROJ/issues/detail?id=456',
+ css: 'strike-through',
+ title: 'ry',
+ content: 'PROJ:#456',
+ },
+ ],
+ );
+ });
+
+ it('Replace tracker refs mixed case refs.', () => {
+ const components = {
+ openRefs: [
+ {projectName: 'mOnOrAIl', localId: 234},
+ ],
+ closedRefs: [
+ {projectName: 'LeMuR', localId: 123},
+ ],
+ };
+ const actualTextRuns = replacer(match, components, 'lEmUr');
+ assert.deepEqual(
+ actualTextRuns,
+ [
+ {content: 'bugs='},
+ {
+ tag: 'a',
+ href: '/p/lEmUr/issues/detail?id=123',
+ css: 'strike-through',
+ title: '',
+ content: '123',
+ },
+ {content: ', '},
+ {
+ tag: 'a',
+ href: '/p/monorail/issues/detail?id=234',
+ css: '',
+ title: '',
+ content: 'monorail:234',
+ },
+ {content: ' or '},
+ {content: '#345'},
+ {content: ' and '},
+ {content: 'PROJ:#456'},
+ ],
+ );
+ });
+
+ it('Recognizes Fixed: syntax', () => {
+ const str = 'Fixed : 123, proj:456';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+
+ const components = {
+ openRefs: [
+ {summary: 'summ', projectName: 'chromium', localId: 123},
+ ],
+ closedRefs: [
+ {summary: 'ary', projectName: 'proj', localId: 456},
+ ],
+ };
+
+ const actualTextRuns = replacer(match, components, 'chromium');
+ assert.deepEqual(
+ actualTextRuns,
+ [
+ {
+ tag: 'a',
+ href: '/p/chromium/issues/detail?id=123',
+ css: '',
+ title: 'summ',
+ content: 'Fixed : 123',
+ },
+ {content: ', '},
+ {
+ tag: 'a',
+ href: '/p/proj/issues/detail?id=456',
+ css: 'strike-through',
+ title: 'ary',
+ content: 'proj:456',
+ },
+ ],
+ );
+ });
+ });
+
+ describe('user email component functions', () => {
+ const {extractRefs, refRegs, replacer} = components.get('03-user-emails');
+ const str = 'We should ask User1@gmail.com to confirm.';
+ const match = refRegs[0].exec(str);
+ refRegs[0].lastIndex = 0;
+
+ it('Extract user email', () => {
+ const actualEmail = extractRefs(match, 'unusedProjectName');
+ assert.equal('User1@gmail.com', actualEmail);
+ });
+
+ it('Replace existing user.', () => {
+ const components = {
+ users: [{displayName: 'user2@gmail.com'},
+ {displayName: 'user1@gmail.com'}]};
+ const actualTextRun = replacer(match, components);
+ assert.deepEqual(
+ actualTextRun,
+ [{tag: 'a', href: '/u/User1@gmail.com', content: 'User1@gmail.com'}],
+ );
+ });
+
+ it('Replace non-existent user.', () => {
+ const actualTextRun = replacer(match, {});
+ assert.deepEqual(
+ actualTextRun,
+ [{
+ tag: 'a',
+ href: 'mailto:User1@gmail.com',
+ content: 'User1@gmail.com',
+ }],
+ );
+ });
+ });
+
+ describe('full url component functions.', () => {
+ const {refRegs, replacer} = components.get('02-full-urls');
+
+ it('test full link regex string', () => {
+ const isLinkRE = refRegs[0];
+ const str =
+ 'https://www.go.com ' +
+ 'nospacehttps://www.blah.com http://website.net/other="(}])"><)';
+ let match;
+ const actualMatches = [];
+ while ((match = isLinkRE.exec(str)) !== null) {
+ actualMatches.push(match[0]);
+ }
+ assert.deepEqual(
+ actualMatches,
+ ['https://www.go.com', 'http://website.net/other="(}])">']);
+ });
+
+ it('Replace URL existing http', () => {
+ const match = refRegs[0].exec('link here: (https://website.net/other="here").');
+ refRegs[0].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+ assert.deepEqual(
+ actualTextRuns,
+ [{tag: 'a',
+ href: 'https://website.net/other="here"',
+ content: 'https://website.net/other="here"',
+ },
+ {content: ').'}],
+ );
+ });
+
+ it('Replace URL with short-link as substring', () => {
+ const match = refRegs[0].exec('https://website.net/who/me/yes/you');
+ refRegs[0].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+
+ assert.deepEqual(
+ actualTextRuns,
+ [{tag: 'a',
+ href: 'https://website.net/who/me/yes/you',
+ content: 'https://website.net/who/me/yes/you',
+ }],
+ );
+ });
+
+ it('Replace URL with email as substring', () => {
+ const match = refRegs[0].exec('https://website.net/who/foo@example.com');
+ refRegs[0].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+
+ assert.deepEqual(
+ actualTextRuns,
+ [{tag: 'a',
+ href: 'https://website.net/who/foo@example.com',
+ content: 'https://website.net/who/foo@example.com',
+ }],
+ );
+ });
+ });
+
+ describe('shorthand url component functions.', () => {
+ const {refRegs, replacer} = components.get('05-linkify-shorthand');
+
+ it('Short link does not match URL with short-link as substring', () => {
+ refRegs[0].lastIndex = 0;
+ assert.isNull(refRegs[0].exec('https://website.net/who/me/yes/you'));
+ });
+
+ it('test short link regex string', () => {
+ const shortLinkRE = refRegs[0];
+ const str =
+ 'go/shortlinks ./_go/shortlinks bo/short bo/1234 ' +
+ 'https://who/shortlinks go/hey/?wct=(go)';
+ let match;
+ const actualMatches = [];
+ while ((match = shortLinkRE.exec(str)) !== null) {
+ actualMatches.push(match[0]);
+ }
+ assert.deepEqual(
+ actualMatches,
+ ['go/shortlinks', ' https://who/shortlinks', ' go/hey/?wct=(go)'],
+ );
+ });
+
+ it('test numeric short link regex string', () => {
+ const shortNumLinkRE = refRegs[1];
+ const str = 'go/nono omg/ohno omg/123 .cl/123 b/1234';
+ let match;
+ const actualMatches = [];
+ while ((match = shortNumLinkRE.exec(str)) !== null) {
+ actualMatches.push(match[0]);
+ }
+ assert.deepEqual(actualMatches, [' omg/123', ' b/1234']);
+ });
+
+ it('test fuchsia short links', () => {
+ const shortNumLinkRE = refRegs[1];
+ const str = 'ignore fxr/123 fxrev/789 fxb/456 tqr/123 ';
+ let match;
+ const actualMatches = [];
+ while ((match = shortNumLinkRE.exec(str)) !== null) {
+ actualMatches.push(match[0]);
+ }
+ assert.deepEqual(actualMatches, [' fxr/123', ' fxrev/789', ' fxb/456',
+ ' tqr/123']);
+ });
+
+ it('test implied link regex string', () => {
+ const impliedLinkRE = refRegs[2];
+ const str = 'incomplete.com .help.com hey.net/other="(blah)"';
+ let match;
+ const actualMatches = [];
+ while ((match = impliedLinkRE.exec(str)) !== null) {
+ actualMatches.push(match[0]);
+ }
+ assert.deepEqual(
+ actualMatches, ['incomplete.com', ' hey.net/other="(blah)"']);
+ });
+
+ it('test implied link alternate domains', () => {
+ const impliedLinkRE = refRegs[2];
+ const str = 'what.net hey.edu google.org fuchsia.dev ignored.domain';
+ let match;
+ const actualMatches = [];
+ while ((match = impliedLinkRE.exec(str)) !== null) {
+ actualMatches.push(match[0]);
+ }
+ assert.deepEqual(
+ actualMatches, ['what.net', ' hey.edu', ' google.org',
+ ' fuchsia.dev']);
+ });
+
+ it('Replace URL plain text', () => {
+ const match = refRegs[2].exec('link here: (website.net/other="here").');
+ refRegs[2].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+ assert.deepEqual(
+ actualTextRuns,
+ [{content: '('},
+ {tag: 'a',
+ href: 'https://website.net/other="here"',
+ content: 'website.net/other="here"',
+ },
+ {content: ').'}],
+ );
+ });
+
+ it('Replace short link existing http', () => {
+ const match = refRegs[0].exec('link here: (http://who/me).');
+ refRegs[0].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+ assert.deepEqual(
+ actualTextRuns,
+ [{content: '('},
+ {tag: 'a',
+ href: 'http://who/me',
+ content: 'http://who/me',
+ },
+ {content: ').'}],
+ );
+ });
+
+ it('Replace short-link plain text', () => {
+ const match = refRegs[0].exec('link here: (who/me).');
+ refRegs[0].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+ assert.deepEqual(
+ actualTextRuns,
+ [{content: '('},
+ {tag: 'a',
+ href: 'http://who/me',
+ content: 'who/me',
+ },
+ {content: ').'}],
+ );
+ });
+
+ it('Replace short-link plain text initial characters', () => {
+ const match = refRegs[0].exec('link here: who/me');
+ refRegs[0].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+ assert.deepEqual(
+ actualTextRuns,
+ [{content: ' '},
+ {tag: 'a',
+ href: 'http://who/me',
+ content: 'who/me',
+ }],
+ );
+ });
+
+ it('Replace URL short link', () => {
+ ['go', 'g', 'shortn', 'who', 'teams'].forEach((prefix) => {
+ const match = refRegs[0].exec(`link here: (${prefix}/abcd).`);
+ refRegs[0].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+ assert.deepEqual(
+ actualTextRuns,
+ [{content: '('},
+ {tag: 'a',
+ href: `http://${prefix}/abcd`,
+ content: `${prefix}/abcd`,
+ },
+ {content: ').'}],
+ );
+ });
+ });
+
+ it('Replace URL numeric short link', () => {
+ ['b', 't', 'o', 'omg', 'cl', 'cr'].forEach((prefix) => {
+ const match = refRegs[1].exec(`link here: (${prefix}/1234).`);
+ refRegs[1].lastIndex = 0;
+ const actualTextRuns = replacer(match);
+ assert.deepEqual(
+ actualTextRuns,
+ [{content: '('},
+ {tag: 'a',
+ href: `http://${prefix}/1234`,
+ content: `${prefix}/1234`,
+ }],
+ );
+ });
+ });
+ });
+
+ describe('versioncontrol component functions.', () => {
+ const {refRegs, replacer} = components.get('06-versioncontrol');
+
+ it('test git hash regex', () => {
+ const gitHashRE = refRegs[0];
+ const str =
+ 'r63b72a71d5fbce6739c51c3846dd94bd62b91091 blha blah ' +
+ 'Revision 63b72a71d5fbce6739c51c3846dd94bd62b91091 blah balh ' +
+ '63b72a71d5fbce6739c51c3846dd94bd62b91091 ' +
+ 'Revision63b72a71d5fbce6739c51c3846dd94bd62b91091';
+ let match;
+ const actualMatches = [];
+ while ((match = gitHashRE.exec(str)) !== null) {
+ actualMatches.push(match[0]);
+ }
+ assert.deepEqual(
+ actualMatches, [
+ 'r63b72a71d5fbce6739c51c3846dd94bd62b91091',
+ 'Revision 63b72a71d5fbce6739c51c3846dd94bd62b91091',
+ '63b72a71d5fbce6739c51c3846dd94bd62b91091',
+ ]);
+ });
+
+ it('test svn regex', () => {
+ const svnRE = refRegs[1];
+ const str =
+ 'r1234 blah blah ' +
+ 'Revision 123456 blah balh ' +
+ 'r12345678' +
+ '1234';
+ let match;
+ const actualMatches = [];
+ while ((match = svnRE.exec(str)) !== null) {
+ actualMatches.push(match[0]);
+ }
+ assert.deepEqual(
+ actualMatches, [
+ 'r1234',
+ 'Revision 123456',
+ ]);
+ });
+
+ it('replace revision refs plain text', () => {
+ const str = 'r63b72a71d5fbce6739c51c3846dd94bd62b91091';
+ const match = refRegs[0].exec(str);
+ const actualTextRuns = replacer(
+ match, null, null, 'https://crrev.com/{revnum}');
+ refRegs[0].lastIndex = 0;
+ assert.deepEqual(
+ actualTextRuns,
+ [{
+ content: 'r63b72a71d5fbce6739c51c3846dd94bd62b91091',
+ tag: 'a',
+ href: 'https://crrev.com/63b72a71d5fbce6739c51c3846dd94bd62b91091',
+ }]);
+ });
+
+ it('replace revision refs plain text different template', () => {
+ const str = 'r63b72a71d5fbce6739c51c3846dd94bd62b91091';
+ const match = refRegs[0].exec(str);
+ const actualTextRuns = replacer(
+ match, null, null, 'https://foo.bar/{revnum}/baz');
+ refRegs[0].lastIndex = 0;
+ assert.deepEqual(
+ actualTextRuns,
+ [{
+ content: 'r63b72a71d5fbce6739c51c3846dd94bd62b91091',
+ tag: 'a',
+ href: 'https://foo.bar/63b72a71d5fbce6739c51c3846dd94bd62b91091/baz',
+ }]);
+ });
+ });
+
+
+ describe('markupAutolinks tests', () => {
+ const componentRefs = new Map();
+ componentRefs.set('01-tracker-crbug', {
+ openRefs: [],
+ closedRefs: [{projectName: 'chromium', localId: 99}],
+ });
+ componentRefs.set('04-tracker-regular', {
+ openRefs: [{summary: 'monorail', projectName: 'monorail', localId: 123}],
+ closedRefs: [{projectName: 'chromium', localId: 456}],
+ });
+ componentRefs.set('03-user-emails', {
+ users: [{displayName: 'user2@example.com'}],
+ });
+
+ it('empty string does not cause error', () => {
+ const actualTextRuns = markupAutolinks('', componentRefs);
+ assert.deepEqual(actualTextRuns, []);
+ });
+
+ it('no nested autolinking', () => {
+ const plainString = 'test <b>autolinking go/testlink</b> is not nested';
+ const actualTextRuns = markupAutolinks(plainString, componentRefs);
+ assert.deepEqual(
+ actualTextRuns, [
+ {content: 'test '},
+ {content: 'autolinking go/testlink', tag: 'b'},
+ {content: ' is not nested'},
+ ]);
+ });
+
+ it('URLs are autolinked', () => {
+ const plainString = 'this http string contains http://google.com for you';
+ const actualTextRuns = markupAutolinks(plainString, componentRefs);
+ assert.deepEqual(
+ actualTextRuns, [
+ {content: 'this http string contains '},
+ {content: 'http://google.com', tag: 'a', href: 'http://google.com'},
+ {content: ' for you'},
+ ]);
+ });
+
+ it('different component types are correctly linked', () => {
+ const plainString = 'test (User2@example.com and crbug.com/99) get link';
+ const actualTextRuns = markupAutolinks(plainString, componentRefs);
+ assert.deepEqual(
+ actualTextRuns,
+ [
+ {
+ content: 'test (',
+ },
+ {
+ content: 'User2@example.com',
+ tag: 'a',
+ href: '/u/User2@example.com',
+ },
+ {
+ content: ' and ',
+ },
+ {
+ content: 'crbug.com/99',
+ tag: 'a',
+ href: '/p/chromium/issues/detail?id=99',
+ title: '',
+ css: 'strike-through',
+ },
+ {
+ content: ') get link',
+ },
+ ],
+ );
+ });
+
+ it('Invalid issue refs do not get linked', () => {
+ const plainString =
+ 'bug123, bug 123a, bug-123 and https://bug:123.example.com ' +
+ 'do not get linked.';
+ const actualTextRuns= markupAutolinks(
+ plainString, componentRefs, 'chromium');
+ assert.deepEqual(
+ actualTextRuns,
+ [
+ {
+ content: 'bug123, bug 123a, bug-123 and ',
+ },
+ {
+ content: 'https://bug:123.example.com',
+ tag: 'a',
+ href: 'https://bug:123.example.com',
+ },
+ {
+ content: ' do not get linked.',
+ },
+ ]);
+ });
+
+ it('Only existing issues get linked', () => {
+ const plainString =
+ 'only existing bugs = 456, monorail:123, 234 and chromium:345 get ' +
+ 'linked';
+ const actualTextRuns = markupAutolinks(
+ plainString, componentRefs, 'chromium');
+ assert.deepEqual(
+ actualTextRuns,
+ [
+ {
+ content: 'only existing ',
+ },
+ {
+ content: 'bugs = ',
+ },
+ {
+ content: '456',
+ tag: 'a',
+ href: '/p/chromium/issues/detail?id=456',
+ title: '',
+ css: 'strike-through',
+ },
+ {
+ content: ', ',
+ },
+ {
+ content: 'monorail:123',
+ tag: 'a',
+ href: '/p/monorail/issues/detail?id=123',
+ title: 'monorail',
+ css: '',
+ },
+ {
+ content: ', ',
+ },
+ {
+ content: '234',
+ },
+ {
+ content: ' and ',
+ },
+ {
+ content: 'chromium:345',
+ },
+ {
+ content: ' ',
+ },
+ {
+ content: 'get linked',
+ },
+ ],
+ );
+ });
+
+ it('multilined bolds are not bolded', () => {
+ const plainString =
+ '<b>no multiline bolding \n' +
+ 'not allowed go/survey is still linked</b>';
+ const actualTextRuns = markupAutolinks(plainString, componentRefs);
+ assert.deepEqual(
+ actualTextRuns, [
+ {content: '<b>no multiline bolding '},
+ {tag: 'br'},
+ {content: 'not allowed'},
+ {content: ' '},
+ {content: 'go/survey', tag: 'a', href: 'http://go/survey'},
+ {content: ' is still linked</b>'},
+ ]);
+
+ const plainString2 =
+ '<b>no multiline bold \rwith carriage \r\nreturns</b>';
+ const actualTextRuns2 = markupAutolinks(plainString2, componentRefs);
+
+ assert.deepEqual(
+ actualTextRuns2, [
+ {content: '<b>no multiline bold '},
+ {tag: 'br'},
+ {content: 'with carriage '},
+ {tag: 'br'},
+ {content: 'returns</b>'},
+ ]);
+ });
+
+ // Check that comment references are properly linked.
+ it('comments are correctly linked', () => {
+ const plainString =
+ 'comment1, comment : 5, Comment =10, comment #4, #c57';
+ const actualTextRuns = markupAutolinks(plainString, componentRefs);
+ assert.deepEqual(
+ actualTextRuns, [
+ {
+ content: 'comment1',
+ tag: 'a',
+ href: '#c1',
+ },
+ {
+ content: ', ',
+ },
+ {
+ content: 'comment : 5',
+ tag: 'a',
+ href: '#c5',
+ },
+ {
+ content: ', ',
+ },
+ {
+ content: 'Comment =10',
+ tag: 'a',
+ href: '#c10',
+ },
+ {
+ content: ', ',
+ },
+ {
+ content: 'comment #4',
+ tag: 'a',
+ href: '#c4',
+ },
+ {
+ content: ', ',
+ },
+ {
+ content: '#c57',
+ tag: 'a',
+ href: '#c57',
+ },
+ ],
+ );
+ });
+
+ // Check that improperly formatted comment references do not get linked.
+ it('comments that should not be linked', () => {
+ const plainString =
+ 'comment number 4, comment-4, comment= # 5, comment#c56';
+ const actualTextRuns = markupAutolinks(plainString, componentRefs);
+ assert.deepEqual(
+ actualTextRuns, [
+ {
+ content: 'comment number 4, comment-4, comment= # 5, comment#c56',
+ },
+ ],
+ );
+ });
+
+ // Check that issue/comment references are properly linked.
+ it('issue/comment that should be linked', () => {
+ const plainString =
+ 'issue 2 comment 3, issue2 comment 9, bug #3 comment=4';
+ const actualTextRuns = markupAutolinks(plainString, componentRefs);
+ assert.deepEqual(
+ actualTextRuns, [
+ {
+ content: 'issue 2 comment 3',
+ tag: 'a',
+ href: '?id=2#c3',
+ },
+ {
+ content: ', ',
+ },
+ {
+ content: 'issue2 comment 9',
+ tag: 'a',
+ href: '?id=2#c9',
+ },
+ {
+ content: ', ',
+ },
+ {
+ content: 'bug #3 comment=4',
+ tag: 'a',
+ href: '?id=3#c4',
+ },
+ ],
+ );
+ });
+
+ // Check that improperly formatted issue/comment references do not get linked.
+ it('issue/comment that should not be linked', () => {
+ const plainString =
+ 'theissue 2comment 3, issue2comment 9';
+ const actualTextRuns = markupAutolinks(plainString, componentRefs);
+ assert.deepEqual(
+ actualTextRuns, [
+ {
+ content: 'theissue 2comment 3, issue2comment 9',
+ },
+ ],
+ );
+ });
+ });
+
+ describe('getReferencedArtifacts', () => {
+ beforeEach(() => {
+ sinon.stub(prpcClient, 'call').returns(Promise.resolve({}));
+ });
+
+ afterEach(() => {
+ prpcClient.call.restore();
+ });
+
+ it('filters invalid issue refs', async () => {
+ const comments = [
+ {
+ content: 'issue 0 issue 1 Bug: chromium:3 Bug: chromium:0',
+ },
+ ];
+ autolink.getReferencedArtifacts(comments, 'proj');
+ assert.isTrue(prpcClient.call.calledWith(
+ 'monorail.Issues',
+ 'ListReferencedIssues',
+ {
+ issueRefs: [
+ {projectName: 'proj', localId: '1'},
+ {projectName: 'chromium', localId: '3'},
+ ],
+ },
+ ));
+ });
+ });
+});