Example #1
0
const sOpenDialogAndAssertInitial = (editor, docBody, language, content) => {
  return GeneralSteps.sequence(Logger.ts('Open dialog and assert initial language and content', [
    Mouse.sClickOn(Element.fromDom(editor.getContainer()), toolbarButtonSelector),
    UiFinder.sWaitForVisible('Waited for dialog to be visible', docBody, dialogSelector),
    sAssertCodeSampleDialog(language, content)
  ]));
};
Example #2
0
 const sSubmitDialog = (docBody) => {
   return GeneralSteps.sequence(Logger.ts('Clicking on the Save button to close dialog', [
     FocusTools.sSetFocus('Focus dialog', docBody, dialogSelector),
     Mouse.sClickOn(docBody, 'button.tox-button:contains(Save)'),
     Waiter.sTryUntil('Dialog should close', UiFinder.sNotExists(docBody, dialogSelector), 100, 3000)
   ]));
 };
Example #3
0
 const sOpenDialog = (editor, docBody) => {
   return GeneralSteps.sequence(Logger.ts('Open dialog and wait for it to be visible', [
     Step.sync(function () {
       const dialog = ColorSwatch.colorPickerDialog(editor);
       dialog(setColor, '#ffffff');
     }),
     UiFinder.sWaitForVisible('Waited for dialog to be visible', docBody, dialogSelector)
   ]));
 };
    (editor, onSuccess, onFailure) => {
      const doc = Element.fromDom(document);

      Pipeline.async({ }, Logger.ts(
        'Check structure of grid collection menu',
        [
          TestHelpers.GuiSetup.mAddStyles(doc, [
            ':focus { background-color: rgb(222, 224, 226); }'
          ]),
          Mouse.sClickOn(Body.body(), '.tox-split-button__chevron'),
          UiFinder.sWaitForVisible('Waiting for menu', Body.body(), '[role="menu"]'),
          Chain.asStep(Body.body(), [
            UiFinder.cFindIn('[role="menu"]'),
            Assertions.cAssertStructure(
              'Checking structure',
              ApproxStructure.build((s, str, arr) => {
                return s.element('div', {
                  classes: [ arr.has('tox-menu'), arr.has('tox-collection'), arr.has('tox-collection--grid') ],
                  children: [
                    s.element('div', {
                      classes: [ arr.has('tox-collection__group') ],
                      children: Arr.map([ '1', '2', '3', '4', '5', '6', '7', '8' ], (num) => {
                        return s.element('div', {
                          classes: [ arr.has('tox-collection__item') ],
                          attrs: {
                            title: str.is(num)
                          },
                          children: [
                            // NOTE: The oxide demo page has div, but I think that's just a mistake
                            s.element('div', {
                             classes: [ arr.has('tox-collection__item-icon') ],
                             children: [
                               s.element('svg', {})
                             ]
                            })
                          ]
                        });
                      })
                    })
                  ]
                });
              })
            )
          ]),

          // Without layout, the flatgrid cannot be calculated on phantom
          navigator.userAgent.indexOf('PhantomJS') > -1 ? Step.pass : GeneralSteps.sequence([
            FocusTools.sTryOnSelector('Focus should be on 1', doc, '.tox-collection__item[title="1"]'),
            Keyboard.sKeydown(doc, Keys.right(), { }),
            FocusTools.sTryOnSelector('Focus should be on 2', doc, '.tox-collection__item[title="2"]'),
            Keyboard.sKeydown(doc, Keys.right(), { }),
            FocusTools.sTryOnSelector('Focus should be on 3', doc, '.tox-collection__item[title="3"]')
          ]),
          TestHelpers.GuiSetup.mRemoveStyles
        ]
      ), onSuccess, onFailure);
    },
Example #5
0
    (editor, onSuccess, onFailure) => {
      const tinyUi = TinyUi(editor);

      Pipeline.async({ }, Logger.ts(
          'Dialog closes without error using close button',
          [
            tinyUi.sWaitForPopup('wait for window', 'div[role="dialog"].tox-dialog'),
            tinyUi.sClickOnUi('click on close button', 'div[role="dialog"] button[aria-label="Close"]'),
          ]
        ), onSuccess, onFailure);
    },
    (editor, onSuccess, onFailure) => {
      const tinyUi = TinyUi(editor);

      Pipeline.async({ }, Logger.ts(
          'Dialog closes without error using cancel button',
          [
            tinyUi.sWaitForPopup('wait for window', 'div[role="dialog"].tox-dialog'),
            tinyUi.sClickOnUi('click on Close button', 'div[role="dialog"] .tox-button--secondary')
          ]
        ), onSuccess, onFailure);
    },
Example #7
0
const sAssertEditorContents = (editorBody, language, content, selector) => {
  /*
   * Since the syntax highlighting wraps tokens in spans which would be annoying to assert, we assert
   * the overall structure of the editor's content, then exact match the textContent of the pre tag
   * to ensure it matches the content we set originally.
   */
  return GeneralSteps.sequence(Logger.ts('Assert overall structure of editor content', [
    sAssertEditorContentStructure(editorBody, language, content),
    sAssertPreText(Element.fromDom(editorBody), selector, content),
  ]));
};
 const sContentAreaContainerTest = (contentAreaContainer) => Logger.ts('Check basic content area container structure', [
   Assertions.sAssertStructure(
     'Content area container structure',
     ApproxStructure.build((s, str, arr) => {
       return s.element('div', {
         classes: [ arr.has('mce-content-body') ],
         children: [
           s.element('p', {
             children: [ s.anything() ]
           })
         ]
       });
     }),
     contentAreaContainer
   )
 ]);
Example #9
0
    (editor, onSuccess, onFailure) => {
      const tinyUi = TinyUi(editor);
      const container = Element.fromDom(editor.getContainer());

      Pipeline.async({ }, Logger.ts(
        'Check basic structure and actions',
        [
          Log.stepsAsStep('TINY-2226', 'Menu should contain a group heading with the correct classes and text', [
            Mouse.sClickOn(container, '.tox-toolbar button'),
            tinyUi.sWaitForUi('Wait for styleselect menu', '.tox-menu.tox-collection'),
            Chain.asStep(Body.body(), [
              UiFinder.cFindIn('.tox-menu.tox-collection'),
              Assertions.cAssertStructure(
                'Container structure',
                ApproxStructure.build((s, str, arr) => {
                  return s.element('div', {
                    classes: [ arr.has('tox-menu'), arr.has('tox-collection'), arr.has('tox-collection--list'), arr.has('tox-selected-menu') ],
                    children: [
                      s.element('div', {
                        classes: [ arr.has('tox-collection__group')],
                        children: [
                          s.element('div', {
                            classes: [ arr.has('tox-menu-nav__js'), arr.has('tox-collection__item') ]
                          })
                        ]
                      }),
                      s.element('div', {
                        classes: [ arr.has('tox-collection__group')],
                        children: [
                          s.element('div', {
                            classes: [ arr.has('tox-collection__item'), arr.has('tox-collection__group-heading') ],
                            children: [ s.text(str.is('Table styles')) ]
                          }),
                          s.element('div', {
                            classes: [ arr.has('tox-menu-nav__js'), arr.has('tox-collection__item') ]
                          })
                        ]
                      })
                    ]
                  });
                }),
              ),
            ])
          ])
        ]
      ), onSuccess, onFailure);
    },
