2016-07-19 4 views
1

Я пытаюсь написать тесты для компонента ember, который имитирует реальный пользовательский ввод. Например:Имитация пользовательского ввода в тестах компонентов Ember

<div> 
    <input class='js-input' type='text' value='{{ bar }}'> </input> 
    <button class='js-save' type='submit' {{action 'save'}}> 
</div> 

Мой компонент в настоящее время использует change и keyUp события для вычисления другого значения, основываясь на том, что поступил, а также для подтверждения ввода на лету:

import Ember from 'ember'; 

export default Ember.Component.extend({ 
    bar: null, 
    modelBar: null, 

    updateBar: Ember.on('change', 'keyUp', function() { 
    let bar = this.get('bar'); 
    if (bar.get('notValid')) { 
     bar = null; 
     this.set('bar', ''); 
    } 
    this.set('modelBar', bar); 
    }), 

    actions: { 
    save() { 
     ... save stuff ... 
    } 
    } 
}); 

Так я» ve использовал $('.js-input').val('some new value') для имитации этого (как рекомендовано here, в разделе «Взаимодействие с визуализированными компонентами»).

test('Updates a thing', function(assert) { 
    assert.expect(1); 

    const newState = 'a new state'; 

    this.set('actions.save', (newTaxes) => { 
    assert.ok(true, 'save has been called'); 
    assert.equal(newState, this.get('modelBar'), 'model is updated correctly'); 
    }); 

    this.set('bar', 'initial state'); 

    this.render(hbs` 
    {{my-component 
     baz=baz 
    }} 
    `); 

    this.$('.js-input').val(newState); 
    this.$('.js-input').trigger('change'); 

    this.$('.js-save').click();  
}); 

Однако, когда я запускаю тест, то change событие не получает обновленное значение для ввода с помощью this.get('bar') (хотя я могу видеть, если я использую this.$('js-input').val()). Если я добавлю наблюдателя, я вижу, что наблюдатель получает обновленное значение для свойства, но только после пользовательского события изменения.

Я пробовал обертывать вещи в циклах запуска Ember и run.next, и это тоже не помогло. Есть ли способ сделать эту работу, надеюсь, без необходимости возвращаться на наблюдателей? (Компонент ранее использовал наблюдателя, но некоторые новые требования усложнили ситуацию.)

+0

Я мог бы быть далеко, но я считаю, 'jQuery.sendKeys' (смотри пример в этом [скрипку] (http://jsfiddle.net/DxER9/)) плагин будет делайте то, что вы пытаетесь сделать. – MilkyWayJoe

+0

Интересно! Что-то, что я мог бы исследовать в будущие времена :) – Hannele

ответ

1

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

One: Закрепить проблема Jquery причины с более JQuery:

updateBar: Ember.on('change', 'keyUp', function() { 
    ... validate bar ... 
    this.set('modelBar', this.get('bar') || this.$('.js-input').val()); 
}), 

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

Два: Вернитесь к наблюдателю (вздох). Кажется, что хотя событие change не получает обновленное значение bar, наблюдатель делает это, но только после событие изменения.

observerBar: Ember.observer('bar', function() { 
    if (!this.get('suspendObserver')) { 
    this.set('suspendObserver', true); 
    this.updateBar(); 
    this.set('suspendObserver', false); 
    } 
}), 

семафора необходимо было в моем случае, потому что updateBar бы очистить bar если вход был недействителен.

1

Я считаю, это потому, что bar не привязан к элементу <input>. Поэтому, даже если вы звоните this.$('.js-input').val(newState), bar не изменится. Затем вызов this.$('.js-input').trigger('change') вызовет updateBar, но не получит ожидаемого результата.

Попробуйте это:

// template.hbs 
<input class='js-input' type='text' value={{bar}} onchange={{action "handleChange" value="target.value"}}> 

// component.js 
actions: { 
    handleChange(value) { 
    // Your logic here -- value is the new value of your input 
    } 
} 
+0

Я забыл добавить в свой ответ - если я добавлю Observer к компоненту, это _does_ получит обновленное значение после того, как событие изменения было запущено.Таким образом, кажется, что значение связано успешно, так же, как если бы мое событие изменения срабатывало перед событием изменения металла Ember, которое обновляло бы значение. – Hannele

Смежные вопросы