From 5dd834640752d329894c77f20becbfed30a4bc6f Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Tue, 17 Mar 2026 23:06:37 +0100 Subject: [PATCH 1/9] chore: adding test for isBoldTextEnabled, isGrayscaleEnabled and isInvertColorsEnabled --- .../AccessibilityInfo/AccessibilityInfo.js | 4 +- .../__tests__/AccessibilityInfo-test.js | 231 ++++++++++++++++++ 2 files changed, 233 insertions(+), 2 deletions(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js index b74d517151b..c698c0c54b1 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js @@ -136,7 +136,7 @@ const AccessibilityInfo = { reject, ); } else { - reject(new Error('AccessibilityInfo native module is not available')); + reject(new Error('NativeAccessibilityManagerIOS is not available')); } }); } @@ -171,7 +171,7 @@ const AccessibilityInfo = { reject, ); } else { - reject(new Error('AccessibilityInfo native module is not available')); + reject(new Error('NativeAccessibilityManagerIOS is not available')); } }); } diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js index a9ca14cbf0b..41b76c577dc 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js @@ -16,6 +16,9 @@ const mockGetCurrentPrefersCrossFadeTransitionsState = jest.fn( const mockGetCurrentDarkerSystemColorsState = jest.fn((onSuccess, onError) => onSuccess(true), ); +const mockGetCurrentBoldTextState = jest.fn((onSuccess, onError) => onSuccess(true)); +const mockGetCurrentGrayscaleState = jest.fn((onSuccess, onError) => onSuccess(true)); +const mockGetCurrentInvertColorsState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockNativeAccessibilityManagerDefault: { getCurrentPrefersCrossFadeTransitionsState: JestMockFn< [ @@ -31,20 +34,57 @@ const mockNativeAccessibilityManagerDefault: { ], void, > | null, + getCurrentBoldTextState: JestMockFn< + [ + onSuccess: (isBoldTextEnabled: boolean) => void, + onError: (error: Error) => void, + ], + void, + > | null, + getCurrentGrayscaleState: JestMockFn< + [ + onSuccess: (isGrayscaleEnabled: boolean) => void, + onError: (error: Error) => void, + ], + void, + > | null, + getCurrentInvertColorsState: JestMockFn< + [ + onSuccess: (isInvertColorsEnabled: boolean) => void, + onError: (error: Error) => void, + ], + void, + > | null, } = { getCurrentPrefersCrossFadeTransitionsState: mockGetCurrentPrefersCrossFadeTransitionsState, getCurrentDarkerSystemColorsState: mockGetCurrentDarkerSystemColorsState, + getCurrentBoldTextState: mockGetCurrentBoldTextState, + getCurrentGrayscaleState: mockGetCurrentGrayscaleState, + getCurrentInvertColorsState: mockGetCurrentInvertColorsState, + }; const mockIsHighTextContrastEnabled = jest.fn(onSuccess => onSuccess(true)); +const mockIsGrayscaleEnabled = jest.fn(onSuccess => onSuccess(true)); +const mockIsInvertColorsEnabled = jest.fn(onSuccess => onSuccess(true)); const mockNativeAccessibilityInfo: { isHighTextContrastEnabled: JestMockFn< [onSuccess: (isHighTextContrastEnabled: boolean) => void], void, > | null, + isGrayscaleEnabled: JestMockFn< + [onSuccess: (isGrayscaleEnabled: boolean) => void], + void, + > | null, + isInvertColorsEnabled: JestMockFn< + [onSuccess: (isInvertColorsEnabled: boolean) => void], + void, + > | null, } = { isHighTextContrastEnabled: mockIsHighTextContrastEnabled, + isGrayscaleEnabled: mockIsGrayscaleEnabled, + isInvertColorsEnabled: mockIsInvertColorsEnabled, }; jest.mock('../NativeAccessibilityManager', () => ({ @@ -61,6 +101,11 @@ const Platform = require('../../../Utilities/Platform').default; const AccessibilityInfo = require('../AccessibilityInfo').default; const invariant = require('invariant'); +// isReduceMotionEnabled +// isReduceTransparencyEnabled +// isScreenReaderEnabled +// isAccessibilityServiceEnabled + describe('AccessibilityInfo', () => { let originalPlatform; @@ -69,6 +114,188 @@ describe('AccessibilityInfo', () => { mockGetCurrentPrefersCrossFadeTransitionsState.mockClear(); mockGetCurrentDarkerSystemColorsState.mockClear(); mockIsHighTextContrastEnabled.mockClear(); + mockGetCurrentBoldTextState.mockClear(); + mockIsGrayscaleEnabled.mockClear(); + mockIsInvertColorsEnabled.mockClear(); + }); + + describe('isBoldTextEnabled', () => { + describe('Android', () => { + it('should return immediately', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const isBoldTextEnabled = + await AccessibilityInfo.isBoldTextEnabled(); + + expect(isBoldTextEnabled).toBe(false); + }); + }) + + describe('iOS', () => { + it('should call getCurrentBoldTextState if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const isBoldTextEnabled = + await AccessibilityInfo.isBoldTextEnabled(); + + expect(mockGetCurrentBoldTextState).toHaveBeenCalled(); + expect(isBoldTextEnabled).toBe(true); + }); + + it('should reject if NativeAccessibilityManagerIOS module is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const nativeAccessibilityManagerModule = + jest.requireMock('../NativeAccessibilityManager'); + nativeAccessibilityManagerModule.default = null; + + const result: mixed = + await AccessibilityInfo.isBoldTextEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isBoldTextEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityManagerIOS is not available', + ); + }); + }); + }); + + describe('isGrayscaleEnabled', () => { + describe('Android', () => { + it('should call isGrayscaleEnabled if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const isGrayscaleEnabled = + await AccessibilityInfo.isGrayscaleEnabled(); + + expect(mockIsGrayscaleEnabled).toHaveBeenCalled(); + expect(isGrayscaleEnabled).toBe(true); + }); + + it('should throw error if isGrayscaleEnabled is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + mockNativeAccessibilityInfo.isGrayscaleEnabled = null; + + const result: mixed = + await AccessibilityInfo.isGrayscaleEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isGrayscaleEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityInfoAndroid.isGrayscaleEnabled is not available', + ); + }); + }); + + describe('iOS', () => { + it('should call getCurrentGrayscaleState if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const isGrayscaleEnabled = + await AccessibilityInfo.isGrayscaleEnabled(); + + expect(mockGetCurrentGrayscaleState).toHaveBeenCalled(); + expect(isGrayscaleEnabled).toBe(true); + }); + + it('should reject if NativeAccessibilityManagerIOS module is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const nativeAccessibilityManagerModule = + jest.requireMock('../NativeAccessibilityManager'); + nativeAccessibilityManagerModule.default = null; + + const result: mixed = + await AccessibilityInfo.isGrayscaleEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isGrayscaleEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityManagerIOS is not available', + ); + }); + }); + }); + + describe('isInvertColorsEnabled', () => { + describe('Android', () => { + it('should call isInvertColorsEnabled if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const isInvertColorsEnabled = + await AccessibilityInfo.isInvertColorsEnabled(); + + expect(mockIsInvertColorsEnabled).toHaveBeenCalled(); + expect(isInvertColorsEnabled).toBe(true); + }); + + it('should throw error if isInvertColorsEnabled is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + mockNativeAccessibilityInfo.isInvertColorsEnabled = null; + + const result: mixed = + await AccessibilityInfo.isInvertColorsEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isInvertColorsEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityInfoAndroid.isInvertColorsEnabled is not available', + ); + }); + }); + + describe('iOS', () => { + it('should call getCurrentInvertColorsState if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const isInvertColorsEnabled = + await AccessibilityInfo.isInvertColorsEnabled(); + + expect(mockGetCurrentInvertColorsState).toHaveBeenCalled(); + expect(isInvertColorsEnabled).toBe(true); + }); + + it('should reject if NativeAccessibilityManagerIOS module is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const nativeAccessibilityManagerModule = + jest.requireMock('../NativeAccessibilityManager'); + nativeAccessibilityManagerModule.default = null; + + const result: mixed = + await AccessibilityInfo.isInvertColorsEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isInvertColorsEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityManagerIOS is not available', + ); + }); + }); }); describe('prefersCrossFadeTransitions', () => { @@ -211,12 +438,16 @@ describe('AccessibilityInfo', () => { }); afterEach(() => { + jest.requireMock('../NativeAccessibilityManager').default = + mockNativeAccessibilityManagerDefault; mockNativeAccessibilityManagerDefault.getCurrentPrefersCrossFadeTransitionsState = mockGetCurrentPrefersCrossFadeTransitionsState; mockNativeAccessibilityManagerDefault.getCurrentDarkerSystemColorsState = mockGetCurrentDarkerSystemColorsState; mockNativeAccessibilityInfo.isHighTextContrastEnabled = mockIsHighTextContrastEnabled; + mockNativeAccessibilityInfo.isGrayscaleEnabled = mockIsGrayscaleEnabled; + mockNativeAccessibilityInfo.isInvertColorsEnabled = mockIsInvertColorsEnabled; /* $FlowFixMe[incompatible-type] */ Platform.OS = originalPlatform; }); From d238764b93682395df7d2c3d43d0db05eeca1aa4 Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Wed, 18 Mar 2026 12:00:25 +0100 Subject: [PATCH 2/9] chore: isReduceMotion test added --- .../AccessibilityInfo/AccessibilityInfo.js | 2 +- .../__tests__/AccessibilityInfo-test.js | 95 +++++++++++++++++-- 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js index c698c0c54b1..79e92c7217d 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js @@ -191,7 +191,7 @@ const AccessibilityInfo = { if (NativeAccessibilityInfoAndroid != null) { NativeAccessibilityInfoAndroid.isReduceMotionEnabled(resolve); } else { - reject(new Error('AccessibilityInfo native module is not available')); + reject(new Error('NativeAccessibilityInfoAndroid is not available')); } } else { if (NativeAccessibilityManagerIOS != null) { diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js index 41b76c577dc..3b97b7bd06b 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js @@ -19,6 +19,7 @@ const mockGetCurrentDarkerSystemColorsState = jest.fn((onSuccess, onError) => const mockGetCurrentBoldTextState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockGetCurrentGrayscaleState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockGetCurrentInvertColorsState = jest.fn((onSuccess, onError) => onSuccess(true)); +const mockGetCurrentReduceMotionState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockNativeAccessibilityManagerDefault: { getCurrentPrefersCrossFadeTransitionsState: JestMockFn< [ @@ -40,7 +41,7 @@ const mockNativeAccessibilityManagerDefault: { onError: (error: Error) => void, ], void, - > | null, + > | null, getCurrentGrayscaleState: JestMockFn< [ onSuccess: (isGrayscaleEnabled: boolean) => void, @@ -55,6 +56,13 @@ const mockNativeAccessibilityManagerDefault: { ], void, > | null, + getCurrentReduceMotionState: JestMockFn< + [ + onSuccess: (isReduceMotionEnabled: boolean) => void, + onError: (error: Error) => void, + ], + void, + > | null, } = { getCurrentPrefersCrossFadeTransitionsState: mockGetCurrentPrefersCrossFadeTransitionsState, @@ -62,12 +70,13 @@ const mockNativeAccessibilityManagerDefault: { getCurrentBoldTextState: mockGetCurrentBoldTextState, getCurrentGrayscaleState: mockGetCurrentGrayscaleState, getCurrentInvertColorsState: mockGetCurrentInvertColorsState, - + getCurrentReduceMotionState: mockGetCurrentReduceMotionState, }; const mockIsHighTextContrastEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsGrayscaleEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsInvertColorsEnabled = jest.fn(onSuccess => onSuccess(true)); +const mockIsReduceMotionEnabled = jest.fn(onSuccess => onSuccess(true)); const mockNativeAccessibilityInfo: { isHighTextContrastEnabled: JestMockFn< [onSuccess: (isHighTextContrastEnabled: boolean) => void], @@ -81,10 +90,15 @@ const mockNativeAccessibilityInfo: { [onSuccess: (isInvertColorsEnabled: boolean) => void], void, > | null, + isReduceMotionEnabled: JestMockFn< + [onSuccess: (isReduceMotionEnabled: boolean) => void], + void, + > | null, } = { isHighTextContrastEnabled: mockIsHighTextContrastEnabled, isGrayscaleEnabled: mockIsGrayscaleEnabled, isInvertColorsEnabled: mockIsInvertColorsEnabled, + isReduceMotionEnabled: mockIsReduceMotionEnabled, }; jest.mock('../NativeAccessibilityManager', () => ({ @@ -101,7 +115,6 @@ const Platform = require('../../../Utilities/Platform').default; const AccessibilityInfo = require('../AccessibilityInfo').default; const invariant = require('invariant'); -// isReduceMotionEnabled // isReduceTransparencyEnabled // isScreenReaderEnabled // isAccessibilityServiceEnabled @@ -129,7 +142,7 @@ describe('AccessibilityInfo', () => { await AccessibilityInfo.isBoldTextEnabled(); expect(isBoldTextEnabled).toBe(false); - }); + }); }) describe('iOS', () => { @@ -177,7 +190,7 @@ describe('AccessibilityInfo', () => { expect(mockIsGrayscaleEnabled).toHaveBeenCalled(); expect(isGrayscaleEnabled).toBe(true); - }); + }); it('should throw error if isGrayscaleEnabled is not available', async () => { /* $FlowFixMe[incompatible-type] */ @@ -243,7 +256,7 @@ describe('AccessibilityInfo', () => { expect(mockIsInvertColorsEnabled).toHaveBeenCalled(); expect(isInvertColorsEnabled).toBe(true); - }); + }); it('should throw error if isInvertColorsEnabled is not available', async () => { /* $FlowFixMe[incompatible-type] */ @@ -298,6 +311,74 @@ describe('AccessibilityInfo', () => { }); }); + describe('isReduceMotionEnabled', () => { + describe('Android', () => { + it('should call isReduceMotionEnabled if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const isReduceMotionEnabled = + await AccessibilityInfo.isReduceMotionEnabled(); + + expect(mockIsReduceMotionEnabled).toHaveBeenCalled(); + expect(isReduceMotionEnabled).toBe(true); + }); + + it('should throw error if isReduceMotionEnabled is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const nativeAccessibilityInfoModule = + jest.requireMock('../NativeAccessibilityInfo'); + nativeAccessibilityInfoModule.default = null; + + + const result: mixed = + await AccessibilityInfo.isReduceMotionEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isReduceMotionEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityInfoAndroid is not available', + ); + }); + }); + + describe('iOS', () => { + it('should call getCurrentReduceMotionState if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const isReduceMotionEnabled = + await AccessibilityInfo.isReduceMotionEnabled(); + + expect(isReduceMotionEnabled).toBe(true); + }); + + it('should reject if NativeAccessibilityManagerIOS module is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const nativeAccessibilityManagerModule = + jest.requireMock('../NativeAccessibilityManager'); + nativeAccessibilityManagerModule.default = null; + + const result: mixed = + await AccessibilityInfo.isReduceMotionEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isReduceMotionEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityManagerIOS is not available', + ); + }); + }); + }); + describe('prefersCrossFadeTransitions', () => { describe('Android', () => { it('should return immediately', async () => { @@ -440,6 +521,8 @@ describe('AccessibilityInfo', () => { afterEach(() => { jest.requireMock('../NativeAccessibilityManager').default = mockNativeAccessibilityManagerDefault; + jest.requireMock('../NativeAccessibilityInfo').default = + mockNativeAccessibilityInfo; mockNativeAccessibilityManagerDefault.getCurrentPrefersCrossFadeTransitionsState = mockGetCurrentPrefersCrossFadeTransitionsState; mockNativeAccessibilityManagerDefault.getCurrentDarkerSystemColorsState = From 688c6a124c73f4d4df605f523a797fa11b2c5e1c Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Thu, 19 Mar 2026 10:31:43 +0100 Subject: [PATCH 3/9] chore: adding test for isReduceTransparencyEnabled --- .../__tests__/AccessibilityInfo-test.js | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js index 3b97b7bd06b..fda9d87463d 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js @@ -20,6 +20,7 @@ const mockGetCurrentBoldTextState = jest.fn((onSuccess, onError) => onSuccess(tr const mockGetCurrentGrayscaleState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockGetCurrentInvertColorsState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockGetCurrentReduceMotionState = jest.fn((onSuccess, onError) => onSuccess(true)); +const mockGetCurrentReduceTransparencyState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockNativeAccessibilityManagerDefault: { getCurrentPrefersCrossFadeTransitionsState: JestMockFn< [ @@ -63,6 +64,13 @@ const mockNativeAccessibilityManagerDefault: { ], void, > | null, + getCurrentReduceTransparencyState: JestMockFn< + [ + onSuccess: (isReduceTransparencyEnabled: boolean) => void, + onError: (error: Error) => void, + ], + void, + > | null, } = { getCurrentPrefersCrossFadeTransitionsState: mockGetCurrentPrefersCrossFadeTransitionsState, @@ -71,6 +79,7 @@ const mockNativeAccessibilityManagerDefault: { getCurrentGrayscaleState: mockGetCurrentGrayscaleState, getCurrentInvertColorsState: mockGetCurrentInvertColorsState, getCurrentReduceMotionState: mockGetCurrentReduceMotionState, + getCurrentReduceTransparencyState: mockGetCurrentReduceTransparencyState, }; const mockIsHighTextContrastEnabled = jest.fn(onSuccess => onSuccess(true)); @@ -115,7 +124,6 @@ const Platform = require('../../../Utilities/Platform').default; const AccessibilityInfo = require('../AccessibilityInfo').default; const invariant = require('invariant'); -// isReduceTransparencyEnabled // isScreenReaderEnabled // isAccessibilityServiceEnabled @@ -311,6 +319,53 @@ describe('AccessibilityInfo', () => { }); }); + describe('isReduceTransparencyEnabled', () => { + describe('Android', () => { + it('should return immediately', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const isReduceTransparencyEnabled = + await AccessibilityInfo.isReduceTransparencyEnabled(); + + expect(isReduceTransparencyEnabled).toBe(false); + }); + }); + + describe('iOS', () => { + it('should call getCurrentReduceTransparencyState if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const isReduceTransparencyEnabled = + await AccessibilityInfo.isReduceTransparencyEnabled(); + + expect(mockGetCurrentReduceTransparencyState).toHaveBeenCalled(); + expect(isReduceTransparencyEnabled).toBe(true); + }); + + it('should reject if NativeAccessibilityManagerIOS module is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const nativeAccessibilityManagerModule = + jest.requireMock('../NativeAccessibilityManager'); + nativeAccessibilityManagerModule.default = null; + + const result: mixed = + await AccessibilityInfo.isReduceTransparencyEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isReduceTransparencyEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityManagerIOS is not available', + ); + }); + }); + }); + describe('isReduceMotionEnabled', () => { describe('Android', () => { it('should call isReduceMotionEnabled if available', async () => { From 7edd0bd2dc1da533c7762fefdc1d05b9258dfec7 Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Thu, 19 Mar 2026 10:50:17 +0100 Subject: [PATCH 4/9] chore: adding test for isScreenReaderEnabled --- .../__tests__/AccessibilityInfo-test.js | 86 ++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js index fda9d87463d..cae4f326c6d 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js @@ -21,6 +21,7 @@ const mockGetCurrentGrayscaleState = jest.fn((onSuccess, onError) => onSuccess(t const mockGetCurrentInvertColorsState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockGetCurrentReduceMotionState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockGetCurrentReduceTransparencyState = jest.fn((onSuccess, onError) => onSuccess(true)); +const mockGetCurrentVoiceOverState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockNativeAccessibilityManagerDefault: { getCurrentPrefersCrossFadeTransitionsState: JestMockFn< [ @@ -71,6 +72,13 @@ const mockNativeAccessibilityManagerDefault: { ], void, > | null, + getCurrentVoiceOverState: JestMockFn< + [ + onSuccess: (isVoiceOverEnabled: boolean) => void, + onError: (error: Error) => void, + ], + void, + > | null, } = { getCurrentPrefersCrossFadeTransitionsState: mockGetCurrentPrefersCrossFadeTransitionsState, @@ -80,12 +88,14 @@ const mockNativeAccessibilityManagerDefault: { getCurrentInvertColorsState: mockGetCurrentInvertColorsState, getCurrentReduceMotionState: mockGetCurrentReduceMotionState, getCurrentReduceTransparencyState: mockGetCurrentReduceTransparencyState, + getCurrentVoiceOverState: mockGetCurrentVoiceOverState, }; const mockIsHighTextContrastEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsGrayscaleEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsInvertColorsEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsReduceMotionEnabled = jest.fn(onSuccess => onSuccess(true)); +const mockIsTouchExplorationEnabled = jest.fn(onSuccess => onSuccess(true)); const mockNativeAccessibilityInfo: { isHighTextContrastEnabled: JestMockFn< [onSuccess: (isHighTextContrastEnabled: boolean) => void], @@ -103,11 +113,16 @@ const mockNativeAccessibilityInfo: { [onSuccess: (isReduceMotionEnabled: boolean) => void], void, > | null, + isTouchExplorationEnabled: JestMockFn< + [onSuccess: (isTouchExplorationEnabled: boolean) => void], + void, + > | null, } = { isHighTextContrastEnabled: mockIsHighTextContrastEnabled, isGrayscaleEnabled: mockIsGrayscaleEnabled, isInvertColorsEnabled: mockIsInvertColorsEnabled, isReduceMotionEnabled: mockIsReduceMotionEnabled, + isTouchExplorationEnabled: mockIsTouchExplorationEnabled, }; jest.mock('../NativeAccessibilityManager', () => ({ @@ -138,6 +153,8 @@ describe('AccessibilityInfo', () => { mockGetCurrentBoldTextState.mockClear(); mockIsGrayscaleEnabled.mockClear(); mockIsInvertColorsEnabled.mockClear(); + mockIsTouchExplorationEnabled.mockClear(); + mockGetCurrentVoiceOverState.mockClear(); }); describe('isBoldTextEnabled', () => { @@ -366,6 +383,74 @@ describe('AccessibilityInfo', () => { }); }); + describe('isScreenReaderEnabled', () => { + describe('Android', () => { + it('should call isScreenReaderEnabled if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const isScreenReaderEnabled = + await AccessibilityInfo.isScreenReaderEnabled(); + + expect(mockIsTouchExplorationEnabled).toHaveBeenCalled(); + expect(isScreenReaderEnabled).toBe(true); + }); + + it('should throw error if isScreenReaderEnabled is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const nativeAccessibilityInfoModule = + jest.requireMock('../NativeAccessibilityInfo'); + nativeAccessibilityInfoModule.default = null; + + const result: mixed = + await AccessibilityInfo.isScreenReaderEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isScreenReaderEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityInfoAndroid is not available', + ); + }); + }); + + describe('iOS', () => { + it('should call getCurrentVoiceOverState if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const isScreenReaderEnabled = + await AccessibilityInfo.isScreenReaderEnabled(); + + expect(mockGetCurrentVoiceOverState).toHaveBeenCalled(); + expect(isScreenReaderEnabled).toBe(true); + }); + + it('should reject if NativeAccessibilityManagerIOS module is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const nativeAccessibilityManagerModule = + jest.requireMock('../NativeAccessibilityManager'); + nativeAccessibilityManagerModule.default = null; + + const result: mixed = + await AccessibilityInfo.isScreenReaderEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isScreenReaderEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityManagerIOS is not available', + ); + }); + }); + }); + describe('isReduceMotionEnabled', () => { describe('Android', () => { it('should call isReduceMotionEnabled if available', async () => { @@ -387,7 +472,6 @@ describe('AccessibilityInfo', () => { jest.requireMock('../NativeAccessibilityInfo'); nativeAccessibilityInfoModule.default = null; - const result: mixed = await AccessibilityInfo.isReduceMotionEnabled().catch(e => e); From d7ba657b92048b1a2621608af5320850d1f87e71 Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Thu, 19 Mar 2026 11:14:02 +0100 Subject: [PATCH 5/9] chore: added test for isAccessibilityServiceEnabled --- .../__tests__/AccessibilityInfo-test.js | 85 ++++++++++++++++++- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js index cae4f326c6d..1cb89e2f6c3 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js @@ -96,6 +96,7 @@ const mockIsGrayscaleEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsInvertColorsEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsReduceMotionEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsTouchExplorationEnabled = jest.fn(onSuccess => onSuccess(true)); +const mockIsAccessibilityServiceEnabled = jest.fn(onSuccess => onSuccess(true)); const mockNativeAccessibilityInfo: { isHighTextContrastEnabled: JestMockFn< [onSuccess: (isHighTextContrastEnabled: boolean) => void], @@ -117,12 +118,17 @@ const mockNativeAccessibilityInfo: { [onSuccess: (isTouchExplorationEnabled: boolean) => void], void, > | null, + isAccessibilityServiceEnabled: JestMockFn< + [onSuccess: (isAccessibilityServiceEnabled: boolean) => void], + void, + > | null, } = { isHighTextContrastEnabled: mockIsHighTextContrastEnabled, isGrayscaleEnabled: mockIsGrayscaleEnabled, isInvertColorsEnabled: mockIsInvertColorsEnabled, isReduceMotionEnabled: mockIsReduceMotionEnabled, isTouchExplorationEnabled: mockIsTouchExplorationEnabled, + isAccessibilityServiceEnabled: mockIsAccessibilityServiceEnabled, }; jest.mock('../NativeAccessibilityManager', () => ({ @@ -139,9 +145,6 @@ const Platform = require('../../../Utilities/Platform').default; const AccessibilityInfo = require('../AccessibilityInfo').default; const invariant = require('invariant'); -// isScreenReaderEnabled -// isAccessibilityServiceEnabled - describe('AccessibilityInfo', () => { let originalPlatform; @@ -155,6 +158,7 @@ describe('AccessibilityInfo', () => { mockIsInvertColorsEnabled.mockClear(); mockIsTouchExplorationEnabled.mockClear(); mockGetCurrentVoiceOverState.mockClear(); + mockIsAccessibilityServiceEnabled.mockClear(); }); describe('isBoldTextEnabled', () => { @@ -451,6 +455,63 @@ describe('AccessibilityInfo', () => { }); }); + describe('isAccessibilityServiceEnabled', () => { + describe('Android', () => { + it('should call isAccessibilityServiceEnabled if available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const isAccessibilityServiceEnabled = + await AccessibilityInfo.isAccessibilityServiceEnabled(); + + expect(mockIsAccessibilityServiceEnabled).toHaveBeenCalled(); + expect(isAccessibilityServiceEnabled).toBe(true); + }); + + it('should throw error if isAccessibilityServiceEnabled is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const nativeAccessibilityInfoModule = + jest.requireMock('../NativeAccessibilityInfo'); + nativeAccessibilityInfoModule.default = null; + + const result: mixed = + await AccessibilityInfo.isAccessibilityServiceEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isAccessibilityServiceEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled is not available', + ); + }); + }); + + describe('iOS', () => { + it('should reject because isAccessibilityServiceEnabled is only available on Android', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const nativeAccessibilityManagerModule = + jest.requireMock('../NativeAccessibilityManager'); + nativeAccessibilityManagerModule.default = null; + + const result: mixed = + await AccessibilityInfo.isAccessibilityServiceEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isAccessibilityServiceEnabled to reject', + ); + expect(result.message).toEqual( + 'isAccessibilityServiceEnabled is only available on Android', + ); + }); + }); + }); + describe('isReduceMotionEnabled', () => { describe('Android', () => { it('should call isReduceMotionEnabled if available', async () => { @@ -662,14 +723,32 @@ describe('AccessibilityInfo', () => { mockNativeAccessibilityManagerDefault; jest.requireMock('../NativeAccessibilityInfo').default = mockNativeAccessibilityInfo; + mockNativeAccessibilityManagerDefault.getCurrentPrefersCrossFadeTransitionsState = mockGetCurrentPrefersCrossFadeTransitionsState; mockNativeAccessibilityManagerDefault.getCurrentDarkerSystemColorsState = mockGetCurrentDarkerSystemColorsState; + mockNativeAccessibilityManagerDefault.getCurrentBoldTextState = + mockGetCurrentBoldTextState; + mockNativeAccessibilityManagerDefault.getCurrentGrayscaleState = + mockGetCurrentGrayscaleState; + mockNativeAccessibilityManagerDefault.getCurrentInvertColorsState = + mockGetCurrentInvertColorsState; + mockNativeAccessibilityManagerDefault.getCurrentReduceMotionState = + mockGetCurrentReduceMotionState; + mockNativeAccessibilityManagerDefault.getCurrentReduceTransparencyState = + mockGetCurrentReduceTransparencyState; + mockNativeAccessibilityManagerDefault.getCurrentVoiceOverState = + mockGetCurrentVoiceOverState; + mockNativeAccessibilityInfo.isHighTextContrastEnabled = mockIsHighTextContrastEnabled; mockNativeAccessibilityInfo.isGrayscaleEnabled = mockIsGrayscaleEnabled; mockNativeAccessibilityInfo.isInvertColorsEnabled = mockIsInvertColorsEnabled; + mockNativeAccessibilityInfo.isAccessibilityServiceEnabled = mockIsAccessibilityServiceEnabled; + mockNativeAccessibilityInfo.isReduceMotionEnabled = mockIsReduceMotionEnabled; + mockNativeAccessibilityInfo.isTouchExplorationEnabled = mockIsTouchExplorationEnabled; + /* $FlowFixMe[incompatible-type] */ Platform.OS = originalPlatform; }); From e7ed459cd5cc21ee421d4dc6e89fabee9d3e34d9 Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Thu, 19 Mar 2026 11:18:27 +0100 Subject: [PATCH 6/9] chore: added missing doc links --- .../Components/AccessibilityInfo/AccessibilityInfo.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js index 79e92c7217d..c3b508d6bc6 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js @@ -211,6 +211,8 @@ const AccessibilityInfo = { * * Returns a promise which resolves to a boolean. * The result is `true` when high text contrast is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo#ishightextcontrastenabled-android */ isHighTextContrastEnabled(): Promise { if (Platform.OS === 'android') { @@ -235,6 +237,8 @@ const AccessibilityInfo = { * * Returns a promise which resolves to a boolean. * The result is `true` when dark system colors is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo#isdarkersystemcolorsenabled-ios */ isDarkerSystemColorsEnabled(): Promise { if (Platform.OS === 'android') { From 03359bb7ea4258d9f20ece1ee2f78ac569d6de0a Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Thu, 19 Mar 2026 12:36:37 +0100 Subject: [PATCH 7/9] chore: improving mock reset and test readability --- .../__tests__/AccessibilityInfo-test.js | 102 +++++++++--------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js index 1cb89e2f6c3..35721801bd8 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js @@ -22,7 +22,7 @@ const mockGetCurrentInvertColorsState = jest.fn((onSuccess, onError) => onSucces const mockGetCurrentReduceMotionState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockGetCurrentReduceTransparencyState = jest.fn((onSuccess, onError) => onSuccess(true)); const mockGetCurrentVoiceOverState = jest.fn((onSuccess, onError) => onSuccess(true)); -const mockNativeAccessibilityManagerDefault: { +let mockNativeAccessibilityManagerIOS: { getCurrentPrefersCrossFadeTransitionsState: JestMockFn< [ onSuccess: (prefersCrossFadeTransitions: boolean) => void, @@ -97,7 +97,7 @@ const mockIsInvertColorsEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsReduceMotionEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsTouchExplorationEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsAccessibilityServiceEnabled = jest.fn(onSuccess => onSuccess(true)); -const mockNativeAccessibilityInfo: { +let mockNativeAccessibilityInfoAndroid: { isHighTextContrastEnabled: JestMockFn< [onSuccess: (isHighTextContrastEnabled: boolean) => void], void, @@ -133,12 +133,12 @@ const mockNativeAccessibilityInfo: { jest.mock('../NativeAccessibilityManager', () => ({ __esModule: true, - default: mockNativeAccessibilityManagerDefault, + default: mockNativeAccessibilityManagerIOS, })); jest.mock('../NativeAccessibilityInfo', () => ({ __esModule: true, - default: mockNativeAccessibilityInfo, + default: mockNativeAccessibilityInfoAndroid, })); const Platform = require('../../../Utilities/Platform').default; @@ -150,15 +150,7 @@ describe('AccessibilityInfo', () => { beforeEach(() => { originalPlatform = Platform.OS; - mockGetCurrentPrefersCrossFadeTransitionsState.mockClear(); - mockGetCurrentDarkerSystemColorsState.mockClear(); - mockIsHighTextContrastEnabled.mockClear(); - mockGetCurrentBoldTextState.mockClear(); - mockIsGrayscaleEnabled.mockClear(); - mockIsInvertColorsEnabled.mockClear(); - mockIsTouchExplorationEnabled.mockClear(); - mockGetCurrentVoiceOverState.mockClear(); - mockIsAccessibilityServiceEnabled.mockClear(); + jest.clearAllMocks(); }); describe('isBoldTextEnabled', () => { @@ -225,7 +217,7 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; - mockNativeAccessibilityInfo.isGrayscaleEnabled = null; + mockNativeAccessibilityInfoAndroid.isGrayscaleEnabled = null; const result: mixed = await AccessibilityInfo.isGrayscaleEnabled().catch(e => e); @@ -291,7 +283,7 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; - mockNativeAccessibilityInfo.isInvertColorsEnabled = null; + mockNativeAccessibilityInfoAndroid.isInvertColorsEnabled = null; const result: mixed = await AccessibilityInfo.isInvertColorsEnabled().catch(e => e); @@ -400,7 +392,7 @@ describe('AccessibilityInfo', () => { expect(isScreenReaderEnabled).toBe(true); }); - it('should throw error if isScreenReaderEnabled is not available', async () => { + it('should throw error if NativeAccessibilityInfoAndroid is not available', async () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; @@ -468,10 +460,29 @@ describe('AccessibilityInfo', () => { expect(isAccessibilityServiceEnabled).toBe(true); }); + it('should throw error if isAccessibilityServiceEnabled is not available', async () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; + mockNativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled = null; + + const result: mixed = + await AccessibilityInfo.isAccessibilityServiceEnabled().catch(e => e); + + invariant( + result instanceof Error, + 'Expected isAccessibilityServiceEnabled to reject', + ); + expect(result.message).toEqual( + 'NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled is not available', + ); + }); + + it('should throw error if NativeAccessibilityInfoAndroid is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + const nativeAccessibilityInfoModule = jest.requireMock('../NativeAccessibilityInfo'); nativeAccessibilityInfoModule.default = null; @@ -494,10 +505,6 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const nativeAccessibilityManagerModule = - jest.requireMock('../NativeAccessibilityManager'); - nativeAccessibilityManagerModule.default = null; - const result: mixed = await AccessibilityInfo.isAccessibilityServiceEnabled().catch(e => e); @@ -610,7 +617,7 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - mockNativeAccessibilityManagerDefault.getCurrentPrefersCrossFadeTransitionsState = + mockNativeAccessibilityManagerIOS.getCurrentPrefersCrossFadeTransitionsState = null; const result: mixed = @@ -656,7 +663,7 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - mockNativeAccessibilityManagerDefault.getCurrentDarkerSystemColorsState = + mockNativeAccessibilityManagerIOS.getCurrentDarkerSystemColorsState = null; const result: mixed = @@ -690,7 +697,7 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; - mockNativeAccessibilityInfo.isHighTextContrastEnabled = null; + mockNativeAccessibilityInfoAndroid.isHighTextContrastEnabled = null; const result: mixed = await AccessibilityInfo.isHighTextContrastEnabled().catch(e => e); @@ -719,35 +726,30 @@ describe('AccessibilityInfo', () => { }); afterEach(() => { + mockNativeAccessibilityManagerIOS = { + getCurrentPrefersCrossFadeTransitionsState: + mockGetCurrentPrefersCrossFadeTransitionsState, + getCurrentDarkerSystemColorsState: mockGetCurrentDarkerSystemColorsState, + getCurrentBoldTextState: mockGetCurrentBoldTextState, + getCurrentGrayscaleState: mockGetCurrentGrayscaleState, + getCurrentInvertColorsState: mockGetCurrentInvertColorsState, + getCurrentReduceMotionState: mockGetCurrentReduceMotionState, + getCurrentReduceTransparencyState: mockGetCurrentReduceTransparencyState, + getCurrentVoiceOverState: mockGetCurrentVoiceOverState, + }; jest.requireMock('../NativeAccessibilityManager').default = - mockNativeAccessibilityManagerDefault; + mockNativeAccessibilityManagerIOS; + + mockNativeAccessibilityInfoAndroid = { + isHighTextContrastEnabled: mockIsHighTextContrastEnabled, + isGrayscaleEnabled: mockIsGrayscaleEnabled, + isInvertColorsEnabled: mockIsInvertColorsEnabled, + isReduceMotionEnabled: mockIsReduceMotionEnabled, + isTouchExplorationEnabled: mockIsTouchExplorationEnabled, + isAccessibilityServiceEnabled: mockIsAccessibilityServiceEnabled, + }; jest.requireMock('../NativeAccessibilityInfo').default = - mockNativeAccessibilityInfo; - - mockNativeAccessibilityManagerDefault.getCurrentPrefersCrossFadeTransitionsState = - mockGetCurrentPrefersCrossFadeTransitionsState; - mockNativeAccessibilityManagerDefault.getCurrentDarkerSystemColorsState = - mockGetCurrentDarkerSystemColorsState; - mockNativeAccessibilityManagerDefault.getCurrentBoldTextState = - mockGetCurrentBoldTextState; - mockNativeAccessibilityManagerDefault.getCurrentGrayscaleState = - mockGetCurrentGrayscaleState; - mockNativeAccessibilityManagerDefault.getCurrentInvertColorsState = - mockGetCurrentInvertColorsState; - mockNativeAccessibilityManagerDefault.getCurrentReduceMotionState = - mockGetCurrentReduceMotionState; - mockNativeAccessibilityManagerDefault.getCurrentReduceTransparencyState = - mockGetCurrentReduceTransparencyState; - mockNativeAccessibilityManagerDefault.getCurrentVoiceOverState = - mockGetCurrentVoiceOverState; - - mockNativeAccessibilityInfo.isHighTextContrastEnabled = - mockIsHighTextContrastEnabled; - mockNativeAccessibilityInfo.isGrayscaleEnabled = mockIsGrayscaleEnabled; - mockNativeAccessibilityInfo.isInvertColorsEnabled = mockIsInvertColorsEnabled; - mockNativeAccessibilityInfo.isAccessibilityServiceEnabled = mockIsAccessibilityServiceEnabled; - mockNativeAccessibilityInfo.isReduceMotionEnabled = mockIsReduceMotionEnabled; - mockNativeAccessibilityInfo.isTouchExplorationEnabled = mockIsTouchExplorationEnabled; + mockNativeAccessibilityInfoAndroid; /* $FlowFixMe[incompatible-type] */ Platform.OS = originalPlatform; From 4b5f51639d0d1e56937444fccaeba1922d2948bb Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Thu, 19 Mar 2026 12:44:17 +0100 Subject: [PATCH 8/9] chore: added test for getRecommendedTimeoutMillis --- .../AccessibilityInfo/AccessibilityInfo.js | 2 +- .../__tests__/AccessibilityInfo-test.js | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js index c3b508d6bc6..db22e3d44e5 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js @@ -516,7 +516,7 @@ const AccessibilityInfo = { getRecommendedTimeoutMillis(originalTimeout: number): Promise { if (Platform.OS === 'android') { return new Promise((resolve, reject) => { - if (NativeAccessibilityInfoAndroid?.getRecommendedTimeoutMillis) { + if (NativeAccessibilityInfoAndroid?.getRecommendedTimeoutMillis != null) { NativeAccessibilityInfoAndroid.getRecommendedTimeoutMillis( originalTimeout, resolve, diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js index 35721801bd8..b06db2e8e1a 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js @@ -91,12 +91,14 @@ let mockNativeAccessibilityManagerIOS: { getCurrentVoiceOverState: mockGetCurrentVoiceOverState, }; +const ANDROID_RECOMMENDED_TIMEOUT = 6000; const mockIsHighTextContrastEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsGrayscaleEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsInvertColorsEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsReduceMotionEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsTouchExplorationEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsAccessibilityServiceEnabled = jest.fn(onSuccess => onSuccess(true)); +const mockGetRecommendedTimeoutMillis = jest.fn((originalTimeout, onSuccess) => onSuccess(ANDROID_RECOMMENDED_TIMEOUT)); let mockNativeAccessibilityInfoAndroid: { isHighTextContrastEnabled: JestMockFn< [onSuccess: (isHighTextContrastEnabled: boolean) => void], @@ -122,6 +124,10 @@ let mockNativeAccessibilityInfoAndroid: { [onSuccess: (isAccessibilityServiceEnabled: boolean) => void], void, > | null, + getRecommendedTimeoutMillis: JestMockFn< + [originalTimeout: number, onSuccess: (recommendedTimeout: number) => void], + void, + > | null, } = { isHighTextContrastEnabled: mockIsHighTextContrastEnabled, isGrayscaleEnabled: mockIsGrayscaleEnabled, @@ -129,6 +135,7 @@ let mockNativeAccessibilityInfoAndroid: { isReduceMotionEnabled: mockIsReduceMotionEnabled, isTouchExplorationEnabled: mockIsTouchExplorationEnabled, isAccessibilityServiceEnabled: mockIsAccessibilityServiceEnabled, + getRecommendedTimeoutMillis: mockGetRecommendedTimeoutMillis, }; jest.mock('../NativeAccessibilityManager', () => ({ @@ -725,6 +732,44 @@ describe('AccessibilityInfo', () => { }); }); + describe('getRecommendedTimeoutMillis', () => { + describe('Android', () => { + it('should return the provided timeout value', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + const recommendedTimeoutMillis = + await AccessibilityInfo.getRecommendedTimeoutMillis(5000); + + expect(recommendedTimeoutMillis).toBe(ANDROID_RECOMMENDED_TIMEOUT); + }); + + it('should return originalTimeout if getRecommendedTimeoutMillis is not available', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'android'; + + mockNativeAccessibilityInfoAndroid.getRecommendedTimeoutMillis = null; + + const recommendedTimeoutMillis = + await AccessibilityInfo.getRecommendedTimeoutMillis(5000); + + expect(recommendedTimeoutMillis).toBe(5000); + }); + }); + + describe('iOS', () => { + it('should return originalTimeout', async () => { + /* $FlowFixMe[incompatible-type] */ + Platform.OS = 'ios'; + + const recommendedTimeoutMillis = + await AccessibilityInfo.getRecommendedTimeoutMillis(5000); + + expect(recommendedTimeoutMillis).toBe(5000); + }); + }); + }); + afterEach(() => { mockNativeAccessibilityManagerIOS = { getCurrentPrefersCrossFadeTransitionsState: @@ -747,6 +792,7 @@ describe('AccessibilityInfo', () => { isReduceMotionEnabled: mockIsReduceMotionEnabled, isTouchExplorationEnabled: mockIsTouchExplorationEnabled, isAccessibilityServiceEnabled: mockIsAccessibilityServiceEnabled, + getRecommendedTimeoutMillis: mockGetRecommendedTimeoutMillis, }; jest.requireMock('../NativeAccessibilityInfo').default = mockNativeAccessibilityInfoAndroid; From ee006a6ccdc4d5220ef517dc76d0bbeb0c65f4bd Mon Sep 17 00:00:00 2001 From: Fabrizio Duroni Date: Thu, 19 Mar 2026 12:47:07 +0100 Subject: [PATCH 9/9] chore: prettier + lint --- .../AccessibilityInfo/AccessibilityInfo.js | 8 +- .../__tests__/AccessibilityInfo-test.js | 103 +++++++++++------- 2 files changed, 66 insertions(+), 45 deletions(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js index db22e3d44e5..6071263103c 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js @@ -211,7 +211,7 @@ const AccessibilityInfo = { * * Returns a promise which resolves to a boolean. * The result is `true` when high text contrast is enabled and `false` otherwise. - * + * * See https://reactnative.dev/docs/accessibilityinfo#ishightextcontrastenabled-android */ isHighTextContrastEnabled(): Promise { @@ -237,7 +237,7 @@ const AccessibilityInfo = { * * Returns a promise which resolves to a boolean. * The result is `true` when dark system colors is enabled and `false` otherwise. - * + * * See https://reactnative.dev/docs/accessibilityinfo#isdarkersystemcolorsenabled-ios */ isDarkerSystemColorsEnabled(): Promise { @@ -516,7 +516,9 @@ const AccessibilityInfo = { getRecommendedTimeoutMillis(originalTimeout: number): Promise { if (Platform.OS === 'android') { return new Promise((resolve, reject) => { - if (NativeAccessibilityInfoAndroid?.getRecommendedTimeoutMillis != null) { + if ( + NativeAccessibilityInfoAndroid?.getRecommendedTimeoutMillis != null + ) { NativeAccessibilityInfoAndroid.getRecommendedTimeoutMillis( originalTimeout, resolve, diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js index b06db2e8e1a..2264cd54147 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/__tests__/AccessibilityInfo-test.js @@ -16,12 +16,24 @@ const mockGetCurrentPrefersCrossFadeTransitionsState = jest.fn( const mockGetCurrentDarkerSystemColorsState = jest.fn((onSuccess, onError) => onSuccess(true), ); -const mockGetCurrentBoldTextState = jest.fn((onSuccess, onError) => onSuccess(true)); -const mockGetCurrentGrayscaleState = jest.fn((onSuccess, onError) => onSuccess(true)); -const mockGetCurrentInvertColorsState = jest.fn((onSuccess, onError) => onSuccess(true)); -const mockGetCurrentReduceMotionState = jest.fn((onSuccess, onError) => onSuccess(true)); -const mockGetCurrentReduceTransparencyState = jest.fn((onSuccess, onError) => onSuccess(true)); -const mockGetCurrentVoiceOverState = jest.fn((onSuccess, onError) => onSuccess(true)); +const mockGetCurrentBoldTextState = jest.fn((onSuccess, onError) => + onSuccess(true), +); +const mockGetCurrentGrayscaleState = jest.fn((onSuccess, onError) => + onSuccess(true), +); +const mockGetCurrentInvertColorsState = jest.fn((onSuccess, onError) => + onSuccess(true), +); +const mockGetCurrentReduceMotionState = jest.fn((onSuccess, onError) => + onSuccess(true), +); +const mockGetCurrentReduceTransparencyState = jest.fn((onSuccess, onError) => + onSuccess(true), +); +const mockGetCurrentVoiceOverState = jest.fn((onSuccess, onError) => + onSuccess(true), +); let mockNativeAccessibilityManagerIOS: { getCurrentPrefersCrossFadeTransitionsState: JestMockFn< [ @@ -64,7 +76,7 @@ let mockNativeAccessibilityManagerIOS: { onError: (error: Error) => void, ], void, - > | null, + > | null, getCurrentReduceTransparencyState: JestMockFn< [ onSuccess: (isReduceTransparencyEnabled: boolean) => void, @@ -98,7 +110,9 @@ const mockIsInvertColorsEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsReduceMotionEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsTouchExplorationEnabled = jest.fn(onSuccess => onSuccess(true)); const mockIsAccessibilityServiceEnabled = jest.fn(onSuccess => onSuccess(true)); -const mockGetRecommendedTimeoutMillis = jest.fn((originalTimeout, onSuccess) => onSuccess(ANDROID_RECOMMENDED_TIMEOUT)); +const mockGetRecommendedTimeoutMillis = jest.fn((originalTimeout, onSuccess) => + onSuccess(ANDROID_RECOMMENDED_TIMEOUT), +); let mockNativeAccessibilityInfoAndroid: { isHighTextContrastEnabled: JestMockFn< [onSuccess: (isHighTextContrastEnabled: boolean) => void], @@ -127,7 +141,7 @@ let mockNativeAccessibilityInfoAndroid: { getRecommendedTimeoutMillis: JestMockFn< [originalTimeout: number, onSuccess: (recommendedTimeout: number) => void], void, - > | null, + > | null, } = { isHighTextContrastEnabled: mockIsHighTextContrastEnabled, isGrayscaleEnabled: mockIsGrayscaleEnabled, @@ -166,20 +180,18 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; - const isBoldTextEnabled = - await AccessibilityInfo.isBoldTextEnabled(); + const isBoldTextEnabled = await AccessibilityInfo.isBoldTextEnabled(); expect(isBoldTextEnabled).toBe(false); }); - }) + }); describe('iOS', () => { it('should call getCurrentBoldTextState if available', async () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const isBoldTextEnabled = - await AccessibilityInfo.isBoldTextEnabled(); + const isBoldTextEnabled = await AccessibilityInfo.isBoldTextEnabled(); expect(mockGetCurrentBoldTextState).toHaveBeenCalled(); expect(isBoldTextEnabled).toBe(true); @@ -189,12 +201,14 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const nativeAccessibilityManagerModule = - jest.requireMock('../NativeAccessibilityManager'); + const nativeAccessibilityManagerModule = jest.requireMock( + '../NativeAccessibilityManager', + ); nativeAccessibilityManagerModule.default = null; - const result: mixed = - await AccessibilityInfo.isBoldTextEnabled().catch(e => e); + const result: mixed = await AccessibilityInfo.isBoldTextEnabled().catch( + e => e, + ); invariant( result instanceof Error, @@ -213,8 +227,7 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; - const isGrayscaleEnabled = - await AccessibilityInfo.isGrayscaleEnabled(); + const isGrayscaleEnabled = await AccessibilityInfo.isGrayscaleEnabled(); expect(mockIsGrayscaleEnabled).toHaveBeenCalled(); expect(isGrayscaleEnabled).toBe(true); @@ -244,8 +257,7 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const isGrayscaleEnabled = - await AccessibilityInfo.isGrayscaleEnabled(); + const isGrayscaleEnabled = await AccessibilityInfo.isGrayscaleEnabled(); expect(mockGetCurrentGrayscaleState).toHaveBeenCalled(); expect(isGrayscaleEnabled).toBe(true); @@ -255,8 +267,9 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const nativeAccessibilityManagerModule = - jest.requireMock('../NativeAccessibilityManager'); + const nativeAccessibilityManagerModule = jest.requireMock( + '../NativeAccessibilityManager', + ); nativeAccessibilityManagerModule.default = null; const result: mixed = @@ -321,8 +334,9 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const nativeAccessibilityManagerModule = - jest.requireMock('../NativeAccessibilityManager'); + const nativeAccessibilityManagerModule = jest.requireMock( + '../NativeAccessibilityManager', + ); nativeAccessibilityManagerModule.default = null; const result: mixed = @@ -368,19 +382,20 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const nativeAccessibilityManagerModule = - jest.requireMock('../NativeAccessibilityManager'); + const nativeAccessibilityManagerModule = jest.requireMock( + '../NativeAccessibilityManager', + ); nativeAccessibilityManagerModule.default = null; const result: mixed = await AccessibilityInfo.isReduceTransparencyEnabled().catch(e => e); - + invariant( result instanceof Error, 'Expected isReduceTransparencyEnabled to reject', ); expect(result.message).toEqual( - 'NativeAccessibilityManagerIOS is not available', + 'NativeAccessibilityManagerIOS is not available', ); }); }); @@ -403,8 +418,9 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; - const nativeAccessibilityInfoModule = - jest.requireMock('../NativeAccessibilityInfo'); + const nativeAccessibilityInfoModule = jest.requireMock( + '../NativeAccessibilityInfo', + ); nativeAccessibilityInfoModule.default = null; const result: mixed = @@ -436,8 +452,9 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const nativeAccessibilityManagerModule = - jest.requireMock('../NativeAccessibilityManager'); + const nativeAccessibilityManagerModule = jest.requireMock( + '../NativeAccessibilityManager', + ); nativeAccessibilityManagerModule.default = null; const result: mixed = @@ -467,7 +484,6 @@ describe('AccessibilityInfo', () => { expect(isAccessibilityServiceEnabled).toBe(true); }); - it('should throw error if isAccessibilityServiceEnabled is not available', async () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; @@ -490,8 +506,9 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; - const nativeAccessibilityInfoModule = - jest.requireMock('../NativeAccessibilityInfo'); + const nativeAccessibilityInfoModule = jest.requireMock( + '../NativeAccessibilityInfo', + ); nativeAccessibilityInfoModule.default = null; const result: mixed = @@ -543,8 +560,9 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'android'; - const nativeAccessibilityInfoModule = - jest.requireMock('../NativeAccessibilityInfo'); + const nativeAccessibilityInfoModule = jest.requireMock( + '../NativeAccessibilityInfo', + ); nativeAccessibilityInfoModule.default = null; const result: mixed = @@ -575,8 +593,9 @@ describe('AccessibilityInfo', () => { /* $FlowFixMe[incompatible-type] */ Platform.OS = 'ios'; - const nativeAccessibilityManagerModule = - jest.requireMock('../NativeAccessibilityManager'); + const nativeAccessibilityManagerModule = jest.requireMock( + '../NativeAccessibilityManager', + ); nativeAccessibilityManagerModule.default = null; const result: mixed = @@ -590,7 +609,7 @@ describe('AccessibilityInfo', () => { 'NativeAccessibilityManagerIOS is not available', ); }); - }); + }); }); describe('prefersCrossFadeTransitions', () => {