import { describe, expect, getFixture, test } from "@odoo/hoot"; import { hover, click } from "@odoo/hoot-dom"; import { animationFrame, tick } from "@odoo/hoot-mock"; import { contains } from "@web/../tests/web_test_helpers"; import { base64Img, setupEditor } from "./_helpers/editor"; import { getContent } from "./_helpers/selection"; import { unformat } from "./_helpers/format"; import { expectElementCount } from "./_helpers/ui_expectations"; import { EMBEDDED_COMPONENT_PLUGINS, MAIN_PLUGINS } from "@html_editor/plugin_sets"; import { captionEmbedding } from "@html_editor/others/embedded_components/backend/caption/caption"; describe.current.tags("desktop"); const styles = ` .odoo-editor-editable { position: fixed; top: 0; left: 30px; width: 100px; } `; test("should show the hook when hovering a P", async () => { const { el } = await setupEditor("

a[]

b

", { styleContent: styles, }); await hover(el.querySelector("p")); expect(".oe-sidewidget-move").toHaveCount(1); expect(".oe-sidewidget-move").toHaveRect({ top: 0, left: 5 }); }); test("should show the hook when hovering the second P", async () => { const { el } = await setupEditor("

a[]

b

", { styleContent: styles, }); await hover(el.querySelector("p:last-child")); expect(".oe-sidewidget-move").toHaveCount(1); expect(".oe-sidewidget-move").toHaveRect({ top: 37, left: 5 }); }); test("should show the hook when hovering a figure element", async () => { const { el } = await setupEditor( `
Hello
`, { config: { Plugins: [...MAIN_PLUGINS, ...EMBEDDED_COMPONENT_PLUGINS], resources: { embedded_components: [captionEmbedding], }, }, styleContent: styles, } ); await hover(el.querySelector("figure")); expect(".oe-sidewidget-move").toHaveCount(1); }); test("should not show the hook when hovering a DIV which is not a baseContainer", async () => { const { el } = await setupEditor(`

a[]


b

`, { styleContent: styles, }); await hover(el.querySelector("div")); expect(".oe-sidewidget-move").toHaveCount(0); }); describe("drag", () => { test("should drop at the same place before the same element", async () => { const { el } = await setupEditor( `

a[]


d

b

c

`, { styleContent: styles, } ); await animationFrame(); const firstP = el.querySelector("p"); await hover(firstP); expect(".oe-dropzone-box-side").toHaveCount(0); await tick(); const { drop } = await contains(".oe-sidewidget-move").drag(); expect(".oe-dropzone-box-side").toHaveCount(8); await drop(".oe-dropzone-box-side:eq(0)"); expect(getContent(el)).toBe( `

a[]


d

b

c

` ); }); test("should drop at the same place after the same element", async () => { const { el } = await setupEditor( `

a[]


d

b

c

`, { styleContent: styles, } ); await animationFrame(); const firstP = el.querySelector("p"); await hover(firstP); expect(".oe-dropzone-box-side").toHaveCount(0); await tick(); const { drop } = await contains(".oe-sidewidget-move").drag(); expect(".oe-dropzone-box-side").toHaveCount(8); await drop(".oe-dropzone-box-side:eq(1)"); expect(getContent(el)).toBe( `

a[]


d

b

c

` ); }); test("should drop before the next baseContainer", async () => { const { el } = await setupEditor( `

a[]


d

b

c

`, { styleContent: styles, } ); await animationFrame(); const firstP = el.querySelector("p"); await hover(firstP); expect(".oe-dropzone-box-side").toHaveCount(0); await tick(); const { drop } = await contains(".oe-sidewidget-move").drag(); expect(".oe-dropzone-box-side").toHaveCount(8); await drop(".oe-dropzone-box-side:eq(2)"); expect(getContent(el)).toBe( `

a[]

d

b

c

` ); }); test("should drop after the next baseContainer", async () => { const { el } = await setupEditor( `

a[]


d

b

c

`, { styleContent: styles, } ); await animationFrame(); const firstP = el.querySelector("p"); await hover(firstP); expect(".oe-dropzone-box-side").toHaveCount(0); await tick(); const { drop } = await contains(".oe-sidewidget-move").drag(); expect(".oe-dropzone-box-side").toHaveCount(8); await drop(".oe-dropzone-box-side:eq(3)"); expect(getContent(el)).toBe( `

d

a[]

b

c

` ); }); test("should drop LI at correct position within list", async () => { const { el } = await setupEditor(`
  1. a[]
  2. b
  3. c
  4. d
`, { styleContent: styles, }); await animationFrame(); const firstLI = el.querySelector("li"); await hover(firstLI); const moveElement = document.querySelector(".oe-sidewidget-move"); let dropzones = [...document.querySelectorAll(".oe-dropzone-box-side")]; expect(dropzones).toHaveLength(0); await tick(); const handle = await contains(moveElement).drag(); dropzones = [...document.querySelectorAll(".oe-dropzone-box-side")]; expect(dropzones).toHaveLength(8); await handle.moveTo(dropzones[5]); await handle.drop(); expect(getContent(el)).toBe(`
  1. b
  2. c
  3. a[]
  4. d
`); }); test("should drop LI from bulleted list to checklist at correct position", async () => { const { el } = await setupEditor( `

p

`, { styleContent: styles, } ); await animationFrame(); const firstLI = el.querySelector("li"); await hover(firstLI); const moveElement = document.querySelector(".oe-sidewidget-move"); let dropzones = [...document.querySelectorAll(".oe-dropzone-box-side")]; expect(dropzones).toHaveLength(0); await tick(); const handle = await contains(moveElement).drag(); dropzones = [...document.querySelectorAll(".oe-dropzone-box-side")]; expect(dropzones).toHaveLength(14); await handle.moveTo(dropzones[11]); await handle.drop(); expect(getContent(el)).toBe( `

p

` ); }); test("should wrap LI in new UL or OL when moved outside existing list", async () => { const { el } = await setupEditor( `

e

`, { styleContent: styles, } ); await animationFrame(); const firstLI = el.querySelector("li"); await hover(firstLI); const moveElement = document.querySelector(".oe-sidewidget-move"); let dropzones = [...document.querySelectorAll(".oe-dropzone-box-side")]; expect(dropzones).toHaveLength(0); await tick(); const handle = await contains(moveElement).drag(); dropzones = [...document.querySelectorAll(".oe-dropzone-box-side")]; expect(dropzones).toHaveLength(10); await handle.moveTo(dropzones[9]); await handle.drop(); expect(getContent(el)).toBe( `

e

` ); }); test("should wrap non-LI element in LI and insert it into list at correct position", async () => { const { el } = await setupEditor( `

e

`, { styleContent: styles, } ); await animationFrame(); const p = el.querySelector("p"); await hover(p); const moveElement = document.querySelector(".oe-sidewidget-move"); let dropzones = [...document.querySelectorAll(".oe-dropzone-box-side")]; expect(dropzones).toHaveLength(0); await tick(); const handle = await contains(moveElement).drag(); dropzones = [...document.querySelectorAll(".oe-dropzone-box-side")]; expect(dropzones).toHaveLength(10); await handle.moveTo(dropzones[3]); await handle.drop(); expect(getContent(el)).toBe( `` ); }); test("should do nothing when dropping outside the editable", async () => { const { el } = await setupEditor( `

a[]


d

b

c

`, { styleContent: styles, } ); await animationFrame(); const firstP = el.querySelector("p"); await hover(firstP); expect(".oe-dropzone-box-side").toHaveCount(0); await tick(); const { drop } = await contains(".oe-sidewidget-move").drag(); expect(".oe-dropzone-box-side").toHaveCount(8); const outsideArea = document.createElement("div"); getFixture().appendChild(outsideArea); await drop(outsideArea); expect(getContent(el)).toBe( `

a[]


d

b

c

` ); }); test("should do nothing when dropping outside the editable and after hovering a hook", async () => { const { el } = await setupEditor( `

a[]


d

b

c

`, { styleContent: styles, } ); await animationFrame(); const firstP = el.querySelector("p"); await hover(firstP); expect(".oe-dropzone-box-side").toHaveCount(0); await tick(); const { drop, moveTo } = await contains(".oe-sidewidget-move").drag(); expect(".oe-dropzone-box-side").toHaveCount(8); await moveTo(".oe-dropzone-box-side:eq(3)"); const outsideArea = document.createElement("div"); getFixture().appendChild(outsideArea); await drop(outsideArea); expect(getContent(el)).toBe( `

a[]


d

b

c

` ); }); }); describe("click", () => { test("should select the text when clicked on a hook", async () => { const { el } = await setupEditor(`

some text

[]other text

`, { styleContent: styles, }); await animationFrame(); const firstP = el.querySelector("p"); await hover(firstP); await animationFrame(); expect(".oe-sidewidget-move").toHaveCount(1); await click(".oe-sidewidget-move"); await animationFrame(); expect(getContent(el)).toBe(`

[some text]

other text

`); await expectElementCount(".o-we-toolbar", 1); }); test("should select the table when clicked on a hook", async () => { const { el } = await setupEditor( unformat(`

[]




`), { styleContent: styles, } ); await animationFrame(); const firstTable = el.querySelector("table"); await hover(firstTable); await animationFrame(); expect(".oe-sidewidget-move").toHaveCount(1); await click(".oe-sidewidget-move"); await animationFrame(); expect(getContent(el)).toBe( unformat(`

[


]


`) ); await expectElementCount(".o-we-toolbar", 1); }); test("should select a non-editable element completely when clicked on a hook", async () => { const { el } = await setupEditor( unformat( `

abc

💡

Some

text[]

def

` ), { styleContent: styles } ); await animationFrame(); const banner = el.querySelector(".o_editor_banner"); await hover(banner); await animationFrame(); expect(".oe-sidewidget-move").toHaveCount(1); await click(".oe-sidewidget-move"); await animationFrame(); expect(getContent(el)).toBe( unformat(`

abc

[
💡

Some

text

]

def

`) ); await expectElementCount(".o-we-toolbar", 1); }); });