import { Chain, Guard, Mouse, NamedChain, UiFinder } from '@ephox/agar'; import { Fun } from '@ephox/katamari'; import { SugarBody, SugarElement, Visibility } from '@ephox/sugar'; import { Editor } from '../../alien/EditorTypes'; import { getThemeSelectors } from '../ThemeSelectors'; export interface UiChains { cClickOnToolbar: (label: string, selector: string) => Chain; cClickOnMenu: (label: string, selector: string) => Chain; cClickOnUi: (label: string, selector: string) => Chain; cWaitForPopup: (label: string, selector: string) => Chain; cWaitForUi: (label: string, selector: string) => Chain; cWaitForState: (hasState: (element: SugarElement) => boolean) => (label: string, selector: string) => Chain; cCloseDialog: (selector: string) => Chain; cSubmitDialog: (selector?: string) => Chain; cTriggerContextMenu: (label: string, target: string, menu: string) => Chain; } const cToolstripRoot = Chain.mapper((editor: Editor) => { return SugarElement.fromDom(editor.getContainer()); }); const cEditorRoot = Chain.mapper((editor: Editor) => { return SugarElement.fromDom(editor.getBody()); }); const cDialogRoot = Chain.injectThunked(SugarBody.body); const cGetToolbarRoot: Chain> = NamedChain.asChain([ NamedChain.direct(NamedChain.inputName(), Chain.identity, 'editor'), NamedChain.direct('editor', cToolstripRoot, 'container'), NamedChain.merge([ 'editor', 'container' ], 'data'), NamedChain.direct('data', Chain.binder((data: { editor: Editor; container: SugarElement }) => UiFinder.findIn(data.container, getThemeSelectors().toolBarSelector(data.editor))), 'toolbar'), NamedChain.output('toolbar') ]); const cGetMenuRoot = Chain.fromChains>([ cToolstripRoot, Chain.binder((container: SugarElement) => UiFinder.findIn(container, getThemeSelectors().menuBarSelector)) ]); const cClickOnWithin = (label: string, selector: string, cContext: Chain>): Chain => { return Chain.control( NamedChain.asChain([ NamedChain.direct(NamedChain.inputName(), cContext, 'context'), NamedChain.direct('context', UiFinder.cFindIn(selector), 'ui'), NamedChain.direct('ui', Mouse.cClick, '_'), NamedChain.outputInput ]), Guard.addLogging(label) ); }; const cClickOnUi = (label: string, selector: string): Chain => { return cClickOnWithin(label, selector, cDialogRoot); }; const cClickOnToolbar = (label: string, selector: string): Chain => { return cClickOnWithin(label, selector, cGetToolbarRoot); }; const cClickOnMenu = (label: string, selector: string): Chain => { return cClickOnWithin(label, selector, cGetMenuRoot); }; const cWaitForState = (hasState: (element: SugarElement) => boolean) => { return (label: string, selector: string): Chain => { return NamedChain.asChain([ NamedChain.write('element', Chain.fromChains([ cDialogRoot, UiFinder.cWaitForState(label, selector, hasState) ])), NamedChain.outputInput ]); }; }; const cWaitForVisible = (label: string, selector: string): Chain => { return Chain.fromChains([ cDialogRoot, UiFinder.cWaitForState(label, selector, Visibility.isVisible) ]); }; const cWaitForPopup = (label: string, selector: string): Chain => { return cWaitForState(Visibility.isVisible)(label, selector); }; const cWaitForUi = (label: string, selector: string): Chain => { return cWaitForState(Fun.always)(label, selector); }; const cTriggerContextMenu = (label: string, target: string, menu: string): Chain => { return Chain.fromChains([ cEditorRoot, UiFinder.cFindIn(target), Mouse.cContextMenu, // Ignores input cWaitForPopup(label, menu) ]); }; const cClickPopupButton = (btnType: 'dialogCloseSelector' | 'dialogSubmitSelector', selector?: string): Chain => { const popupSelector = selector ? selector : '[role="dialog"]'; return NamedChain.asChain([ NamedChain.direct(NamedChain.inputName(), cWaitForVisible('waiting for: ' + popupSelector, popupSelector), 'popup'), NamedChain.direct('popup', Chain.binder((container) => UiFinder.findIn(container, getThemeSelectors()[btnType])), 'button'), NamedChain.direct('button', Mouse.cClick, '_'), NamedChain.outputInput ]); }; const cCloseDialog = (selector: string): Chain => cClickPopupButton('dialogCloseSelector', selector); const cSubmitDialog = (selector?: string): Chain => cClickPopupButton('dialogSubmitSelector', selector); export const UiChains: UiChains = { cClickOnToolbar, cClickOnMenu, cClickOnUi, // Popups need to be visible. cWaitForPopup, // UI does not need to be visible cWaitForUi, // General state predicate cWaitForState, cCloseDialog, cSubmitDialog, cTriggerContextMenu };