From 9e358251f32f2f546c1dacd2dd795d9d7ca1c2d2 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Thu, 7 Nov 2024 09:53:34 +0100 Subject: [PATCH 1/2] refactor: cleanu existing code --- src/fire-event.ts | 11 ++--- src/helpers/__tests__/query-name.test.ts | 10 ----- src/helpers/__tests__/text-input.test.tsx | 36 ++++++++++----- src/helpers/accessibility.ts | 4 +- src/helpers/deprecation.ts | 53 ----------------------- src/helpers/query-name.ts | 4 -- src/helpers/text-input.ts | 8 +--- src/user-event/clear.ts | 4 +- src/user-event/paste.ts | 4 +- src/user-event/press/press.ts | 4 +- src/user-event/type/type.ts | 4 +- 11 files changed, 41 insertions(+), 101 deletions(-) delete mode 100644 src/helpers/__tests__/query-name.test.ts delete mode 100644 src/helpers/deprecation.ts delete mode 100644 src/helpers/query-name.ts diff --git a/src/fire-event.ts b/src/fire-event.ts index fe3fe6d79..7946baaba 100644 --- a/src/fire-event.ts +++ b/src/fire-event.ts @@ -10,7 +10,7 @@ import act from './act'; import { isElementMounted, isHostElement } from './helpers/component-tree'; import { isHostScrollView, isHostTextInput } from './helpers/host-component-names'; import { isPointerEventEnabled } from './helpers/pointer-events'; -import { isTextInputEditable } from './helpers/text-input'; +import { isEditableTextInput } from './helpers/text-input'; import { Point, StringWithAutocomplete } from './types'; import { nativeState } from './native-state'; @@ -54,7 +54,7 @@ export function isEventEnabled( ) { if (nearestTouchResponder != null && isHostTextInput(nearestTouchResponder)) { return ( - isTextInputEditable(nearestTouchResponder) || + isEditableTextInput(nearestTouchResponder) || textInputEventsIgnoringEditableProp.has(eventName) ); } @@ -160,12 +160,7 @@ const scrollEventNames = new Set([ ]); function setNativeStateIfNeeded(element: ReactTestInstance, eventName: string, value: unknown) { - if ( - eventName === 'changeText' && - typeof value === 'string' && - isHostTextInput(element) && - isTextInputEditable(element) - ) { + if (eventName === 'changeText' && typeof value === 'string' && isEditableTextInput(element)) { nativeState.valueForElement.set(element, value); } diff --git a/src/helpers/__tests__/query-name.test.ts b/src/helpers/__tests__/query-name.test.ts deleted file mode 100644 index 3ef7b9529..000000000 --- a/src/helpers/__tests__/query-name.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { getQueryPrefix } from '../query-name'; - -test('getQueryPrefix should return correct prefix', () => { - expect(getQueryPrefix('getByRole')).toBe('get'); - expect(getQueryPrefix('getAllByText')).toEqual('getAll'); - expect(getQueryPrefix('queryByTestId')).toEqual('query'); - expect(getQueryPrefix('queryAllByPlaceholderText')).toEqual('queryAll'); - expect(getQueryPrefix('findByHintText')).toEqual('find'); - expect(getQueryPrefix('findAllByDisplayValue')).toEqual('findAll'); -}); diff --git a/src/helpers/__tests__/text-input.test.tsx b/src/helpers/__tests__/text-input.test.tsx index 77cc20191..2a3ad3f1f 100644 --- a/src/helpers/__tests__/text-input.test.tsx +++ b/src/helpers/__tests__/text-input.test.tsx @@ -1,10 +1,19 @@ import * as React from 'react'; -import { View } from 'react-native'; +import { TextInput, View } from 'react-native'; import { render, screen } from '../..'; -import { getTextInputValue, isTextInputEditable } from '../text-input'; +import { getTextInputValue, isEditableTextInput } from '../text-input'; -test('getTextInputValue() throws error when invoked on non-text input', () => { - render(); +test('getTextInputValue basic test', () => { + render( + + + + + , + ); + + expect(getTextInputValue(screen.getByTestId('value'))).toBe('text-a'); + expect(getTextInputValue(screen.getByTestId('default-value'))).toBe('text-b'); const view = screen.getByTestId('view'); expect(() => getTextInputValue(view)).toThrowErrorMatchingInlineSnapshot( @@ -12,11 +21,18 @@ test('getTextInputValue() throws error when invoked on non-text input', () => { ); }); -test('isTextInputEditable() throws error when invoked on non-text input', () => { - render(); - - const view = screen.getByTestId('view'); - expect(() => isTextInputEditable(view)).toThrowErrorMatchingInlineSnapshot( - `"Element is not a "TextInput", but it has type "View"."`, +test('isEditableTextInput basic test', () => { + render( + + + + + + , ); + + expect(isEditableTextInput(screen.getByTestId('default'))).toBe(true); + expect(isEditableTextInput(screen.getByTestId('editable'))).toBe(true); + expect(isEditableTextInput(screen.getByTestId('non-editable'))).toBe(false); + expect(isEditableTextInput(screen.getByTestId('view'))).toBe(false); }); diff --git a/src/helpers/accessibility.ts b/src/helpers/accessibility.ts index 40f7008ce..e1f193368 100644 --- a/src/helpers/accessibility.ts +++ b/src/helpers/accessibility.ts @@ -10,7 +10,7 @@ import { getHostSiblings, getUnsafeRootElement, isHostElement } from './componen import { findAll } from './find-all'; import { isHostImage, isHostSwitch, isHostText, isHostTextInput } from './host-component-names'; import { getTextContent } from './text-content'; -import { isTextInputEditable } from './text-input'; +import { isEditableTextInput } from './text-input'; type IsInaccessibleOptions = { cache?: WeakMap; @@ -208,7 +208,7 @@ export function computeAriaChecked(element: ReactTestInstance): AccessibilitySta // See: https://github.com/callstack/react-native-testing-library/wiki/Accessibility:-State#disabled-state export function computeAriaDisabled(element: ReactTestInstance): boolean { - if (isHostTextInput(element) && !isTextInputEditable(element)) { + if (isHostTextInput(element) && !isEditableTextInput(element)) { return true; } diff --git a/src/helpers/deprecation.ts b/src/helpers/deprecation.ts deleted file mode 100644 index e6fb723ad..000000000 --- a/src/helpers/deprecation.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { getQueryPrefix } from './query-name'; - -export function deprecateQueries>( - queriesObject: Queries, - recommendation: string, -): Queries { - const result = {} as Queries; - Object.keys(queriesObject).forEach((queryName) => { - const queryFn = queriesObject[queryName]; - // @ts-expect-error: generic typing is hard - result[queryName] = deprecateQuery(queryFn, queryName, recommendation); - }); - - return result; -} - -function deprecateQuery any>( - queryFn: QueryFn, - queryName: string, - recommendation: string, -): QueryFn { - const formattedRecommendation = recommendation.replace( - /{queryPrefix}/g, - getQueryPrefix(queryName), - ); - - // @ts-expect-error: generic typing is hard - const wrapper: QueryFn = (...args: any) => { - const errorMessage = `${queryName}(...) is deprecated and will be removed in the future.\n\n${formattedRecommendation}`; - // eslint-disable-next-line no-console - console.warn(errorMessage); - return queryFn(...args); - }; - - return wrapper; -} - -const warned: { [functionName: string]: boolean } = {}; - -/* istanbul ignore next: occasionally used */ -export function printDeprecationWarning(functionName: string) { - if (warned[functionName]) { - return; - } - - // eslint-disable-next-line no-console - console.warn(` - Deprecation Warning: - Use of ${functionName} is not recommended and will be deleted in future versions of @testing-library/react-native. - `); - - warned[functionName] = true; -} diff --git a/src/helpers/query-name.ts b/src/helpers/query-name.ts deleted file mode 100644 index 1a6a034c8..000000000 --- a/src/helpers/query-name.ts +++ /dev/null @@ -1,4 +0,0 @@ -export function getQueryPrefix(queryName: string) { - const parts = queryName.split('By'); - return parts[0]; -} diff --git a/src/helpers/text-input.ts b/src/helpers/text-input.ts index bf76389fe..d21360a5f 100644 --- a/src/helpers/text-input.ts +++ b/src/helpers/text-input.ts @@ -2,12 +2,8 @@ import { ReactTestInstance } from 'react-test-renderer'; import { nativeState } from '../native-state'; import { isHostTextInput } from './host-component-names'; -export function isTextInputEditable(element: ReactTestInstance) { - if (!isHostTextInput(element)) { - throw new Error(`Element is not a "TextInput", but it has type "${element.type}".`); - } - - return element.props.editable !== false; +export function isEditableTextInput(element: ReactTestInstance) { + return isHostTextInput(element) && element.props.editable !== false; } export function getTextInputValue(element: ReactTestInstance) { diff --git a/src/user-event/clear.ts b/src/user-event/clear.ts index 9b4ce555f..589d0be31 100644 --- a/src/user-event/clear.ts +++ b/src/user-event/clear.ts @@ -1,7 +1,7 @@ import { ReactTestInstance } from 'react-test-renderer'; import { ErrorWithStack } from '../helpers/errors'; import { isHostTextInput } from '../helpers/host-component-names'; -import { getTextInputValue, isTextInputEditable } from '../helpers/text-input'; +import { getTextInputValue, isEditableTextInput } from '../helpers/text-input'; import { isPointerEventEnabled } from '../helpers/pointer-events'; import { EventBuilder } from './event-builder'; import { UserEventInstance } from './setup'; @@ -16,7 +16,7 @@ export async function clear(this: UserEventInstance, element: ReactTestInstance) ); } - if (!isTextInputEditable(element) || !isPointerEventEnabled(element)) { + if (!isEditableTextInput(element) || !isPointerEventEnabled(element)) { return; } diff --git a/src/user-event/paste.ts b/src/user-event/paste.ts index 7ead1d1f3..fc0622b2d 100644 --- a/src/user-event/paste.ts +++ b/src/user-event/paste.ts @@ -2,7 +2,7 @@ import { ReactTestInstance } from 'react-test-renderer'; import { ErrorWithStack } from '../helpers/errors'; import { isHostTextInput } from '../helpers/host-component-names'; import { isPointerEventEnabled } from '../helpers/pointer-events'; -import { getTextInputValue, isTextInputEditable } from '../helpers/text-input'; +import { getTextInputValue, isEditableTextInput } from '../helpers/text-input'; import { nativeState } from '../native-state'; import { EventBuilder } from './event-builder'; import { UserEventInstance } from './setup'; @@ -20,7 +20,7 @@ export async function paste( ); } - if (!isTextInputEditable(element) || !isPointerEventEnabled(element)) { + if (!isEditableTextInput(element) || !isPointerEventEnabled(element)) { return; } diff --git a/src/user-event/press/press.ts b/src/user-event/press/press.ts index 7302c704a..77012d314 100644 --- a/src/user-event/press/press.ts +++ b/src/user-event/press/press.ts @@ -1,7 +1,7 @@ import { ReactTestInstance } from 'react-test-renderer'; import act from '../../act'; import { getHostParent } from '../../helpers/component-tree'; -import { isTextInputEditable } from '../../helpers/text-input'; +import { isEditableTextInput } from '../../helpers/text-input'; import { isPointerEventEnabled } from '../../helpers/pointer-events'; import { isHostText, isHostTextInput } from '../../helpers/host-component-names'; import { EventBuilder } from '../event-builder'; @@ -49,7 +49,7 @@ const basePress = async ( return; } - if (isHostTextInput(element) && isTextInputEditable(element) && isPointerEventEnabled(element)) { + if (isEditableTextInput(element) && isPointerEventEnabled(element)) { await emitTextInputPressEvents(config, element, options); return; } diff --git a/src/user-event/type/type.ts b/src/user-event/type/type.ts index 19fa66cc2..bd76e1c0c 100644 --- a/src/user-event/type/type.ts +++ b/src/user-event/type/type.ts @@ -3,7 +3,7 @@ import { isHostTextInput } from '../../helpers/host-component-names'; import { nativeState } from '../../native-state'; import { EventBuilder } from '../event-builder'; import { ErrorWithStack } from '../../helpers/errors'; -import { getTextInputValue, isTextInputEditable } from '../../helpers/text-input'; +import { getTextInputValue, isEditableTextInput } from '../../helpers/text-input'; import { isPointerEventEnabled } from '../../helpers/pointer-events'; import { UserEventConfig, UserEventInstance } from '../setup'; import { dispatchEvent, wait, getTextContentSize } from '../utils'; @@ -28,7 +28,7 @@ export async function type( } // Skip events if the element is disabled - if (!isTextInputEditable(element) || !isPointerEventEnabled(element)) { + if (!isEditableTextInput(element) || !isPointerEventEnabled(element)) { return; } From 6fb01724d9e2058a6fa07b59055bd292c5f750c8 Mon Sep 17 00:00:00 2001 From: Maciej Jastrzebski Date: Thu, 7 Nov 2024 09:58:29 +0100 Subject: [PATCH 2/2] chore: fix lint --- src/user-event/press/press.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user-event/press/press.ts b/src/user-event/press/press.ts index 77012d314..f5859fc4a 100644 --- a/src/user-event/press/press.ts +++ b/src/user-event/press/press.ts @@ -3,7 +3,7 @@ import act from '../../act'; import { getHostParent } from '../../helpers/component-tree'; import { isEditableTextInput } from '../../helpers/text-input'; import { isPointerEventEnabled } from '../../helpers/pointer-events'; -import { isHostText, isHostTextInput } from '../../helpers/host-component-names'; +import { isHostText } from '../../helpers/host-component-names'; import { EventBuilder } from '../event-builder'; import { UserEventConfig, UserEventInstance } from '../setup'; import { dispatchEvent, wait } from '../utils';