From 5d9cc1580a7f2fd73757f1ec794b09717fbc3b09 Mon Sep 17 00:00:00 2001 From: Oleg Bezrukavnikov Date: Fri, 18 Sep 2026 02:57:55 -0700 Subject: [PATCH] fix(packages/react-native): pass testID to the rendered Svg element (#4881) The Icon component destructured `testID` out of its props and re-emitted it as `data-testid`, which is a web attribute. react-native-svg only forwards `testID` to the native view (see extractProps) and drops `data-testid`, so `` rendered an element that no React Native test query or UI automation tool can find. `LucideProps` extends `SvgProps`, so the prop type checks and the failure is silent. v0 spread `testID` straight onto `Svg`, so this is a regression for React Native consumers. An explicitly passed `data-testid` still reaches the element through the remaining props, so nothing is lost for react-native-web users. The react-native-svg test mock now maps `testID` onto `data-testid`, so the DOM based test suite identifies elements the way React Native does. Every existing `testID` test fails against the previous behaviour. --- .../__mocks__/react-native-svg/index.ts | 5 +++-- packages/lucide-react-native/src/Icon.ts | 2 +- packages/lucide-react-native/tests/Icon.spec.tsx | 11 +++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/lucide-react-native/__mocks__/react-native-svg/index.ts b/packages/lucide-react-native/__mocks__/react-native-svg/index.ts index 8ebb9b6dc..b61dec342 100644 --- a/packages/lucide-react-native/__mocks__/react-native-svg/index.ts +++ b/packages/lucide-react-native/__mocks__/react-native-svg/index.ts @@ -4,8 +4,9 @@ import type { LucideProps } from '../../src/createReactComponent'; export type { SvgProps } from 'react-native-svg'; const createComponent = function (name: string) { - const component = (props: LucideProps) => { - return React.createElement(name, props, props.children); + // React Native identifies elements by `testID`, the DOM equivalent is `data-testid` + const component = ({ testID, ...props }: LucideProps) => { + return React.createElement(name, { ...props, 'data-testid': testID }, props.children); }; component.displayName = name; diff --git a/packages/lucide-react-native/src/Icon.ts b/packages/lucide-react-native/src/Icon.ts index f2346235e..184a8e48e 100644 --- a/packages/lucide-react-native/src/Icon.ts +++ b/packages/lucide-react-native/src/Icon.ts @@ -107,7 +107,7 @@ const Icon = forwardRef( { ref, ...toNativeSvgAttributes(svgAttributes), - 'data-testid': testID, + testID, ...rest, }, [ diff --git a/packages/lucide-react-native/tests/Icon.spec.tsx b/packages/lucide-react-native/tests/Icon.spec.tsx index 5c55e0b1c..09d044cd7 100644 --- a/packages/lucide-react-native/tests/Icon.spec.tsx +++ b/packages/lucide-react-native/tests/Icon.spec.tsx @@ -47,6 +47,17 @@ describe('Using Icon Component', () => { expect(container.firstChild).toBeDefined(); }); + it('should pass the testID to the rendered element', async () => { + const { container, getByTestId } = render( + , + ); + + expect(getByTestId('air-vent-icon')).toBe(container.firstChild); + }); + it('should support nonScalingStroke', async () => { const { container } = render(