Skip to content

Commit

Permalink
added test cases. added is-maxlength-constrained helper. updated fill…
Browse files Browse the repository at this point in the history
…-in and type-in to use helper
  • Loading branch information
jaydgruber committed Apr 22, 2020
1 parent e5648ca commit d1109f3
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
@private
@param {Element} element the element to check
@returns {boolean} `true` when the element should constrain input by the maxlength attribute, `false` otherwise
*/
export default function isMaxLengthConstrained(element: Element) {
// ref: https://html.spec.whatwg.org/multipage/input.html#concept-input-apply
const constrainedInputTypes = ['text', 'search', 'url', 'tel', 'email', 'password'];
return (
element.hasAttribute('maxlength') &&
(element.tagName === 'TEXTAREA' ||
(element.tagName === 'INPUT' &&
constrainedInputTypes.indexOf((element as HTMLInputElement).type) > -1))
);
}
12 changes: 11 additions & 1 deletion addon-test-support/@ember/test-helpers/dom/fill-in.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import getElement from './-get-element';
import isFormControl from './-is-form-control';
import isMaxLengthConstrained from './-is-maxlength-constrained';
import { __focus__ } from './focus';
import settled from '../settled';
import fireEvent from './fire-event';
Expand Down Expand Up @@ -52,6 +53,16 @@ export default function fillIn(target: Target, text: string): Promise<void> {

__focus__(element);

// if (isMaxLengthConstrained(element) && text.length > element.getAttribute('maxlength'))
// throw
// remove else block
// should this be before the focus?
if (isMaxLengthConstrained(element)) {
element.value = text.slice(0, element.getAttribute('maxlength'));
} else {
element.value = text;
}

element.value = text;
} else if (isContentEditable(element)) {
__focus__(element);
Expand All @@ -60,7 +71,6 @@ export default function fillIn(target: Target, text: string): Promise<void> {
} else {
throw new Error('`fillIn` is only usable on form controls or contenteditable elements.');
}

fireEvent(element, 'input');
fireEvent(element, 'change');

Expand Down
15 changes: 13 additions & 2 deletions addon-test-support/@ember/test-helpers/dom/type-in.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import isFormControl, { FormControl } from './-is-form-control';
import { __focus__ } from './focus';
import { Promise } from 'rsvp';
import fireEvent from './fire-event';
import isMaxLengthConstrained from './-is-maxlength-constrained';
import Target from './-target';
import { __triggerKeyEvent__ } from './trigger-key-event';
import { log } from '@ember/test-helpers/dom/-logging';
Expand Down Expand Up @@ -94,8 +95,18 @@ function keyEntry(element: FormControl, character: string): () => void {
.then(() => __triggerKeyEvent__(element, 'keydown', characterKey, options))
.then(() => __triggerKeyEvent__(element, 'keypress', characterKey, options))
.then(() => {
element.value = element.value + character;
fireEvent(element, 'input');
const newValue = element.value + character;
const shouldTruncate =
isMaxLengthConstrained(element) &&
newValue.length > Number(element.getAttribute('maxlength'));
// if (shouldTruncate)
// throw
// else
// set value, fire input event
if (!shouldTruncate) {
element.value = newValue;
fireEvent(element, 'input');
}
})
.then(() => __triggerKeyEvent__(element, 'keyup', characterKey, options));
};
Expand Down
35 changes: 35 additions & 0 deletions tests/unit/dom/fill-in-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,39 @@ module('DOM Helper: fillIn', function (hooks) {
assert.strictEqual(document.activeElement, element, 'activeElement updated');
assert.equal(element.value, '');
});

test('filling an input with a maxlength with suitable value', async function(assert) {
element = buildInstrumentedElement('input');
const maxLengthString = 'f';
element.setAttribute('maxlength', maxLengthString.length);

await setupContext(context);

await fillIn(element, maxLengthString);

assert.verifySteps(clickSteps);
assert.equal(
element.value,
maxLengthString,
`fillIn respects input attribute [maxlength=${maxLengthString.length}]`
);
});

test('filling an input with a maxlength with too long value', async function(assert) {
element = buildInstrumentedElement('input');
const maxLengthString = 'f';
const tooLongString = maxLengthString.concat('oo');
element.setAttribute('maxlength', maxLengthString.length);

await setupContext(context);

await fillIn(element, tooLongString);

assert.verifySteps(clickSteps);
assert.equal(
element.value,
maxLengthString,
`fillIn respects input attribute [maxlength=${maxLengthString.length}]`
);
});
});
22 changes: 22 additions & 0 deletions tests/unit/dom/type-in-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,26 @@ module('DOM Helper: typeIn', function (hooks) {
assert.verifySteps(expectedEvents);
assert.equal(runcount, 1, 'debounced function only called once');
});

test('filling an input with a maxlength', async function(assert) {
element = buildInstrumentedElement('input');
const maxLengthString = 'f';
const tooLongString = maxLengthString.concat('oo');
element.setAttribute('maxlength', maxLengthString.length);

await setupContext(context);

await typeIn(`#${element.id}`, tooLongString);
// only the first 'input' event is fired since the input is truncated
const truncatedEvents = expectedEvents.filter((type, index) => {
return type !== 'input' || index === 4;
});

assert.verifySteps(truncatedEvents);
assert.equal(
element.value,
maxLengthString,
`typeIn respects input attribute [maxlength=${maxLengthString.length}]`
);
});
});

0 comments on commit d1109f3

Please sign in to comment.