Skip to content
Permalink
master
Switch branches/tags
Go to file
Expose deprecation primitives

* `?disableWarnings` queryParam
* `?debugWarnings` queryParam
* `import { getWarnings, getWarningsDuringCallback } from ‘@ember/test-helpers’;`

This is a second step in allowing us to deprecate https://github.com/workmanw/ember-qunit-assert-helpers in-favor of these helpers simply being provided by default.

---

Context: This is motivated by 4.0 changes that are incompatible with the original add-on, and the time trade-off of resurrecting that add-on vs adopting its great ideas into mainline. Although users will need to upgrade their `@ember/test-helpers` + `ember-qunit` they will now get the original functionality, + async + bugfixes by default.

 I was lead down this path getting embroider working properly on `ember@canary`

---

 enables resolving emberjs/ember-string#259 amongst other related issues (basically anyone consuming ember-qunit-assert-helpers)
13 contributors

Users who have contributed to this file

@rwjblue @scalvert @jenweber @sly7-7 @stefanpenner @snewcomer @mattdonnelly @ygongdev @Turbo87 @qpowell @pcambra @jrjohnson

Table of Contents

DOM Interaction Helpers

blur

Unfocus the specified target.

Sends a number of events intending to simulate a "real" user unfocusing an element.

The following events are triggered (in order):

  • blur
  • focusout

The exact listing of events that are triggered may change over time as needed to continue to emulate how actual browsers handle unfocusing a given element.

Parameters

  • target (string | Element) the element or selector to unfocus (optional, default document.activeElement)

Examples

Emulating blurring an input using blur

blur('input');

Returns Promise<void> resolves when settled

click

Clicks on the specified target.

Sends a number of events intending to simulate a "real" user clicking on an element.

For non-focusable elements the following events are triggered (in order):

  • mousedown
  • mouseup
  • click

For focusable (e.g. form control) elements the following events are triggered (in order):

  • mousedown
  • focus
  • focusin
  • mouseup
  • click

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. You can use this to specifiy modifier keys as well.

Parameters

  • target (string | Element) the element or selector to click on
  • _options MouseEventInit the options to be merged into the mouse events. (optional, default {})

Examples

Emulating clicking a button using click

click('button');

Emulating clicking a button and pressing the shift key simultaneously using click with options.

click('button', { shiftKey: true });

Returns Promise<void> resolves when settled

doubleClick

Double-clicks on the specified target.

Sends a number of events intending to simulate a "real" user clicking on an element.

For non-focusable elements the following events are triggered (in order):

  • mousedown
  • mouseup
  • click
  • mousedown
  • mouseup
  • click
  • dblclick

For focusable (e.g. form control) elements the following events are triggered (in order):

  • mousedown
  • focus
  • focusin
  • mouseup
  • click
  • mousedown
  • mouseup
  • click
  • dblclick

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.

Parameters

  • target (string | Element) the element or selector to double-click on
  • _options MouseEventInit the options to be merged into the mouse events (optional, default {})

Examples

Emulating double clicking a button using doubleClick

doubleClick('button');

Emulating double clicking a button and pressing the shift key simultaneously using click with options.

doubleClick('button', { shiftKey: true });

Returns Promise<void> resolves when settled

fillIn

Fill the provided text into the value property (or set .innerHTML when the target is a content editable element) then trigger change and input events on the specified target.

Parameters

  • target (string | Element) the element or selector to enter text into
  • text string the text to fill into the target element

Examples

Emulating filling an input with text using fillIn

fillIn('input', 'hello world');

Returns Promise<void> resolves when the application is settled

focus

Focus the specified target.

Sends a number of events intending to simulate a "real" user focusing an element.

The following events are triggered (in order):

  • focus
  • focusin

The exact listing of events that are triggered may change over time as needed to continue to emulate how actual browsers handle focusing a given element.

Parameters

Examples

Emulating focusing an input using focus

focus('input');

Returns Promise<void> resolves when the application is settled

scrollTo

Scrolls DOM element or selector to the given coordinates.

Parameters

Examples

Scroll DOM element to specific coordinates

scrollTo('#my-long-div', 0, 0); // scroll to top
scrollTo('#my-long-div', 0, 100); // scroll down

