Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 0 additions & 106 deletions src/__tests__/type.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,112 +255,6 @@ test('should delay the typing when opts.delay is not 0', async () => {
}
})

test('honors maxlength', () => {
const {element, getEventSnapshot} = setup('<input maxlength="2" />')
userEvent.type(element, '123')

// NOTE: no input event when typing "3"
expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: input[value="12"]

input[value=""] - pointerover
input[value=""] - pointerenter
input[value=""] - mouseover: Left (0)
input[value=""] - mouseenter: Left (0)
input[value=""] - pointermove
input[value=""] - mousemove: Left (0)
input[value=""] - pointerdown
input[value=""] - mousedown: Left (0)
input[value=""] - focus
input[value=""] - focusin
input[value=""] - pointerup
input[value=""] - mouseup: Left (0)
input[value=""] - click: Left (0)
input[value=""] - keydown: 1 (49)
input[value=""] - keypress: 1 (49)
input[value="1"] - input
"{CURSOR}" -> "1{CURSOR}"
input[value="1"] - keyup: 1 (49)
input[value="1"] - keydown: 2 (50)
input[value="1"] - keypress: 2 (50)
input[value="12"] - input
"1{CURSOR}" -> "12{CURSOR}"
input[value="12"] - keyup: 2 (50)
input[value="12"] - keydown: 3 (51)
input[value="12"] - keypress: 3 (51)
input[value="12"] - keyup: 3 (51)
`)
})

test('honors maxlength with existing text', () => {
const {element, getEventSnapshot} = setup(
'<input value="12" maxlength="2" />',
)
userEvent.type(element, '3')

// NOTE: no input event when typing "3"
expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: input[value="12"]

input[value="12"] - pointerover
input[value="12"] - pointerenter
input[value="12"] - mouseover: Left (0)
input[value="12"] - mouseenter: Left (0)
input[value="12"] - pointermove
input[value="12"] - mousemove: Left (0)
input[value="12"] - pointerdown
input[value="12"] - mousedown: Left (0)
input[value="12"] - focus
input[value="12"] - focusin
input[value="12"] - pointerup
input[value="12"] - mouseup: Left (0)
input[value="12"] - click: Left (0)
input[value="12"] - select
input[value="12"] - keydown: 3 (51)
input[value="12"] - keypress: 3 (51)
input[value="12"] - keyup: 3 (51)
`)
})

test('honors maxlength on textarea', () => {
const {element, getEventSnapshot} = setup(
'<textarea maxlength="2">12</textarea>',
)

userEvent.type(element, '3')

expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: textarea[value="12"]

textarea[value="12"] - pointerover
textarea[value="12"] - pointerenter
textarea[value="12"] - mouseover: Left (0)
textarea[value="12"] - mouseenter: Left (0)
textarea[value="12"] - pointermove
textarea[value="12"] - mousemove: Left (0)
textarea[value="12"] - pointerdown
textarea[value="12"] - mousedown: Left (0)
textarea[value="12"] - focus
textarea[value="12"] - focusin
textarea[value="12"] - pointerup
textarea[value="12"] - mouseup: Left (0)
textarea[value="12"] - click: Left (0)
textarea[value="12"] - select
textarea[value="12"] - keydown: 3 (51)
textarea[value="12"] - keypress: 3 (51)
textarea[value="12"] - keyup: 3 (51)
`)
})

// https://github.com/testing-library/user-event/issues/418
test('ignores maxlength on input[type=number]', () => {
const {element} = setup(`<input maxlength="2" type="number" value="12" />`)

userEvent.type(element, '3')

expect(element).toHaveValue(123)
})

test('should fire events on the currently focused element', () => {
const {element} = setup(`<div><input /><input /></div>`, {
eventHandlers: {keyDown: handleKeyDown},
Expand Down
148 changes: 148 additions & 0 deletions src/__tests__/utils/edit/calculateNewValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import userEvent from 'index'
import {setup} from '__tests__/helpers/utils'

// TODO: focus the maxlength tests on the tested aspects

test('honors maxlength', () => {
const {element, getEventSnapshot} = setup('<input maxlength="2" />')
userEvent.type(element as Element, '123')

// NOTE: no input event when typing "3"
expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: input[value="12"]

input[value=""] - pointerover
input[value=""] - pointerenter
input[value=""] - mouseover: Left (0)
input[value=""] - mouseenter: Left (0)
input[value=""] - pointermove
input[value=""] - mousemove: Left (0)
input[value=""] - pointerdown
input[value=""] - mousedown: Left (0)
input[value=""] - focus
input[value=""] - focusin
input[value=""] - pointerup
input[value=""] - mouseup: Left (0)
input[value=""] - click: Left (0)
input[value=""] - keydown: 1 (49)
input[value=""] - keypress: 1 (49)
input[value="1"] - input
"{CURSOR}" -> "1{CURSOR}"
input[value="1"] - keyup: 1 (49)
input[value="1"] - keydown: 2 (50)
input[value="1"] - keypress: 2 (50)
input[value="12"] - input
"1{CURSOR}" -> "12{CURSOR}"
input[value="12"] - keyup: 2 (50)
input[value="12"] - keydown: 3 (51)
input[value="12"] - keypress: 3 (51)
input[value="12"] - keyup: 3 (51)
`)
})

