// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // Test cases for MessageList markup parsing const JsUnit = imports.jsUnit; import Pango from 'gi://Pango'; import '../../js/ui/environment.js'; imports.ui.main; // eslint-disable-line no-unused-expressions const MessageList = imports.ui.messageList; /** * Assert that `input`, assumed to be markup, gets "fixed" to `output`, * which is valid markup. If `output` is null, `input` is expected to * convert to itself * * @param {string} input the input * @param {string} output the output */ function assertConverts(input, output) { if (!output) output = input; let fixed = MessageList._fixMarkup(input, true); JsUnit.assertEquals(output, fixed); let parsed = false; try { Pango.parse_markup(fixed, -1, ''); parsed = true; } catch (e) {} JsUnit.assertEquals(true, parsed); } /** * Assert that `input`, assumed to be plain text, gets escaped to `output`, * which is valid markup. * * @param {string} input the input * @param {string} output the output */ function assertEscapes(input, output) { let fixed = MessageList._fixMarkup(input, false); JsUnit.assertEquals(output, fixed); let parsed = false; try { Pango.parse_markup(fixed, -1, ''); parsed = true; } catch (e) {} JsUnit.assertEquals(true, parsed); } // CORRECT MARKUP assertConverts('foo'); assertEscapes('foo', 'foo'); assertConverts('foo'); assertEscapes('foo', '<b>foo</b>'); assertConverts('something foo'); assertEscapes('something foo', 'something <i>foo</i>'); assertConverts('foo something'); assertEscapes('foo something', '<u>foo</u> something'); assertConverts('bold italic and underlined'); assertEscapes('bold italic and underlined', '<b>bold</b> <i>italic <u>and underlined</u></i>'); assertConverts('this & that'); assertEscapes('this & that', 'this &amp; that'); assertConverts('this < that'); assertEscapes('this < that', 'this &lt; that'); assertConverts('this < that > the other'); assertEscapes('this < that > the other', 'this &lt; that &gt; the other'); assertConverts('this <that>'); assertEscapes('this <that>', 'this &lt;<i>that</i>&gt;'); assertConverts('this > that'); assertEscapes('this > that', '<b>this</b> > <i>that</i>'); // PARTIALLY CORRECT MARKUP // correct bits are kept, incorrect bits are escaped // unrecognized entity assertConverts('smile ☺!', 'smile &#9786;!'); assertEscapes('smile ☺!', '<b>smile</b> &#9786;!'); // stray '&'; this is really a bug, but it's easier to do it this way assertConverts('this & that', 'this & that'); assertEscapes('this & that', '<b>this</b> & <i>that</i>'); // likewise with stray '<' assertConverts('this < that', 'this < that'); assertEscapes('this < that', 'this < that'); assertConverts('this < that', 'this < that'); assertEscapes('this < that', '<b>this</b> < <i>that</i>'); assertConverts('this < that > the other', 'this < that > the other'); assertEscapes('this < that > the other', 'this < that > the other'); assertConverts('this <that>', 'this <that>'); assertEscapes('this <that>', 'this <<i>that</i>>'); // unknown tags assertConverts('tag', '<unknown>tag</unknown>'); assertEscapes('tag', '<unknown>tag</unknown>'); // make sure we check beyond the first letter assertConverts('tag', '<bunknown>tag</bunknown>'); assertEscapes('tag', '<bunknown>tag</bunknown>'); // with mix of good and bad, we keep the good and escape the bad assertConverts('known and tag', 'known and <unknown>tag</unknown>'); assertEscapes('known and tag', '<i>known</i> and <unknown>tag</unknown>'); // FULLY INCORRECT MARKUP // (fall back to escaping the whole thing) // tags not matched up assertConverts('incomplete', '<b>in<i>com</i>plete'); assertEscapes('incomplete', '<b>in<i>com</i>plete'); assertConverts('incomplete', 'in<i>com</i>plete</b>'); assertEscapes('incomplete', 'in<i>com</i>plete</b>'); // we don't support attributes, and it's too complicated to try // to escape both start and end tags, so we just treat it as bad assertConverts('good and bad', '<b>good</b> and <b style='bad'>bad</b>'); assertEscapes('good and bad', '<b>good</b> and <b style='bad'>bad</b>'); // this is just syntactically invalid assertConverts('unrecognized', '<b>unrecognized</b stuff>'); assertEscapes('unrecognized', '<b>unrecognized</b stuff>'); // mismatched tags assertConverts('mismatched', '<b>mismatched</i>'); assertEscapes('mismatched', '<b>mismatched</i>'); assertConverts('mismatched/unknown', '<b>mismatched/unknown</bunknown>'); assertEscapes('mismatched/unknown', '<b>mismatched/unknown</bunknown>');