]> git.proxmox.com Git - mirror_xterm.js.git/blob - src/Linkifier.test.ts
Merge pull request #623 from Tyriar/612_multiple_links_in_row
[mirror_xterm.js.git] / src / Linkifier.test.ts
1 /**
2 * @license MIT
3 */
4 import jsdom = require('jsdom');
5 import { assert } from 'chai';
6 import { ITerminal, ILinkifier } from './Interfaces';
7 import { Linkifier } from './Linkifier';
8 import { LinkMatcher } from './Types';
9
10 class TestLinkifier extends Linkifier {
11 constructor() {
12 Linkifier.TIME_BEFORE_LINKIFY = 0;
13 super();
14 }
15
16 public get linkMatchers(): LinkMatcher[] { return this._linkMatchers; }
17 }
18
19 describe('Linkifier', () => {
20 let window: Window;
21 let document: Document;
22
23 let container: HTMLElement;
24 let rows: HTMLElement[];
25 let linkifier: TestLinkifier;
26
27 beforeEach(done => {
28 jsdom.env('', (err, w) => {
29 window = w;
30 document = window.document;
31 linkifier = new TestLinkifier();
32 done();
33 });
34 });
35
36 function addRow(html: string) {
37 const element = document.createElement('div');
38 element.innerHTML = html;
39 container.appendChild(element);
40 rows.push(element);
41 }
42
43 describe('before attachToDom', () => {
44 it('should allow link matcher registration', done => {
45 assert.doesNotThrow(() => {
46 const linkMatcherId = linkifier.registerLinkMatcher(/foo/, () => {});
47 assert.isTrue(linkifier.deregisterLinkMatcher(linkMatcherId));
48 done();
49 });
50 });
51 });
52
53 describe('after attachToDom', () => {
54 beforeEach(() => {
55 rows = [];
56 linkifier.attachToDom(document, rows);
57 container = document.createElement('div');
58 document.body.appendChild(container);
59 });
60
61 function clickElement(element: Node) {
62 const event = document.createEvent('MouseEvent');
63 event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
64 element.dispatchEvent(event);
65 }
66
67 function assertLinkifiesEntireRow(uri: string, done: MochaDone) {
68 addRow(uri);
69 linkifier.linkifyRow(0);
70 setTimeout(() => {
71 assert.equal((<HTMLElement>rows[0].firstChild).tagName, 'A');
72 assert.equal((<HTMLElement>rows[0].firstChild).textContent, uri);
73 done();
74 }, 0);
75 }
76
77 describe('http links', () => {
78 function assertLinkifiesEntireRow(uri: string, done: MochaDone) {
79 addRow(uri);
80 linkifier.linkifyRow(0);
81 setTimeout(() => {
82 assert.equal((<HTMLElement>rows[0].firstChild).tagName, 'A');
83 assert.equal((<HTMLElement>rows[0].firstChild).textContent, uri);
84 done();
85 }, 0);
86 }
87 it('should allow ~ character in URI path', done => assertLinkifiesEntireRow('http://foo.com/a~b#c~d?e~f', done));
88 });
89
90 describe('link matcher', () => {
91 function assertLinkifiesRow(rowText: string, linkMatcherRegex: RegExp, expectedHtml: string, done: MochaDone) {
92 addRow(rowText);
93 linkifier.registerLinkMatcher(linkMatcherRegex, () => {});
94 linkifier.linkifyRow(0);
95 // Allow linkify to happen
96 setTimeout(() => {
97 assert.equal(rows[0].innerHTML, expectedHtml);
98 done();
99 }, 0);
100 }
101 it('should match a single link', done => {
102 assertLinkifiesRow('foo', /foo/, '<a>foo</a>', done);
103 });
104 it('should match a single link at the start of a text node', done => {
105 assertLinkifiesRow('foo bar', /foo/, '<a>foo</a> bar', done);
106 });
107 it('should match a single link in the middle of a text node', done => {
108 assertLinkifiesRow('foo bar baz', /bar/, 'foo <a>bar</a> baz', done);
109 });
110 it('should match a single link at the end of a text node', done => {
111 assertLinkifiesRow('foo bar', /bar/, 'foo <a>bar</a>', done);
112 });
113 it('should match a link after a link at the start of a text node', done => {
114 assertLinkifiesRow('foo bar', /foo|bar/, '<a>foo</a> <a>bar</a>', done);
115 });
116 it('should match a link after a link in the middle of a text node', done => {
117 assertLinkifiesRow('foo bar baz', /bar|baz/, 'foo <a>bar</a> <a>baz</a>', done);
118 });
119 it('should match a link immediately after a link at the end of a text node', done => {
120 assertLinkifiesRow('<span>foo bar</span>baz', /bar|baz/, '<span>foo <a>bar</a></span><a>baz</a>', done);
121 });
122 });
123
124 describe('validationCallback', () => {
125 it('should enable link if true', done => {
126 addRow('test');
127 linkifier.registerLinkMatcher(/test/, () => done(), {
128 validationCallback: (url, cb) => {
129 cb(true);
130 assert.equal((<HTMLElement>rows[0].firstChild).tagName, 'A');
131 setTimeout(() => clickElement(rows[0].firstChild), 0);
132 }
133 });
134 linkifier.linkifyRow(0);
135 });
136
137 it('should disable link if false', done => {
138 addRow('test');
139 linkifier.registerLinkMatcher(/test/, () => assert.fail(), {
140 validationCallback: (url, cb) => {
141 cb(false);
142 assert.equal((<HTMLElement>rows[0].firstChild).tagName, 'A');
143 setTimeout(() => clickElement(rows[0].firstChild), 0);
144 }
145 });
146 linkifier.linkifyRow(0);
147 // Allow time for the click to be performed
148 setTimeout(() => done(), 10);
149 });
150
151 it('should trigger for multiple link matches on one row', done => {
152 addRow('test test');
153 let count = 0;
154 linkifier.registerLinkMatcher(/test/, () => assert.fail(), {
155 validationCallback: (url, cb) => {
156 count += 1;
157 if (count === 2) {
158 done();
159 }
160 cb(false);
161 }
162 });
163 linkifier.linkifyRow(0);
164 });
165 });
166
167 describe('priority', () => {
168 it('should order the list from highest priority to lowest #1', () => {
169 const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: 1 });
170 const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: -1 });
171 assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [aId, 0, bId]);
172 });
173
174 it('should order the list from highest priority to lowest #2', () => {
175 const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: -1 });
176 const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: 1 });
177 assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [bId, 0, aId]);
178 });
179
180 it('should order items of equal priority in the order they are added', () => {
181 const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: 0 });
182 const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: 0 });
183 assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [0, aId, bId]);
184 });
185 });
186 });
187 });