From d1109f3ce91f028761354ca2813590faa7f83cd3 Mon Sep 17 00:00:00 2001 From: Jay Gruber Date: Mon, 2 Dec 2019 17:35:40 -0800 Subject: [PATCH 1/6] added test cases. added is-maxlength-constrained helper. updated fill-in and type-in to use helper --- .../dom/-is-maxlength-constrained.ts | 15 ++++++++ .../@ember/test-helpers/dom/fill-in.ts | 12 ++++++- .../@ember/test-helpers/dom/type-in.ts | 15 ++++++-- tests/unit/dom/fill-in-test.js | 35 +++++++++++++++++++ tests/unit/dom/type-in-test.js | 22 ++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts diff --git a/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts b/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts new file mode 100644 index 000000000..8d855cf3d --- /dev/null +++ b/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts @@ -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)) + ); +} diff --git a/addon-test-support/@ember/test-helpers/dom/fill-in.ts b/addon-test-support/@ember/test-helpers/dom/fill-in.ts index 1e20fbde9..cbaffbcce 100644 --- a/addon-test-support/@ember/test-helpers/dom/fill-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/fill-in.ts @@ -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'; @@ -52,6 +53,16 @@ export default function fillIn(target: Target, text: string): Promise { __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); @@ -60,7 +71,6 @@ export default function fillIn(target: Target, text: string): Promise { } else { throw new Error('`fillIn` is only usable on form controls or contenteditable elements.'); } - fireEvent(element, 'input'); fireEvent(element, 'change'); diff --git a/addon-test-support/@ember/test-helpers/dom/type-in.ts b/addon-test-support/@ember/test-helpers/dom/type-in.ts index 113038f16..320e3c55c 100644 --- a/addon-test-support/@ember/test-helpers/dom/type-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/type-in.ts @@ -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'; @@ -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)); }; diff --git a/tests/unit/dom/fill-in-test.js b/tests/unit/dom/fill-in-test.js index 258e80fea..ff54e6476 100644 --- a/tests/unit/dom/fill-in-test.js +++ b/tests/unit/dom/fill-in-test.js @@ -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}]` + ); + }); }); diff --git a/tests/unit/dom/type-in-test.js b/tests/unit/dom/type-in-test.js index 6a821526d..4502ba25f 100644 --- a/tests/unit/dom/type-in-test.js +++ b/tests/unit/dom/type-in-test.js @@ -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}]` + ); + }); }); From daa6d28ee3703bce475d561fed5c0034e831f9ed Mon Sep 17 00:00:00 2001 From: Jay Gruber Date: Fri, 24 Apr 2020 18:11:08 -0700 Subject: [PATCH 2/6] changed fillIn to throw on exceeds maxlength. changed test --- .../test-helpers/dom/-is-maxlength-constrained.ts | 4 ++-- .../@ember/test-helpers/dom/fill-in.ts | 15 +++++---------- tests/unit/dom/fill-in-test.js | 10 +++------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts b/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts index 8d855cf3d..70b6a6410 100644 --- a/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts +++ b/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts @@ -3,11 +3,11 @@ @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) { +export default function isMaxLengthConstrained(element: Element): element is HTMLInputElement | HTMLTextAreaElement { // 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.maxLength && (element.tagName === 'TEXTAREA' || (element.tagName === 'INPUT' && constrainedInputTypes.indexOf((element as HTMLInputElement).type) > -1)) diff --git a/addon-test-support/@ember/test-helpers/dom/fill-in.ts b/addon-test-support/@ember/test-helpers/dom/fill-in.ts index cbaffbcce..792443ba2 100644 --- a/addon-test-support/@ember/test-helpers/dom/fill-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/fill-in.ts @@ -51,18 +51,13 @@ export default function fillIn(target: Target, text: string): Promise { throw new Error(`Can not \`fillIn\` readonly '${target}'.`); } - __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; + const maxlength = element.getAttribute('maxlength'); + if (isMaxLengthConstrained(element) && text && maxlength && text.length > maxlength) { + throw new Error(`Can not \`fillIn\` with text: '${text}' that exceeds maxlength: '${maxlength}'.`); } + __focus__(element); + element.value = text; } else if (isContentEditable(element)) { __focus__(element); diff --git a/tests/unit/dom/fill-in-test.js b/tests/unit/dom/fill-in-test.js index ff54e6476..c63cd5cfb 100644 --- a/tests/unit/dom/fill-in-test.js +++ b/tests/unit/dom/fill-in-test.js @@ -225,13 +225,9 @@ module('DOM Helper: fillIn', function (hooks) { await setupContext(context); - await fillIn(element, tooLongString); - - assert.verifySteps(clickSteps); - assert.equal( - element.value, - maxLengthString, - `fillIn respects input attribute [maxlength=${maxLengthString.length}]` + assert.rejects( + fillIn(element, tooLongString), + new Error("Can not `fillIn` with text: 'foo' that exceeds maxlength: '1'.") ); }); }); From a08253e7108b214f47d3f05937799dbbd21fadb6 Mon Sep 17 00:00:00 2001 From: Jay Gruber Date: Fri, 24 Apr 2020 19:13:04 -0700 Subject: [PATCH 3/6] lint fixes --- .../dom/-is-maxlength-constrained.ts | 6 ++-- .../@ember/test-helpers/dom/fill-in.ts | 6 ++-- .../@ember/test-helpers/dom/type-in.ts | 19 +++++++----- tests/unit/dom/fill-in-test.js | 4 +-- tests/unit/dom/type-in-test.js | 30 +++++++++++++------ 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts b/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts index 70b6a6410..b50ee128b 100644 --- a/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts +++ b/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts @@ -3,11 +3,13 @@ @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): element is HTMLInputElement | HTMLTextAreaElement { +export default function isMaxLengthConstrained( + element: Element +): element is HTMLInputElement | HTMLTextAreaElement { // ref: https://html.spec.whatwg.org/multipage/input.html#concept-input-apply const constrainedInputTypes = ['text', 'search', 'url', 'tel', 'email', 'password']; return ( - element.maxLength && + !!Number(element.getAttribute('maxLength')) && (element.tagName === 'TEXTAREA' || (element.tagName === 'INPUT' && constrainedInputTypes.indexOf((element as HTMLInputElement).type) > -1)) diff --git a/addon-test-support/@ember/test-helpers/dom/fill-in.ts b/addon-test-support/@ember/test-helpers/dom/fill-in.ts index 792443ba2..204c3f4ec 100644 --- a/addon-test-support/@ember/test-helpers/dom/fill-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/fill-in.ts @@ -52,8 +52,10 @@ export default function fillIn(target: Target, text: string): Promise { } const maxlength = element.getAttribute('maxlength'); - if (isMaxLengthConstrained(element) && text && maxlength && text.length > maxlength) { - throw new Error(`Can not \`fillIn\` with text: '${text}' that exceeds maxlength: '${maxlength}'.`); + if (isMaxLengthConstrained(element) && maxlength && text && text.length > Number(maxlength)) { + throw new Error( + `Can not \`fillIn\` with text: '${text}' that exceeds maxlength: '${maxlength}'.` + ); } __focus__(element); diff --git a/addon-test-support/@ember/test-helpers/dom/type-in.ts b/addon-test-support/@ember/test-helpers/dom/type-in.ts index 320e3c55c..2271114c7 100644 --- a/addon-test-support/@ember/test-helpers/dom/type-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/type-in.ts @@ -96,17 +96,20 @@ function keyEntry(element: FormControl, character: string): () => void { .then(() => __triggerKeyEvent__(element, 'keypress', characterKey, options)) .then(() => { const newValue = element.value + character; + const maxlength = element.getAttribute('maxlength'); 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'); + maxlength && + newValue && + newValue.length > Number(maxlength); + if (shouldTruncate) { + throw new Error( + `Can not \`typeIn\` with text: '${newValue}' that exceeds maxlength: '${maxlength}'.` + ); } + + element.value = newValue; + fireEvent(element, 'input'); }) .then(() => __triggerKeyEvent__(element, 'keyup', characterKey, options)); }; diff --git a/tests/unit/dom/fill-in-test.js b/tests/unit/dom/fill-in-test.js index c63cd5cfb..4371cdd13 100644 --- a/tests/unit/dom/fill-in-test.js +++ b/tests/unit/dom/fill-in-test.js @@ -200,7 +200,7 @@ module('DOM Helper: fillIn', function (hooks) { assert.equal(element.value, ''); }); - test('filling an input with a maxlength with suitable value', async function(assert) { + test('filling an input with a maxlength with suitable value', async function (assert) { element = buildInstrumentedElement('input'); const maxLengthString = 'f'; element.setAttribute('maxlength', maxLengthString.length); @@ -217,7 +217,7 @@ module('DOM Helper: fillIn', function (hooks) { ); }); - test('filling an input with a maxlength with too long value', async function(assert) { + 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'); diff --git a/tests/unit/dom/type-in-test.js b/tests/unit/dom/type-in-test.js index 4502ba25f..cba345e36 100644 --- a/tests/unit/dom/type-in-test.js +++ b/tests/unit/dom/type-in-test.js @@ -209,25 +209,37 @@ module('DOM Helper: typeIn', function (hooks) { assert.equal(runcount, 1, 'debounced function only called once'); }); - test('filling an input with a maxlength', async function(assert) { + test('typing in an input with a maxlength with suitable value', async function (assert) { element = buildInstrumentedElement('input'); - const maxLengthString = 'f'; - const tooLongString = maxLengthString.concat('oo'); + const maxLengthString = 'foo'; 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; - }); + await typeIn(element, maxLengthString); - assert.verifySteps(truncatedEvents); + assert.verifySteps(expectedEvents); assert.equal( element.value, maxLengthString, `typeIn respects input attribute [maxlength=${maxLengthString.length}]` ); }); + + test('typing in an input with a maxlength with too long value', async function (assert) { + element = buildInstrumentedElement('input'); + const maxLengthString = 'f'; + const tooLongString = maxLengthString.concat('o'); + element.setAttribute('maxlength', maxLengthString.length); + + await setupContext(context); + + await assert.rejects( + typeIn(element, tooLongString).finally(() => { + // should throw before the second input event + assert.verifySteps(expectedEvents.slice(0, 8)); + }), + new Error("Can not `typeIn` with text: 'fo' that exceeds maxlength: '1'.") + ); + }); }); From fe27abb8acfde02f0c8da03b5a435c462654bdb4 Mon Sep 17 00:00:00 2001 From: Jay Gruber Date: Mon, 4 May 2020 11:12:33 -0700 Subject: [PATCH 4/6] address PR comments --- .../dom/-is-maxlength-constrained.ts | 17 ----------------- .../@ember/test-helpers/dom/fill-in.ts | 9 ++------- .../@ember/test-helpers/dom/type-in.ts | 14 ++------------ 3 files changed, 4 insertions(+), 36 deletions(-) delete mode 100644 addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts diff --git a/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts b/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts deleted file mode 100644 index b50ee128b..000000000 --- a/addon-test-support/@ember/test-helpers/dom/-is-maxlength-constrained.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - @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 -): element is HTMLInputElement | HTMLTextAreaElement { - // ref: https://html.spec.whatwg.org/multipage/input.html#concept-input-apply - const constrainedInputTypes = ['text', 'search', 'url', 'tel', 'email', 'password']; - return ( - !!Number(element.getAttribute('maxLength')) && - (element.tagName === 'TEXTAREA' || - (element.tagName === 'INPUT' && - constrainedInputTypes.indexOf((element as HTMLInputElement).type) > -1)) - ); -} diff --git a/addon-test-support/@ember/test-helpers/dom/fill-in.ts b/addon-test-support/@ember/test-helpers/dom/fill-in.ts index 204c3f4ec..c7f031d0a 100644 --- a/addon-test-support/@ember/test-helpers/dom/fill-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/fill-in.ts @@ -1,6 +1,6 @@ import getElement from './-get-element'; import isFormControl from './-is-form-control'; -import isMaxLengthConstrained from './-is-maxlength-constrained'; +import guardForMaxlength from './-guard-for-maxlength'; import { __focus__ } from './focus'; import settled from '../settled'; import fireEvent from './fire-event'; @@ -51,12 +51,7 @@ export default function fillIn(target: Target, text: string): Promise { throw new Error(`Can not \`fillIn\` readonly '${target}'.`); } - const maxlength = element.getAttribute('maxlength'); - if (isMaxLengthConstrained(element) && maxlength && text && text.length > Number(maxlength)) { - throw new Error( - `Can not \`fillIn\` with text: '${text}' that exceeds maxlength: '${maxlength}'.` - ); - } + guardForMaxlength(element, text, 'fillIn'); __focus__(element); diff --git a/addon-test-support/@ember/test-helpers/dom/type-in.ts b/addon-test-support/@ember/test-helpers/dom/type-in.ts index 2271114c7..6a6e05039 100644 --- a/addon-test-support/@ember/test-helpers/dom/type-in.ts +++ b/addon-test-support/@ember/test-helpers/dom/type-in.ts @@ -5,7 +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 guardForMaxlength from './-guard-for-maxlength'; import Target from './-target'; import { __triggerKeyEvent__ } from './trigger-key-event'; import { log } from '@ember/test-helpers/dom/-logging'; @@ -96,17 +96,7 @@ function keyEntry(element: FormControl, character: string): () => void { .then(() => __triggerKeyEvent__(element, 'keypress', characterKey, options)) .then(() => { const newValue = element.value + character; - const maxlength = element.getAttribute('maxlength'); - const shouldTruncate = - isMaxLengthConstrained(element) && - maxlength && - newValue && - newValue.length > Number(maxlength); - if (shouldTruncate) { - throw new Error( - `Can not \`typeIn\` with text: '${newValue}' that exceeds maxlength: '${maxlength}'.` - ); - } + guardForMaxlength(element, newValue, 'typeIn'); element.value = newValue; fireEvent(element, 'input'); From d9d0d652daa0e5ce85a709c52f496b5e708924e2 Mon Sep 17 00:00:00 2001 From: Jay Gruber Date: Mon, 4 May 2020 11:16:30 -0700 Subject: [PATCH 5/6] forgot to git add. linted --- .../test-helpers/dom/-guard-for-maxlength.ts | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 addon-test-support/@ember/test-helpers/dom/-guard-for-maxlength.ts diff --git a/addon-test-support/@ember/test-helpers/dom/-guard-for-maxlength.ts b/addon-test-support/@ember/test-helpers/dom/-guard-for-maxlength.ts new file mode 100644 index 000000000..236c6e0a0 --- /dev/null +++ b/addon-test-support/@ember/test-helpers/dom/-guard-for-maxlength.ts @@ -0,0 +1,39 @@ +import { FormControl } from './-is-form-control'; + +// ref: https://html.spec.whatwg.org/multipage/input.html#concept-input-apply +const constrainedInputTypes = ['text', 'search', 'url', 'tel', 'email', 'password']; + +/** + @private + @param {Element} element - the element to check + @returns {boolean} `true` when the element should constrain input by the maxlength attribute, `false` otherwise +*/ +function isMaxLengthConstrained( + element: Element +): element is HTMLInputElement | HTMLTextAreaElement { + return ( + !!Number(element.getAttribute('maxLength')) && + (element instanceof HTMLInputElement || + (element instanceof HTMLTextAreaElement && constrainedInputTypes.indexOf(element.type) > -1)) + ); +} + +/** + * @private + * @param {Element} element - the element to check + * @param {string} text - the text being added to element + * @param {string} testHelper - the test helper context the guard is called from (for Error message) + * @throws if `element` has `maxlength` & `value` exceeds `maxlength` + */ +export default function guardForMaxlength( + element: FormControl, + text: string, + testHelper: string +): void { + const maxlength = element.getAttribute('maxlength'); + if (isMaxLengthConstrained(element) && maxlength && text && text.length > Number(maxlength)) { + throw new Error( + `Can not \`${testHelper}\` with text: '${text}' that exceeds maxlength: '${maxlength}'.` + ); + } +} From ba9b22e013d4418b269349b6425101dac9281978 Mon Sep 17 00:00:00 2001 From: Jay Gruber Date: Mon, 4 May 2020 11:25:32 -0700 Subject: [PATCH 6/6] should fix IE test --- tests/unit/dom/type-in-test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/dom/type-in-test.js b/tests/unit/dom/type-in-test.js index cba345e36..a8bad7537 100644 --- a/tests/unit/dom/type-in-test.js +++ b/tests/unit/dom/type-in-test.js @@ -236,8 +236,9 @@ module('DOM Helper: typeIn', function (hooks) { await assert.rejects( typeIn(element, tooLongString).finally(() => { - // should throw before the second input event - assert.verifySteps(expectedEvents.slice(0, 8)); + // should throw before the second input event (or second keyup for IE) + const expectedNumberOfSteps = isIE11 ? 6 : 8; + assert.verifySteps(expectedEvents.slice(0, expectedNumberOfSteps)); }), new Error("Can not `typeIn` with text: 'fo' that exceeds maxlength: '1'.") );