import { RenderingTest, moduleFor } from '../utils/test-case';
import { set } from 'ember-metal';
moduleFor(
'Input element tests',
class extends RenderingTest {
runAttributeTest(attributeName, values) {
let template = ``;
this.render(template, { value: values[0] });
this.assertAttributeHasValue(
attributeName,
values[0],
`${attributeName} is set on initial render`
);
this.runTask(() => this.rerender());
this.assertAttributeHasValue(
attributeName,
values[0],
`${attributeName} is set on noop rerender`
);
this.setComponentValue(values[1]);
this.assertAttributeHasValue(attributeName, values[1], `${attributeName} is set on rerender`);
this.setComponentValue(values[0]);
this.assertAttributeHasValue(
attributeName,
values[0],
`${attributeName} can be set back to the initial value`
);
}
runPropertyTest(propertyName, values) {
let attributeName = propertyName;
let template = ``;
this.render(template, { value: values[0] });
this.assertPropertyHasValue(
propertyName,
values[0],
`${propertyName} is set on initial render`
);
this.runTask(() => this.rerender());
this.assertPropertyHasValue(
propertyName,
values[0],
`${propertyName} is set on noop rerender`
);
this.setComponentValue(values[1]);
this.assertPropertyHasValue(propertyName, values[1], `${propertyName} is set on rerender`);
this.setComponentValue(values[0]);
this.assertPropertyHasValue(
propertyName,
values[0],
`${propertyName} can be set back to the initial value`
);
}
runFalsyValueProperty(values) {
let value = 'value';
let template = ``;
this.render(template, { value: values[0] });
this.assertPropertyHasValue(value, '', `${value} is set on initial render`);
this.runTask(() => this.rerender());
this.assertPropertyHasValue(value, '', `${value} is set on noop rerender`);
this.setComponentValue(values[1]);
this.assertPropertyHasValue(value, values[1], `${value} is set on rerender`);
this.setComponentValue(values[0]);
this.assertPropertyHasValue(value, '', `${value} can be set back to the initial value`);
}
['@test input disabled attribute']() {
let model = { model: { value: false } };
this.render(``, model);
this.assert.equal(this.$inputElement().prop('disabled'), false);
this.runTask(() => this.rerender());
this.assert.equal(this.$inputElement().prop('disabled'), false);
this.runTask(() => this.context.set('model.value', true));
this.assert.equal(this.$inputElement().prop('disabled'), true);
this.assertHTML(''); // Note the DOM output is
this.runTask(() => this.context.set('model.value', 'wat'));
this.assert.equal(this.$inputElement().prop('disabled'), true);
this.assertHTML(''); // Note the DOM output is
this.runTask(() => this.context.set('model', { value: false }));
this.assert.equal(this.$inputElement().prop('disabled'), false);
this.assertHTML('');
}
['@test input value attribute']() {
this.runPropertyTest('value', ['foo', 'bar']);
}
['@test input placeholder attribute']() {
this.runAttributeTest('placeholder', ['foo', 'bar']);
}
['@test input name attribute']() {
this.runAttributeTest('name', ['nam', 'name']);
}
['@test input maxlength attribute']() {
this.runAttributeTest('maxlength', [2, 3]);
}
['@test input size attribute']() {
this.runAttributeTest('size', [2, 3]);
}
['@test input tabindex attribute']() {
this.runAttributeTest('tabindex', [2, 3]);
}
['@test null input value']() {
this.runFalsyValueProperty([null, 'hello']);
}
['@test undefined input value']() {
this.runFalsyValueProperty([undefined, 'hello']);
}
['@test undefined `toString` method as input value']() {
this.runFalsyValueProperty([Object.create(null), 'hello']);
}
['@test cursor position is not lost when updating content']() {
let template = ``;
this.render(template, { value: 'hola' });
this.setDOMValue('hello');
this.setSelectionRange(1, 3);
this.setComponentValue('hello');
this.assertSelectionRange(1, 3);
// Note: We should eventually get around to testing reseting, however
// browsers handle `selectionStart` and `selectionEnd` differently
// when are synthetically testing movement of the cursor.
}
['@test input can be updated multiple times']() {
let template = ``;
this.render(template, { value: 'hola' });
this.assertValue('hola', 'Value is initialised');
this.setComponentValue('');
this.assertValue('', 'Value is set in the DOM');
this.setDOMValue('hola');
this.setComponentValue('hola');
this.assertValue('hola', 'Value is updated the first time');
this.setComponentValue('');
this.assertValue('', 'Value is updated the second time');
}
['@test DOM is SSOT if value is set']() {
let template = ``;
this.render(template, { value: 'hola' });
this.assertValue('hola', 'Value is initialised');
this.setComponentValue('hello');
this.assertValue('hello', 'Value is initialised');
this.setDOMValue('hola');
this.assertValue('hola', 'DOM is used');
this.setComponentValue('bye');
this.assertValue('bye', 'Value is used');
// Simulates setting the input to the same value as it already is which won't cause a rerender
this.setDOMValue('hola');
this.assertValue('hola', 'DOM is used');
this.setComponentValue('hola');
this.assertValue('hola', 'Value is used');
}
// private helpers and assertions
setDOMValue(value) {
this.inputElement().value = value;
}
setComponentValue(value) {
this.runTask(() => set(this.context, 'value', value));
}
setSelectionRange(start, end) {
this.inputElement().selectionStart = start;
this.inputElement().selectionEnd = end;
}
inputElement() {
return this.$inputElement()[0];
}
$inputElement() {
return this.$('input');
}
assertValue(value, message) {
this.assertPropertyHasValue('value', value, message);
}
assertAttributeHasValue(attribute, value, message) {
this.assert.equal(this.$inputElement().attr(attribute), value, `${attribute} ${message}`);
}
assertPropertyHasValue(property, value, message) {
this.assert.equal(this.$inputElement().prop(property), value, `${property} ${message}`);
}
assertSelectionRange(start, end) {
this.assert.equal(this.inputElement().selectionStart, start);
this.assert.equal(this.inputElement().selectionEnd, end);
}
}
);