Тест интеграции компонента Ember: ошибка inFlight при сохранении модели

Я пытаюсь протестировать компонент, обрабатывающий подписки на информационные бюллетени. Я хочу проверить, успешно ли сохранена функция submitForm, установив класс скрытого ввода соответственно после того, как сохранение произошло или не произошло, чтобы я мог подтвердить это в интеграционном тесте.

Вот мой код:

newletter.subscription.js:

import Ember from 'ember';

export default Ember.Component.extend({
  store: Ember.inject.service(),
  displayNotifications: Ember.inject.service(),

  didInsertElement() {
    this.set('model', this.get('store').createRecord('subscription'));
  },
  actions: {
    submitForm() {
      this.get('model').save().then(
        (json) => {
          this.get('displayNotifications').success({
            key: 'subscription.success',
          });
          this.set('model', this.get('store').createRecord('subscription'));
          this.set('subscribed', true);
        },
        (reason) => {
          this.set('subscribed', 'error');
        });
     }
   }
});

Вот код файла newsletter-subscription.hbs:

<div class="ui container row newsletter-form">
  <div class="ui inverted segment">
    <form class="ui form" {{action "submitForm" on="submit"}}>
      <div class="ui stackable grid">
        <div class="eleven wide right aligned column">
          {{input type='string' value=model.email  placeholder=(t 'subscription.email')}}
        </div>
        <div class="five wide inverted left aligned column">
          <button type="submit" class="ui fluid secondary button {{unless model.email 'disabled'}}">
            {{t 'button.newsletter'}}
          </button>
        </div>
        <input type='hidden' id="debug" class="{{subscribed}}" />
      </div>
    </form>
  </div>
</div>

А вот мой тест: newsletter-subscription-test.js

 moduleForComponent('newsletter-subscription', 'Integration | Component | newsletter-subscription', {
   integration: true
 });


 test('newsletter-subscription: submitting newsletter-subscription sets subscribed to true', function(assert){

    this.render(hbs`{{newsletter-subscription subscribed='notSubscribed'}}`);

    assert.equal(this.$('#debug').hasClass("notSubscribed"), true, 'before click, debug element has class notSubscribed');

    this.$('input[name=subscription-email]').val("[email protected]");
    this.$('button[type=submit]').click();

    return wait().then( () => {
      assert.equal(this.$('#debug').hasClass("subscribed"), true, "after callback of click ran, debug element has class subscribed");
    });

 });

Первое утверждение работает. Но затем я продолжаю получать сообщение об ошибке:

✘ Не удалось выполнить утверждение: выгрузить можно только запись, которая не находится в статусе inFlight.

Из анализа точек останова я обнаружил, что это происходит, когда вызывается this.get('model').save(). Мои попытки решить проблему до сих пор оставались неэффективными (например, имитация ответа сервера с помощью миража). Есть ли проблема с циклом запуска Ember в этом контексте, о которой мне как-то нужно позаботиться, или что-то другое?

Спасибо за ваш вклад!


person lifemod    schedule 29.09.2017    source источник


Ответы (1)


Сегодня я столкнулся с этой проблемой; основная проблема заключается в том, что, поскольку приложение не работает в интеграционных и модульных тестах, сохранение записей на самом деле не может работать. Есть два способа обойти это:

  1. (предпочтительно) Заглушите save() модели, которые вы передаете в свои компоненты, используя Sinon. Например,

    const record = new Ember.Object({ save: Sinon.spy(() => Ember.RSVP.resolve()) };
    this.render(hbs`
      {{your-component record=record}}
    `);
    
  2. Если вышеописанное не вариант - в моем случае, потому что запись создается в вашем компоненте, и вы не хотите извлекать это создание в переданный метод (что было бы более чистым вариантом), вы может переопределить поведение хранилища, чтобы сделать сохранения неактивными, переопределив store.scheduleSave (как описано в Келли Саттон, здесь):

    this.inject.service('store');
    
    this.store.scheduleSave = function(context, resolver) {
      resolver.resolve(context);
    };
    

Конечно, есть и другие способы обойти это, в том числе, конечно, просто перейти на приемочный тест, но два вышеупомянутых, вероятно, являются самыми быстрыми исправлениями.

person Robert Nubel    schedule 07.03.2018