import { describe, test } from "@odoo/hoot"; import { testEditor } from "./_helpers/editor"; import { TAB_WIDTH, getCharWidth, getIndentWidth, oeTab, testTabulation } from "./_helpers/tabs"; import { deleteBackward, deleteForward, insertText, keydownShiftTab, keydownTab, } from "./_helpers/user_actions"; describe("insert tabulation", () => { test("should insert a tab character", async () => { const expectedTabWidth = TAB_WIDTH - getCharWidth("p", "a"); await testTabulation({ contentBefore: `

a[]b

`, stepFunction: keydownTab, contentAfterEdit: `

a${oeTab(expectedTabWidth, false)}[]b

`, contentAfter: `

a${oeTab(expectedTabWidth)}[]b

`, }); }); test("should keep selection and insert a tab character at the beginning of the paragraph", async () => { await testTabulation({ contentBefore: `

a[xxx]b

`, stepFunction: keydownTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}a[xxx]b

`, contentAfter: `

${oeTab(TAB_WIDTH)}a[xxx]b

`, }); }); test("should insert two tab characters", async () => { const expectedTabWidth = TAB_WIDTH - getCharWidth("p", "a"); await testTabulation({ contentBefore: `

a[]b

`, stepFunction: async (editor) => { await keydownTab(editor); await keydownTab(editor); }, contentAfterEdit: `

a${oeTab(expectedTabWidth, false)}${oeTab( TAB_WIDTH, false )}[]b

`, contentAfter: `

a${oeTab(expectedTabWidth)}${oeTab(TAB_WIDTH)}[]b

`, }); }); test("should insert two tab characters with one char between them", async () => { const expectedTabWidth = TAB_WIDTH - getCharWidth("p", "a"); await testTabulation({ contentBefore: `

a[]b

`, stepFunction: async (editor) => { await keydownTab(editor); await insertText(editor, "a"); await keydownTab(editor); }, contentAfterEdit: `

a${oeTab(expectedTabWidth, false)}a${oeTab( expectedTabWidth, false )}[]b

`, contentAfter: `

a${oeTab(expectedTabWidth)}a${oeTab(expectedTabWidth)}[]b

`, }); }); test("should insert tab characters at the beginning of two separate paragraphs", async () => { await testTabulation({ contentBefore: `

a[b

` + `

c]d

`, stepFunction: keydownTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}a[b

` + `

${oeTab(TAB_WIDTH, false)}c]d

`, contentAfter: `

${oeTab(TAB_WIDTH)}a[b

` + `

${oeTab(TAB_WIDTH)}c]d

`, }); }); test("should insert tab characters at the beginning of two separate indented paragraphs", async () => { await testTabulation({ contentBefore: `

${oeTab()}a[b

` + `

${oeTab()}c]d

`, // @todo: add contentBeforeEdit in some test cases to test the addition // of the contenteditable="false" attribute by setup. stepFunction: keydownTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}a[b

` + `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}c]d

`, contentAfter: `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}a[b

` + `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}c]d

`, }); }); test("should insert tab characters at the beginning of two separate paragraphs (one indented, the other not)", async () => { await testTabulation({ contentBefore: `

${oeTab()}a[b

` + `

c]d

`, stepFunction: keydownTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}a[b

` + `

${oeTab(TAB_WIDTH, false)}c]d

`, contentAfter: `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}a[b

` + `

${oeTab(TAB_WIDTH)}c]d

`, }); await testTabulation({ contentBefore: `

a[b

` + `

${oeTab()}c]d

`, stepFunction: keydownTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}a[b

` + `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}c]d

`, contentAfter: `

${oeTab(TAB_WIDTH)}a[b

` + `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}c]d

`, }); }); test("should insert tab characters at the beginning of two separate paragraphs with tabs in them", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); const tabAfterB = TAB_WIDTH - getCharWidth("p", "b"); const tabAfterC = TAB_WIDTH - getCharWidth("p", "c"); const tabAfterD = TAB_WIDTH - getCharWidth("p", "d"); await testTabulation({ contentBefore: `

${oeTab()}a[${oeTab()}b${oeTab()}

` + `

c${oeTab()}]d${oeTab()}

`, stepFunction: keydownTab, contentAfter: `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}a[${oeTab(tabAfterA)}b${oeTab( tabAfterB )}

` + `

${oeTab(TAB_WIDTH)}c${oeTab(tabAfterC)}]d${oeTab(tabAfterD)}

`, }); }); test("should insert tab characters at the beginning of three separate blocks", async () => { const tabInBlockquote = TAB_WIDTH - getIndentWidth("blockquote"); await testTabulation({ contentBefore: `

xxx

` + `

a[b

` + `

cd

` + `
e]f
` + `

zzz

`, stepFunction: keydownTab, contentAfterEdit: `

xxx

` + `

${oeTab(TAB_WIDTH, false)}a[b

` + `

${oeTab(TAB_WIDTH, false)}cd

` + `
${oeTab(tabInBlockquote, false)}e]f
` + `

zzz

`, contentAfter: `

xxx

` + `

${oeTab(TAB_WIDTH)}a[b

` + `

${oeTab(TAB_WIDTH)}cd

` + `
${oeTab(tabInBlockquote)}e]f
` + `

zzz

`, }); }); test("should insert tab characters at the beginning of three separate indented blocks", async () => { const tabInBlockquote = TAB_WIDTH - getIndentWidth("blockquote"); await testTabulation({ contentBefore: `

${oeTab()}xxx

` + `

${oeTab()}a[b

` + `

${oeTab()}cd

` + `
${oeTab()}e]f
` + `

${oeTab()}zzz

`, stepFunction: keydownTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}xxx

` + `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}a[b

` + `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}cd

` + `
${oeTab(tabInBlockquote, false)}${oeTab( TAB_WIDTH, false )}e]f
` + `

${oeTab(TAB_WIDTH, false)}zzz

`, contentAfter: `

${oeTab(TAB_WIDTH)}xxx

` + `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}a[b

` + `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}cd

` + `
${oeTab(tabInBlockquote)}${oeTab(TAB_WIDTH)}e]f
` + `

${oeTab(TAB_WIDTH)}zzz

`, }); }); test("should insert tab characters at the beginning of three separate blocks of mixed indentation", async () => { const tabInBlockquote = TAB_WIDTH - getIndentWidth("blockquote"); await testTabulation({ contentBefore: `

xxx

` + `

${oeTab()}${oeTab()}a[b

` + `

${oeTab()}cd

` + `
e]f
` + `

zzz

`, stepFunction: keydownTab, contentAfterEdit: `

xxx

` + `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}${oeTab( TAB_WIDTH, false )}a[b

` + `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}cd

` + `
${oeTab(tabInBlockquote, false)}e]f
` + `

zzz

`, contentAfter: `

xxx

` + `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}a[b

` + `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}cd

` + `
${oeTab(tabInBlockquote)}e]f
` + `

zzz

`, }); }); test("should insert tab characters at the beginning of three separate blocks with tabs in them", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); const tabAfterB = TAB_WIDTH - getCharWidth("p", "b"); const tabAfterCinH1 = TAB_WIDTH - getCharWidth("h1", "c"); const tabAfterDinH1 = TAB_WIDTH - getCharWidth("h1", "d"); const tabInBlockquote = TAB_WIDTH - getIndentWidth("blockquote"); const tabAfterEinBlockquote = TAB_WIDTH - getCharWidth("blockquote", "e"); // in bloquote, after a tab await testTabulation({ contentBefore: `

xxx

` + `

${oeTab()}a[${oeTab()}b${oeTab()}

` + `

c${oeTab()}d${oeTab()}

` + `
e${oeTab()}]f
` + `

zzz

`, stepFunction: keydownTab, contentAfterEdit: `

xxx

` + `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}a[${oeTab( tabAfterA, false )}b${oeTab(tabAfterB, false)}

` + `

${oeTab(TAB_WIDTH, false)}c${oeTab(tabAfterCinH1, false)}d${oeTab( tabAfterDinH1, false )}

` + `
${oeTab(tabInBlockquote, false)}e${oeTab( tabAfterEinBlockquote, false )}]f
` + `

zzz

`, contentAfter: `

xxx

` + `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}a[${oeTab(tabAfterA)}b${oeTab( tabAfterB )}

` + `

${oeTab(TAB_WIDTH)}c${oeTab(tabAfterCinH1)}d${oeTab(tabAfterDinH1)}

` + `
${oeTab(tabInBlockquote)}e${oeTab( tabAfterEinBlockquote )}]f
` + `

zzz

`, }); }); test("should insert tab characters in blocks and indent lists", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); const tabAfterB = TAB_WIDTH - getCharWidth("p", "b"); const tabAfterCinNestedLI = TAB_WIDTH - ((2 * getIndentWidth("li") + getCharWidth("li", "c")) % TAB_WIDTH); const tabAfterD = TAB_WIDTH - getCharWidth("li", "d"); // in LI, after a tab const tabInDoubleNestedList = TAB_WIDTH - ((3 * getIndentWidth("li")) % TAB_WIDTH); const tabAfterE = TAB_WIDTH - getCharWidth("li", "e"); // in LI, after a tab const tabInBlockquote = TAB_WIDTH - getIndentWidth("blockquote"); const tabAfterFinBlockquote = TAB_WIDTH - getCharWidth("blockquote", "f"); // in blockquote, after a tab // prettier-ignore await testTabulation({ // Obs: cannot use `unformat` for tests with tabs (as it removes the \t chars) contentBefore: `

${oeTab()}a[${oeTab()}b${oeTab()}

` + `` + `
f${oeTab()}]g
`, stepFunction: keydownTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}${oeTab(TAB_WIDTH, false)}a[${oeTab(tabAfterA, false)}b${oeTab(tabAfterB,false)}

` + `` + `
${oeTab(tabInBlockquote, false)}f${oeTab(tabAfterFinBlockquote, false)}]g
`, contentAfter: `

${oeTab(TAB_WIDTH)}${oeTab(TAB_WIDTH)}a[${oeTab(tabAfterA)}b${oeTab(tabAfterB)}

` + `` + `
${oeTab(tabInBlockquote)}f${oeTab(tabAfterFinBlockquote)}]g
`, }); }); }); describe("delete backward tabulation", () => { test("should remove one tab character", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); await testEditor({ contentBefore: `

a${oeTab(tabAfterA)}[]b

`, stepFunction: async (editor) => { deleteBackward(editor); }, contentAfter: `

a[]b

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

a${oeTab(tabAfterA)}[]${oeTab()}b

`, stepFunction: async (editor) => { deleteBackward(editor); }, contentAfter: `

a[]${oeTab(tabAfterA)}b

`, }); }); test("should remove two tab characters", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); await testEditor({ contentBefore: `

a${oeTab(tabAfterA)}${oeTab()}[]b

`, stepFunction: async (editor) => { deleteBackward(editor); deleteBackward(editor); }, contentAfter: `

a[]b

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

a${oeTab(tabAfterA)}${oeTab()}[]${oeTab()}b

`, stepFunction: async (editor) => { deleteBackward(editor); deleteBackward(editor); }, contentAfter: `

a[]${oeTab(tabAfterA)}b

`, }); }); test("should remove three tab characters", async () => { await testEditor({ contentBefore: `

a${oeTab()}${oeTab()}${oeTab()}[]b

`, stepFunction: async (editor) => { deleteBackward(editor); deleteBackward(editor); deleteBackward(editor); }, contentAfter: `

a[]b

`, }); }); }); describe("delete forward tabulation", () => { test("should remove one tab character", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); await testTabulation({ contentBefore: `

a[]${oeTab(tabAfterA)}b1

`, stepFunction: async (editor) => { deleteForward(editor); }, contentAfter: `

a[]b1

`, }); await testTabulation({ contentBefore: `

a${oeTab(tabAfterA)}[]${oeTab()}b2

`, stepFunction: async (editor) => { deleteForward(editor); }, contentAfter: `

a${oeTab(tabAfterA)}[]b2

`, }); await testTabulation({ contentBefore: `

a[]${oeTab(tabAfterA)}${oeTab()}b3

`, stepFunction: async (editor) => { deleteForward(editor); }, contentAfter: `

a[]${oeTab(tabAfterA)}b3

`, }); }); test("should remove two tab characters", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); await testEditor({ contentBefore: `

a[]${oeTab(tabAfterA)}${oeTab()}b1

`, stepFunction: async (editor) => { deleteForward(editor); deleteForward(editor); }, contentAfter: `

a[]b1

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

a[]${oeTab(tabAfterA)}${oeTab()}${oeTab()}b2

`, stepFunction: async (editor) => { deleteForward(editor); deleteForward(editor); }, contentAfter: `

a[]${oeTab(tabAfterA)}b2

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

a${oeTab(tabAfterA)}[]${oeTab()}${oeTab()}b3

`, stepFunction: async (editor) => { deleteForward(editor); deleteForward(editor); }, contentAfter: `

a${oeTab(tabAfterA)}[]b3

`, }); }); test("should remove three tab characters", async () => { await testEditor({ contentBefore: `

a[]${oeTab()}${oeTab()}${oeTab()}b

`, stepFunction: async (editor) => { deleteForward(editor); deleteForward(editor); deleteForward(editor); }, contentAfter: `

a[]b

`, }); }); }); describe("delete mixed tabulation", () => { test("should remove all tab characters", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); await testEditor({ contentBefore: `

a${oeTab(tabAfterA)}[]${oeTab()}b1

`, stepFunction: async (editor) => { deleteForward(editor); deleteBackward(editor); }, contentAfter: `

a[]b1

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

a${oeTab(tabAfterA)}[]${oeTab()}b2

`, stepFunction: async (editor) => { deleteBackward(editor); deleteForward(editor); }, contentAfter: `

a[]b2

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

a${oeTab(tabAfterA)}${oeTab()}[]${oeTab()}b3

`, stepFunction: async (editor) => { deleteBackward(editor); deleteForward(editor); deleteBackward(editor); }, contentAfter: `

a[]b3

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

a${oeTab(tabAfterA)}[]${oeTab()}${oeTab()}b4

`, stepFunction: async (editor) => { deleteForward(editor); deleteBackward(editor); deleteForward(editor); }, contentAfter: `

a[]b4

`, }); }); }); describe("remove tabulation with shift+tab", () => { test("should not remove a non-leading tab character", async () => { function oeTab(size, contenteditable = true) { return ( `\u0009\u200B` ); } const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); await testEditor({ contentBefore: `

a${oeTab(tabAfterA)}[]b

`, stepFunction: keydownShiftTab, contentAfterEdit: `

a${oeTab(tabAfterA, false)}[]b

`, contentAfter: `

a${oeTab(tabAfterA)}[]b

`, }); }); test("should remove a tab character", async () => { await testEditor({ contentBefore: `

${oeTab()}a[]b

`, stepFunction: keydownShiftTab, contentAfter: `

a[]b

`, }); }); test("should keep selection and remove a tab character from the beginning of the paragraph", async () => { await testEditor({ contentBefore: `

${oeTab()}a[xxx]b

`, stepFunction: keydownShiftTab, contentAfter: `

a[xxx]b

`, }); }); test("should remove two tab characters", async () => { await testEditor({ contentBefore: `

${oeTab()}${oeTab()}a[]b

`, stepFunction: async (editor) => { await keydownShiftTab(editor); await keydownShiftTab(editor); }, contentAfter: `

a[]b

`, }); }); test("should remove tab characters from the beginning of two separate paragraphs", async () => { await testEditor({ contentBefore: `

${oeTab()}a[b

` + `

${oeTab()}c]d

`, stepFunction: keydownShiftTab, contentAfter: `

a[b

` + `

c]d

`, }); }); test("should remove tab characters from the beginning of two separate double-indented paragraphs", async () => { await testTabulation({ contentBefore: `

${oeTab()}${oeTab()}a[b

` + `

${oeTab()}${oeTab()}c]d

`, stepFunction: keydownShiftTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}a[b

` + `

${oeTab(TAB_WIDTH, false)}c]d

`, contentAfter: `

${oeTab(TAB_WIDTH)}a[b

` + `

${oeTab(TAB_WIDTH)}c]d

`, }); }); test("should remove tab characters from the beginning of two separate paragraphs of mixed indentations", async () => { await testTabulation({ contentBefore: `

${oeTab()}${oeTab()}a[b

` + `

${oeTab()}c]d

`, stepFunction: keydownShiftTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}a[b

` + `

c]d

`, contentAfter: `

${oeTab(TAB_WIDTH)}a[b

` + `

c]d

`, }); await testTabulation({ contentBefore: `

a[b

` + `

${oeTab()}c]d

`, stepFunction: keydownShiftTab, contentAfter: `

a[b

` + `

c]d

`, }); }); test("should remove tab characters from the beginning of two separate paragraphs with tabs in them", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); const tabAfterB = TAB_WIDTH - getCharWidth("p", "b"); const tabAfterC = TAB_WIDTH - getCharWidth("p", "c"); const tabAfterD = TAB_WIDTH - getCharWidth("p", "d"); await testTabulation({ contentBefore: `

${oeTab(TAB_WIDTH)}a[${oeTab(tabAfterA)}b${oeTab(tabAfterB)}

` + `

c${oeTab(tabAfterC)}]d${oeTab(tabAfterD)}

`, stepFunction: keydownShiftTab, contentAfter: `

a[${oeTab(tabAfterA)}b${oeTab(tabAfterB)}

` + `

c${oeTab(tabAfterC)}]d${oeTab(tabAfterD)}

`, }); }); test("should remove tab characters from the beginning of three separate blocks", async () => { await testEditor({ contentBefore: `

xxx

` + `

${oeTab()}a[b

` + `

${oeTab()}cd

` + `
${oeTab()}e]f
` + `

zzz

`, stepFunction: keydownShiftTab, contentAfter: `

xxx

` + `

a[b

` + `

cd

` + `
e]f
` + `

zzz

`, }); }); test("should remove tab characters from the beginning of three separate blocks of mixed indentation", async () => { await testTabulation({ contentBefore: `

xxx

` + `

${oeTab()}${oeTab()}a[b

` + `

${oeTab()}cd

` + `
e]f
` + `

zzz

`, stepFunction: keydownShiftTab, contentAfterEdit: `

xxx

` + `

${oeTab(TAB_WIDTH, false)}a[b

` + `

cd

` + `
e]f
` + `

zzz

`, contentAfter: `

xxx

` + `

${oeTab(TAB_WIDTH)}a[b

` + `

cd

` + `
e]f
` + `

zzz

`, }); }); test("should remove tab characters from the beginning of three separate blocks with tabs in them", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); const tabAfterB = TAB_WIDTH - getCharWidth("p", "b"); const tabAfterCinH1 = TAB_WIDTH - getCharWidth("h1", "c"); const tabAfterDinH1 = TAB_WIDTH - getCharWidth("h1", "d"); const tabAfterEinBlockquote = TAB_WIDTH - (getIndentWidth("blockquote") + getCharWidth("blockquote", "e")); await testTabulation({ contentBefore: `

xxx

` + `

${oeTab()}a[${oeTab()}b${oeTab()}

` + `

${oeTab()}c${oeTab()}d${oeTab()}

` + `
${oeTab()}e${oeTab()}]f
` + `

zzz

`, stepFunction: keydownShiftTab, contentAfterEdit: `

xxx

` + `

a[${oeTab(tabAfterA, false)}b${oeTab(tabAfterB, false)}

` + `

c${oeTab(tabAfterCinH1, false)}d${oeTab(tabAfterDinH1, false)}

` + `
e${oeTab(tabAfterEinBlockquote, false)}]f
` + `

zzz

`, contentAfter: `

xxx

` + `

a[${oeTab(tabAfterA)}b${oeTab(tabAfterB)}

` + `

c${oeTab(tabAfterCinH1)}d${oeTab(tabAfterDinH1)}

` + `
e${oeTab(tabAfterEinBlockquote)}]f
` + `

zzz

`, }); }); test("should remove tab characters from the beginning of blocks and outdent lists", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); const tabAfterB = TAB_WIDTH - getCharWidth("p", "b"); const tabAfterCinLI = TAB_WIDTH - ((getIndentWidth("li") + getCharWidth("li", "c")) % TAB_WIDTH); const tabAfterD = TAB_WIDTH - getCharWidth("li", "d"); // in LI, after a tab const tabAfterE = TAB_WIDTH - getCharWidth("li", "e"); // in LI, after a tab const tabInNestedList = TAB_WIDTH - ((2 * getIndentWidth("li")) % TAB_WIDTH); const tabAfterFinBlockquote = TAB_WIDTH - (getIndentWidth("blockquote") + getCharWidth("blockquote", "f")); await testTabulation({ contentBefore: `

${oeTab()}${oeTab()}a[${oeTab()}b${oeTab()}

` + `` + `
${oeTab()}f${oeTab()}]g
`, stepFunction: keydownShiftTab, contentAfterEdit: `

${oeTab(TAB_WIDTH, false)}a[${oeTab(tabAfterA, false)}b${oeTab( tabAfterB, false )}

` + `` + `
f${oeTab(tabAfterFinBlockquote, false)}]g
`, contentAfter: `

${oeTab(TAB_WIDTH)}a[${oeTab(tabAfterA)}b${oeTab(tabAfterB)}

` + `` + `
f${oeTab(tabAfterFinBlockquote)}]g
`, }); }); test("should remove a tab character from formatted text", async () => { await testEditor({ contentBefore: `

${oeTab()}a[]b

`, stepFunction: keydownShiftTab, contentAfter: `

a[]b

`, }); }); test("should remove tab characters from the beginning of two separate formatted paragraphs", async () => { await testEditor({ contentBefore: `

${oeTab()}a[b

` + `

${oeTab()}c]d

`, stepFunction: keydownShiftTab, contentAfter: `

a[b

` + `

c]d

`, }); }); test("should remove a tab character from styled text", async () => { await testEditor({ contentBefore: `

${oeTab()}a[]b

`, stepFunction: keydownShiftTab, contentAfter: `

a[]b

`, }); }); }); describe("update tab width", () => { test("should update tab width on content change", async () => { const tabAfterA = TAB_WIDTH - getCharWidth("p", "a"); const tabAfterAA = TAB_WIDTH - 2 * getCharWidth("p", "a"); await testEditor({ contentBefore: `

a[]${oeTab(tabAfterA)}

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

aa[]${oeTab(tabAfterAA)}

`, }); }); });