npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ember-concurrency-test-waiter

v0.4.0

Published

An easy way to make async test helpers wait for running tasks to complete.

Downloads

1,317

Readme

ember-concurrency-test-waiter

Easily instrument your ember-concurrency tasks to cause @ember/test-helpers' settled() method to wait for any running instances of those tasks to complete before proceeding.

Motivation

Ember's async-aware test infrastructure will wait for several specific types of asynchronous operations (currently route transitions, AJAX requests and run loop actions/timers), but has no easy centralized way of tracking other asynchronous operations, such as waiting for callbacks from the FileReader API, waiting for an image to load in an <img> tag, etc.

ember-concurrency provides a very nice mechanism for wrapping these (and any other) asynchronous operations into tasks, and this addon adds support for easily telling the Ember testing framework to treat running instances of certain tasks as test-blocking asynchronous operations.

Installation

ember install ember-concurrency-test-waiter

Usage

Import ember-concurrency-test-waiter's withTestWaiter method into your application code and then use it to wrap any tasks that you want to block asynchronous test helpers:

// components/my-component.js
import Component from '@ember/component';
import { task } from 'ember-concurrency';
import withTestWaiter from 'ember-concurrency-test-waiter/with-test-waiter';
import doSomethingAsync from '../utils/do-something-async';

export default Component.extend({
  myTask: withTestWaiter(task(function*() {
    return yield doSomethingAsync();
  }))
});

Alternatively, you can call ember-concurrency-test-waiter's defineModifier method somewhere early in the boot process, such as app.js or an initializer, and then use it as a task modifier:

// app.js
import defineModifier from 'ember-concurrency-test-waiter/define-modifier';

defineModifier();

// remainder of app.js...
// components/my-component.js
import Component from '@ember/component';
import { task } from 'ember-concurrency';
import doSomethingAsync from '../utils/do-something-async';

export default Component.extend({
  myTask: task(function*() {
    return yield doSomethingAsync();
  }).withTestWaiter()
});

If you're using @task decorator provided by ember-concurrency-decorators, then use the task modifier like this:

// app.js
import defineModifier from 'ember-concurrency-test-waiter/define-modifier';

defineModifier();

// remainder of app.js...
// components/my-component.js
import Component from '@ember/component';
import { task } from 'ember-concurrency-decorators';
import doSomethingAsync from '../utils/do-something-async';

export default class MyComponent extends Component {
  @task({
    withTestWaiter: true
  })
  myTask = function*() {
    return yield doSomethingAsync();
  }
}

TypeScript

To use withTestWaiter: true in the task decorator with TypeScript, you will need to import the types for ember-concurrency-test-waiter. This can be done in types/<app-name>/index.d.ts:

// types/<app-name>/index.d.ts

import 'ember-concurrency-test-waiter';

Why?

Here is a full example if how this addon could be useful to you. Suppose you want to test a component that is handed the URL of an image and displays its dimensions. Your component needs to load the image into an <img> tag and wait for a callback indicating that it's loaded so the dimensions can be read. But in your unit test, there's no good way to wait for that load to complete other than polling on a timer or something. Use ember-concurrency-test-waiter!

// app/app.js
import defineModifier from 'ember-concurrency-test-waiter/define-modifier';

defineModifier();

// remainder of app.js...
// app/components/image-size.js

import Component from '@ember/component';
import { Promise } from 'rsvp';
import { run } from '@ember/runloop';
import { task } from 'ember-concurrency';

export default Component.extend({
  src: null,
  dimensions: null,

  init() {
    this._super(...arguments);
    this.computeDimensions.perform(this.src);
  },

  computeDimensions: task(function*(src) {
    let { width, height } = yield new Promise((resolve, reject) => {
      let image = new Image();
      image.addEventListener('load', () => resolve(img));
      image.addEventListener('error', reject);
      image.src = src;
    });
    this.set('dimensions', { width, height });
  }).restartable().withTestWaiter()
});
{{! app/templates/components/image-size.hbs }}
{{#if this.dimensions}}
  dimensions: {{this.dimensions.width}}x{{this.dimensions.height}}
{{else}}
  loading...
{{/if}}
// tests/integration/components/image-size.js

import { A } from '@ember/array';
import { run } from '@ember/runloop';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit'
import hbs from 'htmlbars-inline-precompile';
import { render, settled } from '@ember/test-helpers';

module('image-size', 'Integration | Component | image-size', function(hooks) {
  setupRenderingTest(hooks);

  test('it works', async function(assert) {
    assert.expect(2);

    await render(hbs`<ImageSize @src="assets/test-image.jpg"/>`);
    // render() awaits settled(), which will now wait for computeDimensions
    // to complete before resolving
    assert.dom(this.element).hasText("200x350");
  });
});

Using the older test API

The mechanism that ember-concurrency-test-waiter uses to hook into the settled method also works for the old test framework -- moduleForAcceptance tests will automatically wait for withTestWaiter() tasks, and in unit tests (moduleForComponent, etc.), the wait() method (imported from ember-test-helpers) will wait for withTestWaiter() tasks.