2017-03-18 08:18:47 +00:00
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
const expect = require("chai").expect;
|
2018-09-05 19:21:58 +00:00
|
|
|
|
|
|
|
|
|
import {renderToString} from "@vue/server-test-utils";
|
2019-11-05 10:36:44 +00:00
|
|
|
|
import ParsedMessageTestWrapper from "../../components/ParsedMessageTestWrapper.vue";
|
2018-09-05 19:21:58 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
async function getParsedMessageContents(text, message) {
|
|
|
|
|
let contents = await renderToString(ParsedMessageTestWrapper, {
|
2018-09-05 19:21:58 +00:00
|
|
|
|
propsData: {
|
|
|
|
|
text,
|
|
|
|
|
message,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// The wrapper adds a surrounding div to the message html, so we clean that out here
|
|
|
|
|
contents = contents.replace(/^<div data-server-rendered="true">([^]+)<\/div>$/m, "$1");
|
|
|
|
|
|
|
|
|
|
return contents;
|
|
|
|
|
}
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-05 10:36:44 +00:00
|
|
|
|
describe("IRC formatted message parser", () => {
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should not introduce xss", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input: "<img onerror='location.href=\"//youtube.com\"'>",
|
|
|
|
|
expected:
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<img onerror=\'location.href="<a href="http://youtube.com" dir="auto" target="_blank" rel="noopener">//youtube.com</a>"\'>',
|
2019-07-17 09:33:59 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: '#&">bug',
|
|
|
|
|
expected:
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">#&">bug</span>',
|
2019-07-17 09:33:59 +00:00
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should skip all <32 ASCII codes except linefeed", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input:
|
|
|
|
|
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1B\x1D\x1D\x1E\x1Ftext\x0Awithcontrolcodestest",
|
|
|
|
|
expected:
|
2019-12-27 18:39:28 +00:00
|
|
|
|
' <span class="irc-bold"> </span> <span class="irc-monospace"> </span><span class="irc-underline irc-strikethrough irc-monospace">text\nwithcontrolcodestest</span>',
|
2019-07-17 09:33:59 +00:00
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should find urls", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
2021-05-26 11:43:06 +00:00
|
|
|
|
input: "irc://irc.example.com/thelounge",
|
2019-07-17 09:33:59 +00:00
|
|
|
|
expected:
|
2021-05-26 11:43:06 +00:00
|
|
|
|
'<a href="irc://irc.example.com/thelounge" dir="auto" target="_blank" rel="noopener">' +
|
|
|
|
|
"irc://irc.example.com/thelounge" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "www.nooooooooooooooo.com",
|
|
|
|
|
expected:
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="http://www.nooooooooooooooo.com" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"www.nooooooooooooooo.com" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "look at https://thelounge.chat/ for more information",
|
|
|
|
|
expected:
|
|
|
|
|
"look at " +
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="https://thelounge.chat/" dir="auto" target="_blank" rel="noopener">' +
|
2018-01-14 07:15:08 +00:00
|
|
|
|
"https://thelounge.chat/" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>" +
|
|
|
|
|
" for more information",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "use www.duckduckgo.com for privacy reasons",
|
|
|
|
|
expected:
|
|
|
|
|
"use " +
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="http://www.duckduckgo.com" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"www.duckduckgo.com" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>" +
|
|
|
|
|
" for privacy reasons",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "svn+ssh://example.org",
|
|
|
|
|
expected:
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="svn+ssh://example.org" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"svn+ssh://example.org" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("url with a dot parsed correctly", async () => {
|
2017-03-18 08:18:47 +00:00
|
|
|
|
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 =
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"bonuspunkt: your URL parser misparses this URL: " +
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx" dir="auto" target="_blank" rel="noopener">' +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx" +
|
|
|
|
|
"</a>";
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await getParsedMessageContents(input);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(correctResult);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should balance brackets", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input: "<https://theos.kyriasis.com/~kyrias/stats/archlinux.html>",
|
|
|
|
|
expected:
|
|
|
|
|
"<" +
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="https://theos.kyriasis.com/~kyrias/stats/archlinux.html" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"https://theos.kyriasis.com/~kyrias/stats/archlinux.html" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>" +
|
|
|
|
|
">",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "abc (www.example.com)",
|
|
|
|
|
expected:
|
|
|
|
|
"abc (" +
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="http://www.example.com" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"www.example.com" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>" +
|
|
|
|
|
")",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "http://example.com/Test_(Page)",
|
|
|
|
|
expected:
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="http://example.com/Test_(Page)" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"http://example.com/Test_(Page)" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "www.example.com/Test_(Page)",
|
|
|
|
|
expected:
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="http://www.example.com/Test_(Page)" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"www.example.com/Test_(Page)" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should not find urls", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input: "text www. text",
|
|
|
|
|
expected: "text www. text",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "http://.",
|
|
|
|
|
expected: "http://.",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should find channels", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input: "#a",
|
|
|
|
|
expected:
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"#a" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "#test",
|
|
|
|
|
expected:
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"#test" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "#äöü",
|
|
|
|
|
expected:
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"#äöü" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "inline #channel text",
|
|
|
|
|
expected:
|
|
|
|
|
"inline " +
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"#channel" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>" +
|
|
|
|
|
" text",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "#1,000",
|
|
|
|
|
expected:
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"#1,000" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "@#a",
|
|
|
|
|
expected:
|
|
|
|
|
"@" +
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"#a" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should not find channels", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input: "hi#test",
|
|
|
|
|
expected: "hi#test",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "#",
|
|
|
|
|
expected: "#",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-07-17 09:33:59 +00:00
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
name: "bold",
|
|
|
|
|
input: "\x02bold",
|
|
|
|
|
expected: '<span class="irc-bold">bold</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "foreground color",
|
|
|
|
|
input: "\x038yellowText",
|
|
|
|
|
expected: '<span class="irc-fg8">yellowText</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "foreground and background colors (white)",
|
|
|
|
|
input: "\x030,0white,white",
|
|
|
|
|
expected: '<span class="irc-fg0 irc-bg0">white,white</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "foreground and background colors",
|
|
|
|
|
input: "\x034,8yellowBGredText",
|
|
|
|
|
expected: '<span class="irc-fg4 irc-bg8">yellowBGredText</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "hex foreground color",
|
|
|
|
|
input: "\x04663399rebeccapurple",
|
|
|
|
|
expected: '<span style="color:#663399;">rebeccapurple</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "hex foreground and background colors",
|
|
|
|
|
input: "\x04415364,ff9e18The Lounge",
|
|
|
|
|
expected: '<span style="color:#415364;background-color:#FF9E18;">The Lounge</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "italic",
|
|
|
|
|
input: "\x1ditalic",
|
|
|
|
|
expected: '<span class="irc-italic">italic</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "underline",
|
|
|
|
|
input: "\x1funderline",
|
|
|
|
|
expected: '<span class="irc-underline">underline</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "strikethrough",
|
|
|
|
|
input: "\x1estrikethrough",
|
|
|
|
|
expected: '<span class="irc-strikethrough">strikethrough</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "monospace",
|
|
|
|
|
input: "\x11monospace",
|
|
|
|
|
expected: '<span class="irc-monospace">monospace</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "reverse with foreground and background colors",
|
|
|
|
|
input: "\x0313,1fg and bg \x16and reversed",
|
|
|
|
|
expected:
|
|
|
|
|
'<span class="irc-fg13 irc-bg1">fg and bg </span>' +
|
|
|
|
|
'<span class="irc-fg1 irc-bg13">and reversed</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "toggle reverse with foreground and background colors",
|
|
|
|
|
input: "\x0305,11text \x16reversed and \x16back again and \x16reversed",
|
|
|
|
|
expected:
|
|
|
|
|
'<span class="irc-fg5 irc-bg11">text </span>' +
|
|
|
|
|
'<span class="irc-fg11 irc-bg5">reversed and </span>' +
|
|
|
|
|
'<span class="irc-fg5 irc-bg11">back again and </span>' +
|
|
|
|
|
'<span class="irc-fg11 irc-bg5">reversed</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "escape reverse when new colors are applied",
|
|
|
|
|
input: "\x0311,02text \x16 reversed \x0304,05 and new style",
|
|
|
|
|
expected:
|
|
|
|
|
'<span class="irc-fg11 irc-bg2">text </span>' +
|
|
|
|
|
'<span class="irc-fg2 irc-bg11"> reversed </span>' +
|
|
|
|
|
'<span class="irc-fg4 irc-bg5"> and new style</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "resets",
|
|
|
|
|
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",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "duplicates",
|
|
|
|
|
input: "\x02bold\x02 \x02bold\x02",
|
|
|
|
|
expected:
|
|
|
|
|
'<span class="irc-bold">bold</span>' + " " + '<span class="irc-bold">bold</span>',
|
|
|
|
|
},
|
2019-11-30 09:36:19 +00:00
|
|
|
|
].forEach(({name, input, expected}) => {
|
|
|
|
|
it(`should handle style characters: ${name}`, async () => {
|
|
|
|
|
expect(await getParsedMessageContents(input)).to.equal(expected);
|
2017-11-29 05:31:03 +00:00
|
|
|
|
});
|
2017-03-18 08:18:47 +00:00
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should find nicks", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
message: {
|
|
|
|
|
users: ["MaxLeiter"],
|
|
|
|
|
},
|
|
|
|
|
input: "test, MaxLeiter",
|
|
|
|
|
expected:
|
|
|
|
|
"test, " +
|
2019-11-23 14:26:20 +00:00
|
|
|
|
'<span data-name="MaxLeiter" role="button" dir="auto" class="user color-12">' +
|
2017-11-14 22:36:45 +00:00
|
|
|
|
"MaxLeiter" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-11-14 22:36:45 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input, testCase.message))
|
2019-07-17 09:33:59 +00:00
|
|
|
|
);
|
2017-11-14 22:36:45 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should not find nicks", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
users: ["MaxLeiter, test"],
|
|
|
|
|
input: "#test-channelMaxLeiter",
|
|
|
|
|
expected:
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-11-14 22:36:45 +00:00
|
|
|
|
"#test-channelMaxLeiter" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
users: ["MaxLeiter, test"],
|
|
|
|
|
input: "https://www.MaxLeiter.com/test",
|
|
|
|
|
expected:
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="https://www.MaxLeiter.com/test" dir="auto" target="_blank" rel="noopener">' +
|
2017-11-14 22:36:45 +00:00
|
|
|
|
"https://www.MaxLeiter.com/test" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
2017-11-14 22:36:45 +00:00
|
|
|
|
];
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-11-14 22:36:45 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should go bonkers like mirc", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
2021-05-26 11:43:06 +00:00
|
|
|
|
input: "\x02irc\x0f://\x1dirc.example.com\x0f/\x034,8thelounge",
|
2019-07-17 09:33:59 +00:00
|
|
|
|
expected:
|
2021-05-26 11:43:06 +00:00
|
|
|
|
'<a href="irc://irc.example.com/thelounge" dir="auto" target="_blank" rel="noopener">' +
|
2017-11-26 22:34:28 +00:00
|
|
|
|
'<span class="irc-bold">irc</span>' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"://" +
|
2021-05-26 11:43:06 +00:00
|
|
|
|
'<span class="irc-italic">irc.example.com</span>' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"/" +
|
2017-11-26 22:34:28 +00:00
|
|
|
|
'<span class="irc-fg4 irc-bg8">thelounge</span>' +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "\x02#\x038,9thelounge",
|
|
|
|
|
expected:
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-11-26 22:34:28 +00:00
|
|
|
|
'<span class="irc-bold">#</span>' +
|
|
|
|
|
'<span class="irc-bold irc-fg8 irc-bg9">thelounge</span>' +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2017-11-29 05:31:03 +00:00
|
|
|
|
// Emoji
|
2019-07-17 09:33:59 +00:00
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
name: "in text",
|
|
|
|
|
input: "Hello💬",
|
|
|
|
|
expected:
|
|
|
|
|
'Hello<span role="img" aria-label="Emoji: speech balloon" title="Emoji: speech balloon" class="emoji">💬</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "complicated zero-join-width emoji",
|
|
|
|
|
input: "🤦🏿♀️",
|
|
|
|
|
expected:
|
|
|
|
|
'<span role="img" aria-label="Emoji: woman facepalming" title="Emoji: woman facepalming" class="emoji">🤦🏿♀️</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "unicode 12 emojis",
|
|
|
|
|
input: "🧘🏿👨👨👧👧",
|
|
|
|
|
expected:
|
|
|
|
|
'<span role="img" aria-label="Emoji: person in lotus position" title="Emoji: person in lotus position" class="emoji">🧘🏿</span><span role="img" aria-label="Emoji: family: man, man, girl, girl" title="Emoji: family: man, man, girl, girl" class="emoji">👨👨👧👧</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "unicode 12 emojis with multiple modifiers",
|
|
|
|
|
input: "👩🏾🤝👨🏽",
|
|
|
|
|
expected: '<span role="img" class="emoji">👩🏾🤝👨🏽</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "with modifiers",
|
|
|
|
|
input: "🤷♀️",
|
|
|
|
|
expected:
|
|
|
|
|
'<span role="img" aria-label="Emoji: woman shrugging" title="Emoji: woman shrugging" class="emoji">🤷♀️</span>',
|
|
|
|
|
},
|
2019-10-03 10:35:38 +00:00
|
|
|
|
{
|
|
|
|
|
name: "with emoji variant selector",
|
|
|
|
|
input: "\u{2695}\u{FE0F}",
|
|
|
|
|
expected:
|
|
|
|
|
'<span role="img" aria-label="Emoji: medical symbol" title="Emoji: medical symbol" class="emoji">\u{2695}\u{FE0F}</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "with text variant selector",
|
|
|
|
|
input: "\u{2695}\u{FE0E}",
|
|
|
|
|
expected: "\u{2695}\u{FE0E}", // this does not match because FE0E is specifically a text variant
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "without variant selector",
|
|
|
|
|
input: "\u{2695}",
|
|
|
|
|
expected: "\u{2695}", // this does not match because emoji-regex expects \uFE0F as per the emoji specification
|
|
|
|
|
},
|
2019-07-17 09:33:59 +00:00
|
|
|
|
{
|
|
|
|
|
// FIXME: These multiple `span`s should be optimized into a single one. See https://github.com/thelounge/thelounge/issues/1783
|
|
|
|
|
name: "wrapped in style",
|
|
|
|
|
input: "Super \x034💚 green!",
|
|
|
|
|
expected:
|
|
|
|
|
'Super <span role="img" aria-label="Emoji: green heart" title="Emoji: green heart" class="emoji"><span class="irc-fg4">💚</span></span><span class="irc-fg4"> green!</span>',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "wrapped in URLs",
|
|
|
|
|
input: "https://i.❤️.thelounge.chat",
|
|
|
|
|
// FIXME: Emoji in text should be `<span class="emoji">❤️</span>`. See https://github.com/thelounge/thelounge/issues/1784
|
|
|
|
|
expected:
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="https://i.❤️.thelounge.chat" dir="auto" target="_blank" rel="noopener">https://i.❤️.thelounge.chat</a>',
|
2019-07-17 09:33:59 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "wrapped in channels",
|
|
|
|
|
input: "#i❤️thelounge",
|
|
|
|
|
// FIXME: Emoji in text should be `<span class="emoji">❤️</span>`. See https://github.com/thelounge/thelounge/issues/1784
|
|
|
|
|
expected:
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">#i❤️thelounge</span>',
|
2019-07-17 09:33:59 +00:00
|
|
|
|
},
|
2019-11-30 09:36:19 +00:00
|
|
|
|
].forEach(({name, input, expected}) => {
|
|
|
|
|
it(`should find emoji: ${name}`, async () => {
|
|
|
|
|
expect(await getParsedMessageContents(input)).to.equal(expected);
|
2017-11-29 05:31:03 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should optimize generated html", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input:
|
|
|
|
|
'test \x0312#\x0312\x0312"te\x0312st\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312\x0312a',
|
|
|
|
|
expected:
|
|
|
|
|
"test " +
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
'<span class="irc-fg12">#"testa</span>' +
|
|
|
|
|
"</span>",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should trim common protocols", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input: "like..http://example.com",
|
|
|
|
|
expected:
|
|
|
|
|
"like.." +
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="http://example.com" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"http://example.com" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
input: "like..HTTP://example.com",
|
|
|
|
|
expected:
|
|
|
|
|
"like.." +
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="HTTP://example.com" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"HTTP://example.com" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should not find channel in fragment", async () => {
|
2019-07-17 09:33:59 +00:00
|
|
|
|
const testCases = [
|
|
|
|
|
{
|
|
|
|
|
input: "http://example.com/#hash",
|
|
|
|
|
expected:
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'<a href="http://example.com/#hash" dir="auto" target="_blank" rel="noopener">' +
|
2017-03-18 08:18:47 +00:00
|
|
|
|
"http://example.com/#hash" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</a>",
|
|
|
|
|
},
|
|
|
|
|
];
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await Promise.all(
|
|
|
|
|
testCases.map((testCase) => getParsedMessageContents(testCase.input))
|
|
|
|
|
);
|
2017-04-08 12:34:31 +00:00
|
|
|
|
const expected = testCases.map((testCase) => testCase.expected);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.deep.equal(expected);
|
|
|
|
|
});
|
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should not overlap parts", async () => {
|
2017-03-18 08:18:47 +00:00
|
|
|
|
const input = "Url: http://example.com/path Channel: ##channel";
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await getParsedMessageContents(input);
|
2017-03-18 08:18:47 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.equal(
|
2019-08-09 20:20:08 +00:00
|
|
|
|
'Url: <a href="http://example.com/path" dir="auto" target="_blank" rel="noopener">http://example.com/path</a> ' +
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'Channel: <span dir="auto" role="button" tabindex="0" class="inline-channel">##channel</span>'
|
2017-03-18 08:18:47 +00:00
|
|
|
|
);
|
|
|
|
|
});
|
2017-11-26 19:26:59 +00:00
|
|
|
|
|
2019-11-30 09:36:19 +00:00
|
|
|
|
it("should handle overlapping parts by using first starting", async () => {
|
2017-11-26 19:26:59 +00:00
|
|
|
|
const input = "#test-https://example.com";
|
2019-11-30 09:36:19 +00:00
|
|
|
|
const actual = await getParsedMessageContents(input);
|
2017-11-26 19:26:59 +00:00
|
|
|
|
|
|
|
|
|
expect(actual).to.equal(
|
2019-10-17 14:17:02 +00:00
|
|
|
|
'<span dir="auto" role="button" tabindex="0" class="inline-channel">' +
|
2017-11-26 19:26:59 +00:00
|
|
|
|
"#test-https://example.com" +
|
2019-07-17 09:33:59 +00:00
|
|
|
|
"</span>"
|
2017-11-26 19:26:59 +00:00
|
|
|
|
);
|
|
|
|
|
});
|
2019-12-27 18:39:28 +00:00
|
|
|
|
|
|
|
|
|
it("should find links separated by tab character", async () => {
|
|
|
|
|
const input = "example.com\texample.org";
|
|
|
|
|
const actual = await getParsedMessageContents(input);
|
|
|
|
|
|
|
|
|
|
expect(actual).to.equal(
|
|
|
|
|
'<a href="http://example.com" dir="auto" target="_blank" rel="noopener">example.com</a>' +
|
|
|
|
|
' <a href="http://example.org" dir="auto" target="_blank" rel="noopener">example.org</a>'
|
|
|
|
|
);
|
|
|
|
|
});
|
2017-03-18 08:18:47 +00:00
|
|
|
|
});
|