Example #10
0
        (() => {
          const button4 = getButton('.button4-container .tox-mbtn');

          return Logger.ts('Fourth button (button4): menu button', [
            Assertions.sAssertStructure(
              'Checking initial structure',
              ApproxStructure.build((s, str, arr) => {
                return s.element('button', {
                  classes: [
                    arr.has('tox-mbtn'),
                    arr.has('tox-mbtn--select')
                  ],
                  attrs: {
                    'type': str.is('button'),
                    'title': str.is('tooltip'),
                    'aria-label': str.is('tooltip'),
                    'aria-expanded': str.is('false'),
                    'aria-haspopup': str.is('true')
                  },
                  children: [
                    s.element('span', {
                      classes: [ arr.has('tox-mbtn__select-label') ]
                    }),
                    s.element('div', {
                      classes: [ arr.has('tox-mbtn__select-chevron') ]
                    })
                  ]
                });
              }),
              button4.element()
            ),

            // Select menu item
            Mouse.sClickOn(component.element(), '.button4-container .tox-mbtn'),
            Waiter.sTryUntil('Wait for button menu to show',
              Mouse.sClickOn(body, '.tox-collection .tox-collection__item'),
              100, 1000
            ),
            store.sAssertEq('Store should have item action4', [ 'onAction.4' ]),
            store.sClear
          ]);
        })()
Example #11
0
        (() => {
          const button2 = getButton('.button2-container .tox-tbtn');

          return Logger.ts('Second button (button2): toggle button', [
            Step.sync(() => {
              shouldDisable.set(false);
              shouldActivate.set(false);
            }),
            Mouse.sClickOn(component.element(), '.button2-container .tox-tbtn'),
            store.sAssertEq('Store should have action2', [ 'onToggleAction.2' ]),
            store.sClear,
            sAssertButtonDisabledState('Enabled', false, button2),
            sAssertButtonActiveState('Off', false, button2),

            Step.sync(() => {
              shouldActivate.set(true);
            }),
            Mouse.sClickOn(component.element(), '.button2-container .tox-tbtn'),
            store.sAssertEq('Store should have action2', [ 'onToggleAction.2' ]),
            store.sClear,
            sAssertButtonDisabledState('Disabled', false, button2),
            sAssertButtonActiveState('Off', true, button2),

            Step.sync(() => {
              shouldActivate.set(false);
            }),
            Mouse.sClickOn(component.element(), '.button2-container .tox-tbtn'),
            store.sAssertEq('Store should have action2', [ 'onToggleAction.2' ]),
            store.sClear,
            sAssertButtonDisabledState('Disabled', false, button2),
            sAssertButtonActiveState('Off', false, button2),

            Step.sync(() => {
              shouldDisable.set(true);
            }),
            Mouse.sClickOn(component.element(), '.button2-container .tox-tbtn'),
            store.sAssertEq('Store should now have action2', [ 'onToggleAction.2' ]),
            store.sClear,
            sAssertButtonDisabledState('Disabled', true, button2),
            sAssertButtonActiveState('Off still', false, button2)
          ]);
        })(),
Example #12
0
        (() => {
          const button1 = getButton('.button1-container .tox-tbtn');
          return Logger.ts(
            'First button (button1): normal button',
            [
              Assertions.sAssertStructure(
                'Checking initial structure',
                ApproxStructure.build((s, str, arr) => {
                  return s.element('button', {
                    classes: [ arr.has('tox-tbtn') ],
                    attrs: {
                      'type': str.is('button'),
                      'title': str.is('tooltip'),
                      'aria-label': str.is('tooltip')
                    },
                    children: [
                      s.element('span', {
                        classes: [ arr.has('tox-tbtn__select-label') ]
                      })
                    ]
                  });
                }),
                button1.element()
              ),
              Mouse.sClickOn(component.element(), '.button1-container .tox-tbtn'),
              store.sAssertEq('Store should now have action1', [ 'onAction.1' ]),
              sAssertButtonDisabledState('Enabled', false, button1),
              store.sClear,

              Step.sync(() => {
                shouldDisable.set(true);
              }),
              Mouse.sClickOn(component.element(), '.button1-container .tox-tbtn'),
              store.sAssertEq('Store have action', [ 'onAction.1' ]),
              sAssertButtonDisabledState('Disabled', true, button1),
              store.sClear,
              Mouse.sClickOn(component.element(), '.button1-container .tox-tbtn'),
              store.sAssertEq('No actions should come through a disabled button', [ ])
            ]
          );
        })(),
