Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

package com.facebook.react

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.res.Configuration
Expand Down Expand Up @@ -425,16 +426,20 @@ public open class ReactDelegate {
* Do not store a reference to this, if the React instance is reloaded or destroyed, this context
* will no longer be valid.
*/
@get:SuppressLint("DeprecatedClass")
public val currentReactContext: ReactContext?
get() {
return if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
if (reactHost != null) {
reactHost?.currentReactContext
reactHost?.let {
return it.currentReactContext
}

val reactNativeHost = reactNativeHost ?: return null
synchronized(reactNativeHost) {
return if (reactNativeHost.hasInstance()) {
reactNativeHost.reactInstanceManager.currentReactContext
} else {
null
}
} else {
getReactInstanceManager().currentReactContext
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import com.facebook.react.bridge.ReactContext
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsDefaults
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner

@SuppressLint(
"ActivityStoredInField",
"DeprecatedClass",
"DeprecatedMethod",
"DeprecatedSuperclass",
)
@RunWith(RobolectricTestRunner::class)
class ReactDelegateTest {

private lateinit var activity: Activity

@Before
fun setUp() {
ReactNativeFeatureFlagsForTests.setUp()
activity = Robolectric.buildActivity(Activity::class.java).create().get()
}

@After
fun tearDown() {
ReactNativeFeatureFlags.dangerouslyReset()
}

@Test
fun currentReactContext_withReactHost_returnsContext() {
overrideBridgelessArchitecture(true)
val reactContext = mock<ReactContext>()
val reactHost = mock<ReactHost> { on { currentReactContext } doReturn reactContext }
val delegate = ReactDelegate(activity, reactHost, "test-app", null)

assertThat(delegate.currentReactContext).isSameAs(reactContext)
}

@Test
fun currentReactContext_withReactHost_ignoresArchitectureFlag() {
overrideBridgelessArchitecture(false)
val reactContext = mock<ReactContext>()
val reactHost = mock<ReactHost> { on { currentReactContext } doReturn reactContext }
val delegate = ReactDelegate(activity, reactHost, "test-app", null)

assertThat(delegate.currentReactContext).isSameAs(reactContext)
}

@Suppress("DEPRECATION")
@Test
fun currentReactContext_withoutReactNativeHost_returnsNull() {
overrideBridgelessArchitecture(false)
val delegate = ReactDelegate(activity, null as ReactNativeHost?, "test-app", null)

assertThat(delegate.currentReactContext).isNull()
}

@Suppress("DEPRECATION")
@Test
fun currentReactContext_withUninitializedReactNativeHost_doesNotCreateInstance() {
overrideBridgelessArchitecture(false)
val reactNativeHost =
object : ReactNativeHost(activity.application as Application) {
override fun getUseDeveloperSupport(): Boolean = false

override fun getPackages(): List<ReactPackage> = emptyList()
}
val delegate = ReactDelegate(activity, reactNativeHost, "test-app", null)

assertThat(delegate.currentReactContext).isNull()
assertThat(reactNativeHost.hasInstance()).isFalse()
}

@Suppress("DEPRECATION")
@Test
fun currentReactContext_withInitializedReactNativeHost_returnsContext() {
overrideBridgelessArchitecture(false)
val reactContext = mock<ReactContext>()
val instanceManager =
mock<ReactInstanceManager> { on { currentReactContext } doReturn reactContext }
val reactNativeHost = createInitializedReactNativeHost(instanceManager)
val delegate = ReactDelegate(activity, reactNativeHost, "test-app", null)

assertThat(delegate.currentReactContext).isSameAs(reactContext)
}

@Suppress("DEPRECATION")
@Test
fun currentReactContext_withReactNativeHost_ignoresArchitectureFlag() {
overrideBridgelessArchitecture(true)
val reactContext = mock<ReactContext>()
val instanceManager =
mock<ReactInstanceManager> { on { currentReactContext } doReturn reactContext }
val reactNativeHost = createInitializedReactNativeHost(instanceManager)
val delegate = ReactDelegate(activity, reactNativeHost, "test-app", null)

assertThat(delegate.currentReactContext).isSameAs(reactContext)
}

@Suppress("DEPRECATION")
private fun createInitializedReactNativeHost(
instanceManager: ReactInstanceManager,
): ReactNativeHost =
object : ReactNativeHost(activity.application as Application) {
override val reactInstanceManager: ReactInstanceManager = instanceManager

override fun hasInstance(): Boolean = true

override fun getUseDeveloperSupport(): Boolean = false

override fun getPackages(): List<ReactPackage> = emptyList()
}

private fun overrideBridgelessArchitecture(enabled: Boolean) {
ReactNativeFeatureFlags.override(
object : ReactNativeFeatureFlagsDefaults() {
override fun enableBridgelessArchitecture(): Boolean = enabled
},
)
}
}
Loading