import { Fun, Result } from '@ephox/katamari'; import { type SugarElement, Truncate, Visibility } from '@ephox/sugar'; import * as UiSearcher from '../find/UiSearcher'; import { Chain } from './Chain'; import * as Guard from './Guard'; import { Step } from './Step'; const findIn = UiSearcher.findIn; const findAllIn = UiSearcher.findAllIn; const findTargetByLabel = UiSearcher.findTargetByLabel; const exists = (container: SugarElement, selector: string): void => { findIn(container, selector).fold( () => { throw new Error('Expected ' + selector + ' to exist.'); }, Fun.noop ); }; const notExists = (container: SugarElement, selector: string): void => { return findIn(container, selector).fold( Fun.noop, () => { throw new Error('Expected ' + selector + ' not to exist.'); } ); }; const cWaitFor = (message: string, selector: string): Chain, SugarElement> => cWaitForState(message, selector, Fun.always); const sWaitFor = (message: string, container: SugarElement, selector: string): Step => Chain.asStep>(container, [ cWaitFor(message, selector) ]); const cWaitForVisible = (message: string, selector: string): Chain, SugarElement> => cWaitForState(message, selector, Visibility.isVisible); // TODO: Perhaps create cWaitForNoState rather than Fun.not here? const cWaitForHidden = (message: string, selector: string): Chain, SugarElement> => cWaitForState(message, selector, Fun.not(Visibility.isVisible)); const sWaitForVisible = (message: string, container: SugarElement, selector: string): Step => Chain.asStep>(container, [ cWaitForVisible(message, selector) ]); const sWaitForHidden = (message: string, container: SugarElement, selector: string): Step => Chain.asStep>(container, [ cWaitForHidden(message, selector) ]); const cHasState = (predicate: (element: SugarElement) => boolean): Chain, SugarElement> => Chain.binder((element) => predicate(element) ? Result.value(element) : Result.error(Truncate.getHtml(element) + ' did not match predicate: ' + predicate.toString())); const cFindWithState = (selector: string, predicate: (element: SugarElement) => boolean): Chain, SugarElement> => Chain.fromChains([ cFindIn(selector), cHasState(predicate) ]); // Wait for a selector to have state. Max wait time: 2 seconds. const cWaitForState = (message: string, selector: string, predicate: (element: SugarElement) => boolean): Chain, SugarElement> => Chain.control( cFindWithState(selector, predicate), Guard.tryUntil(message, 10, 2000) ); // Wait for a selector to have state. Max wait time: 2 seconds. const cWaitForNotExists = (message: string, selector: string): Chain, SugarElement> => Chain.control( cNotExists(selector), Guard.tryUntil(message, 10, 2000) ); const sExists = (container: SugarElement, selector: string): Step => Step.sync(() => exists(container, selector)); const sNotExists = (container: SugarElement, selector: string): Step => Step.sync(() => notExists(container, selector)); const cExists = (selector: string): Chain, SugarElement> => Chain.op((container) => exists(container, selector)); const cNotExists = (selector: string): Chain, SugarElement> => Chain.op((container) => notExists(container, selector)); const cFindIn = (selector: string): Chain, SugarElement> => Chain.binder((container) => findIn(container, selector) ); const cFindAllIn = (selector: string): Chain, SugarElement[]> => Chain.mapper((container) => findAllIn(container, selector) ); const pWaitFor = (message: string, container: SugarElement, selector: string): Promise> => Chain.toPromise(cWaitFor(message, selector))(container); const pWaitForNotExists = async (message: string, container: SugarElement, selector: string): Promise => { await Chain.toPromise(cWaitForNotExists(message, selector))(container); }; const pWaitForVisible = (message: string, container: SugarElement, selector: string): Promise> => Chain.toPromise(cWaitForVisible(message, selector))(container); const pWaitForHidden = (message: string, container: SugarElement, selector: string): Promise> => Chain.toPromise(cWaitForHidden(message, selector))(container); const pWaitForState = (message: string, container: SugarElement, selector: string, predicate: (element: SugarElement) => boolean): Promise> => Chain.toPromise(cWaitForState(message, selector, predicate))(container); export { findIn, findAllIn, findTargetByLabel, exists, notExists, sExists, sNotExists, sWaitFor, sWaitForVisible, sWaitForHidden, cExists, cNotExists, cWaitForNotExists, cWaitFor, cWaitForVisible, cWaitForHidden, cWaitForState, cFindIn, cFindAllIn, pWaitFor, pWaitForVisible, pWaitForHidden, pWaitForState, pWaitForNotExists };