Example #13
0
    (editor, onSuccess, onFailure) => {
      const tinyUi = TinyUi(editor);
      const tinyApis = TinyApis(editor);

      const eDoc = Element.fromDom(editor.getDoc());

      const structWithTitleAndIconAndText = (d) => (s, str, arr) => {
        return s.element('div', {
          classes: [ arr.has('tox-collection__item') ],
          attrs: {
            title: str.is(d.title)
          },
          children: [
            s.element('div', {
              classes: [ arr.has('tox-collection__item-icon') ],
              children: [
                s.text(str.is(d.icon))
              ]
            }),
            s.element('div', {
              classes: [ arr.has('tox-collection__item-label') ],
              html: str.is(d.text)
            })
          ]
        });
      };

      const structWithTitleAndText = (d) => (s, str, arr) => {
        return s.element('div', {
          classes: [ arr.has('tox-collection__item') ],
          attrs: {
            title: str.is(d.title)
          },
          children: [
            s.element('div', {
              classes: [ arr.has('tox-collection__item-label') ],
              html: str.is(d.text)
            })
          ]
        });
      };

      const structWithTitleAndIcon = (d) => (s, str, arr) => {
        return s.element('div', {
          classes: [ arr.has('tox-collection__item') ],
          attrs: {
            title: str.is(d.title)
          },
          children: [
            s.element('div', {
              classes: [ arr.has('tox-collection__item-icon') ],
              children: [
                s.text(str.is(d.icon))
              ]
            })
          ]
        });
      };

      const sWaitForAutocompleteToClose = Waiter.sTryUntil(
        'Autocompleter should disappear',
        UiFinder.sNotExists(Body.body(), '.tox-autocompleter'),
        100,
        1000
      );

      const sAssertAutocompleterStructure = (structure: AutocompleterStructure) => {
        return Chain.asStep(Body.body(), [
          UiFinder.cFindIn('.tox-autocompleter'),
          Assertions.cAssertStructure(
            'Checking the autocompleter',
            ApproxStructure.build((s, str, arr) => {
              return s.element('div', {
                classes: [ arr.has('tox-autocompleter') ],
                children: [
                  s.element('div', {
                    classes: [ arr.has('tox-menu'), arr.has(`tox-collection--${structure.type}`), arr.has('tox-collection') ],
                    children: Arr.map(structure.groups, (group) => {
                      return s.element('div', {
                        classes: [ arr.has('tox-collection__group') ],
                        children: Arr.map(group, (d) => {
                          if (structure.type === 'list') {
                            if (structure.hasIcons) {
                              return structWithTitleAndIconAndText(d)(s, str, arr);
                            } else {
                              return structWithTitleAndText(d)(s, str, arr);
                            }
                          } else {
                            return structWithTitleAndIcon(d)(s, str, arr);
                          }
                        })
                      });
                    })
                  })
                ]
              });
            })
          )
        ]);
      };

      const sTestAutocompleter = (scenario: { triggerChar: string, structure: AutocompleterStructure, choice: Step<any, any>, assertion: Step<any, any>, content?: string }) => {
        const content = scenario.content || scenario.triggerChar;
        return GeneralSteps.sequence([
          store.sClear,
          tinyApis.sSetContent(`<p>${content}</p>`),
          tinyApis.sSetCursor([ 0, 0 ], content.length),
          Keyboard.sKeypress(eDoc, scenario.triggerChar.charCodeAt(0), { }),
          tinyUi.sWaitForPopup('wait for autocompleter to appear', '.tox-autocompleter div[role="menu"]'),
          sAssertAutocompleterStructure(scenario.structure),
          scenario.choice,
          sWaitForAutocompleteToClose,
          scenario.assertion
        ]);
      };

      const sTestFirstAutocomplete = sTestAutocompleter({
        triggerChar: '+',
        structure: {
          type: 'list',
          hasIcons: true,
          groups: [
            [
              { title: 'p-a', text: 'p-a', icon: '+' },
              { title: 'p-b', text: 'p-b', icon: '+' },
              { title: 'p-c', text: 'p-c', icon: '+' },
              { title: 'p-d', text: 'p-d', icon: '+' }
            ]
          ]
        },
        choice: GeneralSteps.sequence([
          Keyboard.sKeydown(eDoc, Keys.down(), { }),
          Keyboard.sKeydown(eDoc, Keys.enter(), { })
        ]),
        assertion: tinyApis.sAssertContent('<p>plus-b</p>')
      });

      const sTestSecondAutocomplete = sTestAutocompleter({
        triggerChar: ':',
        structure: {
          type: 'grid',
          groups: [
            [
              { title: 'c1-a', icon: ':' },
              { title: 'c2-a', icon: ':' }
            ],
            [
              { title: 'c2-b', icon: ':' }
            ]
          ]
        },
        choice: GeneralSteps.sequence([
          Keyboard.sKeydown(eDoc, Keys.down(), { }),
          Keyboard.sKeydown(eDoc, Keys.enter(), { }),
        ]),
        assertion: store.sAssertEq('Second action should fire', [ 'colon2:colon2-b' ])
      });

      const sTestThirdAutocomplete = sTestAutocompleter({
        triggerChar: '~',
        structure: {
          type: 'grid',
          groups: [
            [
              { title: 't-a', icon: '~' },
              { title: 't-b', icon: '~' },
              { title: 't-c', icon: '~' },
              { title: 't-d', icon: '~' }
            ]
          ]
        },
        choice: GeneralSteps.sequence([
          Keyboard.sKeydown(eDoc, Keys.right(), { }),
          Keyboard.sKeydown(eDoc, Keys.right(), { }),
          Keyboard.sKeydown(eDoc, Keys.enter(), { })
        ]),
        assertion: store.sAssertEq('Tilde-c should fire', [ 'tilde:tilde-c' ])
      });

      const sTestFourthAutocomplete = sTestAutocompleter({
        triggerChar: '!',
        structure: {
          type: 'list',
          hasIcons: false,
          groups: [
            [
              { title: 'exclamation-a', text: 'exclamation-a' },
              { title: 'exclamation-b', text: 'exclamation-b' },
              { title: 'exclamation-c', text: 'exclamation-c' },
              { title: 'exclamation-d', text: 'exclamation-d' }
            ]
          ]
        },
        choice: GeneralSteps.sequence([
          Keyboard.sKeydown(eDoc, Keys.down(), { }),
          Keyboard.sKeydown(eDoc, Keys.down(), { }),
          Keyboard.sKeydown(eDoc, Keys.enter(), { })
        ]),
        assertion: store.sAssertEq('Exclamation-c should fire', [ 'exclamation:exclamation-c' ])
      });

      const sTestFifthAutocomplete = sTestAutocompleter({
        triggerChar: '=',
        content: 'test=t',
        structure: {
          type: 'grid',
          groups: [
            [
              { title: 'two', icon: '=' },
              { title: 'three', icon: '=' }
            ]
          ]
        },
        choice: GeneralSteps.sequence([
          Keyboard.sKeydown(eDoc, Keys.enter(), { })
        ]),
        assertion: tinyApis.sAssertContent('<p>test=two</p>')
      });

      const sSetContentAndTrigger = (content: string, triggerCharCode: number) => {
        return GeneralSteps.sequence([
          tinyApis.sSetContent(`<p>${content}</p>`),
          tinyApis.sSetCursor([ 0, 0 ], content.length),
          Keyboard.sKeydown(eDoc, triggerCharCode, { }),
          Keyboard.sKeypress(eDoc, triggerCharCode, { })
        ]);
      };

      const sTestAutocompleteActivation = GeneralSteps.sequence([
        store.sClear,
        sSetContentAndTrigger('test=', '='.charCodeAt(0)),
        // Can't wait for anything to change, so just wait for a prefixed amount of time
        Step.wait(500),
        UiFinder.sNotExists(Body.body(), '.tox-autocompleter'),
        sSetContentAndTrigger('test=t', '='.charCodeAt(0)),
        tinyUi.sWaitForPopup('wait for autocompleter to appear', '.tox-autocompleter div[role="menu"]'),
        sAssertAutocompleterStructure({
          type: 'grid',
          groups: [
            [
              { title: 'two', icon: '=' },
              { title: 'three', icon: '=' }
            ]
          ]
        }),
        // Check the options shrink to 1 item
        sSetContentAndTrigger('test=tw', 'w'.charCodeAt(0)),
        Waiter.sTryUntil('Wait for autocompleter to update items', sAssertAutocompleterStructure({
          type: 'grid',
          groups: [
            [
              { title: 'two', icon: '=' }
            ]
          ]
        }), 100, 1000),
        // Check the autocompleter is hidden/closed when no items match
        sSetContentAndTrigger('test=twe', 'e'.charCodeAt(0)),
        sWaitForAutocompleteToClose,
        // Check the autocompleter is shown again when deleting a char
        sSetContentAndTrigger('test=tw', Keys.backspace()),
        tinyUi.sWaitForPopup('wait for autocompleter to appear', '.tox-autocompleter div[role="menu"]'),
        sAssertAutocompleterStructure({
          type: 'grid',
          groups: [
            [
              { title: 'two', icon: '=' }
            ]
          ]
        }),
        Keyboard.sKeydown(eDoc, Keys.enter(), { }),
        sWaitForAutocompleteToClose
      ]);

      Pipeline.async({ }, Logger.ts(
          'Trigger autocompleter',
          [
            tinyApis.sFocus,
            Logger.t('Checking first autocomplete (columns = 1) trigger: "+"', sTestFirstAutocomplete),
            Logger.t('Checking second autocomplete (columns = 2), two sources, trigger ":"', sTestSecondAutocomplete),
            Logger.t('Checking third autocomplete (columns = auto) trigger: "~"', sTestThirdAutocomplete),
            Logger.t('Checking forth autocomplete, (columns = 1), trigger: "!", no icons', sTestFourthAutocomplete),
            Logger.t('Checking fifth autocomplete, trigger: "=", custom activation check', sTestFifthAutocomplete),
            Logger.t('Checking autocomplete activation based on content', sTestAutocompleteActivation)
          ]
        ), onSuccess, onFailure);
    },
