Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ced7046

Browse files
fix: type should not type in readonly or disabled fields (testing-library#51)
1 parent ce4416f commit ced7046

File tree

2 files changed

+94
-27
lines changed

2 files changed

+94
-27
lines changed

‎projects/testing-library/src/lib/user-events/type.ts‎

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,18 @@ export function createType(fireEvent: FireFunction & FireObject) {
3838

3939
return async function type(element: HTMLElement, value: string | number, options?: TypeOptions) {
4040
const { allAtOnce = false, delay = 0 } = options || {};
41-
const initialValue = (element as HTMLInputElement).value;
41+
const inputElement = element as HTMLInputElement;
42+
const initialValue = inputElement.value;
43+
44+
if (inputElement.disabled) {
45+
return;
46+
}
4247

4348
if (allAtOnce || value === '') {
44-
fireEvent.input(element, { target: { value } });
45-
element.addEventListener('blur', createFireChangeEvent(initialValue));
49+
if (!inputElement.readOnly) {
50+
fireEvent.input(inputElement, { target: { value } });
51+
}
52+
inputElement.addEventListener('blur', createFireChangeEvent(initialValue));
4653
return;
4754
}
4855

@@ -57,38 +64,40 @@ export function createType(fireEvent: FireFunction & FireObject) {
5764
await wait(delay);
5865
}
5966

60-
const downEvent = fireEvent.keyDown(element, {
67+
const downEvent = fireEvent.keyDown(inputElement, {
6168
key: key,
6269
keyCode: keyCode,
6370
which: keyCode,
6471
});
6572

6673
if (downEvent) {
67-
const pressEvent = fireEvent.keyPress(element, {
74+
const pressEvent = fireEvent.keyPress(inputElement, {
6875
key: key,
6976
keyCode,
7077
charCode: keyCode,
7178
});
7279

7380
if (pressEvent) {
7481
actuallyTyped += key;
75-
fireEvent.input(element, {
76-
target: {
77-
value: actuallyTyped,
78-
},
79-
bubbles: true,
80-
cancelable: true,
81-
});
82+
if (!inputElement.readOnly) {
83+
fireEvent.input(inputElement, {
84+
target: {
85+
value: actuallyTyped,
86+
},
87+
bubbles: true,
88+
cancelable: true,
89+
});
90+
}
8291
}
8392
}
8493

85-
fireEvent.keyUp(element, {
94+
fireEvent.keyUp(inputElement, {
8695
key: key,
8796
keyCode: keyCode,
8897
which: keyCode,
8998
});
9099
}
91100

92-
element.addEventListener('blur', createFireChangeEvent(initialValue));
101+
inputElement.addEventListener('blur', createFireChangeEvent(initialValue));
93102
};
94103
}

‎projects/testing-library/tests/user-events/type.spec.ts‎

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,15 @@ describe('options', () => {
178178
});
179179
});
180180

181-
test('does not type when event.preventDefault() is called',async () => {
181+
describe('does not type when ', () => {
182182
@Component({
183183
selector: 'fixture',
184184
template: `
185185
<input
186186
type="text"
187187
data-testid="input"
188+
[disabled]="disabled"
189+
[readonly]="readonly"
188190
(input)="onInput($event)"
189191
(change)="onChange($event)"
190192
(keydown)="onKeyDown($event)"
@@ -194,30 +196,86 @@ test('does not type when event.preventDefault() is called', async () => {
194196
`,
195197
})
196198
class FixtureComponent {
199+
@Input() disabled = false;
200+
@Input() readonly = false;
201+
197202
onInput($event) {}
198203
onChange($event) {}
199204
onKeyDown($event) {}
200205
onKeyPress($event) {}
201206
onKeyUp($event) {}
202207
}
203208

204-
const componentProperties = {
205-
onChange: jest.fn(),
206-
onKeyDown: jest.fn().mockImplementation(event => event.preventDefault()),
207-
};
209+
test('input is disabled', async () => {
210+
const componentEvents = {
211+
onInput: jest.fn(),
212+
onChange: jest.fn(),
213+
onKeyDown: jest.fn(),
214+
onKeyPress: jest.fn(),
215+
onKeyUp: jest.fn(),
216+
};
217+
218+
const component = await render(FixtureComponent, {
219+
componentProperties: {
220+
disabled: true,
221+
...componentEvents,
222+
},
223+
});
224+
225+
const inputControl = component.getByTestId('input') as HTMLInputElement;
226+
component.type(inputControl, 'Hello');
208227

209-
const component = await render(FixtureComponent, { componentProperties });
228+
Object.values(componentEvents).forEach(evt => expect(evt).not.toHaveBeenCalled());
229+
expect(inputControl.value).toBe('');
230+
});
210231

211-
const inputControl = component.getByTestId('input') as HTMLInputElement;
212-
const inputValue = 'foobar';
213-
component.type(inputControl, inputValue);
232+
test('input is readonly', async () => {
233+
const componentEvents = {
234+
onInput: jest.fn(),
235+
onChange: jest.fn(),
236+
onKeyDown: jest.fn(),
237+
onKeyPress: jest.fn(),
238+
onKeyUp: jest.fn(),
239+
};
214240

215-
expect(componentProperties.onKeyDown).toHaveBeenCalledTimes(inputValue.length);
241+
const component = await render(FixtureComponent, {
242+
componentProperties: {
243+
readonly: true,
244+
...componentEvents,
245+
},
246+
});
216247

217-
component.blur(inputControl);
218-
expect(componentProperties.onChange).toBeCalledTimes(0);
248+
const inputControl = component.getByTestId('input') as HTMLInputElement;
249+
const value = 'Hello';
250+
component.type(inputControl, value);
251+
252+
expect(componentEvents.onInput).not.toHaveBeenCalled();
253+
expect(componentEvents.onChange).not.toHaveBeenCalled();
254+
expect(componentEvents.onKeyDown).toHaveBeenCalledTimes(value.length);
255+
expect(componentEvents.onKeyPress).toHaveBeenCalledTimes(value.length);
256+
expect(componentEvents.onKeyUp).toHaveBeenCalledTimes(value.length);
257+
expect(inputControl.value).toBe('');
258+
});
219259

220-
expect(inputControl.value).toBe('');
260+
test('event.preventDefault() is called', async () => {
261+
const componentProperties = {
262+
onChange: jest.fn(),
263+
onKeyDown: jest.fn().mockImplementation(event => event.preventDefault()),
264+
};
265+
266+
const component = await render(FixtureComponent, { componentProperties });
267+
268+
const inputControl = component.getByTestId('input') as HTMLInputElement;
269+
const inputValue = 'foobar';
270+
component.type(inputControl, inputValue);
271+
272+
expect(componentProperties.onKeyDown).toHaveBeenCalledTimes(inputValue.length);
273+
274+
component.blur(inputControl);
275+
expect(componentProperties.onChange).toBeCalledTimes(0);
276+
277+
expect(inputControl.value).toBe('');
278+
});
221279
});
222280

223281
test('can clear an input field', async () => {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /