X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2FLinkifier.test.ts;h=132ce5f06e5258780ad48ee18c83f30aff2b0fd4;hb=8ede1fc9d2d0ef91ffcc9ad53587f19cdc6d0427;hp=16e388faff80bb1afec4f4caef453353e93d8426;hpb=361894194a3e84755b1a20f42f5b3b08e5701234;p=mirror_xterm.js.git diff --git a/src/Linkifier.test.ts b/src/Linkifier.test.ts index 16e388f..132ce5f 100644 --- a/src/Linkifier.test.ts +++ b/src/Linkifier.test.ts @@ -8,15 +8,16 @@ import { Linkifier } from './Linkifier'; import { LinkMatcher } from './Types'; class TestLinkifier extends Linkifier { - constructor(document: Document, rows: HTMLElement[]) { + constructor() { Linkifier.TIME_BEFORE_LINKIFY = 0; - super(document, rows); + super(); } public get linkMatchers(): LinkMatcher[] { return this._linkMatchers; } } describe('Linkifier', () => { + let dom: jsdom.JSDOM; let window: Window; let document: Document; @@ -24,16 +25,11 @@ describe('Linkifier', () => { let rows: HTMLElement[]; let linkifier: TestLinkifier; - beforeEach(done => { - rows = []; - jsdom.env('', (err, w) => { - window = w; - document = window.document; - linkifier = new TestLinkifier(document, rows); - container = document.createElement('div'); - document.body.appendChild(container); - done(); - }); + beforeEach(() => { + dom = new jsdom.JSDOM(''); + window = dom.window; + document = window.document; + linkifier = new TestLinkifier(); }); function addRow(html: string) { @@ -43,119 +39,154 @@ describe('Linkifier', () => { rows.push(element); } - function clickElement(element: Node) { - const event = document.createEvent('MouseEvent'); - event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); - element.dispatchEvent(event); - } - - describe('http links', () => { - function assertLinkifiesEntireRow(uri: string, done: MochaDone) { - addRow(uri); - linkifier.linkifyRow(0); - setTimeout(() => { - assert.equal((rows[0].firstChild).tagName, 'A'); - assert.equal((rows[0].firstChild).textContent, uri); + describe('before attachToDom', () => { + it('should allow link matcher registration', done => { + assert.doesNotThrow(() => { + const linkMatcherId = linkifier.registerLinkMatcher(/foo/, () => {}); + assert.isTrue(linkifier.deregisterLinkMatcher(linkMatcherId)); done(); - }, 0); - } - it('should allow ~ character in URI path', done => assertLinkifiesEntireRow('http://foo.com/a~b#c~d?e~f', done)); + }); + }); }); - describe('link matcher', () => { - function assertLinkifiesRow(rowText: string, linkMatcherRegex: RegExp, expectedHtml: string, done: MochaDone) { - addRow(rowText); - linkifier.registerLinkMatcher(linkMatcherRegex, () => {}); - linkifier.linkifyRow(0); - // Allow linkify to happen - setTimeout(() => { - assert.equal(rows[0].innerHTML, expectedHtml); - done(); - }, 0); - } - it('should match a single link', done => { - assertLinkifiesRow('foo', /foo/, 'foo', done); - }); - it('should match a single link at the start of a text node', done => { - assertLinkifiesRow('foo bar', /foo/, 'foo bar', done); - }); - it('should match a single link in the middle of a text node', done => { - assertLinkifiesRow('foo bar baz', /bar/, 'foo bar baz', done); - }); - it('should match a single link at the end of a text node', done => { - assertLinkifiesRow('foo bar', /bar/, 'foo bar', done); - }); - it('should match a link after a link at the start of a text node', done => { - assertLinkifiesRow('foo bar', /foo|bar/, 'foo bar', done); - }); - it('should match a link after a link in the middle of a text node', done => { - assertLinkifiesRow('foo bar baz', /bar|baz/, 'foo bar baz', done); - }); - it('should match a link immediately after a link at the end of a text node', done => { - assertLinkifiesRow('foo barbaz', /bar|baz/, 'foo barbaz', done); + describe('after attachToDom', () => { + beforeEach(() => { + rows = []; + linkifier.attachToDom(document, rows); + container = document.createElement('div'); + document.body.appendChild(container); }); - }); - describe('validationCallback', () => { - it('should enable link if true', done => { - addRow('test'); - linkifier.registerLinkMatcher(/test/, () => done(), { - validationCallback: (url, cb) => { - cb(true); + function clickElement(element: Node) { + const event = document.createEvent('MouseEvent'); + event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + element.dispatchEvent(event); + } + + function assertLinkifiesEntireRow(uri: string, done: MochaDone) { + addRow(uri); + linkifier.linkifyRow(0); + setTimeout(() => { assert.equal((rows[0].firstChild).tagName, 'A'); - setTimeout(() => clickElement(rows[0].firstChild), 0); - } - }); - linkifier.linkifyRow(0); - }); + assert.equal((rows[0].firstChild).textContent, uri); + done(); + }, 0); + } - it('should disable link if false', done => { - addRow('test'); - linkifier.registerLinkMatcher(/test/, () => assert.fail(), { - validationCallback: (url, cb) => { - cb(false); + describe('http links', () => { + function assertLinkifiesEntireRow(uri: string, done: MochaDone) { + addRow(uri); + linkifier.linkifyRow(0); + setTimeout(() => { assert.equal((rows[0].firstChild).tagName, 'A'); - setTimeout(() => clickElement(rows[0].firstChild), 0); - } + assert.equal((rows[0].firstChild).textContent, uri); + done(); + }, 0); + } + it('should allow ~ character in URI path', done => assertLinkifiesEntireRow('http://foo.com/a~b#c~d?e~f', done)); + }); + + describe('link matcher', () => { + function assertLinkifiesRow(rowText: string, linkMatcherRegex: RegExp, expectedHtml: string, done: MochaDone) { + addRow(rowText); + linkifier.registerLinkMatcher(linkMatcherRegex, () => {}); + linkifier.linkifyRow(0); + // Allow linkify to happen + setTimeout(() => { + assert.equal(rows[0].innerHTML, expectedHtml); + done(); + }, 0); + } + it('should match a single link', done => { + assertLinkifiesRow('foo', /foo/, 'foo', done); + }); + it('should match a single link at the start of a text node', done => { + assertLinkifiesRow('foo bar', /foo/, 'foo bar', done); + }); + it('should match a single link in the middle of a text node', done => { + assertLinkifiesRow('foo bar baz', /bar/, 'foo bar baz', done); + }); + it('should match a single link at the end of a text node', done => { + assertLinkifiesRow('foo bar', /bar/, 'foo bar', done); + }); + it('should match a link after a link at the start of a text node', done => { + assertLinkifiesRow('foo bar', /foo|bar/, 'foo bar', done); + }); + it('should match a link after a link in the middle of a text node', done => { + assertLinkifiesRow('foo bar baz', /bar|baz/, 'foo bar baz', done); + }); + it('should match a link immediately after a link at the end of a text node', done => { + assertLinkifiesRow('foo barbaz', /bar|baz/, 'foo barbaz', done); + }); + it('should not duplicate text after a unicode character (wrapped in a span)', done => { + // This is a regression test for an issue that came about when using + // an oh-my-zsh theme that added the large blue diamond unicode + // character (U+1F537) which caused the path to be duplicated. See #642. + assertLinkifiesRow('echo \'🔷foo\'', /foo/, 'echo \'🔷foo\'', done); }); - linkifier.linkifyRow(0); - // Allow time for the click to be performed - setTimeout(() => done(), 10); }); - it('should trigger for multiple link matches on one row', done => { - addRow('test test'); - let count = 0; - linkifier.registerLinkMatcher(/test/, () => assert.fail(), { - validationCallback: (url, cb) => { - count += 1; - if (count === 2) { - done(); + describe('validationCallback', () => { + it('should enable link if true', done => { + addRow('test'); + linkifier.registerLinkMatcher(/test/, () => done(), { + validationCallback: (url, element, cb) => { + cb(true); + assert.equal((rows[0].firstChild).tagName, 'A'); + setTimeout(() => clickElement(rows[0].firstChild), 0); } - cb(false); - } + }); + linkifier.linkifyRow(0); }); - linkifier.linkifyRow(0); - }); - }); - describe('priority', () => { - it('should order the list from highest priority to lowest #1', () => { - const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: 1 }); - const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: -1 }); - assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [aId, 0, bId]); - }); + it('should disable link if false', done => { + addRow('test'); + linkifier.registerLinkMatcher(/test/, () => assert.fail(), { + validationCallback: (url, element, cb) => { + cb(false); + assert.equal((rows[0].firstChild).tagName, 'A'); + setTimeout(() => clickElement(rows[0].firstChild), 0); + } + }); + linkifier.linkifyRow(0); + // Allow time for the click to be performed + setTimeout(() => done(), 10); + }); - it('should order the list from highest priority to lowest #2', () => { - const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: -1 }); - const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: 1 }); - assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [bId, 0, aId]); + it('should trigger for multiple link matches on one row', done => { + addRow('test test'); + let count = 0; + linkifier.registerLinkMatcher(/test/, () => assert.fail(), { + validationCallback: (url, element, cb) => { + count += 1; + if (count === 2) { + done(); + } + cb(false); + } + }); + linkifier.linkifyRow(0); + }); }); - it('should order items of equal priority in the order they are added', () => { - const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: 0 }); - const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: 0 }); - assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [0, aId, bId]); + describe('priority', () => { + it('should order the list from highest priority to lowest #1', () => { + const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: 1 }); + const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: -1 }); + assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [aId, 0, bId]); + }); + + it('should order the list from highest priority to lowest #2', () => { + const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: -1 }); + const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: 1 }); + assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [bId, 0, aId]); + }); + + it('should order items of equal priority in the order they are added', () => { + const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: 0 }); + const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: 0 }); + assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [0, aId, bId]); + }); }); }); });