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">&#65279;</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">&#65279;</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">&#65279;</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('&nbsp;a'),
            tinyApis.sSetCursor([0], 2),
            sFireInsert(editor),
            tinyApis.sAssertSelection([0], 2, [0], 2),
            tinyApis.sAssertContent('&nbsp;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>&nbsp;c'),
            tinyApis.sSetCursor([2], 2),
            sFireInsert(editor),
            tinyApis.sAssertSelection([2], 2, [2], 2),
            tinyApis.sAssertContent('a<em>b </em>&nbsp;c')
          ])),
          Logger.t('Insert in text in node with leading nbsp after inline', GeneralSteps.sequence([
            tinyApis.sFocus,
            tinyApis.sSetRawContent('a<em>b</em>&nbsp;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&nbsp;</em>&nbsp;c'),
            tinyApis.sSetCursor([2], 2),
            sFireInsert(editor),
            tinyApis.sAssertSelection([2], 2, [2], 2),
            tinyApis.sAssertContent('a<em>b&nbsp;</em> c')
          ])),
          Logger.t('Insert at beginning of text node with leading nbsp after a br', GeneralSteps.sequence([
            tinyApis.sFocus,
            tinyApis.sSetRawContent('a<br />&nbsp;b'),
            tinyApis.sSetCursor([2], 0),
            sFireInsert(editor),
            tinyApis.sAssertSelection([2], 0, [2], 0),
            tinyApis.sAssertContent('a<br />&nbsp;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>&nbsp;b</em>'),
            tinyApis.sSetCursor([2, 0], 0),
            sFireInsert(editor),
            tinyApis.sAssertSelection([2, 0], 0, [2, 0], 0),
            tinyApis.sAssertContent('a<br /><em>&nbsp;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&nbsp;'),
            tinyApis.sSetCursor([0], 0),
            sFireInsert(editor),
            tinyApis.sAssertSelection([0], 0, [0], 0),
            tinyApis.sAssertContent('a&nbsp;')
          ])),
          Logger.t('Insert in text in node with leading nbsp after inline with trailing space', GeneralSteps.sequence([
            tinyApis.sFocus,
            tinyApis.sSetRawContent('a&nbsp;<em> b</em>c'),
            tinyApis.sSetCursor([0], 0),
            sFireInsert(editor),
            tinyApis.sAssertSelection([0], 0, [0], 0),
            tinyApis.sAssertContent('a&nbsp;<em> b</em>c')
          ])),
          Logger.t('Insert in text in node with trailing nbsp before inline', GeneralSteps.sequence([
            tinyApis.sFocus,
            tinyApis.sSetRawContent('a&nbsp;<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&nbsp;<em>&nbsp;b</em>c'),
            tinyApis.sSetCursor([0], 0),
            sFireInsert(editor),
            tinyApis.sAssertSelection([0], 0, [0], 0),
            tinyApis.sAssertContent('a <em>&nbsp;b</em>c')
          ])),
          Logger.t('Insert in text in node with single middle nbsp', GeneralSteps.sequence([
            tinyApis.sFocus,
            tinyApis.sSetRawContent('a&nbsp;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&nbsp;b&nbsp;c&nbsp;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);
 },
Exemple #8
0
 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>&nbsp;</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>&nbsp;</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>&nbsp;</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>&nbsp;</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>&nbsp;</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);
  }, {
Exemple #10
0
 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);
   }));
 };