Skip to content

The perform helper crashes QUnit tests when the task fails or is cancelled #435

Closed
@lolmaus

Description

@lolmaus

The problem is that QUnit chooses to crash tests unconditionally on an unhandled rejected promise.

Say, I've got this basic setup:

  @dropTask
  @waitFor
  async _submitTask(): Promise<void> {
    return await this.product.save();
  }
  submitTask = taskFor(this._submitTask);
{{#if this.submitTask.isRunning}}
  Submitting...
{{else if this.subitTask.last.isError}}
  Something wrong happened:
  {{format-error this.submitTask.last.error}}
  <br>
  <button {{on "click" (perform this.submitTask)}}>Retry<button>
{{else}}
  <button {{on "click" (perform this.submitTask)}}>Submit<button>
{{/if}}

This is perfectly valid code: it adheres to Ember Concurrency guidelines and it works flawlessly in production.

The problem happens when I try to test the failed state:

    // ember-cli-mirage
    this.server.post('/products', { message: 'There was an error' }, 500);

    await click('button');

    assert.equal(
      find('.message').textContent.trim(),
      'Something wrong happened: "Ember Data Request POST /api/saved-configurations returned a 500'
    );

This is also a perfectly valid test, yet QUnit chooses to crash it because the promise generated by the perform helper has been rejected and not handled.

The workaround is to replace this:

  <button {{on "click" (perform this.submitTask)}}>Submit<button>

With this:

  <button {{on "click" this.submit}}>Submit<button>
  @action
  async submit(): Promise<void> {
    try {
      await this.submitTask.perform();
    } catch(e) {
      // We don't want tests to unconditionally crash when this happens.
      // The error will be handled by `submitTask.last.isError`
    }
  }

This is a huge bummer, because this runtime boilerplate is absolutely unnecessary for production and only exists to please QUnit.

I believe this is an issue with QUnit and has nothing to do with Ember Concurrency. Yet, @rwjblue has confirmed that this QUnit behavior is intended and that QUnit was deliberately modified to behave like that.

Given that this QUnit behavior is official, it basically renders the perform helper faulty as it would crash the tests for failed and cancelled EC tasks.

I would like to start a discussion regarding what can be done to mitigate this. E. g. can the perform helper internally catch the promise returned by the task?

CC @simonihmig

Metadata

Metadata

Assignees

Labels

feature-requestRequest for featurev2Applies to ember-concurrency v2

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions