03d6bf06ee
Oops, I forgot to rebase and fix after merging a previous PR. I wish there was a way to enforce this with ESLint, but did not find any (only allow) :(
390 lines
11 KiB
JavaScript
390 lines
11 KiB
JavaScript
"use strict";
|
|
|
|
const expect = require("chai").expect;
|
|
const parse = require("../../../../../client/js/libs/handlebars/parse");
|
|
|
|
describe("parse Handlebars helper", () => {
|
|
it("should not introduce xss", () => {
|
|
const testCases = [{
|
|
input: "<img onerror='location.href=\"//youtube.com\"'>",
|
|
expected: "<img onerror='location.href="//youtube.com"'>",
|
|
}, {
|
|
input: '#&">bug',
|
|
expected: '<span class="inline-channel" role="button" tabindex="0" data-chan="#&">bug">#&">bug</span>',
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should skip control codes", () => {
|
|
const testCases = [{
|
|
input: "text\x01with\x04control\x05codes",
|
|
expected: "textwithcontrolcodes",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should find urls", () => {
|
|
const testCases = [{
|
|
input: "irc://freenode.net/thelounge",
|
|
expected:
|
|
'<a href="irc://freenode.net/thelounge" target="_blank" rel="noopener">' +
|
|
"irc://freenode.net/thelounge" +
|
|
"</a>",
|
|
}, {
|
|
input: "www.nooooooooooooooo.com",
|
|
expected:
|
|
'<a href="http://www.nooooooooooooooo.com" target="_blank" rel="noopener">' +
|
|
"www.nooooooooooooooo.com" +
|
|
"</a>",
|
|
}, {
|
|
input: "look at https://thelounge.github.io/ for more information",
|
|
expected:
|
|
"look at " +
|
|
'<a href="https://thelounge.github.io/" target="_blank" rel="noopener">' +
|
|
"https://thelounge.github.io/" +
|
|
"</a>" +
|
|
" for more information",
|
|
}, {
|
|
input: "use www.duckduckgo.com for privacy reasons",
|
|
expected:
|
|
"use " +
|
|
'<a href="http://www.duckduckgo.com" target="_blank" rel="noopener">' +
|
|
"www.duckduckgo.com" +
|
|
"</a>" +
|
|
" for privacy reasons",
|
|
}, {
|
|
input: "svn+ssh://example.org",
|
|
expected:
|
|
'<a href="svn+ssh://example.org" target="_blank" rel="noopener">' +
|
|
"svn+ssh://example.org" +
|
|
"</a>",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("url with a dot parsed correctly", () => {
|
|
const input =
|
|
"bonuspunkt: your URL parser misparses this URL: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx";
|
|
const correctResult =
|
|
"bonuspunkt: your URL parser misparses this URL: " +
|
|
'<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx" target="_blank" rel="noopener">' +
|
|
"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx" +
|
|
"</a>";
|
|
|
|
const actual = parse(input);
|
|
|
|
expect(actual).to.deep.equal(correctResult);
|
|
});
|
|
|
|
it("should balance brackets", () => {
|
|
const testCases = [{
|
|
input: "<https://theos.kyriasis.com/~kyrias/stats/archlinux.html>",
|
|
expected:
|
|
"<" +
|
|
'<a href="https://theos.kyriasis.com/~kyrias/stats/archlinux.html" target="_blank" rel="noopener">' +
|
|
"https://theos.kyriasis.com/~kyrias/stats/archlinux.html" +
|
|
"</a>" +
|
|
">",
|
|
}, {
|
|
input: "abc (www.example.com)",
|
|
expected:
|
|
"abc (" +
|
|
'<a href="http://www.example.com" target="_blank" rel="noopener">' +
|
|
"www.example.com" +
|
|
"</a>" +
|
|
")",
|
|
}, {
|
|
input: "http://example.com/Test_(Page)",
|
|
expected:
|
|
'<a href="http://example.com/Test_(Page)" target="_blank" rel="noopener">' +
|
|
"http://example.com/Test_(Page)" +
|
|
"</a>",
|
|
}, {
|
|
input: "www.example.com/Test_(Page)",
|
|
expected:
|
|
'<a href="http://www.example.com/Test_(Page)" target="_blank" rel="noopener">' +
|
|
"www.example.com/Test_(Page)" +
|
|
"</a>",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should not find urls", () => {
|
|
const testCases = [{
|
|
input: "text www. text",
|
|
expected: "text www. text",
|
|
}, {
|
|
input: "http://.",
|
|
expected: "http://.",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should find channels", () => {
|
|
const testCases = [{
|
|
input: "#a",
|
|
expected:
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#a">' +
|
|
"#a" +
|
|
"</span>",
|
|
}, {
|
|
input: "#test",
|
|
expected:
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#test">' +
|
|
"#test" +
|
|
"</span>",
|
|
}, {
|
|
input: "#äöü",
|
|
expected:
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#äöü">' +
|
|
"#äöü" +
|
|
"</span>",
|
|
}, {
|
|
input: "inline #channel text",
|
|
expected:
|
|
"inline " +
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#channel">' +
|
|
"#channel" +
|
|
"</span>" +
|
|
" text",
|
|
}, {
|
|
input: "#1,000",
|
|
expected:
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#1,000">' +
|
|
"#1,000" +
|
|
"</span>",
|
|
}, {
|
|
input: "@#a",
|
|
expected:
|
|
"@" +
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#a">' +
|
|
"#a" +
|
|
"</span>",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should not find channels", () => {
|
|
const testCases = [{
|
|
input: "hi#test",
|
|
expected: "hi#test",
|
|
}, {
|
|
input: "#",
|
|
expected: "#",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should style like mirc", () => {
|
|
const testCases = [{
|
|
input: "\x02bold",
|
|
expected: '<span class="irc-bold">bold</span>',
|
|
}, {
|
|
input: "\x038yellowText",
|
|
expected: '<span class="irc-fg8">yellowText</span>',
|
|
}, {
|
|
input: "\x030,0white,white",
|
|
expected: '<span class="irc-fg0 irc-bg0">white,white</span>',
|
|
}, {
|
|
input: "\x034,8yellowBGredText",
|
|
expected: '<span class="irc-fg4 irc-bg8">yellowBGredText</span>',
|
|
}, {
|
|
input: "\x1ditalic",
|
|
expected: '<span class="irc-italic">italic</span>',
|
|
}, {
|
|
input: "\x1funderline",
|
|
expected: '<span class="irc-underline">underline</span>',
|
|
}, {
|
|
input: "\x02bold\x038yellow\x02nonBold\x03default",
|
|
expected:
|
|
'<span class="irc-bold">bold</span>' +
|
|
'<span class="irc-bold irc-fg8">yellow</span>' +
|
|
'<span class="irc-fg8">nonBold</span>' +
|
|
"default",
|
|
}, {
|
|
input: "\x02bold\x02 \x02bold\x02",
|
|
expected:
|
|
'<span class="irc-bold">bold</span>' +
|
|
" " +
|
|
'<span class="irc-bold">bold</span>',
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should find nicks", () => {
|
|
const testCases = [{
|
|
users: ["MaxLeiter"],
|
|
input: "test, MaxLeiter",
|
|
expected:
|
|
"test, " +
|
|
'<span role="button" class="user color-12" data-name="MaxLeiter">' +
|
|
"MaxLeiter" +
|
|
"</span>",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input, testCase.users));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should not find nicks", () => {
|
|
const testCases = [{
|
|
users: ["MaxLeiter, test"],
|
|
input: "#test-channelMaxLeiter",
|
|
expected:
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#test-channelMaxLeiter">' +
|
|
"#test-channelMaxLeiter" +
|
|
"</span>",
|
|
},
|
|
{
|
|
users: ["MaxLeiter, test"],
|
|
input: "https://www.MaxLeiter.com/test",
|
|
expected:
|
|
'<a href="https://www.MaxLeiter.com/test" target="_blank" rel="noopener">' +
|
|
"https://www.MaxLeiter.com/test" +
|
|
"</a>",
|
|
},
|
|
|
|
];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should go bonkers like mirc", () => {
|
|
const testCases = [{
|
|
input: "\x02irc\x0f://\x1dfreenode.net\x0f/\x034,8thelounge",
|
|
expected:
|
|
'<a href="irc://freenode.net/thelounge" target="_blank" rel="noopener">' +
|
|
'<span class="irc-bold">irc</span>' +
|
|
"://" +
|
|
'<span class="irc-italic">freenode.net</span>' +
|
|
"/" +
|
|
'<span class="irc-fg4 irc-bg8">thelounge</span>' +
|
|
"</a>",
|
|
}, {
|
|
input: "\x02#\x038,9thelounge",
|
|
expected:
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#thelounge">' +
|
|
'<span class="irc-bold">#</span>' +
|
|
'<span class="irc-bold irc-fg8 irc-bg9">thelounge</span>' +
|
|
"</span>",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should optimize generated html", () => {
|
|
const testCases = [{
|
|
input: 'test \x0312#\x0312\x0312"te\x0312st\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312a',
|
|
expected:
|
|
"test " +
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#"testa">' +
|
|
'<span class="irc-fg12">#"testa</span>' +
|
|
"</span>",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should trim common protocols", () => {
|
|
const testCases = [{
|
|
input: "like..http://example.com",
|
|
expected:
|
|
"like.." +
|
|
'<a href="http://example.com" target="_blank" rel="noopener">' +
|
|
"http://example.com" +
|
|
"</a>",
|
|
}, {
|
|
input: "like..HTTP://example.com",
|
|
expected:
|
|
"like.." +
|
|
'<a href="HTTP://example.com" target="_blank" rel="noopener">' +
|
|
"HTTP://example.com" +
|
|
"</a>",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should not find channel in fragment", () => {
|
|
const testCases = [{
|
|
input: "http://example.com/#hash",
|
|
expected:
|
|
'<a href="http://example.com/#hash" target="_blank" rel="noopener">' +
|
|
"http://example.com/#hash" +
|
|
"</a>",
|
|
}];
|
|
|
|
const actual = testCases.map((testCase) => parse(testCase.input));
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
});
|
|
|
|
it("should not overlap parts", () => {
|
|
const input = "Url: http://example.com/path Channel: ##channel";
|
|
const actual = parse(input);
|
|
|
|
expect(actual).to.equal(
|
|
'Url: <a href="http://example.com/path" target="_blank" rel="noopener">http://example.com/path</a> ' +
|
|
'Channel: <span class="inline-channel" role="button" tabindex="0" data-chan="##channel">##channel</span>'
|
|
);
|
|
});
|
|
|
|
it("should handle overlapping parts by using first starting", () => {
|
|
const input = "#test-https://example.com";
|
|
const actual = parse(input);
|
|
|
|
expect(actual).to.equal(
|
|
'<span class="inline-channel" role="button" tabindex="0" data-chan="#test-https://example.com">' +
|
|
"#test-https://example.com" +
|
|
"</span>"
|
|
);
|
|
});
|
|
});
|