Skip to content

Commit

Permalink
fix: Respect maxLength prop in type() function (#1641)
Browse files Browse the repository at this point in the history
* fix: Respect maxLength prop in type() function

This commit modifies the `type()` function to respect the `maxLength` prop of the input element. If the current text length exceeds the `maxLength` value, typing events will not be emitted. This ensures that the input value does not exceed the specified maximum length.

1. Create an input element with a `maxLength` prop.
2. Use the `type()` function to input text that exceeds the `maxLength` value.
3. Verify that the input value does not exceed the specified maximum length.
4. Check that no typing events are emitted once the `maxLength` is reached.

Additionally, see that `yarn test` passes with an additional test added to `src/user-event/type/__tests__/type.test.tsx`

* refactor: code review changes

* refactor: tweaks

* refactor: final tweaks

* refactor: final tweaks 2

* chore: tweak codecov

---------

Co-authored-by: Maciej Jastrzębski <mdjastrzebski@gmail.com>
  • Loading branch information
joshuayoes and mdjastrzebski authored Aug 9, 2024
1 parent 6cc4c0c commit 6a51a81
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 88 deletions.
6 changes: 5 additions & 1 deletion .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ coverage:
precision: 2
round: down
range: 70...100
status:
project:
default:
threshold: 0.5% # Allowable coverage drop in percentage points

comment:
behavior: default
require_changes: false
require_base: no
require_base: false
6 changes: 5 additions & 1 deletion src/test-utils/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export function createEventLogger() {
return { events, logEvent };
}

export function getEventsName(events: EventEntry[]) {
export function getEventsNames(events: EventEntry[]) {
return events.map((event) => event.name);
}

export function lastEventPayload(events: EventEntry[], name: string) {
return events.filter((e) => e.name === name).pop()?.payload;
}
17 changes: 6 additions & 11 deletions src/user-event/__tests__/clear.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { TextInput, TextInputProps, View } from 'react-native';
import { createEventLogger } from '../../test-utils';
import { createEventLogger, getEventsNames } from '../../test-utils';
import { render, userEvent, screen } from '../..';

beforeEach(() => {
Expand Down Expand Up @@ -47,8 +47,7 @@ describe('clear()', () => {
const user = userEvent.setup();
await user.clear(textInput);

const eventNames = events.map((e) => e.name);
expect(eventNames).toEqual([
expect(getEventsNames(events)).toEqual([
'focus',
'selectionChange',
'keyPress',
Expand All @@ -71,8 +70,7 @@ describe('clear()', () => {
const user = userEvent.setup();
await user.clear(textInput);

const eventNames = events.map((e) => e.name);
expect(eventNames).toEqual([
expect(getEventsNames(events)).toEqual([
'focus',
'selectionChange',
'keyPress',
Expand All @@ -92,8 +90,7 @@ describe('clear()', () => {
const user = userEvent.setup();
await user.clear(textInput);

const eventNames = events.map((e) => e.name);
expect(eventNames).toEqual([
expect(getEventsNames(events)).toEqual([
'focus',
'selectionChange',
'keyPress',
Expand Down Expand Up @@ -140,8 +137,7 @@ describe('clear()', () => {
const user = userEvent.setup();
await user.clear(textInput);

const eventNames = events.map((e) => e.name);
expect(eventNames).toEqual([
expect(getEventsNames(events)).toEqual([
'focus',
'selectionChange',
'keyPress',
Expand Down Expand Up @@ -170,8 +166,7 @@ describe('clear()', () => {
const user = userEvent.setup();
await user.clear(screen.getByTestId('input'));

const eventNames = events.map((e) => e.name);
expect(eventNames).toEqual(['changeText', 'endEditing']);
expect(getEventsNames(events)).toEqual(['changeText', 'endEditing']);

expect(events).toMatchSnapshot();
});
Expand Down
9 changes: 7 additions & 2 deletions src/user-event/clear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,14 @@ export async function clear(this: UserEventInstance, element: ReactTestInstance)
};
dispatchEvent(element, 'selectionChange', EventBuilder.TextInput.selectionChange(selectionRange));

// 3. Press backspace
// 3. Press backspace with selected text
const finalText = '';
await emitTypingEvents(this.config, element, 'Backspace', finalText, previousText);
await emitTypingEvents(element, {
config: this.config,
key: 'Backspace',
text: finalText,
previousText,
});

// 4. Exit element
await wait(this.config);
Expand Down
10 changes: 5 additions & 5 deletions src/user-event/press/__tests__/press.real-timers.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
TouchableOpacity,
View,
} from 'react-native';
import { createEventLogger, getEventsName } from '../../../test-utils';
import { createEventLogger, getEventsNames } from '../../../test-utils';
import { render, screen } from '../../..';
import { userEvent } from '../..';
import * as WarnAboutRealTimers from '../../utils/warn-about-real-timers';
Expand All @@ -34,7 +34,7 @@ describe('userEvent.press with real timers', () => {
);
await user.press(screen.getByTestId('pressable'));

expect(getEventsName(events)).toEqual(['pressIn', 'press', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
});

test('does not trigger event when pressable is disabled', async () => {
Expand Down Expand Up @@ -130,7 +130,7 @@ describe('userEvent.press with real timers', () => {
);
await user.press(screen.getByTestId('pressable'));

expect(getEventsName(events)).toEqual(['pressIn', 'press', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
});

test('crawls up in the tree to find an element that responds to touch events', async () => {
Expand Down Expand Up @@ -200,7 +200,7 @@ describe('userEvent.press with real timers', () => {
);
await userEvent.press(screen.getByText('press me'));

expect(getEventsName(events)).toEqual(['pressIn', 'press', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
});

test('does not trigger on disabled Text', async () => {
Expand Down Expand Up @@ -254,7 +254,7 @@ describe('userEvent.press with real timers', () => {
);
await userEvent.press(screen.getByPlaceholderText('email'));

expect(getEventsName(events)).toEqual(['pressIn', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut']);
});

test('does not call onPressIn and onPressOut on non editable TetInput', async () => {
Expand Down
14 changes: 7 additions & 7 deletions src/user-event/press/__tests__/press.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
View,
Button,
} from 'react-native';
import { createEventLogger, getEventsName } from '../../../test-utils';
import { createEventLogger, getEventsNames } from '../../../test-utils';
import { render, screen } from '../../..';
import { userEvent } from '../..';

Expand Down Expand Up @@ -129,7 +129,7 @@ describe('userEvent.press with fake timers', () => {
);
await user.press(screen.getByTestId('pressable'));

expect(getEventsName(events)).toEqual(['pressIn', 'press', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
});

test('crawls up in the tree to find an element that responds to touch events', async () => {
Expand Down Expand Up @@ -199,7 +199,7 @@ describe('userEvent.press with fake timers', () => {
);

await userEvent.press(screen.getByText('press me'));
expect(getEventsName(events)).toEqual(['pressIn', 'press', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
});

test('press works on Button', async () => {
Expand All @@ -208,7 +208,7 @@ describe('userEvent.press with fake timers', () => {
render(<Button title="press me" onPress={logEvent('press')} />);

await userEvent.press(screen.getByText('press me'));
expect(getEventsName(events)).toEqual(['press']);
expect(getEventsNames(events)).toEqual(['press']);
});

test('longPress works Text', async () => {
Expand All @@ -226,7 +226,7 @@ describe('userEvent.press with fake timers', () => {
);

await userEvent.longPress(screen.getByText('press me'));
expect(getEventsName(events)).toEqual(['pressIn', 'longPress', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'longPress', 'pressOut']);
});

test('does not trigger on disabled Text', async () => {
Expand Down Expand Up @@ -280,7 +280,7 @@ describe('userEvent.press with fake timers', () => {
);

await userEvent.press(screen.getByPlaceholderText('email'));
expect(getEventsName(events)).toEqual(['pressIn', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut']);
});

test('longPress works on TextInput', async () => {
Expand All @@ -295,7 +295,7 @@ describe('userEvent.press with fake timers', () => {
);

await userEvent.longPress(screen.getByPlaceholderText('email'));
expect(getEventsName(events)).toEqual(['pressIn', 'pressOut']);
expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut']);
});

test('does not call onPressIn and onPressOut on non editable TextInput', async () => {
Expand Down
8 changes: 3 additions & 5 deletions src/user-event/type/__tests__/type-managed.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { TextInput } from 'react-native';
import { createEventLogger } from '../../../test-utils';
import { createEventLogger, getEventsNames } from '../../../test-utils';
import { render, screen } from '../../..';
import { userEvent } from '../..';

Expand Down Expand Up @@ -56,8 +56,7 @@ describe('type() for managed TextInput', () => {
const user = userEvent.setup();
await user.type(screen.getByTestId('input'), 'Wow');

const eventNames = events.map((e) => e.name);
expect(eventNames).toEqual([
expect(getEventsNames(events)).toEqual([
'pressIn',
'focus',
'pressOut',
Expand Down Expand Up @@ -90,8 +89,7 @@ describe('type() for managed TextInput', () => {
const user = userEvent.setup();
await user.type(screen.getByTestId('input'), 'ABC');

const eventNames = events.map((e) => e.name);
expect(eventNames).toEqual([
expect(getEventsNames(events)).toEqual([
'pressIn',
'focus',
'pressOut',
Expand Down
Loading

0 comments on commit 6a51a81

Please sign in to comment.