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'},
+            ],
+          },
+      ));
+    });
+  });
+});