import { expect, test } from "@odoo/hoot"; import { manuallyDispatchProgrammaticEvent } from "@odoo/hoot-dom"; import { patchWithCleanup } from "@web/../tests/web_test_helpers"; import { setupEditor, testEditor } from "../_helpers/editor"; import { cleanLinkArtifacts } from "../_helpers/format"; import { getContent, setSelection } from "../_helpers/selection"; import { insertText, undo } from "../_helpers/user_actions"; async function insertSpace(editor) { await manuallyDispatchProgrammaticEvent(editor.editable, "keydown", { key: " " }); // InputEvent is required to simulate the insert text. await manuallyDispatchProgrammaticEvent(editor.editable, "beforeinput", { inputType: "insertText", data: " ", }); const range = editor.document.getSelection().getRangeAt(0); if (!range.collapsed) { throw new Error("need to implement something... maybe"); } let offset = range.startOffset; const node = range.startContainer; // mimic the behavior of the browser when inserting a   const twoSpace = " \u00A0"; node.textContent = ( node.textContent.slice(0, offset) + " " + node.textContent.slice(offset) ).replaceAll(" ", twoSpace); if ( node.nextSibling && node.nextSibling.textContent.startsWith(" ") && node.textContent.endsWith(" ") ) { node.nextSibling.textContent = "\u00A0" + node.nextSibling.textContent.slice(1); } offset++; setSelection({ anchorNode: node, anchorOffset: offset, }); await manuallyDispatchProgrammaticEvent(editor.editable, "input", { inputType: "insertText", data: " ", }); // KeyUpEvent is not required but is triggered like the browser would. await manuallyDispatchProgrammaticEvent(editor.editable, "keyup", { key: " " }); } /** * Automatic link creation when pressing Space, Enter or Shift+Enter after an url */ test("should transform url after space", async () => { await testEditor({ contentBefore: "

a http://test.com b http://test.com[] c http://test.com d

", stepFunction: async (editor) => { await insertSpace(editor); }, contentAfter: '

a http://test.com b http://test.com [] c http://test.com d

', }); await testEditor({ contentBefore: "

http://test.com[]

", stepFunction: async (editor) => { // Setup: simulate multiple text nodes in a p:

"http://test" ".com"

editor.editable.firstChild.firstChild.splitText(11); /** @todo fix warnings */ patchWithCleanup(console, { warn: () => {} }); // Action: insert space await insertSpace(editor); }, contentAfter: '

http://test.com []

', }); }); test("should transform url followed by punctuation characters after space", async () => { await testEditor({ contentBefore: "

http://test.com.[]

", stepFunction: async (editor) => { await insertSpace(editor); }, contentAfter: '

http://test.com. []

', }); await testEditor({ contentBefore: "

test.com...[]

", stepFunction: (editor) => insertSpace(editor), contentAfter: '

test.com... []

', }); await testEditor({ contentBefore: "

test.com,[]

", stepFunction: (editor) => insertSpace(editor), contentAfter: '

test.com, []

', }); await testEditor({ contentBefore: "

test.com,hello[]

", stepFunction: (editor) => insertSpace(editor), contentAfter: '

test.com,hello []

', }); await testEditor({ contentBefore: "

http://test.com[]

", stepFunction: async (editor) => { // Setup: simulate multiple text nodes in a p:

"http://test" ".com"

editor.editable.firstChild.firstChild.splitText(11); /** @todo fix warnings */ patchWithCleanup(console, { warn: () => {} }); // Action: insert space await insertSpace(editor); }, contentAfter: '

http://test.com []

', }); }); test("should transform url after enter", async () => { await testEditor({ contentBefore: "

a http://test.com b http://test.com[] c http://test.com d

", stepFunction: async (editor) => { // Simulate "Enter" await manuallyDispatchProgrammaticEvent(editor.editable, "beforeinput", { inputType: "insertParagraph", }); }, contentAfter: '

a http://test.com b http://test.com

[] c http://test.com d

', }); }); test("should transform url after shift+enter", async () => { await testEditor({ contentBefore: "

a http://test.com b http://test.com[] c http://test.com d

", stepFunction: async (editor) => { // Simulate "Shift + Enter" await manuallyDispatchProgrammaticEvent(editor.editable, "beforeinput", { inputType: "insertLineBreak", }); }, contentAfter: '

a http://test.com b http://test.com
[] c http://test.com d

', }); }); test("should not transform an email url after space", async () => { await testEditor({ contentBefore: "

user@domain.com[]

", stepFunction: (editor) => insertSpace(editor), contentAfter: "

user@domain.com []

", }); }); test("should not transform url after two space", async () => { await testEditor({ contentBefore: "

a http://test.com b http://test.com [] c http://test.com d

", stepFunction: (editor) => insertSpace(editor), contentAfter: "

a http://test.com b http://test.com  [] c http://test.com d

", }); }); test("transform text url into link and undo it", async () => { const { el, editor } = await setupEditor(`

[]

`); await insertText(editor, "www.abc.jpg "); expect(cleanLinkArtifacts(getContent(el))).toBe( '

www.abc.jpg []

' ); undo(editor); expect(cleanLinkArtifacts(getContent(el))).toBe( '

www.abc.jpg[]

' ); undo(editor); expect(cleanLinkArtifacts(getContent(el))).toBe("

www.abc.jpg[]

"); });