import { getDeepestPosition, isEmptyBlock, isShrunkBlock, isVisible, isVisibleTextNode, nextLeaf, previousLeaf, } from "@html_editor/utils/dom_info"; import { describe, expect, test } from "@odoo/hoot"; import { insertTestHtml } from "../_helpers/editor"; const base64Img = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUA\n AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO\n 9TXL0Y4OHwAAAABJRU5ErkJggg=="; describe("previousLeaf", () => { test("should find the previous leaf of a deeply nested node", () => { const [div] = insertTestHtml( "
abcdefghijkl
abcdefghijkl
abcdefgh
ijkl
abcdefgh
ijkl
abcdefgh
ijkl
abcdefghijkl
abcdefghijkl
abcdefgh
ijkl
abcdefgh
ijkl
abcdefgh
ijkl
a
"); const result = isVisible(p.firstChild); expect(result).not.toBe(true); }); test("should identify invisible string space at the end of a paragraph after an inline node", () => { const [p] = insertTestHtml("a
"); const result = isVisible(p.lastChild); expect(result).not.toBe(true); }); test("should identify a single visible space in an inline node in the middle of a paragraph", () => { const [p] = insertTestHtml("a b
"); const result = isVisible(p.querySelector("i").firstChild); expect(result).toBe(true); }); test("should identify a visible string with only one visible space in an inline node in the middle of a paragraph", () => { const [p] = insertTestHtml("a b
"); const result = isVisible(p.querySelector("i").firstChild); expect(result).toBe(true); }); test("should identify a visible space in the middle of a paragraph", () => { const [p] = insertTestHtml(""); // insert 'a b' as three separate text node inside p const textNodes = "a b".split("").map((char) => { const textNode = document.createTextNode(char); p.appendChild(textNode); return textNode; }); const result = isVisible(textNodes[1]); expect(result).toBe(true); }); test("should identify a visible string space in the middle of a paragraph", () => { const [p] = insertTestHtml(""); // inserts 'a', ' ' and 'b' as 3 separate text nodes inside p const textNodes = ["a", " ", "b"].map((char) => { const textNode = document.createTextNode(char); p.appendChild(textNode); return textNode; }); const result = isVisible(textNodes[1]); expect(result).toBe(true); }); test("should identify the first space in a series of spaces as in the middle of a paragraph as visible", () => { const [p] = insertTestHtml(""); // inserts 'a b' as 5 separate text nodes inside p const textNodes = "a b".split("").map((char) => { const textNode = document.createTextNode(char); p.appendChild(textNode); return textNode; }); const result = isVisible(textNodes[1]); expect(result).toBe(true); }); test("should identify the second space in a series of spaces in the middle of a paragraph as invisible", () => { const [p] = insertTestHtml(""); // inserts 'a b' as 5 separate text nodes inside p const textNodes = "a b".split("").map((char) => { const textNode = document.createTextNode(char); p.appendChild(textNode); return textNode; }); const result = isVisible(textNodes[2]); expect(result).not.toBe(true); }); test("should identify empty text node as invisible", () => { const [p] = insertTestHtml(""); // inserts 'a b' as 5 separate text nodes inside p const textNode = document.createTextNode(""); p.appendChild(textNode); const result = isVisible(textNode); expect(result).not.toBe(true); }); test("should identify a space between to visible char in inline nodes as visible", () => { const [p] = insertTestHtml("a b
"); const textNode = p.firstChild.nextSibling; const result = isVisible(textNode); expect(result).toBe(true); }); }); }); describe("getDeepestPosition", () => { test("should get deepest position for text within paragraph", () => { const [p] = insertTestHtml("abc
"); const editable = p.parentElement; const abc = p.firstChild; let [node, offset] = getDeepestPosition(editable, 0); expect([node, offset]).toEqual([abc, 0]); [node, offset] = getDeepestPosition(editable, 1); expect([node, offset]).toEqual([abc, 3]); }); test("should get deepest position within nested formatting tags", () => { const [p] = insertTestHtml("abc
"); const editable = p.parentElement; const abc = p.firstChild.firstChild.firstChild.firstChild.firstChild; let [node, offset] = getDeepestPosition(editable, 0); expect([node, offset]).toEqual([abc, 0]); [node, offset] = getDeepestPosition(editable, 1); expect([node, offset]).toEqual([abc, 3]); }); test("should get deepest position in multiple paragraph", () => { const [p1, p2] = insertTestHtml("abc
def
"); const editable = p1.parentElement; const abc = p1.firstChild; const def = p2.firstChild; let [node, offset] = getDeepestPosition(editable, 0); expect([node, offset]).toEqual([abc, 0]); [node, offset] = getDeepestPosition(editable, 1); expect([node, offset]).toEqual([def, 0]); [node, offset] = getDeepestPosition(editable, 2); expect([node, offset]).toEqual([def, 3]); }); test("should get deepest position for node with invisible element", () => { const [p1] = insertTestHtml("def
"); const editable = p1.parentElement; const def = editable.lastChild.firstChild; let [node, offset] = getDeepestPosition(editable, 0); expect([node, offset]).toEqual([def, 0]); [node, offset] = getDeepestPosition(editable, 2); expect([node, offset]).toEqual([def, 3]); }); test("should get deepest position for invisible block element", () => { const [p1] = insertTestHtml("def
"); const [node, offset] = getDeepestPosition(p1, 0); expect([node, offset]).toEqual([p1, 0]); }); test("should get deepest position for invisible block element(2)", () => { const [p1] = insertTestHtml("abc
"); const p2 = p1.nextSibling; const [node, offset] = getDeepestPosition(p2, 0); expect([node, offset]).toEqual([p2, 0]); }); test("should get deepest position for elements containing invisible text nodes", () => { const [p] = insertTestHtml( `a
` ); const editable = p.parentElement; const a = editable.firstChild.childNodes[1].firstChild; let [node, offset] = getDeepestPosition(editable, 0); expect([node, offset]).toEqual([a, 0]); [node, offset] = getDeepestPosition(editable, 1); expect([node, offset]).toEqual([a, 1]); }); test("should not skip zwnbsp", () => { const [a] = insertTestHtml('\ufeffabc'); const editable = a.parentElement; const zwnbsp = editable.firstChild; const [node, offset] = getDeepestPosition(editable, 0); expect([node, offset]).toEqual([zwnbsp, 0]); }); }); describe("isEmptyBlock", () => { test("should identify empty p element", () => { const [p] = insertTestHtml(""); const result = isEmptyBlock(p); expect(result).toBe(true); }); test("should identify p with single br tag as empty and multiple br tag as non-empty", () => { const [p1, p2] = insertTestHtml("abc
"); const result1 = isEmptyBlock(p); const result2 = isEmptyBlock(p.firstChild); expect(result1).toBe(false); expect(result2).toBe(false); }); test("should identify a empty span with display block", () => { const [span] = insertTestHtml('