import { describe, expect, test } from "@odoo/hoot"; import { setupEditor, testEditor } from "./_helpers/editor"; import { deleteBackward, deleteForward, insertText, undo } from "./_helpers/user_actions"; import { getContent } from "./_helpers/selection"; import { execCommand } from "./_helpers/userCommands"; function insertFontAwesome(faClass) { return (editor) => { execCommand(editor, "insertFontAwesome", { faClass }); }; } describe("parse/render", () => { test("should parse an old-school fontawesome", async () => { await testEditor({ contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a brand fontawesome", async () => { await testEditor({ contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a duotone fontawesome", async () => { await testEditor({ contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a light fontawesome", async () => { await testEditor({ contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a regular fontawesome", async () => { await testEditor({ contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a solid fontawesome", async () => { await testEditor({ // @phoenix content adapted to make it valid html contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a fontawesome in a ", async () => { await testEditor({ contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

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

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a fontawesome in a ", async () => { await testEditor({ // @phoenix content adapted to make it valid html contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); await testEditor({ // @phoenix content adapted to make it valid html contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a fontawesome with more classes", async () => { await testEditor({ contentBefore: '

', contentBeforeEdit: '

\ufeff\u200b\ufeff

', contentAfter: '

', }); }); test("should parse a fontawesome with multi-line classes", async () => { await testEditor({ contentBefore: `

`, contentBeforeEdit: `

\ufeff\u200b\ufeff

`, contentAfter: `

`, }); }); test("should parse a fontawesome with more multi-line classes", async () => { await testEditor({ contentBefore: `

`, contentBeforeEdit: `

\ufeff\u200b\ufeff

`, contentAfter: `

`, }); }); test("should parse a fontawesome at the beginning of a paragraph", async () => { await testEditor({ contentBefore: '

a[b]c

', contentBeforeEdit: '

\ufeff\u200b\ufeffa[b]c

', contentAfter: '

a[b]c

', }); }); test("should parse a fontawesome in the middle of a paragraph", async () => { await testEditor({ contentBefore: '

a[b]cdef

', contentBeforeEdit: '

a[b]c\ufeff\u200b\ufeffdef

', contentAfter: '

a[b]cdef

', }); }); test("should parse a fontawesome at the end of a paragraph", async () => { await testEditor({ contentBefore: '

a[b]c

', contentBeforeEdit: '

a[b]c\ufeff\u200b\ufeff

', contentAfter: '

a[b]c

', }); }); /** not sure this is necessary, keep for now in case it is test('should insert navigation helpers when before a fontawesome, in an editable', async () => { await testEditor({ contentBefore: '

abc[]

', contentAfter: '

abc[]\u200B\u200B

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

[]

', contentAfter: '

\u200B[]\u200B

', }); }); test('should insert navigation helpers when after a fontawesome, in an editable', async () => { await testEditor({ contentBefore: '

[]abc

', contentAfter: '

\u200B\u200B[]abc

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

[]

', contentAfter: '

\u200B\u200B[]

', }); }); test('should not insert navigation helpers when not adjacent to a fontawesome, in an editable', async () => { await testEditor({ contentBefore: '

ab[]c

', contentAfter: '

ab[]c

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

a[]bc

', contentAfter: '

a[]bc

', }); }); test('should not insert navigation helpers when adjacent to a fontawesome in contenteditable=false container', async () => { await testEditor({ contentBefore: '

abc[]

', contentAfter: '

abc

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

[]abc

', contentAfter: '

abc

', }); }); test('should not insert navigation helpers when adjacent to a fontawesome in contenteditable=false format', async () => { await testEditor({ contentBefore: '

abc[]

', contentAfter: '

abc

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

[]abc

', contentAfter: '

abc

', }); }); test('should not insert navigation helpers when adjacent to a fontawesome in contenteditable=false format (oe-nested)', async () => { await testEditor({ contentBefore: '

abc[]

', contentAfter: '

abc

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

[]abc

', contentAfter: '

abc

', }); });*/ }); describe("deleteForward", () => { describe("Selection collapsed", () => { describe("Basic", () => { test("should delete a fontawesome (deleteForward, collapsed)", async () => { await testEditor({ contentBefore: '

ab[]cd

', contentBeforeEdit: '

ab[]\ufeff\u200b\ufeffcd

', stepFunction: deleteForward, contentAfter: "

ab[]cd

", }); }); test("should not delete a fontawesome", async () => { await testEditor({ contentBefore: '

ab[]cd

', contentBeforeEdit: '

ab\ufeff\u200b\ufeff[]cd

', stepFunction: deleteForward, contentAfterEdit: '

ab\ufeff\u200b\ufeff[]d

', contentAfter: '

ab[]d

', }); }); test("should not delete a fontawesome after multiple deleteForward", async () => { await testEditor({ contentBefore: '

ab[]cdefghij

', contentBeforeEdit: '

ab[]cde\ufeff\u200b\ufefffghij

', stepFunction: async (editor) => { deleteForward(editor); deleteForward(editor); deleteForward(editor); }, contentAfterEdit: '

ab[]\ufeff\u200b\ufefffghij

', contentAfter: '

ab[]fghij

', }); }); test("should not delete a fontawesome after one deleteForward with spaces", async () => { await testEditor({ contentBefore: '

ab[] cd

', contentBeforeEdit: '

ab[] \ufeff\u200b\ufeff cd

', stepFunction: async (editor) => { deleteForward(editor); }, contentAfterEdit: '

ab[]\ufeff\u200b\ufeff cd

', contentAfter: '

ab[] cd

', }); }); test("should not delete a fontawesome after multiple deleteForward with spaces", async () => { await testEditor({ contentBefore: '

a[]b cd

', contentBeforeEdit: '

a[]b \ufeff\u200b\ufeff cd

', stepFunction: async (editor) => { deleteForward(editor); deleteForward(editor); }, contentAfterEdit: '

a[]\ufeff\u200b\ufeff cd

', contentAfter: '

a[] cd

', }); }); test("should not delete a fontawesome after multiple deleteForward with spaces inside a ", async () => { await testEditor({ contentBefore: '

ab[]c def

', contentBeforeEdit: '

ab[]c \ufeff\u200b\ufeff def

', stepFunction: async (editor) => { deleteForward(editor); deleteForward(editor); }, contentAfterEdit: '

ab[]\ufeff\u200b\ufeff def

', contentAfter: '

ab[] def

', }); }); }); }); describe("Selection not collapsed", () => { describe("Basic", () => { test("should delete a fontawesome (forward selection, deleteForward, !collapsed)", async () => { await testEditor({ contentBefore: '

ab[]cd

', stepFunction: deleteForward, contentAfter: "

ab[]cd

", }); }); test("should delete a fontawesome (backward selection, deleteForward, !collapsed)", async () => { await testEditor({ contentBefore: '

ab][cd

', stepFunction: deleteForward, contentAfter: "

ab[]cd

", }); }); }); }); }); describe("deleteBackward", () => { describe("Selection collapsed", () => { describe("Basic", () => { test("should delete a fontawesome (deleteBackward, collapsed)", async () => { await testEditor({ contentBefore: '

ab[]cd

', contentBeforeEdit: '

ab\ufeff\u200b\ufeff[]cd

', stepFunction: deleteBackward, contentAfter: "

ab[]cd

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

ab[]cd

', contentBeforeEdit: '

ab\ufeff\u200b\ufeff[]cd

', stepFunction: deleteBackward, contentAfter: "

ab[]cd

", }); }); test("should delete a fontawesome before a span", async () => { await testEditor({ contentBefore: '

ab[]cd

', contentBeforeEdit: '

ab\ufeff\u200b\ufeff[]cd

', stepFunction: deleteBackward, contentAfter: '

ab[]cd

', }); }); test("should not delete a fontawesome before a span", async () => { await testEditor({ contentBefore: '

abc[]d

', contentBeforeEdit: '

ab\ufeff\u200b\ufeffc[]d

', stepFunction: deleteBackward, contentAfterEdit: '

ab\ufeff\u200b\ufeff[]d

', contentAfter: '

ab[]d

', }); }); test("should not delete a fontawesome", async () => { await testEditor({ contentBefore: '

ab[]cd

', contentBeforeEdit: '

ab[]\ufeff\u200b\ufeffcd

', stepFunction: deleteBackward, contentAfterEdit: '

a[]\ufeff\u200b\ufeffcd

', contentAfter: '

a[]cd

', }); }); test("should not delete a fontawesome after multiple deleteBackward", async () => { await testEditor({ contentBefore: '

abcdefgh[]ij

', contentBeforeEdit: '

abcde\ufeff\u200b\ufefffgh[]ij

', stepFunction: async (editor) => { deleteBackward(editor); deleteBackward(editor); deleteBackward(editor); }, contentAfterEdit: '

abcde\ufeff\u200b\ufeff[]ij

', contentAfter: '

abcde[]ij

', }); }); test("should not delete a fontawesome after multiple deleteBackward with spaces", async () => { await testEditor({ contentBefore: '

abcde fg[]hij

', contentBeforeEdit: '

abcde \ufeff\u200b\ufeff fg[]hij

', stepFunction: async (editor) => { deleteBackward(editor); deleteBackward(editor); deleteBackward(editor); }, contentAfterEdit: '

abcde \ufeff\u200b\ufeff[]hij

', contentAfter: '

abcde []hij

', }); }); }); }); describe("Selection not collapsed", () => { describe("Basic", () => { test("should delete a fontawesome (forward selection, deleteBackward, !collapsed)", async () => { // Forward selection await testEditor({ contentBefore: '

ab[]cd

', stepFunction: deleteBackward, contentAfter: "

ab[]cd

", }); }); test("should delete a fontawesome (backward selection, deleteBackward, !collapsed)", async () => { // Backward selection await testEditor({ contentBefore: '

ab][cd

', stepFunction: deleteBackward, contentAfter: "

ab[]cd

", }); }); }); }); }); describe("FontAwesome insertion", () => { test("should insert a fontAwesome at the start of an element", async () => { await testEditor({ contentBefore: "

[]abc

", stepFunction: insertFontAwesome("fa fa-star"), contentAfterEdit: '

\ufeff\u200b[]\ufeffabc

', contentAfter: '

[]abc

', }); }); test("should insert a fontAwesome within an element", async () => { await testEditor({ contentBefore: "

ab[]cd

", stepFunction: insertFontAwesome("fa fa-star"), contentAfterEdit: '

ab\ufeff\u200b[]\ufeffcd

', contentAfter: '

ab[]cd

', }); }); test("should insert a fontAwesome at the end of an element", async () => { await testEditor({ contentBefore: "

abc[]

", stepFunction: insertFontAwesome("fa fa-star"), contentAfterEdit: '

abc\ufeff\u200b[]\ufeff

', contentAfter: '

abc[]

', }); }); test("should insert a fontAwesome after", async () => { await testEditor({ contentBefore: '

abc[]d

', stepFunction: insertFontAwesome("fa fa-star"), contentAfterEdit: '

ab\ufeff\u200b\ufeffc\ufeff\u200b[]\ufeffd

', contentAfter: '

abc[]d

', }); }); test("should insert a fontAwesome before", async () => { await testEditor({ contentBefore: '

ab[]cd

', contentBeforeEdit: '

ab[]\ufeff\u200b\ufeffcd

', stepFunction: insertFontAwesome("fa fa-star"), contentAfterEdit: '

ab\ufeff\u200b[]\ufeff\u200b\ufeffcd

', contentAfter: '

ab[]cd

', }); }); test.skip("should insert a fontAwesome and replace the icon", async () => { await testEditor({ contentBefore: '

ab[]cd

', stepFunction: insertFontAwesome("fa fa-star"), contentAfter: '

abs[]cd

', }); }); test("should insert fontAwesome consecutively", async () => { await testEditor({ contentBefore: "

[]

", stepFunction: async (editor) => { execCommand(editor, "insertFontAwesome", { faClass: "fa fa-star" }); execCommand(editor, "insertFontAwesome", { faClass: "fa fa-glass" }); }, contentAfterEdit: '

\ufeff\u200b\ufeff\u200b[]\ufeff

', contentAfter: '

[]

', }); }); }); describe("Text insertion", () => { test("should insert a character before", async () => { await testEditor({ contentBefore: '

ab[]cd

', contentBeforeEdit: '

ab[]\ufeff\u200b\ufeffcd

', stepFunction: async (editor) => { await insertText(editor, "s"); }, contentAfterEdit: '

abs[]\ufeff\u200b\ufeffcd

', contentAfter: '

abs[]cd

', }); }); test("should insert a character after", async () => { await testEditor({ contentBefore: '

ab[]cd

', contentBeforeEdit: '

ab\ufeff\u200b\ufeff[]cd

', stepFunction: async (editor) => { await insertText(editor, "s"); }, contentAfterEdit: '

ab\ufeff\u200b\ufeffs[]cd

', contentAfter: '

abs[]cd

', }); }); test.skip("should insert a character and replace the icon", async () => { await testEditor({ contentBefore: '

ab[]cd

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

abs[]cd

", }); }); test("undo shouldn't remove changes applied by the editor setup", async () => { const { el, editor } = await setupEditor(`

`); expect(getContent(el)).toBe( `

\ufeff\u200b\ufeff

` ); undo(editor); expect(getContent(el)).toBe( `

\ufeff\u200b\ufeff

` ); }); });