Example #14
0
    (editor, onSuccess, onFailure) => {
      const container = Element.fromDom(editor.getContainer());

      Pipeline.async({ }, Logger.ts(
          'Check basic structure and actions',
          [
            Assertions.sAssertStructure(
              'Container structure',
              ApproxStructure.build((s, str, arr) => {
                return s.element('div', {
                  classes: [ arr.has('tox-tinymce') ],
                  children: [
                    s.element('div', {
                      classes: [ arr.has('tox-editor-container') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-menubar') ],
                          attrs: { role: str.is('menubar') },
                          children: [
                            // Dropdown via text
                            s.element('button', {
                              classes: [ arr.has('tox-mbtn'), arr.has('tox-mbtn--select') ],
                              children: [
                                s.element('span', {
                                  classes: [ arr.has('tox-mbtn__select-label') ],
                                  html: str.is('test')
                                }),
                                s.element('div', {
                                  classes: [ arr.has('tox-mbtn__select-chevron') ],
                                  children: [
                                    s.element('svg', { })
                                  ]
                                }),
                              ]
                            }),
                          ]
                        }),

                        s.element('div', {
                          classes: [ arr.has('tox-toolbar') ],
                          attrs: { role: str.is('group') },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-toolbar__group') ],
                              children: [
                                // Basic button
                                s.element('button', {
                                  classes: [ arr.has('tox-tbtn') ]
                                }),

                                // Toggle button
                                s.element('button', {
                                  classes: [ arr.has('tox-tbtn'), arr.not('tox-btn--enabled') ]
                                }),

                                // Dropdown via text
                                s.element('button', {
                                  classes: [ arr.has('tox-tbtn'), arr.has('tox-tbtn--select') ],
                                  children: [
                                    s.element('span', {
                                      classes: [ arr.has('tox-tbtn__select-label') ],
                                      html: str.is('dropdown1')
                                    }),
                                    s.element('div', {
                                      classes: [ arr.has('tox-tbtn__select-chevron') ],
                                      children: [
                                        s.element('svg', { })
                                      ]
                                    }),
                                  ]
                                }),

                                // Dropdown via icon
                                s.element('button', {
                                  classes: [ arr.has('tox-tbtn'), arr.has('tox-tbtn--select') ],
                                  children: [
                                    s.element('span', {
                                      // NOTE: Not sure what this should be?
                                      classes: [  ],
                                      children: [
                                        s.element('svg', { })
                                      ]
                                    }),
                                    s.element('div', {
                                      classes: [ arr.has('tox-tbtn__select-chevron') ],
                                      children: [
                                        s.element('svg', { })
                                      ]
                                    }),
                                  ]
                                }),

                                // Splitbutton with text
                                s.element('div', {
                                  classes: [ arr.has('tox-split-button') ],
                                  children: [
                                    s.element('span', {
                                      classes: [ arr.has('tox-tbtn') ],
                                      children: [
                                        s.element('span', {
                                          classes: [ arr.has('tox-tbtn__select-label') ],
                                          html: str.is('Delta')
                                        })
                                      ]
                                    }),
                                    s.element('span', {
                                      classes: [ arr.has('tox-tbtn'), arr.has('tox-split-button__chevron') ],
                                      children: [
                                        s.element('svg', { })
                                      ]
                                    }),
                                    s.element('span', {
                                      attrs: {
                                        'aria-hidden': str.is('true'),
                                        'style': str.is('display: none;')
                                      },
                                      children: [
                                        s.text(str.is('To open the popup, press Shift+Enter'))
                                      ]
                                    })
                                  ]
                                }),

                                // Splitbutton with icon
                                s.element('div', {
                                  classes: [ arr.has('tox-split-button') ],
                                  children: [
                                    s.element('span', {
                                      classes: [ arr.has('tox-tbtn') ],
                                      children: [
                                        s.element('span', {
                                          children: [
                                            s.element('svg', { })
                                          ]
                                        })
                                      ]
                                    }),
                                    s.element('span', {
                                      classes: [ arr.has('tox-tbtn'), arr.has('tox-split-button__chevron') ],
                                      children: [
                                        s.element('svg', { })
                                      ]
                                    }),
                                    s.element('span', {
                                      attrs: {
                                        'aria-hidden': str.is('true'),
                                        'style': str.is('display: none;')
                                      },
                                      children: [
                                        s.text(str.is('To open the popup, press Shift+Enter'))
                                      ]
                                    })
                                  ]
                                })
                              ]
                            })
                          ]
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-anchorbar') ]
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-sidebar-wrap')],
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-edit-area') ],
                              children: [
                                s.element('iframe', { })
                              ]
                            }),
                            s.element('div', {
                              classes: [ arr.has('tox-sidebar') ]
                            }),
                          ]
                        }),
                      ]
                    }),
                    s.element('div', {
                      classes: [ arr.has('tox-statusbar') ]
                    }),
                    s.element('div', {
                      classes: [ arr.has('tox-throbber') ]
                    })
                  ]
                });
              }),
              container
            ),

            Mouse.sClickOn(container, '.tox-toolbar button'),
            Step.sync(() => {
              Assertions.assertEq('Button should have been triggered', [ 'button1' ], store.get());
            }),

            Log.stepsAsStep('TBA', 'Menu appearing from menubar should have svg icons', [
              Mouse.sClickOn(container, '[role="menubar"] button[role="menuitem"]:contains("test")'),
              UiFinder.sWaitForVisible('Waiting for menu to appear', Body.body(), '[role="menu"]'),
              Chain.asStep(Body.body(), [
                UiFinder.cFindIn('[role="menu"] .tox-collection__item--active'),
                Assertions.cAssertStructure(
                  'Checking item has svg icon and text',
                  ApproxStructure.build((s, str, arr) => {
                    return s.element('div', {
                      classes: [ arr.has('tox-collection__item') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item-icon') ],
                          children: [
                            s.element('svg', { })
                          ]
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item-label') ],
                          html: str.is('Text with icon')
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item-accessory') ],
                          html: str.is(Env.mac ? '\u2318' + 'M' : 'Ctrl' + '+M')
                        })
                      ]
                    });
                  })
                )
              ]),
              Keyboard.sKeydown(Element.fromDom(document), Keys.escape(), { }),
              UiFinder.sNotExists(Body.body(), '[role="menu"]')
            ]),

            Log.stepsAsStep('TBA', 'Clicking on a toggle button should not toggle. It is up to the setActive api to do that', [
              Mouse.sClickOn(container, '.tox-toolbar .tox-tbtn:contains("ToggleMe")'),
              Chain.asStep(container, [
                UiFinder.cFindIn('.tox-tbtn:contains("ToggleMe")'),
                Assertions.cAssertStructure('Should not be pressed', ApproxStructure.build((s, str, arr) => {
                  return s.element('button', {
                    attrs: {
                      'aria-pressed': str.is('false')
                    },
                    classes: [ arr.not('tox-tbtn--enabled') ]
                  });
                }))
              ])
            ]),

            Log.stepsAsStep('TBA', 'Using the api should toggle a toggle button', [
              Step.sync(() => {
                editor.fire('customtoggle1-toggle');
              }),
              Chain.asStep(container, [
                UiFinder.cFindIn('.tox-tbtn:contains("ToggleMe")'),
                Assertions.cAssertStructure('Should be pressed', ApproxStructure.build((s, str, arr) => {
                  return s.element('button', {
                    attrs: {
                      'aria-pressed': str.is('true')
                    },
                    classes: [ arr.has('tox-tbtn--enabled') ]
                  });
                }))
              ])
            ]),

            Log.stepsAsStep('TBA', 'Clicking on a split button primary part should not toggle. It is up to the setActive api to do that', [
              Mouse.sClickOn(container, '.tox-toolbar .tox-split-button:contains("Delta")'),
              Chain.asStep(container, [
                UiFinder.cFindIn('.tox-split-button > .tox-tbtn:contains("Delta")'),
                Assertions.cAssertStructure('Should not be pressed', ApproxStructure.build((s, str, arr) => {
                  return s.element('span', {
                    classes: [ arr.not('tox-tbtn--enabled') ]
                  });
                }))
              ])
            ]),

            Log.stepsAsStep('TBA', 'Using the api should toggle a split button', [
              Step.sync(() => {
                editor.fire('splitbutton1-toggle');
              }),
              Chain.asStep(container, [
                UiFinder.cFindIn('.tox-split-button > .tox-tbtn:contains("Delta")'),
                Assertions.cAssertStructure('Should be pressed', ApproxStructure.build((s, str, arr) => {
                  return s.element('span', {
                    classes: [ arr.has('tox-tbtn--enabled') ]
                  });
                }))
              ])
            ])
          ]
        ), onSuccess, onFailure);
    },
