javascript - 使用 Ember (cli) 如何获得验收测试以等待 promise ?

标签 javascript ember.js

在我的 Ember 应用程序中,我目前有一个具有 findResults 函数的模型,该函数返回一个 promise ,该 promise 包装了一个 Google Places 库以获取自动完成的结果。为了在我的 UI 中使用它,我设置了一个 PromiseMixin Controller 。我指示 Controller 观察 searchText 值,当它发生变化时,我将 Controller 的 promise 值更新为 findResults 函数返回的 promise ,但新值来自搜索文本。当我在浏览器中使用应用程序时,这很好用,但是当我运行我的验收测试时,测试似乎在 promise 返回之前完成,因此测试失败。我将在下面包含相关文件。

我不确定如何告诉 Ember 在测试期间等待 promise 解决。

app/services/google-autocomplete-location.js

import Ember from "ember";

var googleAutocompleteLocation = Ember.Object.extend({
  placeId: null,
  description: null
});

googleAutocompleteLocation.reopenClass({
  findResults: function(query) {
    var self = this;
    var promise = new Ember.RSVP.Promise(function(resolve, reject) {
      var autocompleteService = new google.maps.places.AutocompleteService();

      return autocompleteService.getPlacePredictions({ input: query },
        function(predictions, status) {
          if (status !== google.maps.places.PlacesServiceStatus.OK) {
            Ember.run(null, reject, status);
          }
          else {
            Ember.run(null, resolve, self._decorateGoogleResults(predictions));
          }
        });
    });

    return promise;
  },

  _decorateGoogleResults: function(predictions) {
    var locations = [];

    predictions.forEach(function(prediction) {
      locations.push(
        googleAutocompleteLocation.create({
          placeId: prediction.place_id,
          description: prediction.description
        })
      );
    });


    return locations;
   }
});

export default googleAutocompleteLocation;

app/controllers/index.js

import Ember from "ember";
import GoogleLocation from "../services/google-location";
import GoogleAutocompleteLocation from '../services/google-autocomplete-location';

export default Ember.ArrayController.extend(Ember.PromiseProxyMixin, {
  searchText: '',
  map: null,
  mapUrl: null,

  actions: {
    submit: function() {
      return this.transitionToRoute('entries.new');
    }
  },

  highlightedResult: function() {
    if (this.get('model').length) {
      return this.get('model')[0];
    } else {
      return null;
    }
  }.property('model'),

  setMap: (function() {
    if (this.get('highlightedResult') === null) {
      return this.set('map', null);
    } else {
      if (this.get('map') === null) {
        return this.set('map', GoogleLocation.create({
          mapContainer: Ember.$('.maps-info'),
          placeId: this.get('highlightedResult').placeId
        }));
      } else {
        return this.get('map').set('placeId', this.get('highlightedResult').placeId);
      }
    }
  }).observes('highlightedResult'),

  searchTextChanged: (function() {
    if (this.get('searchText').length) {
      this.set('promise',
        GoogleAutocompleteLocation.findResults(this.get('searchText')));
      console.log(this.get('promise'));
    } else {
      this.set('model', []);
    }
  }).observes('searchText')
});

tests/acceptance/create-new-entry-test.js

test('finding a location', function() {
  expect(1);
  visit('/');
  click('.location-input input');
  fillIn('.location-input input', "Los Angeles, CA");

  andThen(function() {
    var searchResult = find('.search-results ul li:first a').text();

    equal(searchResult, 'Los Angeles, CA, United States');
  });
});

最佳答案

解决此问题的最佳方法可能是注册您自己的异步测试助手。我已经准备了一个 JSBin,其中包含您的代码模拟和解决方案:http://jsbin.com/ziceratana/3/edit?html,js,output

用于创建助手的代码是这样的:

Ember.Test.registerAsyncHelper('waitForControllerWithPromise', function(app, controllerName) {
  return new Ember.Test.promise(function(resolve) {

    // inform the test framework that there is an async operation in progress,
    // so it shouldn't consider the test complete
    Ember.Test.adapter.asyncStart();

    // get a handle to the promise we want to wait on
    var controller = app.__container__.lookup('controller:' + controllerName);
    var promise = controller.get('promise');

    promise.then(function(){

      // wait until the afterRender queue to resolve this promise,
      // to give any side effects of the promise resolving a chance to
      // occur and settle
      Ember.run.schedule('afterRender', null, resolve);

      // inform the test framework that this async operation is complete
      Ember.Test.adapter.asyncEnd();
    });
  });
});

它会像这样使用:

test('visiting / and searching', function() {
  expect(1);
  visit('/');
  click('.location-input input');
  fillIn('.location-input input', "Los Angeles, CA");
  waitForControllerWithPromise('index'); // <-- simple & elegant!
  andThen(function(){
    var searchResult = find('.search-results ul li:first').text();
    equal(searchResult, 'Los Angeles, CA, United States');
  });
});

在 ember-testing 中,async-helper 会自动等待之前的 promise,随后的 async helper 会在测试执行时等待它。有关这方面的优秀背景,请参阅 Cory Forsyth 的 Demystifying Async Testing

关于javascript - 使用 Ember (cli) 如何获得验收测试以等待 promise ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26498845/

相关文章:

javascript - 在 jquery 中解析 JSON 返回未定义

javascript多个对象实例相同的时间戳

ember.js - ember-data 作为 d3 的数据

php - 带有 PHP 的 Ember.js

javascript - Ember.js 中带有普通 anchor 标记的动态 linkTo

ember.js - HtmlBars 中的条件类

javascript - VueJS 中的 props 和 v-bind 问题

javascript - 网络连接更改的事件监听器

javascript - 将事件位置映射到非文本字段中的文本位置

ember.js - EmberJS 的可重用组件/ View