@datadog/mobile-react-native-session-replay 2.0.2-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DatadogSDKReactNativeSessionReplay.podspec +41 -0
- package/README.md +3 -0
- package/android/build.gradle +239 -0
- package/android/detekt.yml +572 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +11 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/DatadogSDKReactNativeSessionReplayPackage.kt +46 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementation.kt +57 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/NoopTextPropertiesResolver.kt +22 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt +77 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt +196 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/SessionReplaySDKWrapper.kt +24 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/SessionReplayWrapper.kt +22 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt +70 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/TextPropertiesResolver.kt +20 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/extensions/LongExt.kt +15 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactMaskInputTextMapper.kt +54 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactMaskTextMapper.kt +55 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt +54 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactViewGroupMapper.kt +58 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ColorUtils.kt +22 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/DrawableUtils.kt +35 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.kt +66 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ReflectionUtils.kt +30 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtils.kt +40 -0
- package/android/src/newarch/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplay.kt +33 -0
- package/android/src/oldarch/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplay.kt +34 -0
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementationTest.kt +105 -0
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt +127 -0
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolverTest.kt +271 -0
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactViewGroupMapperTest.kt +131 -0
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/ColorUtilsTest.kt +42 -0
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/DrawableUtilsTest.kt +101 -0
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtilsTest.kt +109 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/GenericAssert.kt +69 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/MapExt.kt +29 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/ReflectUtils.kt +266 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/forge/BaseConfigurator.kt +24 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/forge/ForgeConfigurator.kt +24 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/forge/TextWireframeForgeryFactory.kt +64 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/forge/Throwable.kt +31 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/forge/ThrowableForgeryFactory.kt +21 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/forge/WireframeClipForgeryFactory.kt +25 -0
- package/android/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker +1 -0
- package/ios/DatadogSDKReactNativeSessionReplay.xcodeproj/project.pbxproj +272 -0
- package/ios/DatadogSDKReactNativeSessionReplay.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/ios/Sources/DatadogSDKReactNativeSessionReplay.h +8 -0
- package/ios/Sources/DdSessionReplay.h +24 -0
- package/ios/Sources/DdSessionReplay.mm +53 -0
- package/ios/Sources/DdSessionReplayImplementation.swift +70 -0
- package/ios/Sources/RCTTextViewRecorder.swift +157 -0
- package/lib/commonjs/SessionReplay.js +66 -0
- package/lib/commonjs/SessionReplay.js.map +1 -0
- package/lib/commonjs/index.js +26 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/nativeModulesTypes.js +2 -0
- package/lib/commonjs/nativeModulesTypes.js.map +1 -0
- package/lib/commonjs/specs/NativeDdSessionReplay.js +20 -0
- package/lib/commonjs/specs/NativeDdSessionReplay.js.map +1 -0
- package/lib/module/SessionReplay.js +53 -0
- package/lib/module/SessionReplay.js.map +1 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/nativeModulesTypes.js +2 -0
- package/lib/module/nativeModulesTypes.js.map +1 -0
- package/lib/module/specs/NativeDdSessionReplay.js +14 -0
- package/lib/module/specs/NativeDdSessionReplay.js.map +1 -0
- package/lib/typescript/SessionReplay.d.ts +34 -0
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/nativeModulesTypes.d.ts +18 -0
- package/lib/typescript/specs/NativeDdSessionReplay.d.ts +15 -0
- package/package.json +90 -0
- package/src/SessionReplay.ts +84 -0
- package/src/__tests__/SessionReplay.test.ts +49 -0
- package/src/index.ts +13 -0
- package/src/nativeModulesTypes.ts +29 -0
- package/src/specs/NativeDdSessionReplay.ts +28 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
3
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
|
+
* Copyright 2016-Present Datadog, Inc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
package com.datadog.tools.unit
|
|
8
|
+
|
|
9
|
+
import org.assertj.core.api.AbstractAssert
|
|
10
|
+
import org.assertj.core.api.Assertions.assertThat
|
|
11
|
+
|
|
12
|
+
class GenericAssert(actual: Any?) :
|
|
13
|
+
AbstractAssert<GenericAssert, Any>(actual, GenericAssert::class.java) {
|
|
14
|
+
|
|
15
|
+
fun doesNotHaveField(name: String): GenericAssert {
|
|
16
|
+
val field: Any? = actual.getFieldValue(name)
|
|
17
|
+
assertThat(field)
|
|
18
|
+
.overridingErrorMessage(
|
|
19
|
+
"Expecting object to not have $name, but found it having value $field"
|
|
20
|
+
)
|
|
21
|
+
.isNull()
|
|
22
|
+
return this
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
fun <T> getActualValue(name: String): T {
|
|
26
|
+
val field: Any? = actual.getFieldValue(name)
|
|
27
|
+
assertThat(field)
|
|
28
|
+
.overridingErrorMessage(
|
|
29
|
+
"Expecting object to have a non null field named $name, but field was null"
|
|
30
|
+
)
|
|
31
|
+
.isNotNull()
|
|
32
|
+
return field!! as T
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fun hasField(name: String, nestedAssert: (GenericAssert) -> Unit = {}): GenericAssert {
|
|
36
|
+
val field: Any? = actual.getFieldValue(name)
|
|
37
|
+
assertThat(field)
|
|
38
|
+
.overridingErrorMessage(
|
|
39
|
+
"Expecting object to have a non null field named $name, but field was null"
|
|
40
|
+
)
|
|
41
|
+
.isNotNull()
|
|
42
|
+
nestedAssert(GenericAssert(field!!))
|
|
43
|
+
return this
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fun <F> hasFieldEqualTo(name: String, expected: F): GenericAssert {
|
|
47
|
+
val field: Any? = actual.getFieldValue(name)
|
|
48
|
+
assertThat(field).isEqualTo(expected)
|
|
49
|
+
return this
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fun hasFieldWithClass(name: String, expectedClassName: String): GenericAssert {
|
|
53
|
+
val field: Any? = actual.getFieldValue(name)
|
|
54
|
+
assertThat(field?.javaClass?.name).isEqualTo(expectedClassName)
|
|
55
|
+
return this
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fun isInstanceOf(expectedClassName: String): GenericAssert {
|
|
59
|
+
val className = actual.javaClass.canonicalName!!
|
|
60
|
+
assertThat(className).isEqualTo(expectedClassName)
|
|
61
|
+
return this
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
companion object {
|
|
65
|
+
fun assertThat(actual: Any?): GenericAssert {
|
|
66
|
+
return GenericAssert(actual)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
3
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
|
+
* Copyright 2016-Present Datadog, Inc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
package com.datadog.tools.unit
|
|
8
|
+
|
|
9
|
+
import com.facebook.react.bridge.JavaOnlyArray
|
|
10
|
+
import com.facebook.react.bridge.JavaOnlyMap
|
|
11
|
+
import com.facebook.react.bridge.ReadableArray
|
|
12
|
+
import com.facebook.react.bridge.ReadableMap
|
|
13
|
+
|
|
14
|
+
fun Map<*, *>.toReadableMap(): ReadableMap {
|
|
15
|
+
val keysAndValues = mutableListOf<Any?>()
|
|
16
|
+
|
|
17
|
+
entries.forEach {
|
|
18
|
+
keysAndValues.add(it.key)
|
|
19
|
+
keysAndValues.add(it.value)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// this FB implementation is not backed by Android-specific .so library, so ok for unit tests
|
|
23
|
+
return JavaOnlyMap.of(*keysAndValues.toTypedArray())
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
fun List<*>.toReadableArray(): ReadableArray {
|
|
27
|
+
// this FB implementation is not backed by Android-specific .so library, so ok for unit tests
|
|
28
|
+
return JavaOnlyArray.from(this)
|
|
29
|
+
}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
3
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
|
+
* Copyright 2016-Present Datadog, Inc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
package com.datadog.tools.unit
|
|
8
|
+
|
|
9
|
+
import java.lang.reflect.Field
|
|
10
|
+
import java.lang.reflect.InvocationTargetException
|
|
11
|
+
import java.lang.reflect.Method
|
|
12
|
+
import java.lang.reflect.Modifier
|
|
13
|
+
import java.util.LinkedList
|
|
14
|
+
import kotlin.reflect.jvm.isAccessible
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates an instance of the given class name.
|
|
18
|
+
* @param className the full name of the class to instantiate
|
|
19
|
+
* @param params the parameters to provide the constructor
|
|
20
|
+
* @return the created instance
|
|
21
|
+
*/
|
|
22
|
+
@Suppress("SpreadOperator")
|
|
23
|
+
fun createInstance(
|
|
24
|
+
className: String,
|
|
25
|
+
vararg params: Any?
|
|
26
|
+
): Any {
|
|
27
|
+
return Class.forName(className)
|
|
28
|
+
.kotlin
|
|
29
|
+
.constructors.first()
|
|
30
|
+
.apply { isAccessible = true }
|
|
31
|
+
.call(*params)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Sets a static value on the target class.
|
|
36
|
+
* @param fieldName the name of the field
|
|
37
|
+
* @param fieldValue the value to set
|
|
38
|
+
*/
|
|
39
|
+
@Suppress("SwallowedException")
|
|
40
|
+
inline fun <reified T, R> Class<T>.setStaticValue(
|
|
41
|
+
fieldName: String,
|
|
42
|
+
fieldValue: R
|
|
43
|
+
) {
|
|
44
|
+
val field = getDeclaredField(fieldName)
|
|
45
|
+
|
|
46
|
+
// make it accessible
|
|
47
|
+
field.isAccessible = true
|
|
48
|
+
|
|
49
|
+
// Make it non final
|
|
50
|
+
try {
|
|
51
|
+
val modifiersField = Field::class.java.getDeclaredField("modifiers")
|
|
52
|
+
modifiersField.isAccessible = true
|
|
53
|
+
modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv())
|
|
54
|
+
} catch (e: NoSuchFieldException) {
|
|
55
|
+
// do nothing
|
|
56
|
+
@Suppress("PrintStackTrace")
|
|
57
|
+
e.printStackTrace()
|
|
58
|
+
}
|
|
59
|
+
field.set(null, fieldValue)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Gets the static value from the target class.
|
|
64
|
+
* @param className the full name of the class
|
|
65
|
+
* @param fieldName the name of the field
|
|
66
|
+
*/
|
|
67
|
+
inline fun <reified R> getStaticValue(
|
|
68
|
+
className: String,
|
|
69
|
+
fieldName: String
|
|
70
|
+
): R {
|
|
71
|
+
val clazz = Class.forName(className)
|
|
72
|
+
val field = clazz.getDeclaredField(fieldName)
|
|
73
|
+
// make it accessible
|
|
74
|
+
field.isAccessible = true
|
|
75
|
+
|
|
76
|
+
return field.get(null) as R
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Gets the static value from the target class.
|
|
81
|
+
* @param fieldName the name of the field
|
|
82
|
+
*/
|
|
83
|
+
inline fun <reified T, reified R> Class<T>.getStaticValue(fieldName: String): R {
|
|
84
|
+
val field = getDeclaredField(fieldName)
|
|
85
|
+
|
|
86
|
+
// make it accessible
|
|
87
|
+
field.isAccessible = true
|
|
88
|
+
|
|
89
|
+
return field.get(null) as R
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Sets the field value on the target instance.
|
|
94
|
+
* @param fieldName the name of the field
|
|
95
|
+
* @param fieldValue the value of the field
|
|
96
|
+
*/
|
|
97
|
+
@Suppress("SwallowedException")
|
|
98
|
+
inline fun <reified T> Any.setFieldValue(
|
|
99
|
+
fieldName: String,
|
|
100
|
+
fieldValue: T
|
|
101
|
+
): Boolean {
|
|
102
|
+
var field: Field? = null
|
|
103
|
+
val classesToSearch = LinkedList<Class<*>>()
|
|
104
|
+
classesToSearch.add(this.javaClass)
|
|
105
|
+
val classesSearched = mutableSetOf<Class<*>>()
|
|
106
|
+
|
|
107
|
+
while (field == null && classesToSearch.isNotEmpty()) {
|
|
108
|
+
val toSearchIn = classesToSearch.remove()
|
|
109
|
+
try {
|
|
110
|
+
field = toSearchIn.getDeclaredField(fieldName)
|
|
111
|
+
} catch (e: NoSuchFieldException) {
|
|
112
|
+
// do nothing
|
|
113
|
+
}
|
|
114
|
+
classesSearched.add(toSearchIn)
|
|
115
|
+
toSearchIn.superclass?.let {
|
|
116
|
+
if (!classesSearched.contains(it)) {
|
|
117
|
+
classesToSearch.add(it)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// make it accessible
|
|
123
|
+
if (field != null) {
|
|
124
|
+
field.isAccessible = true
|
|
125
|
+
|
|
126
|
+
// Make it non final
|
|
127
|
+
val modifiersField = Field::class.java.getDeclaredField("modifiers")
|
|
128
|
+
modifiersField.isAccessible = true
|
|
129
|
+
modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv())
|
|
130
|
+
|
|
131
|
+
field.set(this, fieldValue)
|
|
132
|
+
return true
|
|
133
|
+
} else {
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Gets the field value from the target instance.
|
|
140
|
+
* @param fieldName the name of the field
|
|
141
|
+
*/
|
|
142
|
+
inline fun <reified T, R : Any> R.getFieldValue(
|
|
143
|
+
fieldName: String,
|
|
144
|
+
enclosingClass: Class<R> = this.javaClass
|
|
145
|
+
): T {
|
|
146
|
+
val field = enclosingClass.getDeclaredField(fieldName)
|
|
147
|
+
field.isAccessible = true
|
|
148
|
+
return field.get(this) as T
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Invokes a method on the target instance.
|
|
153
|
+
* @param methodName the name of the method
|
|
154
|
+
* @param params the parameters to provide the method
|
|
155
|
+
* @return the result from the invoked method
|
|
156
|
+
*/
|
|
157
|
+
@Suppress("SpreadOperator", "UNCHECKED_CAST", "TooGenericExceptionCaught")
|
|
158
|
+
fun <T : Any> T.invokeMethod(
|
|
159
|
+
methodName: String,
|
|
160
|
+
vararg params: Any?
|
|
161
|
+
): Any? {
|
|
162
|
+
val declarationParams = Array<Class<*>?>(params.size) {
|
|
163
|
+
params[it]?.javaClass
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
val method = getDeclaredMethodRecursively(methodName, true, declarationParams)
|
|
167
|
+
val wasAccessible = method.isAccessible
|
|
168
|
+
|
|
169
|
+
val output: Any?
|
|
170
|
+
method.isAccessible = true
|
|
171
|
+
try {
|
|
172
|
+
output = if (params.isEmpty()) {
|
|
173
|
+
method.invoke(this)
|
|
174
|
+
} else {
|
|
175
|
+
method.invoke(this, *params)
|
|
176
|
+
}
|
|
177
|
+
} catch (e: InvocationTargetException) {
|
|
178
|
+
throw e.cause ?: e
|
|
179
|
+
} finally {
|
|
180
|
+
method.isAccessible = wasAccessible
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return output
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Invokes a method on the target instance, where one or more of the parameters
|
|
188
|
+
* are generics.
|
|
189
|
+
* @param methodName the name of the method
|
|
190
|
+
* @param params the parameters to provide the method
|
|
191
|
+
* @return the result from the invoked method
|
|
192
|
+
*/
|
|
193
|
+
@Suppress("SpreadOperator", "UNCHECKED_CAST")
|
|
194
|
+
fun <T : Any> T.invokeGenericMethod(
|
|
195
|
+
methodName: String,
|
|
196
|
+
vararg params: Any
|
|
197
|
+
): Any? {
|
|
198
|
+
val declarationParams = Array<Class<*>?>(params.size) {
|
|
199
|
+
params[it].javaClass
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
val method = getDeclaredMethodRecursively(methodName, false, declarationParams)
|
|
203
|
+
val wasAccessible = method.isAccessible
|
|
204
|
+
|
|
205
|
+
val output: Any?
|
|
206
|
+
method.isAccessible = true
|
|
207
|
+
try {
|
|
208
|
+
output = if (params.isEmpty()) {
|
|
209
|
+
method.invoke(this)
|
|
210
|
+
} else {
|
|
211
|
+
method.invoke(this, *params)
|
|
212
|
+
}
|
|
213
|
+
} catch (e: InvocationTargetException) {
|
|
214
|
+
throw e.cause ?: e
|
|
215
|
+
} finally {
|
|
216
|
+
method.isAccessible = wasAccessible
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return output
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@Suppress("TooGenericExceptionCaught", "SwallowedException", "SpreadOperator")
|
|
223
|
+
private fun <T : Any> T.getDeclaredMethodRecursively(
|
|
224
|
+
methodName: String,
|
|
225
|
+
matchingParams: Boolean,
|
|
226
|
+
declarationParams: Array<Class<*>?>
|
|
227
|
+
): Method {
|
|
228
|
+
val classesToSearch = mutableListOf<Class<*>>(this.javaClass)
|
|
229
|
+
val classesSearched = mutableListOf<Class<*>>()
|
|
230
|
+
var method: Method?
|
|
231
|
+
do {
|
|
232
|
+
val lookingInClass = classesToSearch.removeAt(0)
|
|
233
|
+
classesSearched.add(lookingInClass)
|
|
234
|
+
method = try {
|
|
235
|
+
if (matchingParams) {
|
|
236
|
+
lookingInClass.getDeclaredMethod(methodName, *declarationParams)
|
|
237
|
+
} else {
|
|
238
|
+
lookingInClass.declaredMethods.firstOrNull {
|
|
239
|
+
it.name == methodName &&
|
|
240
|
+
it.parameterTypes.size == declarationParams.size
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
} catch (e: Throwable) {
|
|
244
|
+
null
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
val superclass = lookingInClass.superclass
|
|
248
|
+
if (superclass != null &&
|
|
249
|
+
!classesToSearch.contains(superclass) &&
|
|
250
|
+
!classesSearched.contains(superclass)
|
|
251
|
+
) {
|
|
252
|
+
classesToSearch.add(superclass)
|
|
253
|
+
}
|
|
254
|
+
lookingInClass.interfaces.forEach {
|
|
255
|
+
if (!classesToSearch.contains(it) && !classesSearched.contains(it)) {
|
|
256
|
+
classesToSearch.add(it)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} while (method == null && classesToSearch.isNotEmpty())
|
|
260
|
+
|
|
261
|
+
checkNotNull(method) {
|
|
262
|
+
"Unable to access method $methodName on ${javaClass.canonicalName}"
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return method
|
|
266
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
3
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
|
+
* Copyright 2016-Present Datadog, Inc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
package com.datadog.tools.unit.forge
|
|
8
|
+
|
|
9
|
+
import fr.xgouchet.elmyr.Forge
|
|
10
|
+
import fr.xgouchet.elmyr.ForgeConfigurator
|
|
11
|
+
import fr.xgouchet.elmyr.jvm.useJvmFactories
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Base implementation of a [ForgeConfigurator], adding the JVM Forgery Factories (Date, …) and
|
|
15
|
+
* a [ThrowableForgeryFactory].
|
|
16
|
+
*/
|
|
17
|
+
open class BaseConfigurator :
|
|
18
|
+
ForgeConfigurator {
|
|
19
|
+
/** @inheritDoc */
|
|
20
|
+
override fun configure(forge: Forge) {
|
|
21
|
+
forge.addFactory(ThrowableForgeryFactory())
|
|
22
|
+
forge.useJvmFactories()
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
4
|
+
* * This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
5
|
+
* * Copyright 2016-Present Datadog, Inc.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
package com.datadog.reactnative.tools.unit.forge
|
|
10
|
+
|
|
11
|
+
import com.datadog.tools.unit.forge.BaseConfigurator
|
|
12
|
+
import fr.xgouchet.elmyr.Forge
|
|
13
|
+
import fr.xgouchet.elmyr.jvm.useJvmFactories
|
|
14
|
+
|
|
15
|
+
internal class ForgeConfigurator : BaseConfigurator() {
|
|
16
|
+
override fun configure(forge: Forge) {
|
|
17
|
+
super.configure(forge)
|
|
18
|
+
|
|
19
|
+
forge.addFactory(TextWireframeForgeryFactory())
|
|
20
|
+
forge.addFactory(WireframeClipForgeryFactory())
|
|
21
|
+
|
|
22
|
+
forge.useJvmFactories()
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
4
|
+
* * This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
5
|
+
* * Copyright 2016-Present Datadog, Inc.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
package com.datadog.reactnative.tools.unit.forge
|
|
10
|
+
|
|
11
|
+
import com.datadog.android.sessionreplay.model.MobileSegment
|
|
12
|
+
import fr.xgouchet.elmyr.Forge
|
|
13
|
+
import fr.xgouchet.elmyr.ForgeryFactory
|
|
14
|
+
|
|
15
|
+
internal class TextWireframeForgeryFactory :
|
|
16
|
+
ForgeryFactory<MobileSegment.Wireframe.TextWireframe> {
|
|
17
|
+
override fun getForgery(forge: Forge): MobileSegment.Wireframe.TextWireframe {
|
|
18
|
+
return MobileSegment.Wireframe.TextWireframe(
|
|
19
|
+
id = forge.aPositiveInt().toLong(),
|
|
20
|
+
x = forge.aPositiveLong(),
|
|
21
|
+
y = forge.aPositiveLong(),
|
|
22
|
+
width = forge.aPositiveLong(strict = true),
|
|
23
|
+
height = forge.aPositiveLong(strict = true),
|
|
24
|
+
text = forge.aString(),
|
|
25
|
+
shapeStyle = forge.aNullable {
|
|
26
|
+
MobileSegment.ShapeStyle(
|
|
27
|
+
forge.aStringMatching("#[0-9A-F]{6}FF"),
|
|
28
|
+
opacity = forge.aFloat(min = 0f, max = 1f),
|
|
29
|
+
cornerRadius = forge.aPositiveLong()
|
|
30
|
+
)
|
|
31
|
+
},
|
|
32
|
+
textStyle = MobileSegment.TextStyle(
|
|
33
|
+
family = forge.aString(),
|
|
34
|
+
size = forge.aPositiveLong(strict = true),
|
|
35
|
+
color = forge.aStringMatching("#[0-9A-F]{6}FF")
|
|
36
|
+
),
|
|
37
|
+
textPosition = forge.aNullable {
|
|
38
|
+
MobileSegment.TextPosition(
|
|
39
|
+
padding = forge.aNullable {
|
|
40
|
+
MobileSegment.Padding(
|
|
41
|
+
forge.aNullable { aPositiveLong() },
|
|
42
|
+
forge.aNullable { aPositiveLong() },
|
|
43
|
+
forge.aNullable { aPositiveLong() },
|
|
44
|
+
forge.aNullable { aPositiveLong() }
|
|
45
|
+
)
|
|
46
|
+
},
|
|
47
|
+
alignment = forge.aNullable {
|
|
48
|
+
MobileSegment.Alignment(
|
|
49
|
+
horizontal = forge.aNullable {
|
|
50
|
+
forge.aValueFrom(MobileSegment.Horizontal::class.java)
|
|
51
|
+
},
|
|
52
|
+
vertical = forge.aNullable {
|
|
53
|
+
forge.aValueFrom(MobileSegment.Vertical::class.java)
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
},
|
|
59
|
+
clip = forge.aNullable {
|
|
60
|
+
getForgery()
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
3
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
|
+
* Copyright 2016-Present Datadog, Inc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
package com.datadog.tools.unit.forge
|
|
8
|
+
|
|
9
|
+
import fr.xgouchet.elmyr.Forge
|
|
10
|
+
import fr.xgouchet.elmyr.ForgeryException
|
|
11
|
+
import java.io.FileNotFoundException
|
|
12
|
+
import java.io.IOException
|
|
13
|
+
import java.io.InvalidObjectException
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @return a random [Throwable] instance with a forged message.
|
|
17
|
+
*/
|
|
18
|
+
fun Forge.aThrowable(): Throwable {
|
|
19
|
+
val errorMessage = anAlphabeticalString()
|
|
20
|
+
return anElementFrom(
|
|
21
|
+
IOException(errorMessage),
|
|
22
|
+
IllegalStateException(errorMessage),
|
|
23
|
+
UnknownError(errorMessage),
|
|
24
|
+
ArrayIndexOutOfBoundsException(errorMessage),
|
|
25
|
+
NullPointerException(errorMessage),
|
|
26
|
+
ForgeryException(errorMessage),
|
|
27
|
+
InvalidObjectException(errorMessage),
|
|
28
|
+
UnsupportedOperationException(errorMessage),
|
|
29
|
+
FileNotFoundException(errorMessage)
|
|
30
|
+
)
|
|
31
|
+
}
|
package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/forge/ThrowableForgeryFactory.kt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
3
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
|
+
* Copyright 2016-Present Datadog, Inc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
package com.datadog.tools.unit.forge
|
|
8
|
+
|
|
9
|
+
import fr.xgouchet.elmyr.Forge
|
|
10
|
+
import fr.xgouchet.elmyr.ForgeryFactory
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A [ForgeryFactory] generating a random [Throwable] instance with a forged message.
|
|
14
|
+
*/
|
|
15
|
+
class ThrowableForgeryFactory :
|
|
16
|
+
ForgeryFactory<Throwable> {
|
|
17
|
+
/** @inheritDoc */
|
|
18
|
+
override fun getForgery(forge: Forge): Throwable {
|
|
19
|
+
return forge.aThrowable()
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
4
|
+
* * This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
5
|
+
* * Copyright 2016-Present Datadog, Inc.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
package com.datadog.reactnative.tools.unit.forge
|
|
10
|
+
|
|
11
|
+
import com.datadog.android.sessionreplay.model.MobileSegment
|
|
12
|
+
import fr.xgouchet.elmyr.Forge
|
|
13
|
+
import fr.xgouchet.elmyr.ForgeryFactory
|
|
14
|
+
|
|
15
|
+
internal class WireframeClipForgeryFactory :
|
|
16
|
+
ForgeryFactory<MobileSegment.WireframeClip> {
|
|
17
|
+
override fun getForgery(forge: Forge): MobileSegment.WireframeClip {
|
|
18
|
+
return MobileSegment.WireframeClip(
|
|
19
|
+
top = forge.aNullable { aLong(min = 0, max = 100) },
|
|
20
|
+
bottom = forge.aNullable { aLong(min = 0, max = 100) },
|
|
21
|
+
left = forge.aNullable { aLong(min = 0, max = 100) },
|
|
22
|
+
right = forge.aNullable { aLong(min = 0, max = 100) }
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mock-maker-inline
|