Add message parser tests
This commit is contained in:
parent
0b85ded53f
commit
eb1360c3af
@ -0,0 +1,30 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const expect = require("chai").expect;
|
||||||
|
const anyIntersection = require("../../../../../../client/js/libs/handlebars/ircmessageparser/anyIntersection");
|
||||||
|
|
||||||
|
describe("anyIntersection", () => {
|
||||||
|
it("should not intersect on edges", () => {
|
||||||
|
const a = {start: 1, end: 2};
|
||||||
|
const b = {start: 2, end: 3};
|
||||||
|
|
||||||
|
expect(anyIntersection(a, b)).to.equal(false);
|
||||||
|
expect(anyIntersection(b, a)).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should intersect on overlapping", () => {
|
||||||
|
const a = {start: 0, end: 3};
|
||||||
|
const b = {start: 1, end: 2};
|
||||||
|
|
||||||
|
expect(anyIntersection(a, b)).to.equal(true);
|
||||||
|
expect(anyIntersection(b, a)).to.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not intersect", () => {
|
||||||
|
const a = {start: 0, end: 1};
|
||||||
|
const b = {start: 2, end: 3};
|
||||||
|
|
||||||
|
expect(anyIntersection(a, b)).to.equal(false);
|
||||||
|
expect(anyIntersection(b, a)).to.equal(false);
|
||||||
|
});
|
||||||
|
});
|
123
test/client/js/libs/handlebars/ircmessageparser/findChannels.js
Normal file
123
test/client/js/libs/handlebars/ircmessageparser/findChannels.js
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const expect = require("chai").expect;
|
||||||
|
const analyseText = require("../../../../../../client/js/libs/handlebars/ircmessageparser/findChannels");
|
||||||
|
|
||||||
|
describe("findChannels", () => {
|
||||||
|
it("should find single letter channel", () => {
|
||||||
|
const input = "#a";
|
||||||
|
const expected = [{
|
||||||
|
channel: "#a",
|
||||||
|
start: 0,
|
||||||
|
end: 2
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["#"], ["@", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should find utf8 channels", () => {
|
||||||
|
const input = "#äöü";
|
||||||
|
const expected = [{
|
||||||
|
channel: "#äöü",
|
||||||
|
start: 0,
|
||||||
|
end: 4
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["#"], ["@", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should find inline channel", () => {
|
||||||
|
const input = "inline #channel text";
|
||||||
|
const expected = [{
|
||||||
|
channel: "#channel",
|
||||||
|
start: 7,
|
||||||
|
end: 15
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["#"], ["@", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should stop at \\0x07", () => {
|
||||||
|
const input = "#chan\x07nel";
|
||||||
|
const expected = [{
|
||||||
|
channel: "#chan",
|
||||||
|
start: 0,
|
||||||
|
end: 5
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["#"], ["@", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow classics pranks", () => {
|
||||||
|
const input = "#1,000";
|
||||||
|
const expected = [{
|
||||||
|
channel: "#1,000",
|
||||||
|
start: 0,
|
||||||
|
end: 6
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["#"], ["@", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work with whois reponses", () => {
|
||||||
|
const input = "@#a";
|
||||||
|
const expected = [{
|
||||||
|
channel: "#a",
|
||||||
|
start: 1,
|
||||||
|
end: 3
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["#"], ["@", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work with IRCv3.1 multi-prefix", () => {
|
||||||
|
const input = "!@%+#a";
|
||||||
|
const expected = [{
|
||||||
|
channel: "#a",
|
||||||
|
start: 4,
|
||||||
|
end: 6
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["#"], ["!", "@", "%", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should work with custom channelPrefixes", () => {
|
||||||
|
const input = "@a";
|
||||||
|
const expected = [{
|
||||||
|
channel: "@a",
|
||||||
|
start: 0,
|
||||||
|
end: 2
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["@"], ["#", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle multiple channelPrefix correctly", () => {
|
||||||
|
const input = "##test";
|
||||||
|
const expected = [{
|
||||||
|
channel: "##test",
|
||||||
|
start: 0,
|
||||||
|
end: 6
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = analyseText(input, ["#"], ["@", "+"]);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
});
|
63
test/client/js/libs/handlebars/ircmessageparser/merge.js
Normal file
63
test/client/js/libs/handlebars/ircmessageparser/merge.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const expect = require("chai").expect;
|
||||||
|
const merge = require("../../../../../../client/js/libs/handlebars/ircmessageparser/merge");
|
||||||
|
|
||||||
|
describe("merge", () => {
|
||||||
|
it("should split style information", () => {
|
||||||
|
const textParts = [{
|
||||||
|
start: 0,
|
||||||
|
end: 10,
|
||||||
|
flag1: true
|
||||||
|
}, {
|
||||||
|
start: 10,
|
||||||
|
end: 20,
|
||||||
|
flag2: true
|
||||||
|
}];
|
||||||
|
const styleFragments = [{
|
||||||
|
start: 0,
|
||||||
|
end: 5,
|
||||||
|
text: "01234"
|
||||||
|
}, {
|
||||||
|
start: 5,
|
||||||
|
end: 15,
|
||||||
|
text: "5678901234"
|
||||||
|
}, {
|
||||||
|
start: 15,
|
||||||
|
end: 20,
|
||||||
|
text: "56789"
|
||||||
|
}];
|
||||||
|
|
||||||
|
const expected = [{
|
||||||
|
start: 0,
|
||||||
|
end: 10,
|
||||||
|
flag1: true,
|
||||||
|
fragments: [{
|
||||||
|
start: 0,
|
||||||
|
end: 5,
|
||||||
|
text: "01234"
|
||||||
|
}, {
|
||||||
|
start: 5,
|
||||||
|
end: 10,
|
||||||
|
text: "56789"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
start: 10,
|
||||||
|
end: 20,
|
||||||
|
flag2: true,
|
||||||
|
fragments: [{
|
||||||
|
start: 10,
|
||||||
|
end: 15,
|
||||||
|
text: "01234"
|
||||||
|
}, {
|
||||||
|
start: 15,
|
||||||
|
end: 20,
|
||||||
|
text: "56789"
|
||||||
|
}]
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = merge(textParts, styleFragments);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
});
|
274
test/client/js/libs/handlebars/ircmessageparser/parseStyle.js
Normal file
274
test/client/js/libs/handlebars/ircmessageparser/parseStyle.js
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const expect = require("chai").expect;
|
||||||
|
const parseStyle = require("../../../../../../client/js/libs/handlebars/ircmessageparser/parseStyle");
|
||||||
|
|
||||||
|
describe("parseStyle", () => {
|
||||||
|
it("should skip control codes", () => {
|
||||||
|
const input = "text\x01with\x04control\x05codes";
|
||||||
|
const expected = [{
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "textwithcontrolcodes",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 20
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse bold", () => {
|
||||||
|
const input = "\x02bold";
|
||||||
|
const expected = [{
|
||||||
|
bold: true,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "bold",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 4
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse textColor", () => {
|
||||||
|
const input = "\x038yellowText";
|
||||||
|
const expected = [{
|
||||||
|
bold: false,
|
||||||
|
textColor: 8,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "yellowText",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 10
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse textColor and background", () => {
|
||||||
|
const input = "\x034,8yellowBG redText";
|
||||||
|
const expected = [{
|
||||||
|
textColor: 4,
|
||||||
|
bgColor: 8,
|
||||||
|
bold: false,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "yellowBG redText",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 16
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should parse italic", () => {
|
||||||
|
const input = "\x1ditalic";
|
||||||
|
const expected = [{
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: true,
|
||||||
|
underline: false,
|
||||||
|
text: "italic",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 6
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should carry state corretly forward", () => {
|
||||||
|
const input = "\x02bold\x038yellow\x02nonBold\x03default";
|
||||||
|
const expected = [{
|
||||||
|
bold: true,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "bold",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 4
|
||||||
|
}, {
|
||||||
|
bold: true,
|
||||||
|
textColor: 8,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "yellow",
|
||||||
|
|
||||||
|
start: 4,
|
||||||
|
end: 10
|
||||||
|
}, {
|
||||||
|
bold: false,
|
||||||
|
textColor: 8,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "nonBold",
|
||||||
|
|
||||||
|
start: 10,
|
||||||
|
end: 17
|
||||||
|
}, {
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "default",
|
||||||
|
|
||||||
|
start: 17,
|
||||||
|
end: 24
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should toggle bold correctly", () => {
|
||||||
|
const input = "\x02bold\x02 \x02bold\x02";
|
||||||
|
const expected = [{
|
||||||
|
bold: true,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "bold",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 4
|
||||||
|
}, {
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: " ",
|
||||||
|
|
||||||
|
start: 4,
|
||||||
|
end: 5
|
||||||
|
}, {
|
||||||
|
bold: true,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "bold",
|
||||||
|
|
||||||
|
start: 5,
|
||||||
|
end: 9
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should reset all styles", () => {
|
||||||
|
const input = "\x02\x034\x16\x1d\x1ffull\x0fnone";
|
||||||
|
const expected = [{
|
||||||
|
bold: true,
|
||||||
|
textColor: 4,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: true,
|
||||||
|
italic: true,
|
||||||
|
underline: true,
|
||||||
|
text: "full",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 4
|
||||||
|
}, {
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "none",
|
||||||
|
|
||||||
|
start: 4,
|
||||||
|
end: 8
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not emit empty fragments", () => {
|
||||||
|
const input = "\x031\x031,2\x031\x031,2\x031\x031,2\x03a";
|
||||||
|
const expected = [{
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "a",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 1
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should optimize fragments", () => {
|
||||||
|
const rawString = "oh hi test text";
|
||||||
|
const colorCode = "\x0312";
|
||||||
|
const input = colorCode + rawString.split("").join(colorCode);
|
||||||
|
const expected = [{
|
||||||
|
bold: false,
|
||||||
|
textColor: 12,
|
||||||
|
bgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: rawString,
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: rawString.length
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
});
|
336
test/client/js/libs/handlebars/parse.js
Normal file
336
test/client/js/libs/handlebars/parse.js
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
"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 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 commom 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>"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user