import { expect, test } from "@odoo/hoot"; import { deleteBackward, insertText } from "../_helpers/user_actions"; import { setupEditor, testEditor } from "../_helpers/editor"; import { descendants } from "@html_editor/utils/dom_traversal"; import { tick } from "@odoo/hoot-mock"; import { getContent, setSelection } from "../_helpers/selection"; import { cleanLinkArtifacts } from "../_helpers/format"; import { waitFor } from "@odoo/hoot-dom"; import { dispatchNormalize } from "../_helpers/dispatch"; test("should pad a link with ZWNBSPs and add visual indication", async () => { await testEditor({ contentBefore: '

abc

', contentBeforeEdit: '

a\ufeff\ufeffb\ufeff\ufeffc

', stepFunction: async (editor) => { setSelection({ anchorNode: editor.editable.querySelector("a"), anchorOffset: 1 }); await tick(); }, contentAfterEdit: '

a\ufeff\ufeff[]b\ufeff\ufeffc

', contentAfter: '

a[]bc

', }); }); test("should pad a link with ZWNBSPs and add visual indication (2)", async () => { await testEditor({ contentBefore: '

ab

', contentBeforeEdit: '

a\ufeff\ufeffb\ufeff\ufeff

', stepFunction: async (editor) => { setSelection({ anchorNode: editor.editable.querySelector("a span"), anchorOffset: 0 }); await tick(); }, contentAfterEdit: '

a\ufeff\ufeff[]b\ufeff\ufeff

', contentAfter: '

a[]b

', }); }); test("should keep link padded with ZWNBSPs after a delete", async () => { await testEditor({ contentBefore: '

ab[]c

', stepFunction: deleteBackward, contentAfterEdit: '

a\ufeff\ufeff[]\ufeff\ufeffc

', contentAfter: "

a[]c

", }); }); test("should keep isolated link after a delete and typing", async () => { await testEditor({ contentBefore: '

ab[]c

', stepFunction: async (editor) => { deleteBackward(editor); await insertText(editor, "a"); await insertText(editor, "b"); await insertText(editor, "c"); }, contentAfter: '

aabc[]c

', }); }); test("should delete the content from the link when popover is active", async () => { const { editor, el } = await setupEditor('

abc[]abc

'); await waitFor(".o-we-linkpopover"); expect(".o-we-linkpopover").toHaveCount(1); deleteBackward(editor); deleteBackward(editor); deleteBackward(editor); const content = getContent(el); expect(content).toBe( '

\ufeff\ufeff[]abc\ufeff\ufeff

' ); expect(cleanLinkArtifacts(content)).toBe('

[]abc

'); }); test("should zwnbsp-pad simple text link", async () => { const removeZwnbsp = (editor) => { for (const descendant of descendants(editor.editable)) { if (descendant.nodeType === Node.TEXT_NODE && descendant.textContent === "\ufeff") { descendant.remove(); } } }; await testEditor({ contentBefore: '

a[]bcd

', contentBeforeEdit: '

a[]\ufeff\ufeffbc\ufeff\ufeffd

', stepFunction: async (editor) => { removeZwnbsp(editor); const p = editor.editable.querySelector("p"); // set the selection via the parent setSelection({ anchorNode: p, anchorOffset: 1 }); // insert the zwnbsp again dispatchNormalize(editor); }, contentAfterEdit: '

a\ufeff[]\ufeffbc\ufeff\ufeffd

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

a[]bcd

', contentBeforeEdit: '

a\ufeff\ufeff[]bc\ufeff\ufeffd

', stepFunction: async (editor) => { removeZwnbsp(editor); const a = editor.editable.querySelector("a"); // set the selection via the parent setSelection({ anchorNode: a, anchorOffset: 0 }); await tick(); // insert the zwnbsp again dispatchNormalize(editor); }, contentAfterEdit: '

a\ufeff\ufeff[]bc\ufeff\ufeffd

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

ab[]d

', contentBeforeEdit: '

a\ufeff\ufeffb[]\ufeff\ufeffd

', stepFunction: async (editor) => { const a = editor.editable.querySelector("a"); // Insert an extra character as a text node so we can set // the selection between the characters while still // targetting their parent. a.appendChild(editor.document.createTextNode("c")); removeZwnbsp(editor); // set the selection via the parent setSelection({ anchorNode: a, anchorOffset: 1 }); await tick(); // insert the zwnbsp again dispatchNormalize(editor); }, contentAfterEdit: '

a\ufeff\ufeffb[]c\ufeff\ufeffd

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

abc[]d

', contentBeforeEdit: '

a\ufeff\ufeffbc[]\ufeff\ufeffd

', stepFunction: async (editor) => { removeZwnbsp(editor); const a = editor.editable.querySelector("a"); // set the selection via the parent setSelection({ anchorNode: a, anchorOffset: 1 }); await tick(); // insert the zwnbsp again dispatchNormalize(editor); }, contentAfterEdit: '

a\ufeff\ufeffbc[]\ufeff\ufeffd

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

abc[]d

', contentBeforeEdit: '

a\ufeff\ufeffbc\ufeff\ufeff[]d

', stepFunction: async (editor) => { removeZwnbsp(editor); const p = editor.editable.querySelector("p"); // set the selection via the parent setSelection({ anchorNode: p, anchorOffset: 2 }); await tick(); // insert the zwnbsp again dispatchNormalize(editor); }, contentAfterEdit: '

a\ufeff\ufeffbc\ufeff\ufeff[]d

', }); }); test("should not zwnbsp-pad nav-link", async () => { await testEditor({ contentBefore: '

a[]bc

', contentBeforeEdit: '

a[]bc

', }); }); test("should not zwnbsp-pad in nav", async () => { await testEditor({ contentBefore: '', contentBeforeEdit: '', }); }); test("should not zwnbsp-pad link with block fontawesome", async () => { await testEditor({ contentBefore: '

a[]b

', contentBeforeEdit: '

a[]\u200bb

', }); }); test("should not zwnbsp-pad link with image", async () => { await testEditor({ contentBefore: '

a[]b

', contentBeforeEdit: '

a[]b

', }); }); test("should remove zwnbsp from middle of the link", async () => { await testEditor({ contentBefore: '

content

', contentBeforeEdit: '

\ufeff\ufeffcontent\ufeff\ufeff

', stepFunction: async (editor) => { // Cursor before the FEFF text node setSelection({ anchorNode: editor.editable.querySelector("a"), anchorOffset: 0 }); await insertText(editor, "more "); }, contentAfterEdit: '

\ufeff\ufeffmore []content\ufeff\ufeff

', contentAfter: '

more []content

', }); }); test("should remove zwnbsp from middle of the link (2)", async () => { await testEditor({ contentBefore: '

content

', contentBeforeEdit: '

\ufeff\ufeffcontent\ufeff\ufeff

', stepFunction: async (editor) => { // Cursor inside the FEFF text node setSelection({ anchorNode: editor.editable.querySelector("a").firstChild, anchorOffset: 0, }); await insertText(editor, "more "); }, contentAfterEdit: '

\ufeff\ufeffmore []content\ufeff\ufeff

', contentAfter: '

more []content

', }); }); test("should zwnbps-pad links with .btn class", async () => { await testEditor({ contentBefore: '

content

', contentBeforeEdit: '

\ufeff\ufeffcontent\ufeff\ufeff

', }); }); test("should not add visual indication to a button", async () => { await testEditor({ contentBefore: '

[]content

', contentBeforeEdit: '

\ufeff\ufeffcontent\ufeff\ufeff

', }); });