Example #15
0
        (() => {
          const button3 = getButton('.button3-container .tox-split-button');

          return Logger.ts('Third button (button3): split button', [
            Assertions.sAssertStructure(
              'Checking initial structure',
              ApproxStructure.build((s, str, arr) => {
                return s.element('div', {
                  classes: [ arr.has('tox-split-button') ],
                  attrs: {
                    'role': str.is('button'),
                    'title': str.is('tooltip'),
                    'aria-label': str.is('tooltip'),
                    'aria-expanded': str.is('false'),
                    'aria-haspopup': str.is('true'),
                    'aria-pressed': str.is('false')
                  },
                  children: [
                    s.element('span', {
                      attrs: {
                        role: str.is('presentation')
                      },
                      classes: [ arr.has('tox-tbtn'), arr.has('tox-tbtn--select') ]
                    }),
                    s.element('span', {
                      attrs: {
                        role: str.is('presentation')
                      },
                      classes: [ arr.has('tox-tbtn'), arr.has('tox-split-button__chevron') ]
                    }),
                    s.element('span', {
                      attrs: {
                        'aria-hidden': str.is('true'),
                        'style': str.contains('display: none;')
                      },
                      children: [
                        s.text(str.is('To open the popup, press Shift+Enter'))
                      ]
                    })
                  ]
                });
              }),
              button3.element()
            ),

            Step.sync(() => {
              shouldDisable.set(false);
              shouldActivate.set(false);
            }),
            // Toggle button
            Mouse.sClickOn(component.element(), '.button3-container .tox-split-button .tox-tbtn'),
            store.sAssertEq('Store should have action3', [ 'onToggleAction.3' ]),
            store.sClear,
            sAssertSplitButtonDisabledState('Enabled', false, button3),
            sAssertSplitButtonActiveState('Off', false, button3),

            // Menu item selected
            Mouse.sClickOn(component.element(), '.button3-container .tox-split-button .tox-split-button__chevron'),
            Waiter.sTryUntil('Wait for split button menu item to show',
              Mouse.sClickOn(body, '.tox-collection .tox-collection__item'),
              100, 1000
            ),
            store.sAssertEq('Store should have item action3', [ 'onItemAction.3' ]),
            store.sClear,
            sAssertSplitButtonDisabledState('Enabled', false, button3),
            sAssertSplitButtonActiveState('Off', true, button3),

            Step.sync(() => {
              shouldActivate.set(true);
            }),
            Mouse.sClickOn(component.element(), '.button3-container .tox-split-button .tox-tbtn'),
            store.sAssertEq('Store should have action3', [ 'onToggleAction.3' ]),
            store.sClear,
            sAssertSplitButtonDisabledState('Disabled', false, button3),
            sAssertSplitButtonActiveState('Off', true, button3),

            Step.sync(() => {
              shouldActivate.set(false);
            }),
            Mouse.sClickOn(component.element(), '.button3-container .tox-split-button .tox-tbtn'),
            store.sAssertEq('Store should have action3', [ 'onToggleAction.3' ]),
            store.sClear,
            sAssertSplitButtonDisabledState('Disabled', false, button3),
            sAssertSplitButtonActiveState('Off', false, button3),

            Step.sync(() => {
              shouldDisable.set(true);
            }),
            Mouse.sClickOn(component.element(), '.button3-container .tox-split-button .tox-tbtn'),
            store.sAssertEq('Store should now have action3', [ 'onToggleAction.3' ]),
            store.sClear,
            sAssertSplitButtonDisabledState('Disabled', true, button3),
            sAssertSplitButtonActiveState('Off still', false, button3)
          ]);
        })(),
    (editor, onSuccess, onFailure) => {
      const doc = Element.fromDom(document);

      Pipeline.async({ }, Logger.ts(
        'Check structure of list collection',
        [
          TestHelpers.GuiSetup.mAddStyles(doc, [
            ':focus { background-color: rgb(222, 224, 226); }'
          ]),
          Mouse.sClickOn(Body.body(), '.tox-toolbar button'),
          UiFinder.sWaitForVisible('Waiting for menu', Body.body(), '[role="menu"]'),
          Chain.asStep(Body.body(), [
            UiFinder.cFindIn('[role="menu"]'),
            Assertions.cAssertStructure(
              'Checking structure',
              ApproxStructure.build((s, str, arr) => {
                return s.element('div', {
                  classes: [ arr.has('tox-menu'), arr.has('tox-collection'), arr.has('tox-collection--list') ],
                  children: [
                    s.element('div', {
                      classes: [ arr.has('tox-collection__group') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item') ],
                          attrs: {
                            title: str.is('Alpha')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon'), arr.has('tox-collection__item-checkmark') ],
                              children: [
                                s.element('svg', {})
                              ]
                            }),
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-label') ]
                            }),
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-accessory') ]
                            })
                          ]
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item') ],
                          attrs: {
                            title: str.is('Beta')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon') ],
                              children: [
                                s.element('svg', {})
                              ]
                            }),
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-label') ]
                            }),
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-caret') ]
                            })
                          ]
                        })
                      ]
                    }),
                    s.element('div', {
                      classes: [ arr.has('tox-collection__group') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item') ],
                          attrs: {
                            title: str.is('Gamma')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon') ],
                              children: [
                                s.element('svg', {})
                              ]
                            }),
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-label') ]
                            }),
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-accessory') ]
                            })
                          ]
                        })
                      ]
                    })
                  ]
                });
              })
            )
          ]),
          FocusTools.sTryOnSelector('Focus should be on Alpha', doc, '.tox-collection__item:contains(Alpha)'),
          Keyboard.sKeydown(doc, Keys.down(), { }),
          FocusTools.sTryOnSelector('Focus should be on Beta', doc, '.tox-collection__item:contains(Beta)'),
          Keyboard.sKeydown(doc, Keys.down(), { }),
          FocusTools.sTryOnSelector('Focus should be on Gamma', doc, '.tox-collection__item:contains(Gamma)'),
          TestHelpers.GuiSetup.mRemoveStyles
        ]
      ), onSuccess, onFailure);
    },
