import { Assertions, Chain, Cursors, Step, StructAssert, Waiter } from '@ephox/agar'; import { Fun } from '@ephox/katamari'; import { Editor } from '../../alien/EditorTypes'; import * as Options from '../../alien/Options'; import * as TinyAssertions from '../bdd/TinyAssertions'; import * as TinySelections from '../bdd/TinySelections'; export interface Presence { [selector: string]: number; } export interface TinyApis { getContent: () => string; setContent: (html: string) => void; setRawContent: (html: string) => void; focus: () => void; hasFocus: (expected: boolean) => void; nodeChanged: () => void; assertContent: (expected: string) => void; assertContentPresence: (expected: Presence) => void; assertContentStructure: (expected: StructAssert) => void; assertSelection: (startPath: number[], soffset: number, finishPath: number[], foffset: number) => void; setCursor: (elementPath: number[], offset: number) => void; setSelectionFrom: (spec: Cursors.CursorSpec | Cursors.RangeSpec) => void; setSelection: (startPath: number[], soffset: number, finishPath: number[], foffset: number) => void; select: (selector: string, path: number[]) => void; /** @deprecated use unsetOption instead */ deleteSetting: (key: string) => void; unsetOption: (key: string) => void; /** @deprecated use setOption instead */ setSetting: (key: string, value: any) => void; setOption: (key: string, value: any) => void; execCommand: (command: string, value?: any) => void; pTryAssertFocus: (waitTime?: number) => Promise; sSetContent: (html: string) => Step; sSetRawContent: (html: string) => Step; sFocus: () => Step; sHasFocus: (expected: boolean) => Step; sNodeChanged: () => Step; sAssertContent: (expected: string) => Step; sAssertContentPresence: (expected: Presence) => Step; sAssertContentStructure: (expected: StructAssert) => Step; sAssertSelection: (startPath: number[], soffset: number, finishPath: number[], foffset: number) => Step; sSetCursor: (elementPath: number[], offset: number) => Step; sSetSelectionFrom: (spec: Cursors.CursorSpec | Cursors.RangeSpec) => Step; sSetSelection: (startPath: number[], soffset: number, finishPath: number[], foffset: number) => Step; sSelect: (selector: string, path: number[]) => Step; /** @deprecated use sUnsetOption instead */ sDeleteSetting: (key: string) => Step; sUnsetOption: (key: string) => Step; /** @deprecated use sSetOption instead */ sSetSetting: (key: string, value: any) => Step; sSetOption: (key: string, value: any) => Step; sExecCommand: (command: string, value?: any) => Step; sTryAssertFocus: (waitTime?: number) => Step; cNodeChanged: () => Chain; cGetContent: () => Chain; } export const TinyApis = (editor: Editor): TinyApis => { const getContent = (): string => editor.getContent(); const setContent = (html: string): void => { editor.setContent(html); }; const setRawContent = (html: string): void => { editor.getBody().innerHTML = html; }; const nodeChanged = (): void => { editor.nodeChanged(); }; const setSelectionFrom = Fun.curry(TinySelections.setSelectionFrom, editor); const setCursor = Fun.curry(TinySelections.setCursor, editor); const setSelection = Fun.curry(TinySelections.setSelection, editor); const select = Fun.curry(TinySelections.select, editor); const setOption = (key: string, value: any): void => { Options.set(editor, key, value); }; const unsetOption = (key: string): void => { Options.unset(editor, key); }; const execCommand = (command: string, value?: any) => { editor.execCommand(command, false, value); }; const assertContent = Fun.curry(TinyAssertions.assertContent, editor); const assertContentPresence = Fun.curry(TinyAssertions.assertContentPresence, editor); const assertContentStructure = Fun.curry(TinyAssertions.assertContentStructure, editor); const assertSelection = Fun.curry(TinyAssertions.assertSelection, editor); const focus = (): void => { editor.focus(); }; const hasFocus = (expected: boolean): void => { Assertions.assertEq('Assert whether editor hasFocus', expected, editor.hasFocus()); }; const sSetContent = (html: string) => Step.sync(() => { setContent(html); }); const sSetRawContent = (html: string) => Step.sync(() => { setRawContent(html); }); // Has to be thunked, so it can remain polymorphic const cNodeChanged = () => Chain.op(nodeChanged); const sSetSelectionFrom = (spec: Cursors.CursorSpec | Cursors.RangeSpec) => Step.sync(() => { setSelectionFrom(spec); }); const sSetCursor = (elementPath: number[], offset: number) => sSetSelection(elementPath, offset, elementPath, offset); const sSetSelection = (startPath: number[], soffset: number, finishPath: number[], foffset: number) => Step.sync(() => { setSelection(startPath, soffset, finishPath, foffset); }); const sSetOption = (key: string, value: any) => Step.sync(() => { setOption(key, value); }); const sUnsetOption = (key: string) => Step.sync(() => { unsetOption(key); }); const sSelect = (selector: string, path: number[]) => Step.sync(() => { TinySelections.select(editor, selector, path); }); const cGetContent = () => Chain.injectThunked(getContent); const sExecCommand = (command: string, value?: any) => Step.sync(() => { execCommand(command, value); }); const sAssertContent = (expected: string) => Step.sync(() => { assertContent(expected); }); const sAssertContentPresence = (expected: Presence) => Step.sync(() => { assertContentPresence(expected); }); const sAssertContentStructure = (expected: StructAssert) => Step.sync(() => { assertContentStructure(expected); }); const sAssertSelection = (startPath: number[], soffset: number, finishPath: number[], foffset: number) => Step.sync(() => { assertSelection(startPath, soffset, finishPath, foffset); }); const sFocus = () => Step.sync(focus); const sHasFocus = (expected: boolean) => Step.sync(() => { hasFocus(expected); }); const sNodeChanged = () => Step.sync(nodeChanged); const sTryAssertFocus = (waitTime?: number) => Waiter.sTryUntil( 'Waiting for focus', sHasFocus(true), 50, waitTime ); const pTryAssertFocus = (waitTime?: number) => Step.toPromise(sTryAssertFocus(waitTime))(undefined); return { getContent, setContent, setRawContent, nodeChanged, setSelectionFrom, setCursor, setSelection, select, setSetting: setOption, deleteSetting: unsetOption, setOption, unsetOption, execCommand, assertContent, assertContentStructure, assertContentPresence, assertSelection, focus, hasFocus, pTryAssertFocus, sSetContent, cGetContent, sSetRawContent, cNodeChanged, sAssertContent, sAssertContentPresence, sAssertContentStructure, sSetSelectionFrom, sSetSelection, sSetSetting: sSetOption, sDeleteSetting: sUnsetOption, sSetOption, sUnsetOption, sSetCursor, sSelect, sExecCommand, sAssertSelection, sTryAssertFocus, sFocus, sHasFocus, sNodeChanged }; };