diff --git a/addon-test-support/@ember/test-helpers/-utils.ts b/addon-test-support/@ember/test-helpers/-utils.ts index 702a1f2d1..2008e8b2f 100644 --- a/addon-test-support/@ember/test-helpers/-utils.ts +++ b/addon-test-support/@ember/test-helpers/-utils.ts @@ -78,7 +78,7 @@ export const futureTick = setTimeout; @private @returns {Promise} Promise which can not be forced to be ran synchronously */ -export function nextTickPromise() { +export function nextTickPromise(): RSVP.Promise { // Ember 3.4 removed the auto-run assertion, in 3.4+ we can (and should) avoid the "psuedo promisey" run loop configuration // for our `nextTickPromise` implementation. This allows us to have real microtask based next tick timing... if (hasEmberVersion(3, 4)) { diff --git a/addon-test-support/@ember/test-helpers/application.ts b/addon-test-support/@ember/test-helpers/application.ts index cb8a1ac75..4c5b554e8 100644 --- a/addon-test-support/@ember/test-helpers/application.ts +++ b/addon-test-support/@ember/test-helpers/application.ts @@ -1,6 +1,8 @@ +import Application from '@ember/application'; + import { getResolver, setResolver } from './resolver'; -var __application__; +var __application__: Application; /** Stores the provided application instance so that tests being ran will be aware of the application under test. @@ -11,11 +13,11 @@ var __application__; @public @param {Ember.Application} application the application that will be tested */ -export function setApplication(application) { +export function setApplication(application: Application): void { __application__ = application; if (!getResolver()) { - let Resolver = application.Resolver; + let Resolver = (application as any).Resolver; let resolver = Resolver.create({ namespace: application }); setResolver(resolver); @@ -28,6 +30,6 @@ export function setApplication(application) { @public @returns {Ember.Application} the previously stored application instance under test */ -export function getApplication() { +export function getApplication(): Application { return __application__; } diff --git a/addon-test-support/@ember/test-helpers/dom/-target.ts b/addon-test-support/@ember/test-helpers/dom/-target.ts new file mode 100644 index 000000000..20ad678d7 --- /dev/null +++ b/addon-test-support/@ember/test-helpers/dom/-target.ts @@ -0,0 +1,3 @@ +type Target = string | Element; + +export default Target; diff --git a/addon-test-support/@ember/test-helpers/dom/blur.ts b/addon-test-support/@ember/test-helpers/dom/blur.ts index a31dc42b3..5186134a7 100644 --- a/addon-test-support/@ember/test-helpers/dom/blur.ts +++ b/addon-test-support/@ember/test-helpers/dom/blur.ts @@ -3,6 +3,7 @@ import fireEvent from './fire-event'; import settled from '../settled'; import isFocusable from './-is-focusable'; import { nextTickPromise } from '../-utils'; +import Target from './-target'; /** @private @@ -42,7 +43,7 @@ export function __blur__(element) { @param {string|Element} [target=document.activeElement] the element or selector to unfocus @return {Promise} resolves when settled */ -export default function blur(target = document.activeElement) { +export default function blur(target: Target = document.activeElement!): Promise { return nextTickPromise().then(() => { let element = getElement(target); if (!element) { diff --git a/addon-test-support/@ember/test-helpers/dom/click.ts b/addon-test-support/@ember/test-helpers/dom/click.ts index a896338e3..184e3ddd4 100644 --- a/addon-test-support/@ember/test-helpers/dom/click.ts +++ b/addon-test-support/@ember/test-helpers/dom/click.ts @@ -5,6 +5,7 @@ import settled from '../settled'; import isFocusable from './-is-focusable'; import { nextTickPromise } from '../-utils'; import isFormControl from './-is-form-control'; +import Target from './-target'; /** @private @@ -46,14 +47,14 @@ export function __click__(element, options) { The exact listing of events that are triggered may change over time as needed to continue to emulate how actual browsers handle clicking a given element. - Use the `options` hash to change the parameters of the MouseEvents. + Use the `options` hash to change the parameters of the MouseEvents. @public @param {string|Element} target the element or selector to click on @param {Object} options the options to be merged into the mouse events @return {Promise} resolves when settled */ -export default function click(target, options = {}) { +export default function click(target: Target, options: object = {}): Promise { return nextTickPromise().then(() => { if (!target) { throw new Error('Must pass an element or selector to `click`.'); diff --git a/addon-test-support/@ember/test-helpers/dom/double-click.ts b/addon-test-support/@ember/test-helpers/dom/double-click.ts index 343259186..9ce79a3fb 100644 --- a/addon-test-support/@ember/test-helpers/dom/double-click.ts +++ b/addon-test-support/@ember/test-helpers/dom/double-click.ts @@ -4,6 +4,7 @@ import { __focus__ } from './focus'; import settled from '../settled'; import isFocusable from './-is-focusable'; import { nextTickPromise } from '../-utils'; +import Target from './-target'; /** @private @@ -57,14 +58,14 @@ export function __doubleClick__(element, options) { The exact listing of events that are triggered may change over time as needed to continue to emulate how actual browsers handle clicking a given element. - Use the `options` hash to change the parameters of the MouseEvents. + Use the `options` hash to change the parameters of the MouseEvents. @public @param {string|Element} target the element or selector to double-click on @param {Object} options the options to be merged into the mouse events @return {Promise} resolves when settled */ -export default function doubleClick(target, options = {}) { +export default function doubleClick(target: Target, options: object = {}): Promise { return nextTickPromise().then(() => { if (!target) { throw new Error('Must pass an element or selector to `doubleClick`.'); diff --git a/addon-test-support/@ember/test-helpers/dom/fill-in.ts b/addon-test-support/@ember/test-helpers/dom/fill-in.ts index 6341d1695..660484433 100644 --- a/addon-test-support/@ember/test-helpers/dom/fill-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/fill-in.ts @@ -4,6 +4,7 @@ import { __focus__ } from './focus'; import settled from '../settled'; import fireEvent from './fire-event'; import { nextTickPromise } from '../-utils'; +import Target from './-target'; /** Fill the provided text into the `value` property (or set `.innerHTML` when @@ -15,7 +16,7 @@ import { nextTickPromise } from '../-utils'; @param {string} text the text to fill into the target element @return {Promise} resolves when the application is settled */ -export default function fillIn(target: any, text: string): Promise { +export default function fillIn(target: Target, text: string): Promise { return nextTickPromise().then(() => { if (!target) { throw new Error('Must pass an element or selector to `fillIn`.'); diff --git a/addon-test-support/@ember/test-helpers/dom/find-all.ts b/addon-test-support/@ember/test-helpers/dom/find-all.ts index a73cf5586..2d060c2f9 100644 --- a/addon-test-support/@ember/test-helpers/dom/find-all.ts +++ b/addon-test-support/@ember/test-helpers/dom/find-all.ts @@ -9,7 +9,7 @@ import toArray from './-to-array'; @param {string} selector the selector to search for @return {Array} array of matched elements */ -export default function find(selector) { +export default function find(selector: string): Element[] { if (!selector) { throw new Error('Must pass a selector to `findAll`.'); } diff --git a/addon-test-support/@ember/test-helpers/dom/find.ts b/addon-test-support/@ember/test-helpers/dom/find.ts index 421e7f4ed..6d6a8682a 100644 --- a/addon-test-support/@ember/test-helpers/dom/find.ts +++ b/addon-test-support/@ember/test-helpers/dom/find.ts @@ -8,7 +8,7 @@ import getElement from './-get-element'; @param {string} selector the selector to search for @return {Element} matched element or null */ -export default function find(selector) { +export default function find(selector: string): Element | null { if (!selector) { throw new Error('Must pass a selector to `find`.'); } diff --git a/addon-test-support/@ember/test-helpers/dom/focus.ts b/addon-test-support/@ember/test-helpers/dom/focus.ts index 27a1c70de..c658b9e35 100644 --- a/addon-test-support/@ember/test-helpers/dom/focus.ts +++ b/addon-test-support/@ember/test-helpers/dom/focus.ts @@ -3,6 +3,7 @@ import fireEvent from './fire-event'; import settled from '../settled'; import isFocusable from './-is-focusable'; import { nextTickPromise } from '../-utils'; +import Target from './-target'; /** @private @@ -45,7 +46,7 @@ export function __focus__(element) { @param {string|Element} target the element or selector to focus @return {Promise} resolves when the application is settled */ -export default function focus(target) { +export default function focus(target: Target): Promise { return nextTickPromise().then(() => { if (!target) { throw new Error('Must pass an element or selector to `focus`.'); diff --git a/addon-test-support/@ember/test-helpers/dom/get-root-element.ts b/addon-test-support/@ember/test-helpers/dom/get-root-element.ts index 661924357..99def56be 100644 --- a/addon-test-support/@ember/test-helpers/dom/get-root-element.ts +++ b/addon-test-support/@ember/test-helpers/dom/get-root-element.ts @@ -6,7 +6,7 @@ import { getContext } from '../setup-context'; @public @returns {Element} the root element */ -export default function getRootElement() { +export default function getRootElement(): Element { let context = getContext(); let owner = context && context.owner; @@ -30,7 +30,7 @@ export default function getRootElement() { ) { return rootElement; } else if (typeof rootElement === 'string') { - return document.querySelector(rootElement); + return document.querySelector(rootElement)!; // TODO remove "!" } else { throw new Error('Application.rootElement must be an element or a selector string'); } diff --git a/addon-test-support/@ember/test-helpers/dom/tap.ts b/addon-test-support/@ember/test-helpers/dom/tap.ts index 58bd0ce26..ea3740100 100644 --- a/addon-test-support/@ember/test-helpers/dom/tap.ts +++ b/addon-test-support/@ember/test-helpers/dom/tap.ts @@ -3,6 +3,7 @@ import fireEvent from './fire-event'; import { __click__ } from './click'; import settled from '../settled'; import { nextTickPromise } from '../-utils'; +import Target from './-target'; /** Taps on the specified target. @@ -32,14 +33,14 @@ import { nextTickPromise } from '../-utils'; The exact listing of events that are triggered may change over time as needed to continue to emulate how actual browsers handle tapping on a given element. - Use the `options` hash to change the parameters of the tap events. + Use the `options` hash to change the parameters of the tap events. @public @param {string|Element} target the element or selector to tap on @param {Object} options the options to be merged into the touch events @return {Promise} resolves when settled */ -export default function tap(target, options = {}) { +export default function tap(target: Target, options: object = {}): Promise { return nextTickPromise().then(() => { if (!target) { throw new Error('Must pass an element or selector to `tap`.'); diff --git a/addon-test-support/@ember/test-helpers/dom/trigger-event.ts b/addon-test-support/@ember/test-helpers/dom/trigger-event.ts index 4944d6be5..52e71faf3 100644 --- a/addon-test-support/@ember/test-helpers/dom/trigger-event.ts +++ b/addon-test-support/@ember/test-helpers/dom/trigger-event.ts @@ -2,6 +2,7 @@ import getElement from './-get-element'; import fireEvent from './fire-event'; import settled from '../settled'; import { nextTickPromise } from '../-utils'; +import Target from './-target'; /** * Triggers an event on the specified target. @@ -24,7 +25,11 @@ import { nextTickPromise } from '../-utils'; * [new Blob(['Ember Rules!'])] * ); */ -export default function triggerEvent(target, eventType, options) { +export default function triggerEvent( + target: Target, + eventType: string, + options?: object +): Promise { return nextTickPromise().then(() => { if (!target) { throw new Error('Must pass an element or selector to `triggerEvent`.'); diff --git a/addon-test-support/@ember/test-helpers/dom/trigger-key-event.ts b/addon-test-support/@ember/test-helpers/dom/trigger-key-event.ts index 168346f35..2bdeb1e92 100644 --- a/addon-test-support/@ember/test-helpers/dom/trigger-key-event.ts +++ b/addon-test-support/@ember/test-helpers/dom/trigger-key-event.ts @@ -4,8 +4,18 @@ import fireEvent from './fire-event'; import settled from '../settled'; import { KEYBOARD_EVENT_TYPES } from './fire-event'; import { nextTickPromise, isNumeric } from '../-utils'; +import Target from './-target'; -const DEFAULT_MODIFIERS = Object.freeze({ +export type KeyEvent = 'keydown' | 'keyup' | 'keypress'; + +export interface KeyModifiers { + ctrlKey?: boolean; + altKey?: boolean; + shiftKey?: boolean; + metaKey?: boolean; +} + +const DEFAULT_MODIFIERS: KeyModifiers = Object.freeze({ ctrlKey: false, altKey: false, shiftKey: false, @@ -122,7 +132,12 @@ function keyCodeFromKey(key) { @param {boolean} [modifiers.metaKey=false] if true the generated event will indicate the meta key was pressed during the key event @return {Promise} resolves when the application is settled */ -export default function triggerKeyEvent(target, eventType, key, modifiers = DEFAULT_MODIFIERS) { +export default function triggerKeyEvent( + target: Target, + eventType: KeyEvent, + key: number | string, + modifiers: KeyModifiers = DEFAULT_MODIFIERS +): Promise { return nextTickPromise().then(() => { if (!target) { throw new Error('Must pass an element or selector to `triggerKeyEvent`.'); diff --git a/addon-test-support/@ember/test-helpers/dom/type-in.ts b/addon-test-support/@ember/test-helpers/dom/type-in.ts index 9799aa7a1..ec2286052 100644 --- a/addon-test-support/@ember/test-helpers/dom/type-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/type-in.ts @@ -5,6 +5,7 @@ import isFormControl from './-is-form-control'; import { __focus__ } from './focus'; import { Promise } from 'rsvp'; import fireEvent from './fire-event'; +import Target from './-target'; /** * Mimics character by character entry into the target `input` or `textarea` element. @@ -23,7 +24,7 @@ import fireEvent from './fire-event'; * @param {Object} options {delay: x} (default 50) number of milliseconds to wait per keypress * @return {Promise} resolves when the application is settled */ -export default function typeIn(target, text, options = { delay: 50 }) { +export default function typeIn(target: Target, text, options = { delay: 50 }): Promise { return nextTickPromise().then(() => { if (!target) { throw new Error('Must pass an element or selector to `typeIn`.'); diff --git a/addon-test-support/@ember/test-helpers/dom/wait-for.ts b/addon-test-support/@ember/test-helpers/dom/wait-for.ts index 4765dcb25..917e488d9 100644 --- a/addon-test-support/@ember/test-helpers/dom/wait-for.ts +++ b/addon-test-support/@ember/test-helpers/dom/wait-for.ts @@ -18,7 +18,7 @@ import { nextTickPromise } from '../-utils'; export default function waitFor( selector, { timeout = 1000, count = null, timeoutMessage = '' } = {} -) { +): Promise { return nextTickPromise().then(() => { if (!selector) { throw new Error('Must pass a selector to `waitFor`.'); @@ -27,7 +27,7 @@ export default function waitFor( timeoutMessage = `waitFor timed out waiting for selector "${selector}"`; } - let callback; + let callback: () => Element | Element[] | void; if (count !== null) { callback = () => { let elements = getElements(selector); diff --git a/addon-test-support/@ember/test-helpers/resolver.ts b/addon-test-support/@ember/test-helpers/resolver.ts index 532646c28..f208d9481 100644 --- a/addon-test-support/@ember/test-helpers/resolver.ts +++ b/addon-test-support/@ember/test-helpers/resolver.ts @@ -1,4 +1,6 @@ -var __resolver__; +import Resolver from '@ember/application/resolver'; + +var __resolver__: Resolver; /** Stores the provided resolver instance so that tests being ran can resolve @@ -9,7 +11,7 @@ var __resolver__; @public @param {Ember.Resolver} resolver the resolver to be used for testing */ -export function setResolver(resolver) { +export function setResolver(resolver: Resolver): void { __resolver__ = resolver; } @@ -19,6 +21,6 @@ export function setResolver(resolver) { @public @returns {Ember.Resolver} the previously stored resolver */ -export function getResolver() { +export function getResolver(): Resolver { return __resolver__; } diff --git a/addon-test-support/@ember/test-helpers/settled.ts b/addon-test-support/@ember/test-helpers/settled.ts index 232a48070..70941e3b4 100644 --- a/addon-test-support/@ember/test-helpers/settled.ts +++ b/addon-test-support/@ember/test-helpers/settled.ts @@ -139,6 +139,14 @@ function checkWaiters() { return false; } +export interface SettledState { + hasRunLoop: boolean; + hasPendingTimers: boolean; + hasPendingWaiters: boolean; + hasPendingRequests: boolean; + pendingRequestCount: number; +} + /** Check various settledness metrics, and return an object with the following properties: @@ -158,7 +166,7 @@ function checkWaiters() { @public @returns {Object} object with properties for each of the metrics used to determine settledness */ -export function getSettledState() { +export function getSettledState(): SettledState { let pendingRequestCount = pendingRequests(); return { @@ -180,7 +188,7 @@ export function getSettledState() { @public @returns {boolean} `true` if settled, `false` otherwise */ -export function isSettled() { +export function isSettled(): boolean { let { hasPendingTimers, hasRunLoop, hasPendingRequests, hasPendingWaiters } = getSettledState(); if (hasPendingTimers || hasRunLoop || hasPendingRequests || hasPendingWaiters) { diff --git a/addon-test-support/@ember/test-helpers/setup-application-context.ts b/addon-test-support/@ember/test-helpers/setup-application-context.ts index 2f9716139..2b910f0b1 100644 --- a/addon-test-support/@ember/test-helpers/setup-application-context.ts +++ b/addon-test-support/@ember/test-helpers/setup-application-context.ts @@ -9,9 +9,10 @@ import settled from './settled'; Navigate the application to the provided URL. @public + @param {string} url The URL to visit (e.g. `/posts`) @returns {Promise} resolves when settled */ -export function visit() { +export function visit(url: string): Promise { let context = getContext(); let { owner } = context; @@ -33,7 +34,7 @@ export function visit() { @public @returns {string} the currently active route name */ -export function currentRouteName() { +export function currentRouteName(): string { let { owner } = getContext(); let router = owner.lookup('router:main'); return get(router, 'currentRouteName'); @@ -45,7 +46,7 @@ const HAS_CURRENT_URL_ON_ROUTER = hasEmberVersion(2, 13); @public @returns {string} the applications current url */ -export function currentURL() { +export function currentURL(): string { let { owner } = getContext(); let router = owner.lookup('router:main'); @@ -69,6 +70,8 @@ export function currentURL() { @param {Object} context the context to setup @returns {Promise} resolves with the context that was setup */ -export default function setupApplicationContext() { +export default function setupApplicationContext( + context: Context +): Promise { return nextTickPromise(); } diff --git a/addon-test-support/@ember/test-helpers/setup-context.ts b/addon-test-support/@ember/test-helpers/setup-context.ts index 489b0ff4b..dec8cce5a 100644 --- a/addon-test-support/@ember/test-helpers/setup-context.ts +++ b/addon-test-support/@ember/test-helpers/setup-context.ts @@ -1,6 +1,8 @@ import { run } from '@ember/runloop'; import { set, setProperties, get, getProperties } from '@ember/object'; import { guidFor } from '@ember/object/internals'; +import Resolver from '@ember/application/resolver'; + import buildOwner from './build-owner'; import { _setupAJAXHooks } from './settled'; import Ember from 'ember'; @@ -11,7 +13,7 @@ import { getResolver } from './resolver'; import { getApplication } from './application'; import { nextTickPromise } from './-utils'; -let __test_context__; +let __test_context__: any | undefined; /** Stores the provided context as the "global testing context". @@ -21,7 +23,7 @@ let __test_context__; @public @param {Object} context the context to use */ -export function setContext(context) { +export function setContext(context: any): void { __test_context__ = context; } @@ -31,7 +33,7 @@ export function setContext(context) { @public @returns {Object} the previously stored testing context */ -export function getContext() { +export function getContext(): any | undefined { return __test_context__; } @@ -42,7 +44,7 @@ export function getContext() { @public */ -export function unsetContext() { +export function unsetContext(): void { __test_context__ = undefined; } @@ -80,7 +82,7 @@ export function unsetContext() { * }); * }); */ -export function pauseTest() { +export function pauseTest(): Promise { let context = getContext(); if (!context || typeof context.pauseTest !== 'function') { @@ -97,7 +99,7 @@ export function pauseTest() { @public */ -export function resumeTest() { +export function resumeTest(): void { let context = getContext(); if (!context || typeof context.resumeTest !== 'function') { @@ -128,7 +130,10 @@ export const CLEANUP = Object.create(null); @param {Resolver} [options.resolver] a resolver to use for customizing normal resolution @returns {Promise} resolves with the context that was setup */ -export default function(context, options: any = {}) { +export default function( + context: Context, + options: { resolver?: Resolver } = {} +): Promise { (Ember as any).testing = true; setContext(context); @@ -139,8 +144,9 @@ export default function(context, options: any = {}) { .then(() => { let application = getApplication(); if (application) { - return application.boot(); + return application.boot().then(() => {}); } + return; }) .then(() => { let testElementContainer = document.getElementById('ember-testing-container')!; // TODO remove "!" diff --git a/addon-test-support/@ember/test-helpers/setup-rendering-context.ts b/addon-test-support/@ember/test-helpers/setup-rendering-context.ts index 511af1dc3..a70707e7c 100644 --- a/addon-test-support/@ember/test-helpers/setup-rendering-context.ts +++ b/addon-test-support/@ember/test-helpers/setup-rendering-context.ts @@ -6,7 +6,7 @@ import global from './global'; import { getContext } from './setup-context'; import { nextTickPromise } from './-utils'; import settled from './settled'; -import hbs from 'htmlbars-inline-precompile'; +import hbs, { TemplateFactory } from 'htmlbars-inline-precompile'; import getRootElement from './dom/get-root-element'; export const RENDERING_CLEANUP = Object.create(null); @@ -49,7 +49,7 @@ let templateId = 0; @param {CompiledTemplate} template the template to render @returns {Promise} resolves when settled */ -export function render(template) { +export function render(template: TemplateFactory): Promise { let context = getContext(); if (!template) { @@ -112,7 +112,7 @@ export function render(template) { @public @returns {Promise} resolves when settled */ -export function clearRender() { +export function clearRender(): Promise { let context = getContext(); if (!context || typeof context.clearRender !== 'function') { @@ -143,7 +143,9 @@ export function clearRender() { @param {Object} context the context to setup for rendering @returns {Promise} resolves with the context that was setup */ -export default function setupRenderingContext(context) { +export default function setupRenderingContext( + context: Context +): Promise { let contextGuid = guidFor(context); RENDERING_CLEANUP[contextGuid] = []; diff --git a/addon-test-support/@ember/test-helpers/teardown-application-context.ts b/addon-test-support/@ember/test-helpers/teardown-application-context.ts index 4c5bdaa23..9aab9c67d 100644 --- a/addon-test-support/@ember/test-helpers/teardown-application-context.ts +++ b/addon-test-support/@ember/test-helpers/teardown-application-context.ts @@ -7,6 +7,6 @@ import settled from './settled'; @param {Object} context the context to setup @returns {Promise} resolves when settled */ -export default function() { +export default function(context: object): Promise { return settled(); } diff --git a/addon-test-support/@ember/test-helpers/teardown-context.ts b/addon-test-support/@ember/test-helpers/teardown-context.ts index 0f9f6b46d..14d2fe4b5 100644 --- a/addon-test-support/@ember/test-helpers/teardown-context.ts +++ b/addon-test-support/@ember/test-helpers/teardown-context.ts @@ -19,7 +19,9 @@ import Ember from 'ember'; @param {Object} context the context to setup @returns {Promise} resolves when settled */ -export default function teardownContext(context) { +export default function teardownContext( + context: Context +): Promise { return nextTickPromise() .then(() => { let { owner } = context; diff --git a/addon-test-support/@ember/test-helpers/teardown-rendering-context.ts b/addon-test-support/@ember/test-helpers/teardown-rendering-context.ts index 7c7787420..01f8bdd1e 100644 --- a/addon-test-support/@ember/test-helpers/teardown-rendering-context.ts +++ b/addon-test-support/@ember/test-helpers/teardown-rendering-context.ts @@ -15,7 +15,7 @@ import settled from './settled'; @param {Object} context the context to setup @returns {Promise} resolves when settled */ -export default function teardownRenderingContext(context) { +export default function teardownRenderingContext(context: object): Promise { return nextTickPromise().then(() => { let contextGuid = guidFor(context); diff --git a/addon-test-support/@ember/test-helpers/wait-until.ts b/addon-test-support/@ember/test-helpers/wait-until.ts index f5af37d13..3f2f179f0 100644 --- a/addon-test-support/@ember/test-helpers/wait-until.ts +++ b/addon-test-support/@ember/test-helpers/wait-until.ts @@ -3,6 +3,11 @@ import { futureTick, _Promise as Promise } from './-utils'; const TIMEOUTS = [0, 1, 2, 5, 7]; const MAX_TIMEOUT = 10; +export interface Options { + timeout?: number; + timeoutMessage?: string; +} + /** Wait for the provided callback to return a truthy value. @@ -16,8 +21,11 @@ const MAX_TIMEOUT = 10; @param {string} [options.timeoutMessage='waitUntil timed out'] the message to use in the reject on timeout @returns {Promise} resolves with the callback value when it returns a truthy value */ -export default function waitUntil(callback, options: any = {}) { - let timeout = 'timeout' in options ? options.timeout : 1000; +export default function waitUntil( + callback: () => T | void | false | null | undefined | '', + options: Options = {} +): Promise { + let timeout = 'timeout' in options ? (options.timeout as number) : 1000; let timeoutMessage = 'timeoutMessage' in options ? options.timeoutMessage : 'waitUntil timed out'; // creating this error eagerly so it has the proper invocation stack