Example #17
0
 const sOpenDialog = () => {
   return GeneralSteps.sequence(Logger.ts('Open dialog and wait for it to be visible', [
     tinyUi.sClickOnToolbar('click on preview toolbar', 'button'),
     tinyUi.sWaitForPopup('wait for preview popup', '[role="dialog"] iframe')
   ]));
 };
Example #18
0
  TinyLoader.setup(function (editor: Editor, onSuccess, onFailure) {
    const sOverrideDefaultMode = Step.label('validate default modes cannot be overwritten', Step.async((next, die) => {
      // TODO: once `assert.throws` supports error objects simplify this
      try {
        editor.mode.register('design', {
          activate: Fun.noop,
          deactivate: Fun.noop,
          editorReadOnly: false
        });
        die('registering a new design mode should fail');
        return;
      } catch (e) {
        // pass
      }
      try {
        editor.mode.register('readonly', {
          activate: Fun.noop,
          deactivate: Fun.noop,
          editorReadOnly: false
        });
        die('registering a new readonly mode should fail');
        return;
      } catch (e) {
        // pass
      }
      next();
    }));

    const sRegisterTestModes = Step.sync(() => {
      editor.mode.register('customDesign', {
        activate: Fun.noop,
        deactivate: Fun.noop,
        editorReadOnly: false
      });
      editor.mode.register('customReadonly', {
        activate: Fun.noop,
        deactivate: Fun.noop,
        editorReadOnly: true
      });

      editor.mode.register('failingActivateReadonly', {
        activate: Fun.die('whoops'),
        deactivate: Fun.noop,
        editorReadOnly: true
      });
      editor.mode.register('failingDeactivateDesign', {
        activate: Fun.noop,
        deactivate: Fun.die('haha'),
        editorReadOnly: false
      });
    });

    const sAssertMode = (expectedMode: string) => {
      return Step.label('sAssertMode: checking editor is in mode ' + expectedMode, Step.sync(() => {
        Assertions.assertEq('Should be the expected mode', expectedMode, editor.mode.get());
      }));
    };

    const sSetMode = (mode: string) => {
      return Step.label('sSetMode: setting the editor mode to ' + mode, Step.sync(() => {
        editor.mode.set(mode);
      }));
    };

    Pipeline.async({}, Arr.flatten([
      [
        sOverrideDefaultMode,
        sRegisterTestModes,
      ],
      Logger.ts('test default API', [
        sAssertMode('readonly'),
        sAssertBodyClass(editor, 'mce-content-readonly', true),
        sSetMode('design'),
        sAssertMode('design'),
        sAssertBodyClass(editor, 'mce-content-readonly', false),
        sSetMode('readonly'),
        sAssertMode('readonly'),
        sAssertBodyClass(editor, 'mce-content-readonly', true),
      ]),
      Logger.ts('test custom modes (aliases of design and readonly)', [
        sSetMode('customDesign'),
        sAssertMode('customDesign'),
        sAssertBodyClass(editor, 'mce-content-readonly', false),
        sSetMode('customReadonly'),
        sAssertMode('customReadonly'),
        sAssertBodyClass(editor, 'mce-content-readonly', true),
      ]),
      Logger.ts('test failing to activate a readonly-like mode leaves the editor in design', [
        sSetMode('design'),
        sSetMode('failingActivateReadonly'),
        sAssertMode('design'),
        sAssertBodyClass(editor, 'mce-content-readonly', false),
      ]),
      Logger.ts('test failing to deactivate a design-like mode still switches to readonly', [
        sSetMode('failingDeactivateDesign'),
        sSetMode('readonly'),
        sAssertMode('readonly'),
        sAssertBodyClass(editor, 'mce-content-readonly', true),
      ])
    ]), onSuccess, onFailure);
  }, {
    (editor, onSuccess, onFailure) => {
      const doc = Element.fromDom(document);

      Pipeline.async({ }, Logger.ts(
        'Check structure of toolbar collection',
        [
          Mouse.sClickOn(Body.body(), '.tox-split-button__chevron'),
          UiFinder.sWaitForVisible('Waiting for menu', Body.body(), '[role="menu"]'),
          Chain.asStep(Body.body(), [
            UiFinder.cFindIn('[role="menu"]'),
            Assertions.cAssertStructure(
              'Checking menu structure',
              ApproxStructure.build((s, str, arr) => {
                return s.element('div', {
                  classes: [
                    arr.has('tox-menu'),
                    arr.has('tox-collection'),
                    arr.has('tox-collection--toolbar'),
                    arr.has('tox-collection--toolbar-lg')
                  ],
                  children: [
                    s.element('div', {
                      classes: [ arr.has('tox-collection__group') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item'), arr.not('tox-tbtn') ],
                          attrs: {
                            title: str.is('A-button')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon') ],
                              children: [
                                s.element('svg', {})
                              ]
                            })
                          ]
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item'), arr.not('tox-tbtn') ],
                          attrs: {
                            title: str.is('B-button')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon') ],
                              children: [
                                s.element('svg', {})
                              ]
                            })
                          ]
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item'), arr.not('tox-tbtn') ],
                          attrs: {
                            title: str.is('C-button')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon') ],
                              children: [
                                s.element('svg', {})
                              ]
                            })
                          ]
                        })
                      ]
                    }),
                    s.element('div', {
                      classes: [ arr.has('tox-collection__group') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item'), arr.not('tox-tbtn') ],
                          attrs: {
                            title: str.is('D-button')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon') ],
                              children: [
                                s.element('svg', {})
                              ]
                            })
                          ]
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item'), arr.not('tox-tbtn') ],
                          attrs: {
                            title: str.is('E-button')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon') ],
                              children: [
                                s.element('svg', {})
                              ]
                            })
                          ]
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-collection__item'), arr.not('tox-tbtn') ],
                          attrs: {
                            title: str.is('F-button')
                          },
                          children: [
                            s.element('div', {
                              classes: [ arr.has('tox-collection__item-icon') ],
                              children: [
                                s.element('svg', {})
                              ]
                            })
                          ]
                        })
                      ]
                    })
                  ]
                });
              })
            )
          ]),
          FocusTools.sTryOnSelector('Focus should start on A', doc, '.tox-collection__item[title="A-button"]'),
          Keyboard.sKeydown(doc, Keys.down(), { }),
          FocusTools.sTryOnSelector('Focus should move to D', doc, '.tox-collection__item[title="D-button"]'),
          Keyboard.sKeydown(doc, Keys.right(), { }),
          FocusTools.sTryOnSelector('Focus should move to E', doc, '.tox-collection__item[title="E-button"]')
        ]
      ), onSuccess, onFailure);
    },
