在 Ember 个组件测试中模拟用户输入
Simulating user input in Ember component tests
我正在尝试为模拟真实用户输入的 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 ...
}
}
});
所以我一直在使用 $('.js-input').val('some new value')
来模拟这个(推荐 here,在 "Interacting with Rendered Components" 下)。
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的原因更多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
。
我认为这是因为 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
}
}
我正在尝试为模拟真实用户输入的 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 ...
}
}
});
所以我一直在使用 $('.js-input').val('some new value')
来模拟这个(推荐 here,在 "Interacting with Rendered Components" 下)。
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的原因更多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
。
我认为这是因为 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
}
}