Skip to content

Commit ce6efa1

Browse files
committed
refactor: self code review
1 parent 5f81922 commit ce6efa1

File tree

7 files changed

+46
-5
lines changed

7 files changed

+46
-5
lines changed

src/fire-event.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,7 @@ type EventName = StringWithAutocomplete<
121121
>;
122122

123123
function fireEvent(element: ReactTestInstance, eventName: EventName, ...data: unknown[]) {
124-
if (eventName === 'changeText' && isHostTextInput(element) && typeof data[0] === 'string') {
125-
nativeState?.elementValues.set(element, data[0]);
126-
}
124+
setNativeStateIfNeeded(element, eventName, data[0]);
127125

128126
const handler = findEventHandler(element, eventName);
129127
if (!handler) {
@@ -148,3 +146,14 @@ fireEvent.scroll = (element: ReactTestInstance, ...data: unknown[]) =>
148146
fireEvent(element, 'scroll', ...data);
149147

150148
export default fireEvent;
149+
150+
function setNativeStateIfNeeded(element: ReactTestInstance, eventName: string, value: unknown) {
151+
if (
152+
eventName === 'changeText' &&
153+
typeof value === 'string' &&
154+
isHostTextInput(element) &&
155+
isTextInputEditable(element)
156+
) {
157+
nativeState?.elementValues.set(element, value);
158+
}
159+
}

src/native-state.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { ReactTestInstance } from 'react-test-renderer';
22

3+
/**
4+
* Simulated native state for unmanaged controls.
5+
*
6+
* Values from `value` props (managed controls) should take precedence over these values.
7+
*/
38
export type NativeState = {
49
elementValues: WeakMap<ReactTestInstance, string>;
510
};

src/user-event/__tests__/clear.test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from 'react';
22
import { TextInput, TextInputProps, View } from 'react-native';
33
import { createEventLogger, getEventsNames } from '../../test-utils';
44
import { render, userEvent, screen } from '../..';
5+
import '../../matchers/extend-expect';
56

67
beforeEach(() => {
78
jest.useRealTimers();
@@ -205,4 +206,16 @@ describe('clear()', () => {
205206
await user.clear(screen.getByTestId('input'));
206207
expect(parentHandler).not.toHaveBeenCalled();
207208
});
209+
210+
it('sets native state value for unmanaged text inputs', async () => {
211+
render(<TextInput testID="input" />);
212+
213+
const user = userEvent.setup();
214+
const input = screen.getByTestId('input');
215+
await user.type(input, 'abc');
216+
expect(input).toHaveDisplayValue('abc');
217+
218+
await user.clear(input);
219+
expect(input).toHaveDisplayValue('');
220+
});
208221
});

src/user-event/__tests__/paste.test.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from 'react';
22
import { TextInput, TextInputProps, View } from 'react-native';
33
import { createEventLogger, getEventsNames } from '../../test-utils';
44
import { render, userEvent, screen } from '../..';
5+
import '../../matchers/extend-expect';
56

67
beforeEach(() => {
78
jest.useRealTimers();
@@ -221,4 +222,15 @@ describe('paste()', () => {
221222
await user.paste(screen.getByTestId('input'), 'Hi!');
222223
expect(parentHandler).not.toHaveBeenCalled();
223224
});
225+
226+
it('sets native state value for unmanaged text inputs', async () => {
227+
render(<TextInput testID="input" />);
228+
229+
const user = userEvent.setup();
230+
const input = screen.getByTestId('input');
231+
expect(input).toHaveDisplayValue('');
232+
233+
await user.paste(input, 'abc');
234+
expect(input).toHaveDisplayValue('abc');
235+
});
224236
});

src/user-event/paste.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ErrorWithStack } from '../helpers/errors';
33
import { isHostTextInput } from '../helpers/host-component-names';
44
import { isPointerEventEnabled } from '../helpers/pointer-events';
55
import { isTextInputEditable } from '../helpers/text-input';
6+
import { nativeState } from '../native-state';
67
import { EventBuilder } from './event-builder';
78
import { UserEventInstance } from './setup';
89
import { dispatchEvent, getTextContentSize, wait } from './utils';
@@ -32,6 +33,7 @@ export async function paste(
3233
dispatchEvent(element, 'selectionChange', EventBuilder.TextInput.selectionChange(rangeToClear));
3334

3435
// 3. Paste the text
36+
nativeState?.elementValues.set(element, text);
3537
dispatchEvent(element, 'change', EventBuilder.TextInput.change(text));
3638
dispatchEvent(element, 'changeText', text);
3739

src/user-event/type/__tests__/type.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ describe('type()', () => {
374374
});
375375
});
376376

377-
it('supports value of unmanaged text inputs', async () => {
377+
it('sets native state value for unmanaged text inputs', async () => {
378378
render(<TextInput testID="input" />);
379379

380380
const user = userEvent.setup();

src/user-event/type/type.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ export async function emitTypingEvents(
9595
return;
9696
}
9797

98+
nativeState?.elementValues.set(element, text);
9899
dispatchEvent(element, 'change', EventBuilder.TextInput.change(text));
99100
dispatchEvent(element, 'changeText', text);
100-
nativeState?.elementValues.set(element, text);
101101

102102
const selectionRange = {
103103
start: text.length,

0 commit comments

Comments
 (0)