Example #20
0
UnitTest.asynctest('ColorPickerSanityTest', (success, failure) => {
  // mutation is yummy
  let currentColor = '';

  const setColor = (hexOpt) => {
    hexOpt.each((hex) => {
      currentColor = hex;
    });
  };

  const dialogSelector = 'div[role="dialog"]';

  const docBody = Element.fromDom(document.body);

  const sAssertColor = function (expected) {
    return Logger.t('Asserting color', Step.sync(function () {
      Assertions.assertEq('Asserting current colour is ' + expected, expected, currentColor);
    }));
  };

  const sSetHex = (hex) => {
    return Logger.t('Changing textarea content to ' + hex, Step.sync(() => {
      const inputs = SelectorFilter.descendants(docBody, 'div[role="dialog"] input');
      const hexInput = inputs[inputs.length - 1];
      hexInput.dom().value = hex;
    }));
  };

  const sOpenDialog = (editor, docBody) => {
    return GeneralSteps.sequence(Logger.ts('Open dialog and wait for it to be visible', [
      Step.sync(function () {
        const dialog = ColorSwatch.colorPickerDialog(editor);
        dialog(setColor, '#ffffff');
      }),
      UiFinder.sWaitForVisible('Waited for dialog to be visible', docBody, dialogSelector)
    ]));
  };

  const sAssertColorWhite = sAssertColor('#ffffff');

  const sAssertColorBlack = sAssertColor('#000000');

  const sSetHexWhite = sSetHex('ffffff');

  const sSetHexBlack = sSetHex('000000');

  const sSubmitDialog = GeneralSteps.sequence(Logger.ts('Click Save and close dialog', [
    FocusTools.sSetFocus('Focus dialog', docBody, dialogSelector),
    Waiter.sTryUntil('Button is not disabled', UiFinder.sNotExists(docBody, 'button.tox-button:contains("Save")[disabled]'), 100, 1000),
    Mouse.sClickOn(docBody, 'button.tox-button:contains(Save)'),
    Waiter.sTryUntil('Dialog should close', UiFinder.sNotExists(docBody, dialogSelector), 100, 3000),
  ]));

  const sCancelDialog = GeneralSteps.sequence(Logger.ts('Click Cancel and close dialog', [
    FocusTools.sSetFocus('Focus dialog', docBody, dialogSelector),
    Mouse.sClickOn(docBody, 'button.tox-button:contains(Cancel)'),
    Waiter.sTryUntil('Dialog should close', UiFinder.sNotExists(docBody, dialogSelector), 100, 3000),
  ]));

  TinyLoader.setup(function (editor, onSuccess, onFailure) {
    Pipeline.async({}, [
      Log.stepsAsStep('TBA', 'ColorPicker: Open dialog, click Save and assert color is white', [
        sOpenDialog(editor, docBody),
        sSubmitDialog,
        sAssertColorWhite
      ]),

      Log.stepsAsStep('TBA', 'ColorPicker: Open dialog, pick a color, click Save and assert color changes to picked color', [
        sOpenDialog(editor, docBody),
        sSetHexBlack,
        sSubmitDialog,
        sAssertColorBlack
      ]),

      Log.stepsAsStep('TBA', 'ColorPicker: Open dialog, pick a different color, click Cancel and assert color does not change', [
        sOpenDialog(editor, docBody),
        sSetHexWhite,
        sCancelDialog,
        sAssertColorBlack
      ])
    ], onSuccess, onFailure);
  }, {
    plugins: '',
    theme: 'silver',
    toolbar: '',
    base_url: '/project/tinymce/js/tinymce',
  }, success, failure);
});
Example #21
0
const sCancelDialog = (docBody) => {
  return GeneralSteps.sequence(Logger.ts('Click on the Cancel button to close the dialog', [
    Mouse.sClickOn(docBody, 'button:contains(Cancel)'),
    Waiter.sTryUntil('Dialog should close', UiFinder.sNotExists(docBody, dialogSelector), 100, 3000)
  ]));
};
    (editor, onSuccess, onFailure) => {
      const doc = Element.fromDom(document);

      const structureItem = (optText: Option<string>, optIcon: Option<string>) => (s, str, arr) => {
        return s.element('div', {
          classes: [ arr.has('tox-collection__item') ],
          children: Options.cat([
            optIcon.map((icon) => s.element('div', {
              classes: [ arr.has('tox-collection__item-icon') ],
              html: str.is(icon)
            })),

            optText.map((text) => s.element('div', {
              classes: [ arr.has('tox-collection__item-label') ],
              html: str.is(text)
            }))
          ])
        });
      };

      const cFindNthIn = (selector, n) => Chain.binder((elem: Element) => {
        const matches = UiFinder.findAllIn(elem, selector);
        return matches.length > 0 && n < matches.length ? Result.value(matches[n]) :
          Result.error(`Could not find match ${n} of selector: ${selector}`);
      });

      Pipeline.async({ }, Logger.ts(
        'Check structure of collection in a dialog',
        [
          TestHelpers.GuiSetup.mAddStyles(doc, [
            ':focus { outline: 2px solid green; }'
          ]),
          Mouse.sClickOn(Body.body(), '.tox-toolbar button'),
          UiFinder.sWaitForVisible('Waiting for dialog', Body.body(), '[role="dialog"]'),

          FocusTools.sTryOnSelector('Focus should start on input', doc, 'input'),
          Keyboard.sKeydown(doc, Keys.tab(), { }),

          Logger.t(
            'Checking the first collection: columns = 1, list',
            GeneralSteps.sequence([
              Chain.asStep(Body.body(), [
                cFindNthIn('[role="dialog"] .tox-form__group .tox-collection', 0),
                Assertions.cAssertStructure(
                  'Checking structure',
                  ApproxStructure.build((s, str, arr) => {
                    return s.element('div', {
                      classes: [ arr.has('tox-collection'), arr.has('tox-collection--list'), arr.not('tox-menu') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-collection__group') ],
                          children: Arr.map([ 'A', 'B', 'C' ], (letter) =>
                            structureItem(Option.some('text-' + letter), Option.some('icon-' + letter))(s, str, arr)
                          )
                        })
                      ]
                    });
                  })
                )
              ]),
              FocusTools.sTryOnSelector('Focus should be on A', doc, '.tox-collection__item:contains(A).tox-collection__item--active'),
              Keyboard.sKeydown(doc, Keys.down(), { }),
              FocusTools.sTryOnSelector('Focus should be on B', doc, '.tox-collection__item:contains(B)'),
              Keyboard.sKeydown(doc, Keys.down(), { }),
              FocusTools.sTryOnSelector('Focus should be on C', doc, '.tox-collection__item:contains(C)'),
            ])
          ),

          // NOTE: We need a layout engine to use flex-wrap navigation.
          navigator.userAgent.indexOf('PhantomJS') > -1 ?
            FocusTools.sSetFocus('Force focus to F on phantom', Body.body(), '.tox-collection__item:contains("F")')
            : Logger.t(
            'Checking the second collection: columns = auto',
            GeneralSteps.sequence([
              Chain.asStep(Body.body(), [
                cFindNthIn('[role="dialog"] .tox-form__group .tox-collection', 1),
                Assertions.cAssertStructure(
                  'Checking structure',
                  ApproxStructure.build((s, str, arr) => {
                    return s.element('div', {
                      classes: [ arr.has('tox-collection'), arr.has('tox-collection--grid'), arr.not('tox-menu') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-collection__group') ],
                          children: Arr.map([ 'D', 'E', 'F' ], (letter) =>
                            structureItem(Option.none(), Option.some('icon-' + letter))(s, str, arr)
                          )
                        })
                      ]
                    });
                  })
                )
              ]),
              FocusTools.sTryOnSelector('Focus should be on C', doc, '.tox-collection__item:contains(C)'),
              Keyboard.sKeydown(doc, Keys.tab(), { }),
              FocusTools.sTryOnSelector('Focus should be on D', doc, '.tox-collection__item:contains(D)'),
              Keyboard.sKeydown(doc, Keys.right(), { }),
              FocusTools.sTryOnSelector('Focus should be on E', doc, '.tox-collection__item:contains(E)'),
              Keyboard.sKeydown(doc, Keys.right(), { }),
              FocusTools.sTryOnSelector('Focus should be on F', doc, '.tox-collection__item:contains(F)'),
            ])
          ),

          Logger.t(
            'Checking the third collection: columns = 2',
            GeneralSteps.sequence([
              Chain.asStep(Body.body(), [
                cFindNthIn('[role="dialog"] .tox-form__group .tox-collection', 2),
                Assertions.cAssertStructure(
                  'Checking structure',
                  ApproxStructure.build((s, str, arr) => {
                    return s.element('div', {
                      classes: [ arr.has('tox-collection'), arr.has('tox-collection--grid'), arr.not('tox-menu') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-collection__group') ],
                          children: Arr.map([ 'G', 'H' ], (letter) =>
                            structureItem(Option.none(), Option.some('icon-' + letter))(s, str, arr)
                          )
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-collection__group') ],
                          children: Arr.map([ 'I' ], (letter) =>
                            structureItem(Option.none(), Option.some('icon-' + letter))(s, str, arr)
                          )
                        })
                      ]
                    });
                  })
                )
              ]),
              FocusTools.sTryOnSelector('Focus should be on F', doc, '.tox-collection__item:contains(F)'),
              Keyboard.sKeydown(doc, Keys.tab(), { }),
              FocusTools.sTryOnSelector('Focus should be on G', doc, '.tox-collection__item:contains(G)'),
              Keyboard.sKeydown(doc, Keys.right(), { }),
              FocusTools.sTryOnSelector('Focus should be on H', doc, '.tox-collection__item:contains(H)'),
              Keyboard.sKeydown(doc, Keys.down(), { }),
              FocusTools.sTryOnSelector('Focus should be on I', doc, '.tox-collection__item:contains(I)'),
            ])
          ),

          Log.stepsAsStep('TBA', 'Check focus follows mouse also', [
            Mouse.sHoverOn(Body.body(), '.tox-collection__item:contains(G)'),
            Chain.asStep(Body.body(), [
              UiFinder.cFindIn('.tox-collection__item--active'),
              Chain.op((activeElem) => {
                const value = Attr.get(activeElem, 'data-collection-item-value');
                Assertions.assertEq('Checking selected value', 'g', value);
              })
            ])
          ]),
          TestHelpers.GuiSetup.mRemoveStyles
        ]
      ), onSuccess, onFailure);
    },