Returns Promise<void> resolves when settled

select

Set the selected property true for the provided option the target is a select element (or set the select property true for multiple options if the multiple attribute is set true on the HTMLSelectElement) then trigger change and input events on the specified target.

Parameters

  • target (string | Element) the element or selector for the select element
  • options (string | Array<string>) the value/values of the items to select
  • keepPreviouslySelected boolean a flag keep any existing selections (optional, default false)

Examples

Emulating selecting an option or multiple options using select

select('select', 'apple');

select('select', ['apple', 'orange']);

select('select', ['apple', 'orange'], true);

Returns Promise<void> resolves when the application is settled

tap

Taps on the specified target.

Sends a number of events intending to simulate a "real" user tapping on an element.

For non-focusable elements the following events are triggered (in order):

  • touchstart
  • touchend
  • mousedown
  • mouseup
  • click

For focusable (e.g. form control) elements the following events are triggered (in order):

  • touchstart
  • touchend
  • mousedown
  • focus
  • focusin
  • mouseup
  • click

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.

Parameters

  • target (string | Element) the element or selector to tap on
  • options Object the options to be merged into the touch events (optional, default {})

Examples

Emulating tapping a button using tap

tap('button');

Returns Promise<void> resolves when settled

triggerEvent

Triggers an event on the specified target.

Parameters

  • target (string | Element) the element or selector to trigger the event on
  • eventType string the type of event to trigger
  • options Object additional properties to be set on the event

Examples

Using triggerEvent to upload a file

When using triggerEvent to upload a file the eventType must be change and you must pass the options param as an object with a key files containing an array of Blob.

triggerEvent(
  'input.fileUpload',
  'change',
  { files: [new Blob(['Ember Rules!'])] }
);

Using triggerEvent to upload a dropped file

When using triggerEvent to handle a dropped (via drag-and-drop) file, the eventType must be drop. Assuming your drop event handler uses the DataTransfer API, you must pass the options param as an object with a key of dataTransfer. The options.dataTransfer object should have a files key, containing an array of File.

triggerEvent(
  '[data-test-drop-zone]',
  'drop',
  {
    dataTransfer: {
      files: [new File(['Ember Rules!'], 'ember-rules.txt')]
    }
  }
)

Returns Promise<void> resolves when the application is settled

triggerKeyEvent

Triggers a keyboard event of given type in the target element. It also requires the developer to provide either a string with the key or the numeric keyCode of the pressed key. Optionally the user can also provide a POJO with extra modifiers for the event.

Parameters

  • target (string | Element) the element or selector to trigger the event on

  • eventType ("keydown" | "keyup" | "keypress") the type of event to trigger

  • key (number | string) the keyCode(number) or key(string) of the event being triggered

  • modifiers Object? the state of various modifier keys (optional, default DEFAULT_MODIFIERS)

    • modifiers.ctrlKey boolean if true the generated event will indicate the control key was pressed during the key event (optional, default false)
    • modifiers.altKey boolean if true the generated event will indicate the alt key was pressed during the key event (optional, default false)
    • modifiers.shiftKey boolean if true the generated event will indicate the shift key was pressed during the key event (optional, default false)
    • modifiers.metaKey boolean if true the generated event will indicate the meta key was pressed during the key event (optional, default false)

Examples

Emulating pressing the ENTER key on a button using triggerKeyEvent

triggerKeyEvent('button', 'keydown', 'Enter');

Returns Promise<void> resolves when the application is settled unless awaitSettled is false

typeIn

Mimics character by character entry into the target input or textarea element.

Allows for simulation of slow entry by passing an optional millisecond delay between key events.

The major difference between typeIn and fillIn is that typeIn triggers keyboard events as well as input and change. Typically this looks like focus -> focusin -> keydown -> keypress -> keyup -> input -> change per character of the passed text (this may vary on some browsers).

Parameters

  • target (string | Element) the element or selector to enter text into
  • text string the test to fill the element with
  • options Object {delay: x} (default 50) number of milliseconds to wait per keypress (optional, default {})

Examples

Emulating typing in an input using typeIn

typeIn('input', 'hello world');

Returns Promise<void> resolves when the application is settled

DOM Query Helpers

find

Find the first element matched by the given selector. Equivalent to calling querySelector() on the test root element.

