"use strict"; const assert = require("node:assert/strict"); const {JSDOM} = require("jsdom"); const katex_tests = require("../../zerver/tests/fixtures/katex_test_cases.json"); const {parse} = require("../src/markdown.ts"); const {zrequire, set_global} = require("./lib/namespace.cjs"); const {run_test} = require("./lib/test.cjs"); const {window} = new JSDOM(); const compose_paste = zrequire("compose_paste"); const stream_data = zrequire("stream_data"); set_global("document", {}); stream_data.add_sub_for_tests({ stream_id: 4, name: "Rome", }); stream_data.add_sub_for_tests({ stream_id: 5, name: "Romeo`s lair", }); run_test("try_stream_topic_syntax_text", () => { const test_cases = [ [ "http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT", "#**Rome>old FAILED EXPORT**", ], [ "http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/100.25.20profits", "#**Rome>100% profits**", ], [ "http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/old.20API.20wasn't.20compiling.20erratically", "#**Rome>old API wasn't compiling erratically**", ], ["http://different.origin.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT"], [ "http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT/near/100", "#**Rome>old FAILED EXPORT@100**", ], ["http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic//near/100", "#**Rome>@100**"], [ "http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT/with/100", "#**Rome>old FAILED EXPORT**", ], // malformed urls ["http://zulip.zulipdev.com/narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT"], ["http://zulip.zulipdev.com/#not_narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT"], ["http://zulip.zulipdev.com/#narrow/not_stream/4-Rome/topic/old.20FAILED.20EXPORT"], ["http://zulip.zulipdev.com/#narrow/channel/4-Rome/not_topic/old.20FAILED.20EXPORT"], ["http://zulip.zulipdev.com/#narrow/channel/4-Rome/", "#**Rome**"], ["http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic"], ["http://zulip.zulipdev.com/#narrow/topic/cheese"], ["http://zulip.zulipdev.com/#narrow/topic/pizza/stream/Rome"], ["http://zulip.zulipdev.com/#narrow/channel/4-Rome/topic/old.20FAILED.20EXPORT/near/"], // When a url containing characters which are known to produce broken // #**stream>topic** urls is pasted, a normal markdown link syntax is produced. [ "http://zulip.zulipdev.com/#narrow/stream/4-Rome/topic/100.25.20profits.60", "[#Rome > 100% profits`](#narrow/channel/4-Rome/topic/100.25.20profits.60)", ], [ "http://zulip.zulipdev.com/#narrow/stream/4-Rome/topic/100.25.20*profits", "[#Rome > 100% *profits](#narrow/channel/4-Rome/topic/100.25.20*profits)", ], [ "http://zulip.zulipdev.com/#narrow/stream/4-Rome/topic/.24.24 100.25.20profits", "[#Rome > $$ 100% profits](#narrow/channel/4-Rome/topic/.24.24.20100.25.20profits)", ], [ "http://zulip.zulipdev.com/#narrow/stream/4-Rome/topic/>100.25.20profits", "[#Rome > >100% profits](#narrow/channel/4-Rome/topic/.3E100.25.20profits)", ], [ "http://zulip.zulipdev.com/#narrow/stream/5-Romeo.60s-lair/topic/normal", "[#Romeo`s lair > normal](#narrow/channel/5-Romeo.60s-lair/topic/normal)", ], [ "http://zulip.zulipdev.com/#narrow/stream/4-Rome/topic/100.25.20profits.60/near/20", "[#Rome > 100% profits` @ 💬](#narrow/channel/4-Rome/topic/100.25.20profits.60/near/20)", ], ]; for (const test_case of test_cases) { const result = compose_paste.try_stream_topic_syntax_text(test_case[0]); const expected = test_case[1] ?? null; assert.equal(result, expected, "Failed for url: " + test_case[0]); } }); run_test("maybe_transform_html", () => { // Copied HTML from VS Code let paste_html = `
" + escaped_paste_text + "";
assert.equal(compose_paste.maybe_transform_html(paste_html, paste_text), expected_output);
// Untransformed HTML
paste_html = "JSDOM constructor';
assert.equal(compose_paste.paste_handler_converter(input), "The `JSDOM` constructor");
// A python code block
input = `zulip code block in python
print("hello")\nprint("world")single line';
assert.equal(compose_paste.paste_handler_converter(input), "`single line`");
// No code formatting if the given text area has a backtick at the cursor position
input =
'single line';
assert.equal(
compose_paste.paste_handler_converter(input, {
caret: () => 6,
val: () => "e.g. `",
}),
"single line",
);
// Yes code formatting if the given text area has a backtick but not at the cursor position
input =
'single line';
assert.equal(
compose_paste.paste_handler_converter(input, {
caret: () => 0,
}),
"`single line`",
);
// Raw links without custom text
input =
'https://zulip.readthedocs.io/en/latest/subsystems/logging.html';
assert.equal(
compose_paste.paste_handler_converter(input),
"https://zulip.readthedocs.io/en/latest/subsystems/logging.html",
);
// Links with custom text
input =
'Contributing guide';
assert.equal(
compose_paste.paste_handler_converter(input),
"[Contributing guide](https://zulip.readthedocs.io/en/latest/contributing/contributing.html)",
);
// Only numbered list (list style retained)
input =
'normal text
'; assert.equal(compose_paste.paste_handler_converter(input), "# Zulip overview\n\nnormal text"); // Only heading (strip heading style) input = 'paragraph 1
paragraph 2
'; assert.equal(compose_paste.paste_handler_converter(input), "paragraph 1\n\nparagraph 2"); // Pasting from external sources // Pasting list from GitHub input = '| $\n 20.00 | \n
| $ 7.00 | \n
| Kathleen | Hanner | Female | United States |
| Nereida | Magwood | Female | United States |
ello world
X | as | Jak | J | Nm |
,mn | ,nnf | Adlk | Asn | ,amns |
Nm | Oi | Poi | B | Ijo |
,mn, | ;ih | Oug | Iu | G |
Ug | Bkjb | Kjbk | ;jbj | ;jb; |
Bkjb | Ugug | I9 | 68 | 0 |
90kjb | ,bnbiu | Ofif | P8gp | pugp |
Melgar | Female | UnitedStates |
Weiland | Female | UnitedStates |
Winward | Female | GreatBritain |
insertions
'; assert.equal(compose_paste.paste_handler_converter(input), "insertions"); // Math block tests /* This first batch of math block tests uses captured fixtures (`input`). This lets us verify behavior like the empty `.katex-display` divs in case of newlines in the `original_markdown` See https://github.com/zulip/zulip/pull/32629#discussion_r1883810127 */ for (const math_block_test of katex_tests.math_block_tests) { input = math_block_test.input; assert.equal(compose_paste.paste_handler_converter(input), math_block_test.expected_output); } // This next batch of tests round-trips the LaTeX syntax through // the Markdown processor and then the paste handler. const dummy_helper_config = { should_translate_emoticons: () => false, get_linkifier_map: () => new Map(), }; assert.equal(dummy_helper_config.should_translate_emoticons(), false); assert.deepEqual(dummy_helper_config.get_linkifier_map(), new Map()); for (const inline_math_expression_test of katex_tests.inline_math_expression_tests) { const paste_html = parse({ raw_content: inline_math_expression_test.original_markup, helper_config: dummy_helper_config, }).content; assert.equal( compose_paste.paste_handler_converter(paste_html), inline_math_expression_test.expected_output, ); } for (const span_conversion_test of katex_tests.text_node_to_span_conversion_tests) { const paste_html = parse({ raw_content: span_conversion_test.original_markup, helper_config: dummy_helper_config, }).content; assert.equal( compose_paste.paste_handler_converter(paste_html), span_conversion_test.expected_output, ); } });
Test list: