TinyLoader.setup(function (editor, onSuccess, onFailure) { const tinyUi = TinyUi(editor); const tinyApis = TinyApis(editor); const sDeleteSetting = function (key) { return Step.sync(function () { delete editor.settings[key]; }); }; Pipeline.async({}, [ Logger.t('test cdate in snippet with default class', GeneralSteps.sequence([ tinyApis.sSetSetting('templates', [{ title: 'a', description: 'b', content: '<p class="cdate">x</p>' }]), tinyApis.sSetSetting('template_cdate_format', 'fake date'), tinyUi.sClickOnToolbar('click on template button', 'div[aria-label="Insert template"] > button'), tinyUi.sWaitForPopup('wait for popup', 'div[role="dialog"][aria-label="Insert template"]'), tinyUi.sClickOnUi('click on ok button', 'div.mce-primary button'), tinyApis.sAssertContent('<p class="cdate">fake date</p>'), tinyApis.sSetContent('') ])), Logger.t('test cdate in snippet with custom class', GeneralSteps.sequence([ tinyApis.sSetSetting('template_cdate_classes', 'customCdateClass'), tinyApis.sSetSetting('templates', [{ title: 'a', description: 'b', content: '<p class="customCdateClass">x</p>' }]), tinyApis.sSetSetting('template_cdate_format', 'fake date'), tinyUi.sClickOnToolbar('click on template button', 'div[aria-label="Insert template"] > button'), tinyUi.sWaitForPopup('wait for popup', 'div[role="dialog"][aria-label="Insert template"]'), tinyUi.sClickOnUi('click on ok button', 'div.mce-primary button'), tinyApis.sAssertContent('<p class="customCdateClass">fake date</p>'), sDeleteSetting('template_cdate_classes'), sDeleteSetting('templates'), sDeleteSetting('template_cdate_format'), tinyApis.sSetContent('') ])), Logger.t('test mdate updates with each serialization', GeneralSteps.sequence([ tinyApis.sSetSetting( 'templates', [{ title: 'a', description: 'b', content: '<div class="mceTmpl"><p class="mdate"></p><p class="cdate"></p></div>' }] ), tinyApis.sSetSetting('template_mdate_format', 'fake modified date'), tinyApis.sSetSetting('template_cdate_format', 'fake created date'), tinyUi.sClickOnToolbar('click on template button', 'div[aria-label="Insert template"] > button'), tinyUi.sWaitForPopup('wait for popup', 'div[role="dialog"][aria-label="Insert template"]'), tinyUi.sClickOnUi('click on ok button', 'div.mce-primary button'), tinyApis.sAssertContent('<div class="mceTmpl"><p class="mdate">fake modified date</p><p class="cdate">fake created date</p></div>'), tinyApis.sSetSetting('template_mdate_format', 'changed modified date'), tinyApis.sAssertContent('<div class="mceTmpl"><p class="mdate">changed modified date</p><p class="cdate">fake created date</p></div>'), sDeleteSetting('templates'), sDeleteSetting('template_mdate_format'), sDeleteSetting('template_cdate_template'), tinyApis.sSetContent('') ])), Logger.t('test mdate updates with each serialization with custom class', GeneralSteps.sequence([ tinyApis.sSetSetting('template_mdate_classes', 'modified'), tinyApis.sSetSetting( 'templates', [{ title: 'a', description: 'b', content: '<div class="mceTmpl"><p class="modified"></p><p class="cdate"></p></div>' }] ), tinyApis.sSetSetting('template_mdate_format', 'fake modified date'), tinyApis.sSetSetting('template_cdate_format', 'fake created date'), tinyUi.sClickOnToolbar('click on template button', 'div[aria-label="Insert template"] > button'), tinyUi.sWaitForPopup('wait for popup', 'div[role="dialog"][aria-label="Insert template"]'), tinyUi.sClickOnUi('click on ok button', 'div.mce-primary button'), tinyApis.sAssertContent('<div class="mceTmpl"><p class="modified">fake modified date</p><p class="cdate">fake created date</p></div>'), tinyApis.sSetSetting('template_mdate_format', 'changed modified date'), tinyApis.sAssertContent('<div class="mceTmpl"><p class="modified">changed modified date</p><p class="cdate">fake created date</p></div>'), sDeleteSetting('template_mdate_classes'), sDeleteSetting('templates'), sDeleteSetting('template_mdate_format'), sDeleteSetting('template_cdate_template') ])) ], onSuccess, onFailure); }, {
TinyLoader.setup(function (editor, onSuccess, onFailure) { const tinyApis = TinyApis(editor); const inlineFormat = [{ inline: 'b' }]; const blockFormat = [{ block: 'div' }]; const selectorFormat = [{ selector: 'div', classes: 'b' }]; const selectorFormatCollapsed = [{ selector: 'div', classes: 'b', collapsed: true }]; Pipeline.async({}, [ tinyApis.sFocus, Logger.t('Expand inline format words', GeneralSteps.sequence([ Logger.t('In middle of single word in paragraph', Chain.asStep(editor, [ cSetRawContent('<p>ab</p>'), cExpandRng([0, 0], 1, [0, 0], 1, inlineFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('In middle of single word in paragraph with paragraph siblings', Chain.asStep(editor, [ cSetRawContent('<p>a</p><p>bc</p><p>de</p>'), cExpandRng([1, 0], 1, [1, 0], 1, inlineFormat, false), cAssertRange(editor, [], 1, [], 2) ])), Logger.t('In middle of single word wrapped in b', Chain.asStep(editor, [ cSetRawContent('<p><b>ab</b></p>'), cExpandRng([0, 0, 0], 1, [0, 0, 0], 1, inlineFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('In middle of first word', Chain.asStep(editor, [ cSetRawContent('<p>ab cd</p>'), cExpandRng([0, 0], 1, [0, 0], 1, inlineFormat, false), cAssertRange(editor, [], 0, [0, 0], 2) ])), Logger.t('In middle of last word', Chain.asStep(editor, [ cSetRawContent('<p>ab cd</p>'), cExpandRng([0, 0], 4, [0, 0], 4, inlineFormat, false), cAssertRange(editor, [0, 0], 3, [], 1) ])), Logger.t('In middle of middle word', Chain.asStep(editor, [ cSetRawContent('<p>ab cd ef</p>'), cExpandRng([0, 0], 4, [0, 0], 4, inlineFormat, false), cAssertRange(editor, [0, 0], 3, [0, 0], 5) ])), Logger.t('In middle of word with bold siblings expand to sibling spaces', Chain.asStep(editor, [ cSetRawContent('<p><b>ab </b>cd<b> ef</b></p>'), cExpandRng([0, 1], 1, [0, 1], 1, inlineFormat, false), cAssertRange(editor, [0, 0, 0], 3, [0, 2, 0], 0) ])), Logger.t('In middle of word with block sibling and inline sibling expand to sibling space to the right', Chain.asStep(editor, [ cSetRawContent('<div><p>ab </p>cd<b> ef</b></div>'), cExpandRng([0, 1], 1, [0, 1], 1, inlineFormat, false), cAssertRange(editor, [0, 1], 0, [0, 2, 0], 0) ])), Logger.t('In middle of word with block sibling and inline sibling expand to sibling space to the left', Chain.asStep(editor, [ cSetRawContent('<div><b>ab </b>cd<p> ef</p></div>'), cExpandRng([0, 1], 1, [0, 1], 1, inlineFormat, false), cAssertRange(editor, [0, 0, 0], 3, [0, 1], 2) ])), Logger.t('In middle of middle word separated by nbsp characters', Chain.asStep(editor, [ cSetRawContent('<p>ab\u00a0cd\u00a0ef</p>'), cExpandRng([0, 0], 4, [0, 0], 4, inlineFormat, false), cAssertRange(editor, [0, 0], 3, [0, 0], 5) ])), Logger.t('In empty paragraph', Chain.asStep(editor, [ cSetRawContent('<p><br></p>'), cExpandRng([0], 0, [0], 0, inlineFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('Fully selected word', Chain.asStep(editor, [ cSetRawContent('<p>ab</p>'), cExpandRng([0, 0], 0, [0, 0], 2, inlineFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('Partially selected word', Chain.asStep(editor, [ cSetRawContent('<p>abc</p>'), cExpandRng([0, 0], 1, [0, 0], 2, inlineFormat, false), cAssertRange(editor, [0, 0], 1, [0, 0], 2) ])), Logger.t('Whole word selected wrapped in multiple inlines', Chain.asStep(editor, [ cSetRawContent('<p><b><i>c</i></b></p>'), cExpandRng([0, 0, 0, 0], 0, [0, 0, 0, 0], 1, inlineFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('Whole word inside td', Chain.asStep(editor, [ cSetRawContent('<table><tbody><tr><td>a</td></tr></tbody></table>'), cExpandRng([0, 0, 0, 0, 0], 0, [0, 0, 0, 0, 0], 1, inlineFormat, false), cAssertRange(editor, [0, 0, 0], 0, [0, 0, 0], 1) ])), Logger.t('In middle of single word in paragraph (index based)', Chain.asStep(editor, [ cSetRawContent('<p>ab</p>'), cExpandRng([0], 0, [0], 1, inlineFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('In middle of single word wrapped in bold in paragraph (index based)', Chain.asStep(editor, [ cSetRawContent('<p><b>ab</b></p>'), cExpandRng([0], 0, [0], 1, inlineFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('In middle of word inside bookmark then exclude bookmark', Chain.asStep(editor, [ cSetRawContent('<p><span data-mce-type="bookmark">ab cd ef</span></p>'), cExpandRng([0, 0, 0], 3, [0, 0, 0], 5, inlineFormat, false), cAssertRange(editor, [], 0, [], 1) ])) ])), Logger.t('Expand inline format words (remove format)', GeneralSteps.sequence([ Logger.t('In middle of single word in paragraph', Chain.asStep(editor, [ cSetRawContent('<p>ab</p>'), cExpandRng([0, 0], 1, [0, 0], 1, inlineFormat, true), cAssertRange(editor, [], 0, [], 1) ])) ])), Logger.t('Expand block format', GeneralSteps.sequence([ Logger.t('In middle word', Chain.asStep(editor, [ cSetRawContent('<p>ab cd ef</p>'), cExpandRng([0, 0], 4, [0, 0], 4, blockFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('In middle bold word', Chain.asStep(editor, [ cSetRawContent('<p>ab <b>cd</b> ef</p>'), cExpandRng([0, 1, 0], 1, [0, 1, 0], 1, blockFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('Whole word inside td', Chain.asStep(editor, [ cSetRawContent('<table><tbody><tr><td>a</td></tr></tbody></table>'), cExpandRng([0, 0, 0, 0, 0], 0, [0, 0, 0, 0, 0], 1, blockFormat, false), cAssertRange(editor, [0, 0, 0], 0, [0, 0, 0], 1) ])) ])), Logger.t('Expand selector format', GeneralSteps.sequence([ Logger.t('Do not expand over element if selector does not match', Chain.asStep(editor, [ cSetRawContent('<p>ab</p>'), cExpandRng([0, 0], 1, [0, 0], 1, selectorFormat, false), cAssertRange(editor, [0, 0], 0, [0, 0], 2) ])), Logger.t('Do not expand outside of element if selector does not match - from bookmark at middle', Chain.asStep(editor, [ cSetRawContent('<p>a<span data-mce-type="bookmark"></span>b</p>'), cExpandRng([0, 1, 0], 0, [0, 1, 0], 0, selectorFormat, false), cAssertRange(editor, [0, 0], 0, [0, 2], 1) ])), Logger.t('Do not expand outside of element if selector does not match - from bookmark at start', Chain.asStep(editor, [ cSetRawContent('<p><span data-mce-type="bookmark"></span>ab</p>'), cExpandRng([0, 0, 0], 0, [0, 0, 0], 0, selectorFormat, false), cAssertRange(editor, [0], 0, [0, 1], 2) ])), Logger.t('Do not expand outside of element if selector does not match - from bookmark at end', Chain.asStep(editor, [ cSetRawContent('<p>ab<span data-mce-type="bookmark"></span></p>'), cExpandRng([0, 1, 0], 0, [0, 1, 0], 0, selectorFormat, false), cAssertRange(editor, [0, 0], 0, [0], 2) ])), Logger.t('Expand since selector matches', Chain.asStep(editor, [ cSetRawContent('<div>ab</div>'), cExpandRng([0, 0], 1, [0, 0], 1, selectorFormat, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('Expand since selector matches non collapsed', Chain.asStep(editor, [ cSetRawContent('<div>ab</div>'), cExpandRng([0, 0], 1, [0, 0], 2, selectorFormat, false), cAssertRange(editor, [], 0, [], 1) ])) ])), Logger.t('Expand selector format with collapsed property', GeneralSteps.sequence([ Logger.t('Expand since selector matches collapsed on collapsed format', Chain.asStep(editor, [ cSetRawContent('<div>ab</div>'), cExpandRng([0, 0], 1, [0, 0], 1, selectorFormatCollapsed, false), cAssertRange(editor, [], 0, [], 1) ])), Logger.t('Expand since selector matches non collapsed on collapsed format', Chain.asStep(editor, [ cSetRawContent('<div>ab</div>'), cExpandRng([0, 0], 1, [0, 0], 2, selectorFormatCollapsed, false), cAssertRange(editor, [0, 0], 1, [0, 0], 2) ])) ])) ], onSuccess, onFailure); }, {
UnitTest.asynctest('browser.tinymce.core.keyboard.InlineUtilsTest', function () { const success = arguments[arguments.length - 2]; const failure = arguments[arguments.length - 1]; const ZWSP = Zwsp.ZWSP; const cCreateElement = function (html) { return Chain.mapper(function (_) { return Element.fromHtml(html); }); }; const cNormalizePosition = function (forward, path, offset) { return Chain.mapper(function (elm: any) { const container = Hierarchy.follow(elm, path).getOrDie(); const pos = CaretPosition(container.dom(), offset); return { pos: InlineUtils.normalizePosition(forward, pos), elm }; }); }; const cAssertPosition = function (path, expectedOffset) { return Chain.mapper(function (elmPos: any) { const expectedContainer = Hierarchy.follow(elmPos.elm, path).getOrDie(); Assertions.assertDomEq('Should be expected container', Element.fromDom(elmPos.pos.container()), expectedContainer); Assertions.assertEq('Should be expected offset', elmPos.pos.offset(), expectedOffset); return {}; }); }; const cSplitAt = function (path, offset) { return Chain.mapper(function (elm: any) { const textNode = Hierarchy.follow(elm, path).getOrDie(); textNode.dom().splitText(offset); return elm; }); }; const createFakeEditor = function (settings) { return { settings } as any; }; Pipeline.async({}, [ Logger.t('isInlineTarget with various editor settings', Step.sync(function () { Assertions.assertEq('Links should be inline target', true, InlineUtils.isInlineTarget(createFakeEditor({ }), Element.fromHtml('<a href="a">').dom())); Assertions.assertEq('Code should be inline target', true, InlineUtils.isInlineTarget(createFakeEditor({ }), Element.fromHtml('<code>').dom())); Assertions.assertEq('None link anchor should not be inline target', false, InlineUtils.isInlineTarget(createFakeEditor({ }), Element.fromHtml('<a>').dom())); Assertions.assertEq('Bold should not be inline target', false, InlineUtils.isInlineTarget(createFakeEditor({ }), Element.fromHtml('<b>').dom())); Assertions.assertEq('Bold should be inline target if configured', true, InlineUtils.isInlineTarget(createFakeEditor({ inline_boundaries_selector: 'b' }), Element.fromHtml('<b>').dom())); Assertions.assertEq('Italic should be inline target if configured', true, InlineUtils.isInlineTarget(createFakeEditor({ inline_boundaries_selector: 'b,i' }), Element.fromHtml('<i>').dom())); })), Logger.t('normalizePosition on text forwards', GeneralSteps.sequence([ Logger.t('normalizePosition start of zwsp before text', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + 'a</p>'), cNormalizePosition(true, [0], 0), cAssertPosition([0], 1) ])), Logger.t('normalizePosition end of zwsp before text', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + 'a</p>'), cNormalizePosition(true, [0], 1), cAssertPosition([0], 1) ])), Logger.t('normalizePosition start of zwsp after text', Chain.asStep({}, [ cCreateElement('<p>a' + ZWSP + '</p>'), cNormalizePosition(true, [0], 1), cAssertPosition([0], 2) ])), Logger.t('normalizePosition end of zwsp after text', Chain.asStep({}, [ cCreateElement('<p>a' + ZWSP + '</p>'), cNormalizePosition(true, [0], 2), cAssertPosition([0], 2) ])) ])), Logger.t('normalizePosition on text backwards', GeneralSteps.sequence([ Logger.t('normalizePosition end of zwsp after text', Chain.asStep({}, [ cCreateElement('<p>a' + ZWSP + '</p>'), cNormalizePosition(false, [0], 2), cAssertPosition([0], 1) ])), Logger.t('normalizePosition start of zwsp after text', Chain.asStep({}, [ cCreateElement('<p>a' + ZWSP + '</p>'), cNormalizePosition(false, [0], 1), cAssertPosition([0], 1) ])), Logger.t('normalizePosition end of zwsp before text', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + 'a</p>'), cNormalizePosition(false, [0], 1), cAssertPosition([0], 0) ])), Logger.t('normalizePosition start of zwsp before text', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + 'a</p>'), cNormalizePosition(false, [0], 0), cAssertPosition([0], 0) ])) ])), Logger.t('normalizePosition on element forwards', GeneralSteps.sequence([ Logger.t('normalizePosition start of zwsp before element', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + '<input></p>'), cNormalizePosition(true, [0], 0), cAssertPosition([], 1) ])), Logger.t('normalizePosition end of zwsp before element', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + '<input></p>'), cNormalizePosition(true, [0], 1), cAssertPosition([], 1) ])), Logger.t('normalizePosition start of zwsp after element', Chain.asStep({}, [ cCreateElement('<p><input>' + ZWSP + '</p>'), cNormalizePosition(true, [1], 0), cAssertPosition([], 2) ])), Logger.t('normalizePosition end of zwsp after element', Chain.asStep({}, [ cCreateElement('<p><input>' + ZWSP + '</p>'), cNormalizePosition(true, [1], 1), cAssertPosition([], 2) ])) ])), Logger.t('normalizePosition on element backwards', GeneralSteps.sequence([ Logger.t('normalizePosition end of zwsp after element', Chain.asStep({}, [ cCreateElement('<p><input>' + ZWSP + '</p>'), cNormalizePosition(false, [1], 1), cAssertPosition([], 1) ])), Logger.t('normalizePosition start of zwsp after element', Chain.asStep({}, [ cCreateElement('<p><input>' + ZWSP + '</p>'), cNormalizePosition(false, [1], 0), cAssertPosition([], 1) ])), Logger.t('normalizePosition end of zwsp before element', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + '<input></p>'), cNormalizePosition(false, [0], 1), cAssertPosition([], 0) ])), Logger.t('normalizePosition start of zwsp before element', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + '<input></p>'), cNormalizePosition(false, [0], 0), cAssertPosition([], 0) ])) ])), Logger.t('normalizePosition on text forwards', GeneralSteps.sequence([ Logger.t('normalizePosition start of zwsp before text', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + 'a</p>'), cSplitAt([0], 1), cNormalizePosition(true, [0], 0), cAssertPosition([1], 0) ])), Logger.t('normalizePosition end of zwsp before text', Chain.asStep({}, [ cCreateElement('<p>' + ZWSP + 'a</p>'), cSplitAt([0], 1), cNormalizePosition(true, [0], 1), cAssertPosition([1], 0) ])), Logger.t('normalizePosition start of zwsp after text', Chain.asStep({}, [ cCreateElement('<p>a' + ZWSP + '</p>'), cSplitAt([0], 1), cNormalizePosition(true, [1], 0), cAssertPosition([], 2) ])), Logger.t('normalizePosition end of zwsp after text', Chain.asStep({}, [ cCreateElement('<p>a' + ZWSP + '</p>'), cSplitAt([0], 1), cNormalizePosition(true, [1], 1), cAssertPosition([], 2) ])) ])) ], function () { success(); }, failure); });
const sRedo = function (editor) { return Logger.t('Redo', Step.sync(function () { editor.undoManager.redo(); })); };
TinyLoader.setup(function (editor, onSuccess, onFailure) { const tinyApis = TinyApis(editor); Pipeline.async({}, [ Logger.t('Insert key in text with in nbsp text node', GeneralSteps.sequence([ Logger.t('Nbsp at first character position', GeneralSteps.sequence([ Logger.t('Insert in text node with nbsp at start of body', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent(' a'), tinyApis.sSetCursor([0], 2), sFireInsert(editor), tinyApis.sAssertSelection([0], 2, [0], 2), tinyApis.sAssertContent(' a') ])), Logger.t('Insert in text in node with leading nbsp after inline with trailing space', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a<em>b </em> c'), tinyApis.sSetCursor([2], 2), sFireInsert(editor), tinyApis.sAssertSelection([2], 2, [2], 2), tinyApis.sAssertContent('a<em>b </em> c') ])), Logger.t('Insert in text in node with leading nbsp after inline', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a<em>b</em> c'), tinyApis.sSetCursor([2], 2), sFireInsert(editor), tinyApis.sAssertSelection([2], 2, [2], 2), tinyApis.sAssertContent('a<em>b</em> c') ])), Logger.t('Insert in text in node with leading nbsp after inline with trailing nbsp', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a<em>b </em> c'), tinyApis.sSetCursor([2], 2), sFireInsert(editor), tinyApis.sAssertSelection([2], 2, [2], 2), tinyApis.sAssertContent('a<em>b </em> c') ])), Logger.t('Insert at beginning of text node with leading nbsp after a br', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a<br /> b'), tinyApis.sSetCursor([2], 0), sFireInsert(editor), tinyApis.sAssertSelection([2], 0, [2], 0), tinyApis.sAssertContent('a<br /> b') ])), Logger.t('Insert at beginning of text node with leading nbsp within inline element followed by br', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a<br /><em> b</em>'), tinyApis.sSetCursor([2, 0], 0), sFireInsert(editor), tinyApis.sAssertSelection([2, 0], 0, [2, 0], 0), tinyApis.sAssertContent('a<br /><em> b</em>') ])) ])), Logger.t('Nbsp at last character position', GeneralSteps.sequence([ Logger.t('Insert in text node with nbsp at end of body', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a '), tinyApis.sSetCursor([0], 0), sFireInsert(editor), tinyApis.sAssertSelection([0], 0, [0], 0), tinyApis.sAssertContent('a ') ])), Logger.t('Insert in text in node with leading nbsp after inline with trailing space', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a <em> b</em>c'), tinyApis.sSetCursor([0], 0), sFireInsert(editor), tinyApis.sAssertSelection([0], 0, [0], 0), tinyApis.sAssertContent('a <em> b</em>c') ])), Logger.t('Insert in text in node with trailing nbsp before inline', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a <em>b</em>c'), tinyApis.sSetCursor([0], 0), sFireInsert(editor), tinyApis.sAssertSelection([0], 0, [0], 0), tinyApis.sAssertContent('a <em>b</em>c') ])), Logger.t('Insert in text in node with trailing nbsp before inline with leading nbsp', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a <em> b</em>c'), tinyApis.sSetCursor([0], 0), sFireInsert(editor), tinyApis.sAssertSelection([0], 0, [0], 0), tinyApis.sAssertContent('a <em> b</em>c') ])), Logger.t('Insert in text in node with single middle nbsp', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a b'), tinyApis.sSetCursor([0], 3), sFireInsert(editor), tinyApis.sAssertSelection([0], 3, [0], 3), tinyApis.sAssertContent('a b') ])), Logger.t('Insert in text in node with multiple middle nbsp', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetRawContent('a b c d'), tinyApis.sSetCursor([0], 7), sFireInsert(editor), tinyApis.sAssertSelection([0], 7, [0], 7), tinyApis.sAssertContent('a b c d') ])) ])), ])) ], onSuccess, onFailure); }, {
const steps = function (editor, tinyApis) { return [ tinyApis.sFocus, Logger.t('Public Selection API', GeneralSteps.sequence([ Logger.t('Scroll to element align to bottom', GeneralSteps.sequence([ sScrollReset(editor), sSetContent(editor, tinyApis, '<div style="height: 1000px">a</div><div style="height: 50px">b</div><div style="height: 1000px">a</div>'), sScrollIntoView(editor, 'div:nth-child(2)', false), sAssertScrollPosition(editor, 0, 975) ])), Logger.t('Scroll to element align to top', GeneralSteps.sequence([ sScrollReset(editor), sSetContent(editor, tinyApis, '<div style="height: 1000px">a</div><div style="height: 50px">b</div><div style="height: 1000px">a</div>'), sScrollIntoView(editor, 'div:nth-child(2)', true), sAssertScrollPosition(editor, 0, 925) ])) ])), Logger.t('Private ScrollIntoView API', GeneralSteps.sequence([ Logger.t('Scroll to element align to bottom', GeneralSteps.sequence([ sScrollReset(editor), sSetContent(editor, tinyApis, '<div style="height: 1000px">a</div><div style="height: 50px">b</div><div style="height: 1000px">a</div>'), sScrollIntoViewPrivateApi(editor, 'div:nth-child(2)', false), sAssertScrollPosition(editor, 0, 975) ])), Logger.t('Scroll to element align to top', GeneralSteps.sequence([ sScrollReset(editor), sSetContent(editor, tinyApis, '<div style="height: 1000px">a</div><div style="height: 50px">b</div><div style="height: 1000px">a</div>'), sScrollIntoViewPrivateApi(editor, 'div:nth-child(2)', true), sAssertScrollPosition(editor, 0, 925) ])) ])), Logger.t('Override scrollIntoView event', GeneralSteps.sequence([ Logger.t('Scroll to element align to bottom', GeneralSteps.sequence([ sScrollReset(editor), sSetContent(editor, tinyApis, '<div style="height: 1000px">a</div><div style="height: 50px">b</div><div style="height: 1000px">a</div>'), mBindScrollIntoViewEvent(editor), sScrollIntoView(editor, 'div:nth-child(2)', false), mAssertScrollIntoViewEventInfo(editor, 'div:nth-child(2)', false), sAssertScrollPosition(editor, 0, 0) ])), Logger.t('Scroll to element align to top', GeneralSteps.sequence([ sScrollReset(editor), sSetContent(editor, tinyApis, '<div style="height: 1000px">a</div><div style="height: 50px">b</div><div style="height: 1000px">a</div>'), mBindScrollIntoViewEvent(editor), sScrollIntoView(editor, 'div:nth-child(2)', true), mAssertScrollIntoViewEventInfo(editor, 'div:nth-child(2)', true), sAssertScrollPosition(editor, 0, 0) ])), Logger.t('Scroll to element align to bottom (private api)', GeneralSteps.sequence([ sScrollReset(editor), sSetContent(editor, tinyApis, '<div style="height: 1000px">a</div><div style="height: 50px">b</div><div style="height: 1000px">a</div>'), mBindScrollIntoViewEvent(editor), sScrollIntoViewPrivateApi(editor, 'div:nth-child(2)', false), mAssertScrollIntoViewEventInfo(editor, 'div:nth-child(2)', false), sAssertScrollPosition(editor, 0, 0) ])), Logger.t('Scroll to element align to top (private api)', GeneralSteps.sequence([ sScrollReset(editor), sSetContent(editor, tinyApis, '<div style="height: 1000px">a</div><div style="height: 50px">b</div><div style="height: 1000px">a</div>'), mBindScrollIntoViewEvent(editor), sScrollIntoViewPrivateApi(editor, 'div:nth-child(2)', true), mAssertScrollIntoViewEventInfo(editor, 'div:nth-child(2)', true), sAssertScrollPosition(editor, 0, 0) ])) ])) ]; };
(editor, onSuccess, onFailure) => { Pipeline.async({ }, Logger.ts( 'Check structure of font format', [ Mouse.sClickOn(Body.body(), '.tox-toolbar button'), UiFinder.sWaitForVisible('Waiting for dialog', Body.body(), '[role="dialog"]'), Mouse.sClickOn(Body.body(), 'button:contains("Make Busy")'), Waiter.sTryUntil( 'Waiting for busy structure to match expected', Chain.asStep(Body.body(), [ UiFinder.cFindIn('[role="dialog"]'), Assertions.cAssertStructure( 'Checking dialog structure to see where "busy" is', ApproxStructure.build((s, str, arr) => { return s.element('div', { classes: [ arr.has('tox-dialog') ], children: [ s.element('div', { classes: [ arr.has('tox-dialog__header') ] }), s.element('div', { classes: [ arr.has('tox-dialog__content-js') ] }), s.element('div', { classes: [ arr.has('tox-dialog__footer') ] }), s.element('div', { classes: [ arr.has('tox-dialog__busy-spinner') ], children: [ s.element('div', { classes: [ arr.has('tox-spinner') ], children: [ // The three loading dots s.element('div', { }), s.element('div', { }), s.element('div', { }) ] }) ] }) ] }); }) ) ]), 100, 3000 ), Step.sync(() => { testDialogApi.get().unblock(); }), Waiter.sTryUntil( 'Waiting for busy structure to go away', Chain.asStep(Body.body(), [ UiFinder.cFindIn('[role="dialog"]'), Assertions.cAssertStructure( 'Checking dialog structure to see where "busy" is', ApproxStructure.build((s, str, arr) => { return s.element('div', { classes: [ arr.has('tox-dialog') ], children: [ s.element('div', { classes: [ arr.has('tox-dialog__header') ] }), s.element('div', { classes: [ arr.has('tox-dialog__content-js') ] }), s.element('div', { classes: [ arr.has('tox-dialog__footer') ] }) ] }); }) ) ]), 100, 3000 ) ] ), onSuccess, onFailure); },
const sAssertCalcCols = function (editor, colors, expected) { return Logger.t(`Assert calced cols: ${expected}`, Step.sync(function () { const sqrt = ColorSwatch.calcCols(colors); RawAssertions.assertEq('should be same', expected, sqrt); })); };
TinyLoader.setup(function (editor, onSuccess, onFailure) { const tinyApis = TinyApis(editor); const tinyActions = TinyActions(editor); Pipeline.async({}, [ Logger.t('Up navigation', GeneralSteps.sequence([ Logger.t('Arrow up on first position in table cell', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetContent('<table><tbody><tr><td>a</td><td>b</td></tr></tbody></table>'), tinyApis.sSetCursor([0, 0, 0, 0, 0], 0), tinyActions.sContentKeystroke(Keys.up(), {}), tinyApis.sAssertSelection([0], 0, [0], 0), tinyApis.sAssertContent('<p> </p><table><tbody><tr><td>a</td><td>b</td></tr></tbody></table>') ])), Logger.t('Arrow up on first position in table cell to caption', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetContent('<table><caption>a</caption><tbody><tr><td>b</td></tr></tbody></table>'), tinyApis.sSetCursor([0, 1, 0, 0, 0], 0), tinyActions.sContentKeystroke(Keys.up(), {}), tinyApis.sAssertSelection([0, 0, 0], 0, [0, 0, 0], 0), tinyApis.sAssertContent('<table><caption>a</caption><tbody><tr><td>b</td></tr></tbody></table>') ])), Logger.t('Arrow up on second position in first table cell', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetContent('<table><tbody><tr><td>a</td><td>b</td></tr></tbody></table>'), tinyApis.sSetCursor([0, 0, 0, 0, 0], 1), tinyActions.sContentKeystroke(Keys.up(), {}), tinyApis.sAssertSelection([0], 0, [0], 0), tinyApis.sAssertContent('<p> </p><table><tbody><tr><td>a</td><td>b</td></tr></tbody></table>') ])), Logger.t('Arrow up on first position in first table cell on the second row', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetContent('<table><tbody><tr><td>a</td><td>b</td></tr><tr><td>c</td><td>d</td></tr></tbody></table>'), tinyApis.sSetCursor([0, 0, 1, 0, 0], 0), tinyActions.sContentKeystroke(Keys.up(), {}), tinyApis.sAssertSelection([0, 0, 0, 0, 0], 0, [0, 0, 0, 0, 0], 0), tinyApis.sAssertContent('<table><tbody><tr><td>a</td><td>b</td></tr><tr><td>c</td><td>d</td></tr></tbody></table>') ])), ])), Logger.t('Down navigation', GeneralSteps.sequence([ Logger.t('Arrow down on last position in last table cell', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetContent('<table><tbody><tr><td>a</td><td>b</td></tr></tbody></table>'), tinyApis.sSetCursor([0, 0, 0, 1, 0], 1), tinyActions.sContentKeystroke(Keys.down(), {}), tinyApis.sAssertSelection([1], 0, [1], 0), tinyApis.sAssertContent('<table><tbody><tr><td>a</td><td>b</td></tr></tbody></table><p> </p>') ])), Logger.t('Arrow down on last position in last table cell with br', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetContent('<table><tbody><tr><td>a</td><td>b<br></td></tr></tbody></table>'), tinyApis.sSetCursor([0, 0, 0, 1, 0], 1), tinyActions.sContentKeystroke(Keys.down(), {}), tinyApis.sAssertSelection([1], 0, [1], 0), tinyApis.sAssertContent('<table><tbody><tr><td>a</td><td>b</td></tr></tbody></table><p> </p>') ])), Logger.t('Arrow down on second last position in last table cell', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetContent('<table><tbody><tr><td>a</td><td>b</td></tr></tbody></table>'), tinyApis.sSetCursor([0, 0, 0, 1, 0], 0), tinyActions.sContentKeystroke(Keys.down(), {}), tinyApis.sAssertSelection([1], 0, [1], 0), tinyApis.sAssertContent('<table><tbody><tr><td>a</td><td>b</td></tr></tbody></table><p> </p>') ])), Logger.t('Arrow down on last position in last table cell on the first row', GeneralSteps.sequence([ tinyApis.sFocus, tinyApis.sSetContent('<table><tbody><tr><td>a</td><td>b</td></tr><tr><td>c</td><td>d</td></tr></tbody></table>'), tinyApis.sSetCursor([0, 0, 0, 1, 0], 1), tinyActions.sContentKeystroke(Keys.down(), {}), tinyApis.sAssertSelection([0, 0, 1, 1, 0], 1, [0, 0, 1, 1, 0], 1), tinyApis.sAssertContent('<table><tbody><tr><td>a</td><td>b</td></tr><tr><td>c</td><td>d</td></tr></tbody></table>') ])), ])) ], onSuccess, onFailure); }, {
const sAssertColors = function (input, expected) { return Logger.t(`Assert colors: ${expected}`, Step.sync(function () { const colors = Settings.mapColors(input); RawAssertions.assertEq('should be same', expected, colors); })); };