import { describe, expect, test } from "@odoo/hoot"; import { manuallyDispatchProgrammaticEvent, press, queryOne } from "@odoo/hoot-dom"; import { animationFrame, tick } from "@odoo/hoot-mock"; import { patchWithCleanup } from "@web/../tests/web_test_helpers"; import { setupEditor, testEditor } from "../_helpers/editor"; import { unformat } from "../_helpers/format"; import { getContent } from "../_helpers/selection"; import { BOLD_TAGS, notStrong, span, strong } from "../_helpers/tags"; import { bold, simulateArrowKeyPress, tripleClick } from "../_helpers/user_actions"; const styleH1Bold = `h1 { font-weight: bold; }`; test("should make a few characters bold", async () => { await testEditor({ contentBefore: "
ab[cde]fg
", stepFunction: bold, contentAfter: `ab${strong(`[cde]`)}fg
`, }); }); test("should make a few characters not bold", async () => { await testEditor({ contentBefore: `${strong(`ab[cde]fg`)}
`, stepFunction: bold, contentAfter: `${strong(`ab`)}[cde]${strong(`fg`)}
`, }); }); test("should make two paragraphs bold", async () => { await testEditor({ contentBefore: "[abc
def]
", stepFunction: bold, contentAfter: `${strong(`[abc`)}
${strong(`def]`)}
`, }); }); test("should make two paragraphs not bold", async () => { await testEditor({ contentBefore: `${strong(`[abc`)}
${strong(`def]`)}
`, stepFunction: bold, contentAfter: `[abc
def]
`, }); }); test("should make qweb tag bold", async () => { await testEditor({ contentBefore: `[Test]
Test
][Test]
Test
]T[e]st
Test
]]cd
`, stepFunction: bold, contentAfter: `cd
`, }); }); test("should make a whole heading not bold after a triple click (heading is considered bold)", async () => { const { el, editor } = await setupEditor(`]cd
`, { styleContent: styleH1Bold, }); await tripleClick(el.querySelector("h1")); bold(editor); expect(getContent(el)).toBe(`cd
`); }); test("should make a selection starting with bold text fully bold", async () => { await testEditor({ contentBefore: `${strong(`[ab`)}
c]d
`, stepFunction: bold, contentAfter: `${strong(`[ab`)}
${strong(`c]`)}d
`, }); }); test("should make a selection with bold text in the middle fully bold", async () => { await testEditor({ contentBefore: `[a${strong(`b`)}
${strong(`c`)}d]e
`, stepFunction: bold, contentAfter: `${strong(`[ab`)}
${strong(`cd]`)}e
`, }); }); test("should make a selection ending with bold text fully bold", async () => { await testEditor({ styleContent: styleH1Bold, contentBefore: `${strong(`c]d`)}
`, stepFunction: bold, contentAfter: `${strong(`c]d`)}
`, }); }); test("should get ready to type in bold", async () => { await testEditor({ contentBefore: "ab[]cd
", stepFunction: bold, contentAfterEdit: `ab${strong(`[]\u200B`, "first")}cd
`, contentAfter: `ab[]cd
`, }); }); test("should get ready to type in not bold", async () => { await testEditor({ contentBefore: `${strong(`ab[]cd`)}
`, stepFunction: bold, contentAfterEdit: `${strong(`ab`)}${span(`[]\u200B`, "first")}${strong(`cd`)}
`, contentAfter: `${strong(`ab[]cd`)}
`, }); }); test("should remove a bold tag that was redondant while performing the command", async () => { for (const tag of BOLD_TAGS) { await testEditor({ contentBefore: `a${tag(`b${tag(`[c]`)}d`)}e
`, stepFunction: bold, contentAfter: `a${tag("b")}[c]${tag("d")}e
`, }); } }); test("should remove a bold tag that was redondant with different tags while performing the command", async () => { await testEditor({ contentBefore: unformat(`a b c[d]e f g
`), stepFunction: bold, contentAfter: unformat(`a bc [d] ef g
`), }); }); test("should not format non-editable text (bold)", async () => { await testEditor({ contentBefore: '[a
b
c]
', stepFunction: bold, contentAfter: `${strong("[a")}
b
${strong( "c]" )}
`, }); }); test("should make a few characters bold inside table (bold)", async () => { await testEditor({ contentBefore: unformat(`[abc |
def |
] |
${strong(`[abc`)} |
${strong(`def`)} |
${strong(`] |
[]
${span(`[]\u200B`, "first")}
`, }); }); // This test uses execCommand to reproduce as closely as possible the browser's // default behaviour when typing in a contenteditable=true zone. test("should type in bold", async () => { async function typeChar(editor, char) { await manuallyDispatchProgrammaticEvent(editor.editable, "keydown", { key: char }); await manuallyDispatchProgrammaticEvent(editor.editable, "beforeinput", { inputType: "insertText", data: char, }); // Simulate text insertion as done by the contenteditable. editor.document.execCommand("insertText", false, char); // Input event is dispatched and handlers are called synchronously. await manuallyDispatchProgrammaticEvent(editor.editable, "keyup", { key: char }); } const { editor, el } = await setupEditor("ab[]cd
"); /** @todo fix warnings */ patchWithCleanup(console, { warn: () => {} }); // Toggle bold on. bold(editor); expect(getContent(el)).toBe(`ab${strong("[]\u200B", "first")}cd
`); // Simulate text insertion as done by the contenteditable. await typeChar(editor, "x"); // Check that character was inserted inside the strong tag. expect(getContent(el)).toBe(`ab${strong("x[]")}cd
`); // Keep typing. await typeChar(editor, "y"); expect(getContent(el)).toBe(`ab${strong("xy[]")}cd
`); // Toggle bold off and type more. bold(editor); expect(getContent(el)).toBe(`ab${strong("xy")}${span("[]\u200B", "first")}cd
`); await typeChar(editor, "z"); expect(getContent(el)).toBe(`ab${strong("xy")}z[]cd
`); }); test.tags("desktop"); test("create bold with shortcut + selected with arrow", async () => { const { editor, el } = await setupEditor("ab[]cd
"); await press(["control", "b"]); expect(getContent(el)).toBe(`ab${strong("[]\u200B", "first")}cd
`); await simulateArrowKeyPress(editor, ["Shift", "ArrowRight"]); await tick(); // await selectionchange await animationFrame(); expect(".o-we-toolbar").toHaveCount(1); expect(getContent(el)).toBe(`ab${strong("[\u200B", "first")}c]d
`); await simulateArrowKeyPress(editor, ["Shift", "ArrowLeft"]); await tick(); // await selectionchange await animationFrame(); expect(".o-we-toolbar").toHaveCount(0); expect(getContent(el)).toBe(`ab${strong("[\u200B]", "first")}cd
`); }); const styleContentBold = `.boldClass { font-weight: bold; }`; describe("inside container or inline with class already bold", () => { test("should force the font-weight to normal with an inline with class", async () => { await testEditor({ styleContent: styleContentBold, contentBefore: `