【问题标题】:Simulating user input in Ember component tests在 Ember 组件测试中模拟用户输入
【发布时间】:2016-07-19 16:19:03
【问题描述】:

我正在尝试为模拟真实用户输入的 ember 组件编写测试。例如:

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

我的组件目前使用changekeyUp 事件根据输入的内容计算另一个值,并即时验证输入:

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 ...
    }
  }
});

所以我一直在使用$('.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 循环中包装东西,但这也没有帮助。有没有办法让这项工作,希望不需要依靠观察者? (该组件之前使用了观察者,但一些新的要求使事情变得更加复杂。)

【问题讨论】:

  • 我可能会走得很远,但我相信jQuery.sendKeys(请参阅此fiddle 中的示例)插件会做你想做的事情。
  • 有趣!我将来可能会探索的东西:)

标签: jquery ember.js qunit


【解决方案1】:

我相信这是因为bar 没有与&lt;input&gt; 元素绑定。所以即使你调用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
  }
}

【讨论】:

  • 我忘了在答案中添加 - 如果我向组件添加一个观察者,这 确实 在更改事件触发后获取更新的值。所以看起来值绑定成功了,就好像我的更改事件在 Ember 金属更改事件会更新值之前触发一样。
【解决方案2】:

我找到了几种解决此问题的方法,具体取决于您的舒适程度。不幸的是,它们都没有简单地改变测试本身,所以我仍然很高兴听到有人有更好的解决方案。

一:用更多的jquery修复jquery引起的问题:

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

我对此表示同意,因为它应该仅用于测试目的。你可以担心bar 有一个以前的值,但在我的情况下,它总是从空变为一个值,所以|| 是一个足够的指标。

二:回到观察者(叹气)。看起来虽然change事件没有得到bar的更新值,但是观察者得到了,但只是 change事件之后。

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

在我的情况下,信号量是必要的,因为如果输入无效,updateBar 会清除 bar

【讨论】:

    猜你喜欢
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 2017-03-18
    相关资源
    最近更新 更多