Parameters

  • selector string the selector to search for

Returns Element matched element or null

findAll

Find all elements matched by the given selector. Similar to calling querySelectorAll() on the test root element, but returns an array instead of a NodeList.

Parameters

  • selector string the selector to search for

Returns Array array of matched elements

getRootElement

Get the root element of the application under test (usually #ember-testing)

Returns Element the root element

Routing Helpers

visit

Navigate the application to the provided URL.

Parameters

  • url string The URL to visit (e.g. /posts)
  • options object app boot options

Returns Promise<void> resolves when settled

currentRouteName

Returns string the currently active route name

currentURL

Returns string the applications current url

Rendering Helpers

render

Renders the provided template and appends it to the DOM.

Parameters

  • template CompiledTemplate the template to render

Returns Promise<void> resolves when settled

clearRender

Clears any templates previously rendered. This is commonly used for confirming behavior that is triggered by teardown (e.g. willDestroyElement).

Returns Promise<void> resolves when settled

Wait Helpers

waitFor

Used to wait for a particular selector to appear in the DOM. Due to the fact that it does not wait for general settledness, this is quite useful for testing interim DOM states (e.g. loading states, pending promises, etc).

Parameters

  • selector string the selector to wait for

  • options Object? the options to be used (optional, default {})

    • options.timeout number the time to wait (in ms) for a match (optional, default 1000)
    • options.count number the number of elements that should match the provided selector (null means one or more) (optional, default null)

Examples

Waiting until a selector is rendered:

await waitFor('.my-selector', { timeout: 2000 })

Returns Promise<(Element | Array<Element>)> resolves when the element(s) appear on the page

waitUntil

Wait for the provided callback to return a truthy value.

This does not leverage settled(), and as such can be used to manage async while not settled (e.g. "loading" or "pending" states).

Parameters

  • callback Function the callback to use for testing when waiting should stop

  • options Object? options used to override defaults (optional, default {})

    • options.timeout number the maximum amount of time to wait (optional, default 1000)
    • options.timeoutMessage string the message to use in the reject on timeout (optional, default 'waitUntil timed out')

Examples

Waiting until a selected element displays text:

await waitUntil(function() {
return find('.my-selector').textContent.includes('something')
}, { timeout: 2000 })

Returns Promise resolves with the callback value when it returns a truthy value

settled

Returns a promise that resolves when in a settled state (see isSettled for a definition of "settled state").

Returns Promise<void> resolves when settled

isSettled

Checks various settledness metrics (via getSettledState()) to determine if things are settled or not.

Settled generally means that there are no pending timers, no pending waiters, no pending AJAX requests, and no current run loop. However, new settledness metrics may be added and used as they become available.

Returns boolean true if settled, false otherwise

getSettledState

Check various settledness metrics, and return an object with the following properties:

  • hasRunLoop - Checks if a run-loop has been started. If it has, this will

be true otherwise it will be false.

  • hasPendingTimers - Checks if there are scheduled timers in the run-loop.

These pending timers are primarily registered by Ember.run.schedule. If there are pending timers, this will be true, otherwise false.

  • hasPendingWaiters - Checks if any registered test waiters are still

pending (e.g. the waiter returns true). If there are pending waiters, this will be true, otherwise false.

  • hasPendingRequests - Checks if there are pending AJAX requests (based on

ajaxSend / ajaxComplete events triggered by jQuery.ajax). If there are pending requests, this will be true, otherwise false.

  • hasPendingTransitions - Checks if there are pending route transitions. If the

router has not been instantiated / setup for the test yet this will return null, if there are pending transitions, this will be true, otherwise false.

  • pendingRequestCount - The count of pending AJAX requests.
  • debugInfo - Debug information that's combined with info return from backburner's

getDebugInfo method.

Returns Object object with properties for each of the metrics used to determine settledness

Pause Helpers

pauseTest

Returns a promise to be used to pauses the current test (due to being returned from the test itself). This is useful for debugging while testing or for test-driving. It allows you to inspect the state of your application at any point.

The test framework wrapper (e.g. ember-qunit or ember-mocha) should ensure that when pauseTest() is used, any framework specific test timeouts are disabled.

Examples

Usage via ember-qunit

import { setupRenderingTest } from 'ember-qunit';
import { render, click, pauseTest } from '@ember/test-helpers';


module('awesome-sauce', function(hooks) {
  setupRenderingTest(hooks);

  test('does something awesome', async function(assert) {
    await render(hbs`{{awesome-sauce}}`);

    // added here to visualize / interact with the DOM prior
    // to the interaction below
    await pauseTest();

    click('.some-selector');

    assert.equal(this.element.textContent, 'this sauce is awesome!');
  });
});

Returns Promise<void> resolves only when resumeTest() is invoked

resumeTest

Resumes a test previously paused by await pauseTest().

Debug Helpers

getDebugInfo

Retrieves debug information from backburner's current deferred actions queue (runloop instance). If the getDebugInfo method isn't available, it returns null.

Returns (MaybeDebugInfo | null) Backburner debugInfo or, if the getDebugInfo method is not present, null

registerDebugInfoHelper

Registers a custom debug info helper to augment the output for test isolation validation.

Parameters

  • debugHelper DebugInfoHelper a custom debug info helper

Examples

import { registerDebugInfoHelper } from '@ember/test-helpers';

registerDebugInfoHelper({
  name: 'Date override detection',
  log() {
    if (dateIsOverridden()) {
      console.log(this.name);
      console.log('The date object has been overridden');
    }
  }
})

Test Framework APIs

setResolver

Stores the provided resolver instance so that tests being ran can resolve objects in the same way as a normal application.

Used by setupContext and setupRenderingContext as a fallback when setApplication was not used.

Parameters

  • resolver Ember.Resolver the resolver to be used for testing

getResolver

Retrieve the resolver instance stored by setResolver.

Returns Ember.Resolver the previously stored resolver

setupContext

Used by test framework addons to setup the provided context for testing.

Responsible for:

  • sets the "global testing context" to the provided context (setContext)
  • create an owner object and set it on the provided context (e.g. this.owner)
  • setup this.set, this.setProperties, this.get, and this.getProperties to the provided context
  • setting up AJAX listeners
  • setting up pauseTest (also available as this.pauseTest()) and resumeTest helpers

Parameters

  • context Object the context to setup

  • options Object? options used to override defaults (optional, default {})

    • options.resolver Resolver? a resolver to use for customizing normal resolution

Returns Promise<Object> resolves with the context that was setup

getContext

Retrive the "global testing context" as stored by setContext.

Returns Object the previously stored testing context

setContext

Stores the provided context as the "global testing context".

Generally setup automatically by setupContext.

Parameters

  • context Object the context to use

unsetContext

Clear the "global testing context".

Generally invoked from teardownContext.

teardownContext

Used by test framework addons to tear down the provided context after testing is completed.

Responsible for:

  • un-setting the "global testing context" (unsetContext)
  • destroy the contexts owner object
  • remove AJAX listeners

Parameters

  • context Object the context to setup

  • options Object? options used to override defaults

    • options.waitForSettled boolean should the teardown wait for settled()ness (optional, default true)

Returns Promise<void> resolves when settled

setupRenderingContext

Used by test framework addons to setup the provided context for rendering.

setupContext must have been ran on the provided context prior to calling setupRenderingContext.

Responsible for:

  • Setup the basic framework used for rendering by the

render helper.

  • Ensuring the event dispatcher is properly setup.
  • Setting this.element to the root element of the testing

container (things rendered via render will go into this element).

Parameters

  • context Object the context to setup for rendering

Returns Promise<Object> resolves with the context that was setup

getApplication

Retrieve the application instance stored by setApplication.

Returns Ember.Application the previously stored application instance under test

setApplication

Stores the provided application instance so that tests being ran will be aware of the application under test.

  • Required by setupApplicationContext method.
  • Used by setupContext and setupRenderingContext when present.

Parameters

  • application Ember.Application the application that will be tested

setupApplicationContext

Used by test framework addons to setup the provided context for working with an application (e.g. routing).

setupContext must have been run on the provided context prior to calling setupApplicationContext.

Sets up the basic framework used by application tests.

Parameters

  • context Object the context to setup

Returns Promise<Object> resolves with the context that was setup

validateErrorHandler

Validate the provided error handler to confirm that it properly re-throws errors when Ember.testing is true.

This is intended to be used by test framework hosts (or other libraries) to ensure that Ember.onerror is properly configured. Without a check like this, Ember.onerror could easily swallow all errors and make it seem like everything is just fine (and have green tests) when in reality everything is on fire...

Parameters

  • callback Function the callback to validate (optional, default Ember.onerror)

Examples

Example implementation for ember-qunit

import { validateErrorHandler } from '@ember/test-helpers';

test('Ember.onerror is functioning properly', function(assert) {
  let result = validateErrorHandler();
  assert.ok(result.isValid, result.message);
});

Returns Object object with isValid and message

setupOnerror

Sets the Ember.onerror function for tests. This value is intended to be reset after each test to ensure correct test isolation. To reset, you should simply call setupOnerror without an onError argument.

Parameters

  • onError Function the onError function to be set on Ember.onerror

Examples

Example implementation for ember-qunit or ember-mocha

import { setupOnerror } from '@ember/test-helpers';

test('Ember.onerror is stubbed properly', function(assert) {
  setupOnerror(function(err) {
    assert.ok(err);
  });
});

resetOnerror

Resets Ember.onerror to the value it originally was at the start of the test run. If there is no context or cached value this is a no-op.

Examples

import { resetOnerror } from '@ember/test-helpers';

QUnit.testDone(function() {
  resetOnerror();
})

getTestMetadata

Gets the test metadata associated with the provided test context. Will create a new test metadata object if one does not exist.

Parameters

  • context BaseContext the context to use

Returns ITestMetadata the test metadata for the provided context

getDeprecations

Returns deprecations which have occured so far for a the current test context

Examples

Usage via ember-qunit

import { getDeprecations } from '@ember/test-helpers';

module('awesome-sauce', function(hooks) {
  setupRenderingTest(hooks);

  test('does something awesome', function(assert) {
const deprecations = getDeprecations() // => returns deprecations which have occured so far in this test
  });
});

Returns Array<DeprecationFailure> An array of deprecation messages

getDeprecationsDuringCallback

Returns deprecations which have occured so far for a the current test context

Parameters

  • callback CallableFunction? The callback that when executed will have its DeprecationFailure recorded

Examples

Usage via ember-qunit

import { getDeprecationsDuringCallback } from '@ember/test-helpers';

module('awesome-sauce', function(hooks) {
  setupRenderingTest(hooks);

  test('does something awesome', function(assert) {
    const deprecations = getDeprecationsDuringCallback(() => {
      // code that might emit some deprecations

    }); // => returns deprecations which occured while the callback was invoked
  });


  test('does something awesome', async function(assert) {
    const deprecations = await getDeprecationsDuringCallback(async () => {
      // awaited code that might emit some deprecations
    }); // => returns deprecations which occured while the callback was invoked
  });
});

Returns (Array<DeprecationFailure> | Promise<Array<DeprecationFailure>>) An array of deprecation messages

getWarnings

Returns warnings which have occured so far for a the current test context

Examples

Usage via ember-qunit

import { getWarnings } from '@ember/test-helpers';

module('awesome-sauce', function(hooks) {
  setupRenderingTest(hooks);

  test('does something awesome', function(assert) {
const warnings = getWarnings() // => returns warnings which have occured so far in this test
  });
});

Returns Array<Warning> An array of warnings

getWarningsDuringCallback

Returns warnings which have occured so far for a the current test context

Parameters

  • callback CallableFunction? The callback that when executed will have its warnings recorded

Examples

Usage via ember-qunit

import { getWarningsDuringCallback } from '@ember/test-helpers';
import { warn } from '@ember/debug';

module('awesome-sauce', function(hooks) {
  setupRenderingTest(hooks);

  test('does something awesome', function(assert) {
    const warnings = getWarningsDuringCallback(() => {
    warn('some warning');

    }); // => returns warnings which occured while the callback was invoked
  });

  test('does something awesome', async function(assert) {
    warn('some warning');

    const warnings = await getWarningsDuringCallback(async () => {
      warn('some other warning');
    }); // => returns warnings which occured while the callback was invoked
  });
});

Returns (Array<Warning> | Promise<Array<Warning>>) An array of warnings information