diff --git a/__tests__/react/type.js b/__tests__/react/type.js index 048ec61a..a6dda71c 100644 --- a/__tests__/react/type.js +++ b/__tests__/react/type.js @@ -159,7 +159,7 @@ describe("userEvent.type", () => { ); it.each(["input", "textarea"])( - "should type text in <%s> up to maxLength if provided", + "should enter text in <%s> up to maxLength if provided", (type) => { const onChange = jest.fn(); const onKeyDown = jest.fn(); @@ -208,4 +208,58 @@ describe("userEvent.type", () => { expect(onKeyUp).not.toHaveBeenCalled(); } ); + + it.each(["input", "textarea"])( + "should append text in <%s> up to maxLength if provided", + (type) => { + const onChange = jest.fn(); + const onKeyDown = jest.fn(); + const onKeyPress = jest.fn(); + const onKeyUp = jest.fn(); + const maxLength = 10; + + const { getByTestId } = render( + React.createElement(type, { + "data-testid": "input", + onChange, + onKeyDown, + onKeyPress, + onKeyUp, + maxLength, + }) + ); + + const text1 = "superlong"; + const text2 = "text"; + const text = text1 + text2; + const slicedText = text.slice(0, maxLength); + + const inputEl = getByTestId("input"); + + userEvent.type(inputEl, text1); + userEvent.type(inputEl, text2); + + expect(inputEl).toHaveProperty("value", slicedText); + expect(onChange).toHaveBeenCalledTimes(slicedText.length); + expect(onKeyPress).toHaveBeenCalledTimes(text.length); + expect(onKeyDown).toHaveBeenCalledTimes(text.length); + expect(onKeyUp).toHaveBeenCalledTimes(text.length); + + inputEl.value = ""; + onChange.mockClear(); + onKeyPress.mockClear(); + onKeyDown.mockClear(); + onKeyUp.mockClear(); + + userEvent.type(inputEl, text, { + allAtOnce: true, + }); + + expect(inputEl).toHaveProperty("value", slicedText); + expect(onChange).toHaveBeenCalledTimes(1); + expect(onKeyPress).not.toHaveBeenCalled(); + expect(onKeyDown).not.toHaveBeenCalled(); + expect(onKeyUp).not.toHaveBeenCalled(); + } + ); }); diff --git a/__tests__/vue/type.js b/__tests__/vue/type.js index c7616934..1b28410e 100644 --- a/__tests__/vue/type.js +++ b/__tests__/vue/type.js @@ -147,7 +147,7 @@ describe("userEvent.type", () => { ); it.each(["input", "textarea"])( - "should type text in <%s> up to maxLength if provided", + "should enter text in <%s> up to maxLength if provided", (type) => { const input = jest.fn(); const keydown = jest.fn(); @@ -189,4 +189,52 @@ describe("userEvent.type", () => { expect(keyup).not.toHaveBeenCalled(); } ); + + it.each(["input", "textarea"])( + "should append text in <%s> up to maxLength if provided", + (type) => { + const input = jest.fn(); + const keydown = jest.fn(); + const keypress = jest.fn(); + const keyup = jest.fn(); + const maxLength = 10; + + const { getByTestId } = renderComponent( + type, + { input, keydown, keypress, keyup }, + { maxLength } + ); + + const text1 = "superlong"; + const text2 = "text"; + const text = text1 + text2; + const slicedText = text.slice(0, maxLength); + + const inputEl = getByTestId("input"); + + userEvent.type(inputEl, text1); + userEvent.type(inputEl, text2); + + expect(inputEl).toHaveProperty("value", slicedText); + expect(keydown).toHaveBeenCalledTimes(text.length); + expect(keypress).toHaveBeenCalledTimes(text.length); + expect(keyup).toHaveBeenCalledTimes(text.length); + + inputEl.value = ""; + input.mockClear(); + keydown.mockClear(); + keypress.mockClear(); + keyup.mockClear(); + + userEvent.type(inputEl, text, { + allAtOnce: true, + }); + + expect(inputEl).toHaveProperty("value", slicedText); + expect(input).toHaveBeenCalledTimes(1); + expect(keydown).not.toHaveBeenCalled(); + expect(keypress).not.toHaveBeenCalled(); + expect(keyup).not.toHaveBeenCalled(); + } + ); }); diff --git a/src/index.js b/src/index.js index 1c612444..60b8f2c0 100644 --- a/src/index.js +++ b/src/index.js @@ -236,11 +236,13 @@ const userEvent = { }; const opts = Object.assign(defaultOpts, userOpts); - const computedText = - element.maxLength > 0 ? text.slice(0, element.maxLength) : text; - const previousText = element.value; + const computedText = + element.maxLength > 0 + ? text.slice(0, Math.max(element.maxLength - previousText.length, 0)) + : text; + if (opts.allAtOnce) { if (element.readOnly) return; fireEvent.input(element, {