test('honors maxlength="" as if there was no maxlength', () => {
const {element, getEventSnapshot} = setup('<input maxlength="" />')
userEvent.type(element as Element, '123')

expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: input[value="123"]

input[value=""] - pointerover
input[value=""] - pointerenter
input[value=""] - mouseover: Left (0)
input[value=""] - mouseenter: Left (0)
input[value=""] - pointermove
input[value=""] - mousemove: Left (0)
input[value=""] - pointerdown
input[value=""] - mousedown: Left (0)
input[value=""] - focus
input[value=""] - focusin
input[value=""] - pointerup
input[value=""] - mouseup: Left (0)
input[value=""] - click: Left (0)
input[value=""] - keydown: 1 (49)
input[value=""] - keypress: 1 (49)
input[value="1"] - input
"{CURSOR}" -> "1{CURSOR}"
input[value="1"] - keyup: 1 (49)
input[value="1"] - keydown: 2 (50)
input[value="1"] - keypress: 2 (50)
input[value="12"] - input
"1{CURSOR}" -> "12{CURSOR}"
input[value="12"] - keyup: 2 (50)
input[value="12"] - keydown: 3 (51)
input[value="12"] - keypress: 3 (51)
input[value="123"] - input
"12{CURSOR}" -> "123{CURSOR}"
input[value="123"] - keyup: 3 (51)
`)
})

test('honors maxlength with existing text', () => {
const {element, getEventSnapshot} = setup(
'<input value="12" maxlength="2" />',
)
userEvent.type(element as Element, '3')

// NOTE: no input event when typing "3"
expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: input[value="12"]

input[value="12"] - pointerover
input[value="12"] - pointerenter
input[value="12"] - mouseover: Left (0)
input[value="12"] - mouseenter: Left (0)
input[value="12"] - pointermove
input[value="12"] - mousemove: Left (0)
input[value="12"] - pointerdown
input[value="12"] - mousedown: Left (0)
input[value="12"] - focus
input[value="12"] - focusin
input[value="12"] - pointerup
input[value="12"] - mouseup: Left (0)
input[value="12"] - click: Left (0)
input[value="12"] - select
input[value="12"] - keydown: 3 (51)
input[value="12"] - keypress: 3 (51)
input[value="12"] - keyup: 3 (51)
`)
})

test('honors maxlength on textarea', () => {
const {element, getEventSnapshot} = setup(
'<textarea maxlength="2">12</textarea>',
)

userEvent.type(element as Element, '3')

expect(getEventSnapshot()).toMatchInlineSnapshot(`
Events fired on: textarea[value="12"]

textarea[value="12"] - pointerover
textarea[value="12"] - pointerenter
textarea[value="12"] - mouseover: Left (0)
textarea[value="12"] - mouseenter: Left (0)
textarea[value="12"] - pointermove
textarea[value="12"] - mousemove: Left (0)
textarea[value="12"] - pointerdown
textarea[value="12"] - mousedown: Left (0)
textarea[value="12"] - focus
textarea[value="12"] - focusin
textarea[value="12"] - pointerup
textarea[value="12"] - mouseup: Left (0)
textarea[value="12"] - click: Left (0)
textarea[value="12"] - select
textarea[value="12"] - keydown: 3 (51)
textarea[value="12"] - keypress: 3 (51)
textarea[value="12"] - keyup: 3 (51)
`)
})

// https://github.com/testing-library/user-event/issues/418
test('ignores maxlength on input[type=number]', () => {
const {element} = setup(`<input maxlength="2" type="number" value="12" />`)

userEvent.type(element as Element, '3')

expect(element).toHaveValue(123)
})
20 changes: 15 additions & 5 deletions src/utils/edit/calculateNewValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ export function calculateNewValue(
} {
const {selectionStart, selectionEnd} = selectionRange

// can't use .maxLength property because of a jsdom bug:
// https://github.com/jsdom/jsdom/issues/2927
const maxLength = Number(element.getAttribute('maxlength') ?? -1)

let newValue: string, newSelectionStart: number

if (selectionStart === null) {
Expand Down Expand Up @@ -72,7 +68,11 @@ export function calculateNewValue(
}
}

if (!supportsMaxLength(element) || maxLength < 0) {
// can't use .maxLength property because of a jsdom bug:
// https://github.com/jsdom/jsdom/issues/2927
const maxLength = getSanitizedMaxLength(element)

if (maxLength === undefined) {
return {
newValue,
newSelectionStart,
Expand All @@ -86,6 +86,16 @@ export function calculateNewValue(
}
}

function getSanitizedMaxLength(element: Element) {
if (!supportsMaxLength(element)) {
return undefined
}

const attr = element.getAttribute('maxlength') ?? ''

return /^\d+$/.test(attr) && Number(attr) >= 0 ? Number(attr) : undefined
}

function supportsMaxLength(element: Element) {
if (element.tagName === 'TEXTAREA') return true

Expand Down