Example #23
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);
 },
    (editor, onSuccess, onFailure) => {
      const doc = Element.fromDom(document);

      const structColors = (values: string[]) => (s, str, arr) => {
        return Arr.map(values, (v) => structColor(v)(s, str, arr));
      };

      const structColor = (value: string) => (s, str, arr) => {
        return s.element('div', {
          classes: [ arr.has('tox-swatch') ],
          styles: {
            'background-color': str.is(value)
          }
        });
      };

      const sFocusOnColor = (expected: string) => Chain.asStep(doc, [
        FocusTools.cGetFocused,
        Assertions.cAssertStructure('Checking focus is on ' + expected, ApproxStructure.build((s, str, arr) => {
          return structColor(expected)(s, str, arr);
        }))
      ]);

      Pipeline.async({ }, Logger.ts(
        'Check structure of color swatch',
        [
          // Give a visual indication of focus
          TestHelpers.GuiSetup.mAddStyles(doc, [
            ':focus { transform: scale(0.8) }'
          ]),

          Mouse.sClickOn(Body.body(), '.tox-split-button__chevron'),
          Chain.asStep(Body.body(), [
            Chain.control(
              UiFinder.cFindIn('[role="menu"]'),
              Guard.tryUntil('Waiting for menu', 100, 1000)
            ),
            Assertions.cAssertStructure(
              'Checking menu structure for color swatches',
              ApproxStructure.build((s, str, arr) => {
                return s.element('div', {
                  classes: [ arr.has('tox-menu') ],
                  children: [
                    s.element('div', {
                      classes: [ arr.has('tox-swatches') ],
                      children: [
                        s.element('div', {
                          classes: [ arr.has('tox-swatches__row') ],
                          children: structColors([ 'green', 'red' ])(s, str, arr)
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-swatches__row') ],
                          children: structColors([ 'blue', 'black' ])(s, str, arr)
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-swatches__row') ],
                          children: (structColors([ 'white' ])(s, str, arr)).concat([
                            s.element('div', {
                              classes: [ arr.has('tox-swatch'), arr.has('tox-swatch--remove') ],
                              children: [
                                s.element('svg', {})
                              ]
                            })
                          ])
                        }),
                        s.element('div', {
                          classes: [ arr.has('tox-swatches__row') ],
                          children: [
                            s.element('button', {
                              classes: [ arr.has('tox-swatch'), arr.has('tox-swatches__picker-btn') ],
                              children: [
                                s.element('svg', {})
                              ]
                            })
                          ]
                        })
                      ]
                    })
                  ]
                });
              })
            )
          ]),

          sFocusOnColor('green'),
          Keyboard.sKeydown(doc, Keys.down(), { }),
          sFocusOnColor('blue'),
          Keyboard.sKeydown(doc, Keys.right(), { }),
          sFocusOnColor('black'),

          TestHelpers.GuiSetup.mRemoveStyles
        ]
      ), onSuccess, onFailure);
    },