Вот простой компонент:
App.FooBarComponent = Ember.Component.extend({
tagName: "button",
status: "Ready",
revertStatusPeriodMs: 2000,
click: function() {
this.set('status', 'Pending');
// A fake ajax
this.run()
.then( function() {
this.updateStatus('Finished');
}.bind(this))
.catch( function() {
this.updateStatus('Error');
}.bind(this));
},
run: function() {
return new Ember.RSVP.Promise( function(resolve) {
Ember.run.later( function() {
resolve();
}, 500);
});
},
updateStatus: function(statusText) {
this.set('status', statusText);
var periodMs = this.get('revertStatusPeriodMs') || 1000;
Ember.run.later( function() {
this.set('status', 'Ready');
}.bind(this), periodMs);
}
});
Он делает простую вещь: при нажатии на него отображается текст. Позже заменяет текст другим. Еще позже он возвращает текст к исходному.
Код работает нормально. Моя проблема в том, что я не могу написать для него тест.
test('clicking the button should set the label', function(assert) {
expect(4);
visit('/');
assert.equal( find('button').text().trim(), 'Ready', 'Should initially be "Ready"');
andThen(function() {
click('button');
assert.equal( find('button').text().trim(), 'Pending', 'Should "Pending" right after click');
});
// This one fires too late!
andThen(function() {
assert.equal( find('button').text().trim(), 'Finished', 'Should become "Finished" after promise fulfills');
});
andThen(function() {
assert.equal( find('button').text().trim(), 'Ready', 'Should eventually return to the "Ready" state');
});
});
У меня две проблемы:
Я не могу проверить состояние
Finished
. Кажется, чтоandThen
ждет завершения всех обещаний иrun.later
, а я хочу проверить промежуточное состояние. Как запустить утверждение между двумя последовательными обещаниями/run.later
?Времена могут быть долгими, а тесты могут длиться целую вечность. Обычно я не возражаю против рефакторинга кода для лучшей тестируемости, но я отказываюсь корректировать время в приложении в зависимости от среды (например, 2000 для dev/prod, 0 для теста). Вместо этого я хотел бы использовать макет таймера или какое-либо другое решение.
Я пробовал Sinon и потерпел неудачу: когда я издеваюсь над таймером,
andThen
никогда не возвращается. Ни одно из этих решений не помогло мне.
JSBin: http://emberjs.jsbin.com/fohava/2/edit?html,js,output (Sinon включен)
andThen
используетassert.async
. Что до остального, то я и так уже знал. Но спасибо, что вмешался, Барни. 10.03.2015