diff --git a/packages/core/android/build.gradle b/packages/core/android/build.gradle index 72d09314b..d6877d50e 100644 --- a/packages/core/android/build.gradle +++ b/packages/core/android/build.gradle @@ -171,10 +171,10 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compileOnly "com.squareup.okhttp3:okhttp:3.12.13" - implementation "com.datadoghq:dd-sdk-android-rum:2.3.0" - implementation "com.datadoghq:dd-sdk-android-logs:2.3.0" - implementation "com.datadoghq:dd-sdk-android-trace:2.3.0" - implementation "com.datadoghq:dd-sdk-android-webview:2.3.0" + implementation "com.datadoghq:dd-sdk-android-rum:2.4.0" + implementation "com.datadoghq:dd-sdk-android-logs:2.4.0" + implementation "com.datadoghq:dd-sdk-android-trace:2.4.0" + implementation "com.datadoghq:dd-sdk-android-webview:2.4.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" testImplementation "org.junit.jupiter:junit-jupiter-engine:5.6.2" diff --git a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/ActionEventForgeryFactory.kt b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/ActionEventForgeryFactory.kt index 994f28703..ddfdbb2b3 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/ActionEventForgeryFactory.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/ActionEventForgeryFactory.kt @@ -79,7 +79,7 @@ internal class ActionEventForgeryFactory : type = ActionEvent.ActionEventSessionType.USER, hasReplay = forge.aNullable { aBool() } ), - source = forge.aNullable { aValueFrom(ActionEvent.Source::class.java) }, + source = forge.aNullable { aValueFrom(ActionEvent.ActionEventSource::class.java) }, ciTest = forge.aNullable { ActionEvent.CiTest(anHexadecimalString()) }, diff --git a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/ResourceEventForgeryFactory.kt b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/ResourceEventForgeryFactory.kt index dae18a67d..a4b7288b0 100644 --- a/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/ResourceEventForgeryFactory.kt +++ b/packages/core/android/src/test/kotlin/com/datadog/tools/unit/forge/ResourceEventForgeryFactory.kt @@ -87,7 +87,7 @@ internal class ResourceEventForgeryFactory : type = ResourceEvent.ResourceEventSessionType.USER, hasReplay = forge.aNullable { aBool() } ), - source = forge.aNullable { aValueFrom(ResourceEvent.Source::class.java) }, + source = forge.aNullable { aValueFrom(ResourceEvent.ResourceEventSource::class.java) }, ciTest = forge.aNullable { ResourceEvent.CiTest(anHexadecimalString()) }, diff --git a/packages/react-native-session-replay/android/build.gradle b/packages/react-native-session-replay/android/build.gradle index 7a3585d48..8b74366d1 100644 --- a/packages/react-native-session-replay/android/build.gradle +++ b/packages/react-native-session-replay/android/build.gradle @@ -169,7 +169,7 @@ dependencies { api "com.facebook.react:react-android:$reactNativeVersion" } implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "com.datadoghq:dd-sdk-android-session-replay:2.3.0" + implementation "com.datadoghq:dd-sdk-android-session-replay:2.4.0" testImplementation "org.junit.platform:junit-platform-launcher:1.6.2" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2" diff --git a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt index c415e9734..ad1dee845 100644 --- a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt +++ b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt @@ -13,6 +13,8 @@ import com.datadog.android.sessionreplay.ExtensionSupport import com.datadog.android.sessionreplay.SessionReplayPrivacy import com.datadog.android.sessionreplay.internal.recorder.OptionSelectorDetector import com.datadog.android.sessionreplay.internal.recorder.mapper.WireframeMapper +import com.datadog.reactnative.sessionreplay.mappers.ReactMaskInputTextMapper +import com.datadog.reactnative.sessionreplay.mappers.ReactMaskTextMapper import com.datadog.reactnative.sessionreplay.mappers.ReactTextMapper import com.datadog.reactnative.sessionreplay.mappers.ReactViewGroupMapper import com.facebook.react.bridge.ReactContext @@ -34,10 +36,20 @@ internal class ReactNativeSessionReplayExtensionSupport( ReactViewGroup::class.java to ReactViewGroupMapper(), ReactTextView::class.java to ReactTextMapper(reactContext, uiManagerModule), ReactEditText::class.java to ReactTextMapper(reactContext, uiManagerModule) - ).mapValues{ - it.value as WireframeMapper - } - ) + ), + SessionReplayPrivacy.MASK to mapOf( + ReactViewGroup::class.java to ReactViewGroupMapper(), + ReactTextView::class.java to ReactMaskTextMapper(reactContext, uiManagerModule), + ReactEditText::class.java to ReactMaskTextMapper(reactContext, uiManagerModule) + ), + SessionReplayPrivacy.MASK_USER_INPUT to mapOf( + ReactViewGroup::class.java to ReactViewGroupMapper(), + ReactTextView::class.java to ReactMaskInputTextMapper(reactContext, uiManagerModule), + ReactEditText::class.java to ReactMaskInputTextMapper(reactContext, uiManagerModule) + ) + ).mapValues { + it.value as Map, WireframeMapper> + } } override fun getOptionSelectorDetectors(): List { diff --git a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactMaskInputTextMapper.kt b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactMaskInputTextMapper.kt new file mode 100644 index 000000000..63080b045 --- /dev/null +++ b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactMaskInputTextMapper.kt @@ -0,0 +1,55 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.reactnative.sessionreplay.mappers + +import android.widget.TextView +import com.datadog.android.sessionreplay.internal.AsyncJobStatusCallback +import com.datadog.android.sessionreplay.internal.recorder.MappingContext +import com.datadog.android.sessionreplay.internal.recorder.mapper.MaskInputTextViewMapper +import com.datadog.android.sessionreplay.model.MobileSegment +import com.datadog.reactnative.sessionreplay.NoopTextPropertiesResolver +import com.datadog.reactnative.sessionreplay.ReactTextPropertiesResolver +import com.datadog.reactnative.sessionreplay.TextPropertiesResolver +import com.datadog.reactnative.sessionreplay.utils.TextViewUtils +import com.facebook.react.bridge.ReactContext +import com.facebook.react.uimanager.UIManagerModule + +internal class ReactMaskInputTextMapper( + private val reactTextPropertiesResolver: TextPropertiesResolver = + NoopTextPropertiesResolver(), + private val textViewUtils: TextViewUtils = TextViewUtils() +): MaskInputTextViewMapper() { + + internal constructor( + reactContext: ReactContext, + uiManagerModule: UIManagerModule? + ): this( + reactTextPropertiesResolver = if (uiManagerModule == null) { + NoopTextPropertiesResolver() + } else { + ReactTextPropertiesResolver( + reactContext = reactContext, + uiManagerModule = uiManagerModule + ) + } + ) + + override fun map( + view: TextView, + mappingContext: MappingContext, + asyncJobStatusCallback: AsyncJobStatusCallback + ): List { + val wireframes = super.map(view, mappingContext, asyncJobStatusCallback) + return textViewUtils.mapTextViewToWireframes( + wireframes = wireframes, + view = view, + mappingContext = mappingContext, + reactTextPropertiesResolver = reactTextPropertiesResolver + ) + } +} + diff --git a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactMaskTextMapper.kt b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactMaskTextMapper.kt new file mode 100644 index 000000000..e7aa2b2d5 --- /dev/null +++ b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactMaskTextMapper.kt @@ -0,0 +1,55 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.reactnative.sessionreplay.mappers + +import android.widget.TextView +import com.datadog.android.sessionreplay.internal.AsyncJobStatusCallback +import com.datadog.android.sessionreplay.internal.recorder.MappingContext +import com.datadog.android.sessionreplay.internal.recorder.mapper.MaskTextViewMapper +import com.datadog.android.sessionreplay.model.MobileSegment +import com.datadog.reactnative.sessionreplay.NoopTextPropertiesResolver +import com.datadog.reactnative.sessionreplay.ReactTextPropertiesResolver +import com.datadog.reactnative.sessionreplay.TextPropertiesResolver +import com.datadog.reactnative.sessionreplay.utils.TextViewUtils +import com.facebook.react.bridge.ReactContext +import com.facebook.react.uimanager.UIManagerModule + +internal class ReactMaskTextMapper( + private val reactTextPropertiesResolver: TextPropertiesResolver = + NoopTextPropertiesResolver(), + private val textViewUtils: TextViewUtils = TextViewUtils() +): MaskTextViewMapper() { + + internal constructor( + reactContext: ReactContext, + uiManagerModule: UIManagerModule? + ): this( + reactTextPropertiesResolver = if (uiManagerModule == null) { + NoopTextPropertiesResolver() + } else { + ReactTextPropertiesResolver( + reactContext = reactContext, + uiManagerModule = uiManagerModule + ) + } + ) + + override fun map( + view: TextView, + mappingContext: MappingContext, + asyncJobStatusCallback: AsyncJobStatusCallback + ): List { + val wireframes = super.map(view, mappingContext, asyncJobStatusCallback) + return textViewUtils.mapTextViewToWireframes( + wireframes = wireframes, + view = view, + mappingContext = mappingContext, + reactTextPropertiesResolver = reactTextPropertiesResolver + ) + } +} + diff --git a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt index 6b5330912..4ff59505c 100644 --- a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt +++ b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt @@ -7,7 +7,6 @@ package com.datadog.reactnative.sessionreplay.mappers import android.widget.TextView -import androidx.annotation.VisibleForTesting import com.datadog.android.sessionreplay.internal.AsyncJobStatusCallback import com.datadog.android.sessionreplay.internal.recorder.MappingContext import com.datadog.android.sessionreplay.internal.recorder.mapper.TextViewMapper @@ -15,12 +14,14 @@ import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.reactnative.sessionreplay.NoopTextPropertiesResolver import com.datadog.reactnative.sessionreplay.ReactTextPropertiesResolver import com.datadog.reactnative.sessionreplay.TextPropertiesResolver +import com.datadog.reactnative.sessionreplay.utils.TextViewUtils import com.facebook.react.bridge.ReactContext import com.facebook.react.uimanager.UIManagerModule internal class ReactTextMapper( private val reactTextPropertiesResolver: TextPropertiesResolver = - NoopTextPropertiesResolver() + NoopTextPropertiesResolver(), + private val textViewUtils: TextViewUtils = TextViewUtils() ): TextViewMapper() { internal constructor( @@ -42,31 +43,12 @@ internal class ReactTextMapper( mappingContext: MappingContext, asyncJobStatusCallback: AsyncJobStatusCallback ): List { - val result = mutableListOf() - val wireframes = mapOnSuperclass(view, mappingContext, asyncJobStatusCallback) - val pixelDensity = mappingContext.systemInformation.screenDensity - - wireframes.forEach { originalWireframe -> - if (originalWireframe !is MobileSegment.Wireframe.TextWireframe) { - result.add(originalWireframe) - } else { - result.add(reactTextPropertiesResolver.addReactNativeProperties( - originalWireframe = originalWireframe, - view = view, - pixelDensity = pixelDensity, - )) - } - } - - return result - } - - @VisibleForTesting - internal fun mapOnSuperclass( - textView: TextView, - mappingContext: MappingContext, - asyncJobStatusCallback: AsyncJobStatusCallback - ): List { - return super.map(textView, mappingContext, asyncJobStatusCallback) + val wireframes = super.map(view, mappingContext, asyncJobStatusCallback) + return textViewUtils.mapTextViewToWireframes( + wireframes = wireframes, + view = view, + mappingContext = mappingContext, + reactTextPropertiesResolver = reactTextPropertiesResolver + ) } } diff --git a/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtils.kt b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtils.kt new file mode 100644 index 000000000..021990d07 --- /dev/null +++ b/packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtils.kt @@ -0,0 +1,40 @@ +/* + * + * * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * * This product includes software developed at Datadog (https://www.datadoghq.com/). + * * Copyright 2016-Present Datadog, Inc. + * + */ + +package com.datadog.reactnative.sessionreplay.utils + +import android.widget.TextView +import com.datadog.android.sessionreplay.internal.recorder.MappingContext +import com.datadog.android.sessionreplay.model.MobileSegment +import com.datadog.reactnative.sessionreplay.TextPropertiesResolver + +internal class TextViewUtils { + internal fun mapTextViewToWireframes( + wireframes: List, + view: TextView, + mappingContext: MappingContext, + reactTextPropertiesResolver: TextPropertiesResolver + ): List { + val result = mutableListOf() + val pixelDensity = mappingContext.systemInformation.screenDensity + + wireframes.forEach { originalWireframe -> + if (originalWireframe !is MobileSegment.Wireframe.TextWireframe) { + result.add(originalWireframe) + } else { + result.add(reactTextPropertiesResolver.addReactNativeProperties( + originalWireframe = originalWireframe, + view = view, + pixelDensity = pixelDensity, + )) + } + } + + return result + } +} diff --git a/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt b/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt index 93c931c03..d393d30da 100644 --- a/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt +++ b/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt @@ -8,6 +8,8 @@ package com.datadog.reactnative.sessionreplay import com.datadog.android.api.InternalLogger import com.datadog.android.sessionreplay.SessionReplayPrivacy +import com.datadog.reactnative.sessionreplay.mappers.ReactMaskInputTextMapper +import com.datadog.reactnative.sessionreplay.mappers.ReactMaskTextMapper import com.datadog.reactnative.sessionreplay.mappers.ReactTextMapper import com.datadog.reactnative.sessionreplay.mappers.ReactViewGroupMapper import com.facebook.react.bridge.NativeModule @@ -76,6 +78,40 @@ internal class ReactNativeSessionReplayExtensionSupportTest { .isInstanceOf(ReactTextMapper::class.java) } + @Test + fun `M get mask input mappers W getCustomViewMappers()`() { + // When + val customViewMappers = testedExtensionSupport.getCustomViewMappers() + val maskUserInputMappers = customViewMappers[SessionReplayPrivacy.MASK_USER_INPUT] + + // Then + check(maskUserInputMappers != null) + assertThat(maskUserInputMappers).hasSize(3) + assertThat(maskUserInputMappers[ReactViewGroup::class.java]) + .isInstanceOf(ReactViewGroupMapper::class.java) + assertThat(maskUserInputMappers[ReactTextView::class.java]) + .isInstanceOf(ReactMaskInputTextMapper::class.java) + assertThat(maskUserInputMappers[ReactEditText::class.java]) + .isInstanceOf(ReactMaskInputTextMapper::class.java) + } + + @Test + fun `M get mask mappers W getCustomViewMappers()`() { + // When + val customViewMappers = testedExtensionSupport.getCustomViewMappers() + val maskMappers = customViewMappers[SessionReplayPrivacy.MASK] + + // Then + check(maskMappers != null) + assertThat(maskMappers).hasSize(3) + assertThat(maskMappers[ReactViewGroup::class.java]) + .isInstanceOf(ReactViewGroupMapper::class.java) + assertThat(maskMappers[ReactTextView::class.java]) + .isInstanceOf(ReactMaskTextMapper::class.java) + assertThat(maskMappers[ReactEditText::class.java]) + .isInstanceOf(ReactMaskTextMapper::class.java) + } + @Test fun `M return null W getUiManagerModule() { cannot get uiManagerModule }`() { // Given diff --git a/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ColorUtilsTest.kt b/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/ColorUtilsTest.kt similarity index 91% rename from packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ColorUtilsTest.kt rename to packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/ColorUtilsTest.kt index fc8ae3ac8..6580cf61c 100644 --- a/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ColorUtilsTest.kt +++ b/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/ColorUtilsTest.kt @@ -4,9 +4,8 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.reactnative.sessionreplay +package com.datadog.reactnative.sessionreplay.utils -import com.datadog.reactnative.sessionreplay.utils.formatAsRgba import fr.xgouchet.elmyr.junit5.ForgeExtension import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test diff --git a/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/DrawableUtilsTest.kt b/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/DrawableUtilsTest.kt similarity index 96% rename from packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/DrawableUtilsTest.kt rename to packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/DrawableUtilsTest.kt index 5e2668bc2..f71c351d7 100644 --- a/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/DrawableUtilsTest.kt +++ b/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/DrawableUtilsTest.kt @@ -4,12 +4,11 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.reactnative.sessionreplay +package com.datadog.reactnative.sessionreplay.utils import android.graphics.drawable.ColorDrawable import android.graphics.drawable.InsetDrawable import android.graphics.drawable.LayerDrawable -import com.datadog.reactnative.sessionreplay.utils.DrawableUtils import com.facebook.react.views.view.ReactViewBackgroundDrawable import fr.xgouchet.elmyr.junit5.ForgeExtension import org.assertj.core.api.Assertions.assertThat diff --git a/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapperTest.kt b/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtilsTest.kt similarity index 61% rename from packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapperTest.kt rename to packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtilsTest.kt index 29ff84190..ea758d3c4 100644 --- a/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapperTest.kt +++ b/packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtilsTest.kt @@ -4,13 +4,12 @@ * Copyright 2016-Present Datadog, Inc. */ -package com.datadog.reactnative.sessionreplay.mappers +package com.datadog.reactnative.sessionreplay.utils import android.content.res.Resources import android.graphics.Typeface import android.util.DisplayMetrics import android.widget.TextView -import com.datadog.android.sessionreplay.internal.AsyncJobStatusCallback import com.datadog.android.sessionreplay.internal.recorder.MappingContext import com.datadog.android.sessionreplay.internal.recorder.SystemInformation import com.datadog.android.sessionreplay.model.MobileSegment @@ -23,10 +22,10 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.extension.Extensions import org.mockito.Mock +import org.mockito.Mockito.spy import org.mockito.junit.jupiter.MockitoExtension import org.mockito.junit.jupiter.MockitoSettings import org.mockito.kotlin.eq -import org.mockito.kotlin.spy import org.mockito.kotlin.whenever import org.mockito.quality.Strictness @@ -35,8 +34,8 @@ import org.mockito.quality.Strictness ExtendWith(ForgeExtension::class) ) @MockitoSettings(strictness = Strictness.LENIENT) -internal class ReactTextMapperTest { - private lateinit var testedMapper: ReactTextMapper +internal class TextViewUtilsTest { + private lateinit var testedUtils: TextViewUtils @Mock private lateinit var mockReactTextPropertiesResolver: ReactTextPropertiesResolver @@ -44,9 +43,6 @@ internal class ReactTextMapperTest { @Mock private lateinit var mockMappingContext: MappingContext - @Mock - private lateinit var mockAsyncJobStatusCallback: AsyncJobStatusCallback - @Mock private lateinit var mockTextView: TextView @@ -59,9 +55,6 @@ internal class ReactTextMapperTest { @Mock private lateinit var mockDisplayMetrics: DisplayMetrics - @Mock - private lateinit var mockTextWireframe: MobileSegment.Wireframe.TextWireframe - @BeforeEach fun `set up`(forge: Forge) { whenever(mockResources.displayMetrics).thenReturn(mockDisplayMetrics) @@ -71,56 +64,30 @@ internal class ReactTextMapperTest { whenever(mockTextView.text).thenReturn(forge.aString()) whenever(mockTextView.typeface).thenReturn(Typeface.SANS_SERIF) - whenever( - mockReactTextPropertiesResolver.addReactNativeProperties( - originalWireframe = eq(mockTextWireframe), - view = eq(mockTextView), - pixelDensity = eq(0f) - ) - ).thenReturn(mockTextWireframe) - - testedMapper = spy( - ReactTextMapper( - reactTextPropertiesResolver = mockReactTextPropertiesResolver - ) - ) + testedUtils = spy(TextViewUtils()) } @Test fun `M return wireframe W map() { even if not TextWireframeType }`( @Mock mockImageWireframe: MobileSegment.Wireframe.ImageWireframe ) { - // Given - whenever( - testedMapper.mapOnSuperclass( - textView = eq(mockTextView), - mappingContext = eq(mockMappingContext), - asyncJobStatusCallback = eq(mockAsyncJobStatusCallback) - ) - ).thenReturn( - listOf(mockImageWireframe) - ) - // When - val result = testedMapper.map(mockTextView, mockMappingContext, mockAsyncJobStatusCallback) + val result = testedUtils.mapTextViewToWireframes( + wireframes = listOf(mockImageWireframe), + view = mockTextView, + mappingContext = mockMappingContext, + reactTextPropertiesResolver = mockReactTextPropertiesResolver + ) // Then assertThat(result).contains(mockImageWireframe) } @Test - fun `M return textWireframe W map()`() { + fun `M return textWireframe W map()`( + @Mock mockTextWireframe: MobileSegment.Wireframe.TextWireframe + ) { // Given - whenever( - testedMapper.mapOnSuperclass( - textView = eq(mockTextView), - mappingContext = eq(mockMappingContext), - asyncJobStatusCallback = eq(mockAsyncJobStatusCallback) - ) - ).thenReturn( - listOf(mockTextWireframe) - ) - whenever( mockReactTextPropertiesResolver.addReactNativeProperties( originalWireframe = eq(mockTextWireframe), @@ -130,13 +97,14 @@ internal class ReactTextMapperTest { ).thenReturn(mockTextWireframe) // When - val result = testedMapper.map( - mockTextView, - mockMappingContext, - mockAsyncJobStatusCallback + val result = testedUtils.mapTextViewToWireframes( + wireframes = listOf(mockTextWireframe), + view = mockTextView, + mappingContext = mockMappingContext, + reactTextPropertiesResolver = mockReactTextPropertiesResolver )[0] as MobileSegment.Wireframe.TextWireframe // Then - assertThat(result.text).isEqualTo(mockTextWireframe.text) + assertThat(result).isEqualTo(mockTextWireframe) } }