From 67ba290f766f24eea446cec210ec57eae14ac590 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Mon, 17 Jul 2023 22:07:53 -0700 Subject: [PATCH] Decouple isTesting Platform flag from disabling/enabling animations when testing (#38490) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/38490 ## Changelog [Internal] - The internal `Platform.isTesting` is tightly coupled to animations being disabled, which in turn can lead to subtle problems in some of the corner cases: * Since `isTesting` is force override to `false` on JS side in non-dev builds, it means that e2e tests, that would like to use release builds, are out of luck when animation disabling is desired * Conversely, some of the e2e tests may actually rely on animations being enabled in order to work, which means they are also out of luck if trying to test a dev build * Finally, we have cases of hybrid builds, which are build in release on native side, but also have `__DEV__=true` on the native side To both cover the above scenarios, but also to be backwards compatible to all the existing once, this change introduces another flag, `Platform.isDisableAnimations`. The way it works is: * If it's not specified, the e2e tests behaviour will be exactly the same as before, since by default `isDisableAnimations` will be true when `isTesting` is true * If it's specified and is equal to `false`, it means that animations will be still enabled, even if `isTesting` is true (for those e2e tests that rely on animations being enabled) * If it's specified and is equal to 'true', it means that animations will be force disabled, no matter whether we test a release or a dev build Note that this only specifies the JS side of things, defaulting `Platform.isDisableAnimations` to "not specified" (i.e. all the tests will behave as before). Pulling it through for different platforms is done as a separate follow-up. Differential Revision: D47516800 fbshipit-source-id: efcb78f68f9102fec025ecce9a475c9c0bc1ecca --- packages/react-native/Libraries/Animated/Animated.js | 2 +- .../Libraries/LayoutAnimation/LayoutAnimation.js | 2 +- .../Libraries/Utilities/NativePlatformConstantsAndroid.js | 1 + .../Libraries/Utilities/NativePlatformConstantsIOS.js | 1 + .../react-native/Libraries/Utilities/Platform.android.js | 6 ++++++ packages/react-native/Libraries/Utilities/Platform.d.ts | 1 + packages/react-native/Libraries/Utilities/Platform.ios.js | 6 ++++++ 7 files changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/react-native/Libraries/Animated/Animated.js b/packages/react-native/Libraries/Animated/Animated.js index ec17ef764543ee..a9df993ad2981c 100644 --- a/packages/react-native/Libraries/Animated/Animated.js +++ b/packages/react-native/Libraries/Animated/Animated.js @@ -21,7 +21,7 @@ import Platform from '../Utilities/Platform'; import AnimatedImplementation from './AnimatedImplementation'; import AnimatedMock from './AnimatedMock'; -const Animated = ((Platform.isTesting +const Animated = ((Platform.isDisableAnimations ? AnimatedMock : AnimatedImplementation): typeof AnimatedImplementation); diff --git a/packages/react-native/Libraries/LayoutAnimation/LayoutAnimation.js b/packages/react-native/Libraries/LayoutAnimation/LayoutAnimation.js index e4489d0543bf60..6283e673c64846 100644 --- a/packages/react-native/Libraries/LayoutAnimation/LayoutAnimation.js +++ b/packages/react-native/Libraries/LayoutAnimation/LayoutAnimation.js @@ -49,7 +49,7 @@ function configureNext( onAnimationDidEnd?: OnAnimationDidEndCallback, onAnimationDidFail?: OnAnimationDidFailCallback, ) { - if (Platform.isTesting) { + if (Platform.isDisableAnimations) { return; } diff --git a/packages/react-native/Libraries/Utilities/NativePlatformConstantsAndroid.js b/packages/react-native/Libraries/Utilities/NativePlatformConstantsAndroid.js index e1329e8c5896b6..b470f9b350ec7f 100644 --- a/packages/react-native/Libraries/Utilities/NativePlatformConstantsAndroid.js +++ b/packages/react-native/Libraries/Utilities/NativePlatformConstantsAndroid.js @@ -15,6 +15,7 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; export interface Spec extends TurboModule { +getConstants: () => {| isTesting: boolean, + isDisableAnimations?: boolean, reactNativeVersion: {| major: number, minor: number, diff --git a/packages/react-native/Libraries/Utilities/NativePlatformConstantsIOS.js b/packages/react-native/Libraries/Utilities/NativePlatformConstantsIOS.js index cf60d5ec984877..c1defa9981f0c1 100644 --- a/packages/react-native/Libraries/Utilities/NativePlatformConstantsIOS.js +++ b/packages/react-native/Libraries/Utilities/NativePlatformConstantsIOS.js @@ -15,6 +15,7 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; export interface Spec extends TurboModule { +getConstants: () => {| isTesting: boolean, + isDisableAnimations?: boolean, reactNativeVersion: {| major: number, minor: number, diff --git a/packages/react-native/Libraries/Utilities/Platform.android.js b/packages/react-native/Libraries/Utilities/Platform.android.js index 29234be81a7baa..3d4b9e40f545bb 100644 --- a/packages/react-native/Libraries/Utilities/Platform.android.js +++ b/packages/react-native/Libraries/Utilities/Platform.android.js @@ -28,6 +28,7 @@ const Platform = { // $FlowFixMe[unsafe-getters-setters] get constants(): {| isTesting: boolean, + isDisableAnimations?: boolean, reactNativeVersion: {| major: number, minor: number, @@ -61,6 +62,11 @@ const Platform = { return false; }, // $FlowFixMe[unsafe-getters-setters] + get isDisableAnimations(): boolean { + // $FlowFixMe[object-this-reference] + return this.constants.isDisableAnimations ?? this.isTesting; + }, + // $FlowFixMe[unsafe-getters-setters] get isTV(): boolean { // $FlowFixMe[object-this-reference] return this.constants.uiMode === 'tv'; diff --git a/packages/react-native/Libraries/Utilities/Platform.d.ts b/packages/react-native/Libraries/Utilities/Platform.d.ts index 465a82b35c6df1..1ff836839110be 100644 --- a/packages/react-native/Libraries/Utilities/Platform.d.ts +++ b/packages/react-native/Libraries/Utilities/Platform.d.ts @@ -19,6 +19,7 @@ export type PlatformOSType = | 'native'; type PlatformConstants = { isTesting: boolean; + isDisableAnimations?: boolean | undefined; reactNativeVersion: { major: number; minor: number; diff --git a/packages/react-native/Libraries/Utilities/Platform.ios.js b/packages/react-native/Libraries/Utilities/Platform.ios.js index 4adf4201c52b3e..4d0217a80945f4 100644 --- a/packages/react-native/Libraries/Utilities/Platform.ios.js +++ b/packages/react-native/Libraries/Utilities/Platform.ios.js @@ -30,6 +30,7 @@ const Platform = { forceTouchAvailable: boolean, interfaceIdiom: string, isTesting: boolean, + isDisableAnimations?: boolean, osVersion: string, reactNativeVersion: {| major: number, @@ -65,6 +66,11 @@ const Platform = { } return false; }, + // $FlowFixMe[unsafe-getters-setters] + get isDisableAnimations(): boolean { + // $FlowFixMe[object-this-reference] + return this.constants.isDisableAnimations ?? this.isTesting; + }, select: (spec: PlatformSelectSpec): T => // $FlowFixMe[incompatible-return] 'ios' in spec ? spec.ios : 'native' in spec ? spec.native : spec.default,