@datadog/mobile-react-native-webview 2.4.4 → 2.5.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/DatadogSDKReactNativeWebView.podspec +46 -0
- package/android/build.gradle +249 -0
- package/android/detekt.yml +572 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +11 -0
- package/android/src/newarch/com/datadog/reactnative/webview/DdSdkReactNativeWebViewPackage.kt +35 -0
- package/android/src/oldarch/com/datadog/reactnative/webview/DdSdkReactNativeWebViewManager.kt +112 -0
- package/android/src/oldarch/com/datadog/reactnative/webview/DdSdkReactNativeWebViewPackage.kt +36 -0
- package/android/src/test/kotlin/com/datadog/reactnative/tools/unit/GenericAssert.kt +18 -0
- package/android/src/test/kotlin/com/datadog/reactnative/webview/DatadogWebViewTest.kt +126 -0
- package/android/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker +1 -0
- package/ios/DatadogSDKReactNativeWebView.xcodeproj/project.pbxproj +272 -0
- package/ios/DatadogSDKReactNativeWebView.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/ios/Sources/DatadogSDKReactNativeWebView.h +12 -0
- package/ios/Sources/RCTDatadogWebView.h +21 -0
- package/ios/Sources/RCTDatadogWebView.mm +53 -0
- package/ios/Sources/RCTDatadogWebViewManager.h +10 -0
- package/ios/Sources/RCTDatadogWebViewManager.mm +84 -0
- package/ios/Sources/RCTDatadogWebViewTracking.swift +67 -0
- package/lib/commonjs/ext-specs/NativeDdLogs.js +19 -0
- package/lib/commonjs/ext-specs/NativeDdLogs.js.map +1 -0
- package/lib/commonjs/ext-specs/NativeDdSdk.js.map +1 -0
- package/lib/commonjs/index.js +40 -7
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/NativeDdWebView.js +16 -0
- package/lib/commonjs/specs/NativeDdWebView.js.map +1 -0
- package/lib/commonjs/utils/env-utils.js +17 -0
- package/lib/commonjs/utils/env-utils.js.map +1 -0
- package/lib/commonjs/utils/webview-js-utils.js +124 -0
- package/lib/commonjs/utils/webview-js-utils.js.map +1 -0
- package/lib/module/ext-specs/NativeDdLogs.js +17 -0
- package/lib/module/ext-specs/NativeDdLogs.js.map +1 -0
- package/lib/module/ext-specs/NativeDdSdk.js.map +1 -0
- package/lib/module/index.js +39 -7
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/NativeDdWebView.js +11 -0
- package/lib/module/specs/NativeDdWebView.js.map +1 -0
- package/lib/module/utils/env-utils.js +10 -0
- package/lib/module/utils/env-utils.js.map +1 -0
- package/lib/module/utils/webview-js-utils.js +115 -0
- package/lib/module/utils/webview-js-utils.js.map +1 -0
- package/lib/typescript/ext-specs/NativeDdLogs.d.ts +16 -0
- package/lib/typescript/ext-specs/NativeDdLogs.d.ts.map +1 -0
- package/lib/typescript/ext-specs/NativeDdSdk.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +20 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/NativeDdWebView.d.ts +4 -0
- package/lib/typescript/specs/NativeDdWebView.d.ts.map +1 -0
- package/lib/typescript/utils/env-utils.d.ts +2 -0
- package/lib/typescript/utils/env-utils.d.ts.map +1 -0
- package/lib/typescript/utils/webview-js-utils.d.ts +34 -0
- package/lib/typescript/utils/webview-js-utils.d.ts.map +1 -0
- package/package.json +22 -4
- package/src/__tests__/WebviewDatadog.test.tsx +39 -43
- package/src/__tests__/WebviewDatadogInjectedJS.test.tsx +200 -1
- package/src/__tests__/WebviewDatadogPerformance.test.tsx +12 -0
- package/src/__tests__/__utils__/string-utils.ts +13 -0
- package/src/__tests__/webview-js-utils.test.ts +51 -0
- package/src/ext-specs/NativeDdLogs.ts +25 -0
- package/src/{NativeDdSdk.ts → ext-specs/NativeDdSdk.ts} +1 -0
- package/src/index.tsx +70 -13
- package/src/specs/NativeDdWebView.ts +16 -0
- package/src/utils/env-utils.ts +9 -0
- package/src/utils/webview-js-utils.ts +150 -0
- package/lib/commonjs/NativeDdSdk.js.map +0 -1
- package/lib/commonjs/__utils__/formatAllowedHosts.js +0 -65
- package/lib/commonjs/__utils__/formatAllowedHosts.js.map +0 -1
- package/lib/commonjs/__utils__/getInjectedJavaScriptBeforeContentLoaded.js +0 -32
- package/lib/commonjs/__utils__/getInjectedJavaScriptBeforeContentLoaded.js.map +0 -1
- package/lib/module/NativeDdSdk.js.map +0 -1
- package/lib/module/__utils__/formatAllowedHosts.js +0 -58
- package/lib/module/__utils__/formatAllowedHosts.js.map +0 -1
- package/lib/module/__utils__/getInjectedJavaScriptBeforeContentLoaded.js +0 -24
- package/lib/module/__utils__/getInjectedJavaScriptBeforeContentLoaded.js.map +0 -1
- package/lib/typescript/NativeDdSdk.d.ts.map +0 -1
- package/lib/typescript/__utils__/formatAllowedHosts.d.ts +0 -2
- package/lib/typescript/__utils__/formatAllowedHosts.d.ts.map +0 -1
- package/lib/typescript/__utils__/getInjectedJavaScriptBeforeContentLoaded.d.ts +0 -3
- package/lib/typescript/__utils__/getInjectedJavaScriptBeforeContentLoaded.d.ts.map +0 -1
- package/src/__tests__/formatAllowedHosts.test.ts +0 -40
- package/src/__tests__/getInjectedJavaScriptBeforeContentLoaded.test.ts +0 -86
- package/src/__utils__/formatAllowedHosts.ts +0 -70
- package/src/__utils__/getInjectedJavaScriptBeforeContentLoaded.ts +0 -29
- /package/lib/commonjs/{NativeDdSdk.js → ext-specs/NativeDdSdk.js} +0 -0
- /package/lib/module/{NativeDdSdk.js → ext-specs/NativeDdSdk.js} +0 -0
- /package/lib/typescript/{NativeDdSdk.d.ts → ext-specs/NativeDdSdk.d.ts} +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
import { NativeDdSdk } from '../ext-specs/NativeDdSdk';
|
|
7
|
+
export const DATADOG_MESSAGE_PREFIX = '[DATADOG]';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Internal Datadog Message Type
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Internal Datadog Message Format.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Wraps the given JS Code in a try and catch block.
|
|
19
|
+
* @param javascriptCode The JS Code to wrap in a try and catch block.
|
|
20
|
+
* @returns the wrapped JS code.
|
|
21
|
+
*/
|
|
22
|
+
export const wrapJsCodeInTryAndCatch = javascriptCode => javascriptCode ? `
|
|
23
|
+
try{
|
|
24
|
+
${javascriptCode}
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
28
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
29
|
+
source: 'DATADOG',
|
|
30
|
+
type: 'ERROR',
|
|
31
|
+
message: errorMsg
|
|
32
|
+
}));
|
|
33
|
+
true;
|
|
34
|
+
}` : undefined;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Legacy JS code for bridging the WebView events to DataDog native SDKs for consumption.
|
|
38
|
+
* @param allowedHosts The list of allowed hosts.
|
|
39
|
+
* @param customJavaScriptCode Custom user JS code to inject along with the Datadog bridging logic.
|
|
40
|
+
* @returns The JS code block as a string.
|
|
41
|
+
*/
|
|
42
|
+
export const getWebViewEventBridgingJS = (allowedHosts, customJavaScriptCode) => `
|
|
43
|
+
window.DatadogEventBridge = {
|
|
44
|
+
send(msg) {
|
|
45
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
46
|
+
source: 'DATADOG',
|
|
47
|
+
type: 'NATIVE_EVENT',
|
|
48
|
+
message: msg
|
|
49
|
+
}));
|
|
50
|
+
true;
|
|
51
|
+
},
|
|
52
|
+
getAllowedWebViewHosts() {
|
|
53
|
+
return ${formatAllowedHosts(allowedHosts)}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
try{
|
|
57
|
+
${customJavaScriptCode}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
61
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
62
|
+
source: 'DATADOG',
|
|
63
|
+
type: 'ERROR',
|
|
64
|
+
message: errorMsg
|
|
65
|
+
}));
|
|
66
|
+
true;
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
function formatAllowedHosts(allowedHosts) {
|
|
70
|
+
try {
|
|
71
|
+
return `'${JSON.stringify(allowedHosts)}'`;
|
|
72
|
+
} catch (e) {
|
|
73
|
+
if (NativeDdSdk) {
|
|
74
|
+
NativeDdSdk.telemetryError(getErrorMessage(e), getErrorStackTrace(e), 'AllowedHostsError');
|
|
75
|
+
}
|
|
76
|
+
return "'[]'";
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const getErrorMessage = error => {
|
|
80
|
+
const EMPTY_MESSAGE = 'Unknown Error';
|
|
81
|
+
let message = EMPTY_MESSAGE;
|
|
82
|
+
if (error === undefined || error === null) {
|
|
83
|
+
message = EMPTY_MESSAGE;
|
|
84
|
+
} else if (typeof error === 'object' && 'message' in error) {
|
|
85
|
+
message = String(error.message);
|
|
86
|
+
} else {
|
|
87
|
+
message = String(error);
|
|
88
|
+
}
|
|
89
|
+
return message;
|
|
90
|
+
};
|
|
91
|
+
const getErrorStackTrace = error => {
|
|
92
|
+
const EMPTY_STACK_TRACE = '';
|
|
93
|
+
let stack = EMPTY_STACK_TRACE;
|
|
94
|
+
try {
|
|
95
|
+
if (error === undefined || error === null) {
|
|
96
|
+
stack = EMPTY_STACK_TRACE;
|
|
97
|
+
} else if (typeof error === 'string') {
|
|
98
|
+
stack = EMPTY_STACK_TRACE;
|
|
99
|
+
} else if (typeof error === 'object') {
|
|
100
|
+
if ('stacktrace' in error) {
|
|
101
|
+
stack = String(error.stacktrace);
|
|
102
|
+
} else if ('stack' in error) {
|
|
103
|
+
stack = String(error.stack);
|
|
104
|
+
} else if ('componentStack' in error) {
|
|
105
|
+
stack = String(error.componentStack);
|
|
106
|
+
} else if ('sourceURL' in error && 'line' in error && 'column' in error) {
|
|
107
|
+
stack = `at ${error.sourceURL}:${error.line}:${error.column}`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} catch (e) {
|
|
111
|
+
// Do nothing
|
|
112
|
+
}
|
|
113
|
+
return stack;
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=webview-js-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeDdSdk","DATADOG_MESSAGE_PREFIX","wrapJsCodeInTryAndCatch","javascriptCode","undefined","getWebViewEventBridgingJS","allowedHosts","customJavaScriptCode","formatAllowedHosts","JSON","stringify","e","telemetryError","getErrorMessage","getErrorStackTrace","error","EMPTY_MESSAGE","message","String","EMPTY_STACK_TRACE","stack","stacktrace","componentStack","sourceURL","line","column"],"sourceRoot":"../../../src","sources":["utils/webview-js-utils.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
/**
|
|
3
|
+
* Do not import this Spec directly, use DdNativeLogsType instead.
|
|
4
|
+
*/
|
|
5
|
+
export interface Spec extends TurboModule {
|
|
6
|
+
readonly getConstants: () => {};
|
|
7
|
+
/**
|
|
8
|
+
* Send a log with ERROR level.
|
|
9
|
+
* @param message: The message to send.
|
|
10
|
+
* @param context: The additional context to send.
|
|
11
|
+
*/
|
|
12
|
+
readonly error: (message: string, context: Object) => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
declare const _default: Spec | null;
|
|
15
|
+
export default _default;
|
|
16
|
+
//# sourceMappingURL=NativeDdLogs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeDdLogs.d.ts","sourceRoot":"","sources":["../../../src/ext-specs/NativeDdLogs.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD;;GAEG;AACH,MAAM,WAAW,IAAK,SAAQ,WAAW;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;;AAGD,wBAAuD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeDdSdk.d.ts","sourceRoot":"","sources":["../../../src/ext-specs/NativeDdSdk.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD;;;GAGG;AACH,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACvD,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/E;AAED,eAAO,MAAM,WAAW,+BAEvB,CAAC"}
|
|
@@ -2,11 +2,31 @@ import type { WebViewProps } from 'react-native-webview';
|
|
|
2
2
|
import { WebView as RNWebView } from 'react-native-webview';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
type Props = WebViewProps & {
|
|
5
|
+
/**
|
|
6
|
+
* The list of allowed hosts for Datadog WebView tracking.
|
|
7
|
+
*/
|
|
5
8
|
allowedHosts?: string[];
|
|
9
|
+
/**
|
|
10
|
+
* Whether injected User JS Code errors should be logged to Datadog (default: false).
|
|
11
|
+
*/
|
|
12
|
+
logUserCodeErrors?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Custom JS Code to inject before the WebView content is loaded.
|
|
15
|
+
*/
|
|
6
16
|
injectedJavaScriptBeforeContentLoaded?: string;
|
|
7
17
|
};
|
|
8
18
|
export declare const WebView: React.ForwardRefExoticComponent<import("react-native-webview/lib/WebViewTypes").IOSWebViewProps & import("react-native-webview/lib/WebViewTypes").AndroidWebViewProps & import("react-native-webview/lib/WebViewTypes").WindowsWebViewProps & {
|
|
19
|
+
/**
|
|
20
|
+
* The list of allowed hosts for Datadog WebView tracking.
|
|
21
|
+
*/
|
|
9
22
|
allowedHosts?: string[] | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Whether injected User JS Code errors should be logged to Datadog (default: false).
|
|
25
|
+
*/
|
|
26
|
+
logUserCodeErrors?: boolean | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Custom JS Code to inject before the WebView content is loaded.
|
|
29
|
+
*/
|
|
10
30
|
injectedJavaScriptBeforeContentLoaded?: string | undefined;
|
|
11
31
|
} & React.RefAttributes<RNWebView<Props>>>;
|
|
12
32
|
export default WebView;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAkC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAkC,MAAM,OAAO,CAAC;AAYvD,KAAK,KAAK,GAAG,YAAY,GAAG;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,qCAAqC,CAAC,EAAE,MAAM,CAAC;CAClD,CAAC;AAyEF,eAAO,MAAM,OAAO;IArFhB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;0CA2E4C,CAAC;AAEpD,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeDdWebView.d.ts","sourceRoot":"","sources":["../../../src/specs/NativeDdWebView.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAKtF,QAAA,MAAM,eAAe,4EAEN,CAAC;AAEhB,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/env-utils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,iBAAiB,QAAO,OAEpC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const DATADOG_MESSAGE_PREFIX = "[DATADOG]";
|
|
2
|
+
/**
|
|
3
|
+
* Internal Datadog Message Type
|
|
4
|
+
*/
|
|
5
|
+
export type DatadogMessageType =
|
|
6
|
+
/**
|
|
7
|
+
* Signals errors that occured during the execution of JavaScript code in the WebView.
|
|
8
|
+
*/
|
|
9
|
+
'ERROR'
|
|
10
|
+
/**
|
|
11
|
+
* Signals events that should be forwarded and consumed by the native SDK.
|
|
12
|
+
*/
|
|
13
|
+
| 'NATIVE_EVENT';
|
|
14
|
+
/**
|
|
15
|
+
* Internal Datadog Message Format.
|
|
16
|
+
*/
|
|
17
|
+
export type DatadogMessageFormat = {
|
|
18
|
+
type: DatadogMessageType;
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Wraps the given JS Code in a try and catch block.
|
|
23
|
+
* @param javascriptCode The JS Code to wrap in a try and catch block.
|
|
24
|
+
* @returns the wrapped JS code.
|
|
25
|
+
*/
|
|
26
|
+
export declare const wrapJsCodeInTryAndCatch: (javascriptCode?: string) => string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Legacy JS code for bridging the WebView events to DataDog native SDKs for consumption.
|
|
29
|
+
* @param allowedHosts The list of allowed hosts.
|
|
30
|
+
* @param customJavaScriptCode Custom user JS code to inject along with the Datadog bridging logic.
|
|
31
|
+
* @returns The JS code block as a string.
|
|
32
|
+
*/
|
|
33
|
+
export declare const getWebViewEventBridgingJS: (allowedHosts?: string[], customJavaScriptCode?: string) => string;
|
|
34
|
+
//# sourceMappingURL=webview-js-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webview-js-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/webview-js-utils.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD;;GAEG;AACH,MAAM,MAAM,kBAAkB;AAC1B;;GAEG;AACD,OAAO;AACT;;GAEG;GACD,cAAc,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAC/B,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,oBACf,MAAM,KACxB,MAAM,GAAG,SAeO,CAAC;AAEpB;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,kBACnB,MAAM,EAAE,yBACA,MAAM,KAC9B,MA2BA,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datadog/mobile-react-native-webview",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "A client-side React Native module to interact with react-native-webview and Datadog",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"datadog",
|
|
@@ -23,7 +23,16 @@
|
|
|
23
23
|
"main": "lib/commonjs/index",
|
|
24
24
|
"files": [
|
|
25
25
|
"src/**",
|
|
26
|
-
"lib/**"
|
|
26
|
+
"lib/**",
|
|
27
|
+
"android/build.gradle",
|
|
28
|
+
"android/detekt.yml",
|
|
29
|
+
"android/gradle.properties",
|
|
30
|
+
"android/src/**",
|
|
31
|
+
"ios/Sources/**",
|
|
32
|
+
"ios/DatadogSDKReactNativeWebView.xcodeproj/project.xcworkspace/xcsharedata",
|
|
33
|
+
"ios/DatadogSDKReactNativeWebView.xcodeproj/project.xcworkspace/*.xcworkspacedata",
|
|
34
|
+
"ios/DatadogSDKReactNativeWebView.xcodeproj/*.pbxproj",
|
|
35
|
+
"DatadogSDKReactNativeWebView.podspec"
|
|
27
36
|
],
|
|
28
37
|
"types": "lib/typescript/index.d.ts",
|
|
29
38
|
"react-native": "src/index",
|
|
@@ -39,7 +48,8 @@
|
|
|
39
48
|
},
|
|
40
49
|
"devDependencies": {
|
|
41
50
|
"@testing-library/react-native": "7.0.2",
|
|
42
|
-
"react-native-builder-bob": "0.26.0"
|
|
51
|
+
"react-native-builder-bob": "0.26.0",
|
|
52
|
+
"react-native-webview": "^13.12.2"
|
|
43
53
|
},
|
|
44
54
|
"peerDependencies": {
|
|
45
55
|
"@datadog/mobile-react-native": "^2.0.1",
|
|
@@ -76,5 +86,13 @@
|
|
|
76
86
|
]
|
|
77
87
|
]
|
|
78
88
|
},
|
|
79
|
-
"
|
|
89
|
+
"codegenConfig": {
|
|
90
|
+
"name": "DdSdkReactNativeWebView",
|
|
91
|
+
"type": "all",
|
|
92
|
+
"jsSrcsDir": "./src/specs",
|
|
93
|
+
"android": {
|
|
94
|
+
"javaPackageName": "com.datadog.reactnative.webview"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"gitHead": "2ef793eaf02bf1ac20d49932ff13762177142430"
|
|
80
98
|
}
|
|
@@ -3,62 +3,58 @@
|
|
|
3
3
|
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
4
|
* Copyright 2016-Present Datadog, Inc.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
6
|
+
|
|
7
|
+
import { render } from '@testing-library/react-native';
|
|
8
|
+
import { WebView as RNWebView } from 'react-native-webview';
|
|
9
9
|
import React from 'react';
|
|
10
10
|
|
|
11
|
-
import { DATADOG_MESSAGE_PREFIX } from '../__utils__/getInjectedJavaScriptBeforeContentLoaded';
|
|
12
11
|
import { WebView } from '../index';
|
|
12
|
+
import { NativeDdWebView } from '../specs/NativeDdWebView';
|
|
13
|
+
|
|
14
|
+
jest.mock('react-native-webview', () => {
|
|
15
|
+
return {
|
|
16
|
+
WebView: jest.fn()
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
jest.mock('../specs/NativeDdWebView', () => {
|
|
21
|
+
return {
|
|
22
|
+
NativeDdWebView: jest.fn()
|
|
23
|
+
};
|
|
24
|
+
});
|
|
13
25
|
|
|
14
26
|
describe('WebView', () => {
|
|
15
27
|
beforeEach(() => {
|
|
16
28
|
jest.clearAllMocks();
|
|
17
29
|
});
|
|
18
|
-
const DdMessage = 'custom datadog event';
|
|
19
|
-
const datadogEvent = {
|
|
20
|
-
nativeEvent: {
|
|
21
|
-
data: `${DATADOG_MESSAGE_PREFIX} ${DdMessage}`
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
const userDefinedEvent = {
|
|
25
|
-
nativeEvent: {
|
|
26
|
-
data: 'custom user-defined message'
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
it('calls provided onMessage props', async () => {
|
|
30
|
-
const onMessage = jest.fn();
|
|
31
|
-
const { findByTestId } = render(
|
|
32
|
-
<WebView onMessage={onMessage} testID="webView" allowedHosts={[]} />
|
|
33
|
-
);
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
it('WebView is rendered with native component', () => {
|
|
32
|
+
// Given
|
|
33
|
+
const allowedHosts = ['example.com', 'localhost'];
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
// When
|
|
36
|
+
render(<WebView allowedHosts={allowedHosts} />);
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const { findByTestId } = render(
|
|
46
|
-
<WebView testID="webView" allowedHosts={[]} />
|
|
47
|
-
);
|
|
48
|
-
const webView = await findByTestId('webView');
|
|
49
|
-
fireEvent(webView, 'message', datadogEvent);
|
|
38
|
+
// Then
|
|
39
|
+
const mockedWebView = jest.mocked(RNWebView);
|
|
40
|
+
const component =
|
|
41
|
+
mockedWebView.mock.calls[0][0].nativeConfig?.component;
|
|
42
|
+
const mockedNativeWebView = jest.mocked(NativeDdWebView);
|
|
50
43
|
|
|
51
|
-
expect(
|
|
52
|
-
DdMessage
|
|
53
|
-
);
|
|
44
|
+
expect(component).toBe(mockedNativeWebView);
|
|
54
45
|
});
|
|
55
|
-
it('forwards ref to the actual RN Webview component', async () => {
|
|
56
|
-
const ref = React.createRef<RNWebView>();
|
|
57
46
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
it('Datadog WebView allowedHosts are forwarded to WebView nativeConfig props', () => {
|
|
48
|
+
// Given
|
|
49
|
+
const allowedHosts = ['example.com', 'localhost'];
|
|
50
|
+
|
|
51
|
+
// When
|
|
52
|
+
render(<WebView allowedHosts={allowedHosts} />);
|
|
53
|
+
|
|
54
|
+
// Then
|
|
55
|
+
const mockedWebView = jest.mocked(RNWebView);
|
|
56
|
+
const props = mockedWebView.mock.calls[0][0].nativeConfig?.props as any;
|
|
57
|
+
|
|
58
|
+
expect(props?.allowedHosts).toBe(allowedHosts);
|
|
63
59
|
});
|
|
64
60
|
});
|
|
@@ -3,26 +3,45 @@
|
|
|
3
3
|
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
4
|
* Copyright 2016-Present Datadog, Inc.
|
|
5
5
|
*/
|
|
6
|
+
|
|
6
7
|
import { render } from '@testing-library/react-native';
|
|
8
|
+
import { WebView as RNWebView } from 'react-native-webview';
|
|
7
9
|
import React from 'react';
|
|
8
10
|
|
|
9
11
|
import { WebView } from '../index';
|
|
10
12
|
|
|
13
|
+
import { dedent } from './__utils__/string-utils';
|
|
14
|
+
|
|
11
15
|
jest.mock('react-native-webview', () => {
|
|
12
16
|
return {
|
|
13
17
|
WebView: jest.fn(props => {
|
|
14
18
|
// eslint-disable-next-line no-eval
|
|
15
19
|
eval(props.injectedJavaScriptBeforeContentLoaded);
|
|
16
|
-
|
|
20
|
+
// eslint-disable-next-line no-eval
|
|
21
|
+
eval(props.injectedJavaScript);
|
|
22
|
+
return undefined;
|
|
17
23
|
})
|
|
18
24
|
};
|
|
19
25
|
});
|
|
26
|
+
|
|
20
27
|
const callfunction = jest.fn();
|
|
28
|
+
const postMessageMock = jest.fn();
|
|
29
|
+
|
|
30
|
+
window['ReactNativeWebView'] = {
|
|
31
|
+
postMessage: postMessageMock
|
|
32
|
+
};
|
|
21
33
|
|
|
22
34
|
describe('Webview', () => {
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
jest.clearAllMocks();
|
|
37
|
+
});
|
|
38
|
+
|
|
23
39
|
it('should pass injectedJavaScriptBeforeContentLoaded prop to WebView component', () => {
|
|
40
|
+
// Given
|
|
24
41
|
const injectedJavaScriptBeforeContentLoaded = 'callfunction()';
|
|
25
42
|
const allowedHosts = ['example.com', 'localhost'];
|
|
43
|
+
|
|
44
|
+
// When
|
|
26
45
|
render(
|
|
27
46
|
<WebView
|
|
28
47
|
allowedHosts={allowedHosts}
|
|
@@ -31,6 +50,186 @@ describe('Webview', () => {
|
|
|
31
50
|
}
|
|
32
51
|
/>
|
|
33
52
|
);
|
|
53
|
+
|
|
54
|
+
// Then
|
|
55
|
+
expect(callfunction).toHaveBeenCalled();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should pass injectedJavaScript prop to WebView component', () => {
|
|
59
|
+
// Given
|
|
60
|
+
const injectedJavaScript = 'callfunction()';
|
|
61
|
+
const allowedHosts = ['example.com', 'localhost'];
|
|
62
|
+
|
|
63
|
+
// When
|
|
64
|
+
render(
|
|
65
|
+
<WebView
|
|
66
|
+
allowedHosts={allowedHosts}
|
|
67
|
+
injectedJavaScript={injectedJavaScript}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Then
|
|
72
|
+
expect(callfunction).toHaveBeenCalled();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should pass injectedJavaScriptBeforeContentLoaded prop to WebView component W { injectedJavaScriptBeforeContentLoadedForMainFrameOnly = true }', () => {
|
|
76
|
+
// Given
|
|
77
|
+
const injectedJavaScript = 'callfunction()';
|
|
78
|
+
const allowedHosts = ['example.com', 'localhost'];
|
|
79
|
+
|
|
80
|
+
// When
|
|
81
|
+
render(
|
|
82
|
+
<WebView
|
|
83
|
+
allowedHosts={allowedHosts}
|
|
84
|
+
injectedJavaScriptBeforeContentLoadedForMainFrameOnly={true}
|
|
85
|
+
injectedJavaScriptBeforeContentLoaded={injectedJavaScript}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Then
|
|
90
|
+
expect(callfunction).toHaveBeenCalled();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should pass injectedJavaScript prop to WebView component W { injectedJavaScriptForMainFrameOnly = true }', () => {
|
|
94
|
+
// Given
|
|
95
|
+
const injectedJavaScript = 'callfunction()';
|
|
96
|
+
const allowedHosts = ['example.com', 'localhost'];
|
|
97
|
+
|
|
98
|
+
// When
|
|
99
|
+
render(
|
|
100
|
+
<WebView
|
|
101
|
+
allowedHosts={allowedHosts}
|
|
102
|
+
injectedJavaScriptForMainFrameOnly={true}
|
|
103
|
+
injectedJavaScript={injectedJavaScript}
|
|
104
|
+
/>
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Then
|
|
34
108
|
expect(callfunction).toHaveBeenCalled();
|
|
35
109
|
});
|
|
110
|
+
|
|
111
|
+
it('should wrap injectedJavaScript in try & catch block', () => {
|
|
112
|
+
// Given
|
|
113
|
+
const onMessage = jest.fn();
|
|
114
|
+
const allowedHosts = ['localhost', 'example.com'];
|
|
115
|
+
const injectedJavaScript = 'testInjectedJavaScript()';
|
|
116
|
+
|
|
117
|
+
// When
|
|
118
|
+
render(
|
|
119
|
+
<WebView
|
|
120
|
+
onMessage={onMessage}
|
|
121
|
+
allowedHosts={allowedHosts}
|
|
122
|
+
injectedJavaScript={injectedJavaScript}
|
|
123
|
+
/>
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// Then
|
|
127
|
+
const mockedWebView = jest.mocked(RNWebView);
|
|
128
|
+
const realInjectedJs = dedent(
|
|
129
|
+
mockedWebView.mock.calls[0][0].injectedJavaScript ?? ''
|
|
130
|
+
);
|
|
131
|
+
const expected = dedent(`
|
|
132
|
+
try{
|
|
133
|
+
testInjectedJavaScript()
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
137
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
138
|
+
source: 'DATADOG',
|
|
139
|
+
type: 'ERROR',
|
|
140
|
+
message: errorMsg
|
|
141
|
+
}));
|
|
142
|
+
true;
|
|
143
|
+
}`);
|
|
144
|
+
|
|
145
|
+
expect(realInjectedJs).toBe(expected);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should wrap injectedJavaScriptBeforeContentLoaded in try & catch block', () => {
|
|
149
|
+
// Given
|
|
150
|
+
const onMessage = jest.fn();
|
|
151
|
+
const allowedHosts = ['localhost', 'example.com'];
|
|
152
|
+
const injectedJavaScript = 'testInjectedJavaScript()';
|
|
153
|
+
|
|
154
|
+
// When
|
|
155
|
+
render(
|
|
156
|
+
<WebView
|
|
157
|
+
onMessage={onMessage}
|
|
158
|
+
allowedHosts={allowedHosts}
|
|
159
|
+
injectedJavaScriptBeforeContentLoaded={injectedJavaScript}
|
|
160
|
+
/>
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Then
|
|
164
|
+
const mockedWebView = jest.mocked(RNWebView);
|
|
165
|
+
const realInjectedJs = dedent(
|
|
166
|
+
mockedWebView.mock.calls[0][0]
|
|
167
|
+
.injectedJavaScriptBeforeContentLoaded ?? ''
|
|
168
|
+
);
|
|
169
|
+
const expected = dedent(`
|
|
170
|
+
try{
|
|
171
|
+
testInjectedJavaScript()
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
175
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
176
|
+
source: 'DATADOG',
|
|
177
|
+
type: 'ERROR',
|
|
178
|
+
message: errorMsg
|
|
179
|
+
}));
|
|
180
|
+
true;
|
|
181
|
+
}`);
|
|
182
|
+
|
|
183
|
+
expect(realInjectedJs).toBe(expected);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('should call postMessage with datadog error event W injectedJavaScript has errors', () => {
|
|
187
|
+
// Given
|
|
188
|
+
const onMessage = jest.fn();
|
|
189
|
+
const allowedHosts = ['localhost', 'example.com'];
|
|
190
|
+
const injectedJavaScript = 'testInjectedJavaScript()';
|
|
191
|
+
|
|
192
|
+
// When
|
|
193
|
+
render(
|
|
194
|
+
<WebView
|
|
195
|
+
onMessage={onMessage}
|
|
196
|
+
allowedHosts={allowedHosts}
|
|
197
|
+
injectedJavaScript={injectedJavaScript}
|
|
198
|
+
/>
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Then
|
|
202
|
+
expect(postMessageMock).toHaveBeenCalledWith(
|
|
203
|
+
JSON.stringify({
|
|
204
|
+
source: 'DATADOG',
|
|
205
|
+
type: 'ERROR',
|
|
206
|
+
message: 'testInjectedJavaScript is not defined'
|
|
207
|
+
})
|
|
208
|
+
);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should call postMessage with datadog error event W injectedJavaScriptBeforeContentLoaded has errors', () => {
|
|
212
|
+
// Given
|
|
213
|
+
const onMessage = jest.fn();
|
|
214
|
+
const allowedHosts = ['localhost', 'example.com'];
|
|
215
|
+
const injectedJavaScript = 'testInjectedJavaScript()';
|
|
216
|
+
|
|
217
|
+
// When
|
|
218
|
+
render(
|
|
219
|
+
<WebView
|
|
220
|
+
onMessage={onMessage}
|
|
221
|
+
allowedHosts={allowedHosts}
|
|
222
|
+
injectedJavaScriptBeforeContentLoaded={injectedJavaScript}
|
|
223
|
+
/>
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
// Then
|
|
227
|
+
expect(postMessageMock).toHaveBeenCalledWith(
|
|
228
|
+
JSON.stringify({
|
|
229
|
+
source: 'DATADOG',
|
|
230
|
+
type: 'ERROR',
|
|
231
|
+
message: 'testInjectedJavaScript is not defined'
|
|
232
|
+
})
|
|
233
|
+
);
|
|
234
|
+
});
|
|
36
235
|
});
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
4
|
* Copyright 2016-Present Datadog, Inc.
|
|
5
5
|
*/
|
|
6
|
+
|
|
6
7
|
import { render } from '@testing-library/react-native';
|
|
7
8
|
import { WebView as RNWebView } from 'react-native-webview';
|
|
8
9
|
import React from 'react';
|
|
@@ -20,8 +21,15 @@ describe('WebView performance', () => {
|
|
|
20
21
|
jest.clearAllMocks();
|
|
21
22
|
});
|
|
22
23
|
it('should update the onMessage prop of the RNWebView component', () => {
|
|
24
|
+
/**
|
|
25
|
+
* GIVEN
|
|
26
|
+
*/
|
|
23
27
|
const onMessage = jest.fn();
|
|
24
28
|
const allowedHosts = ['localhost', 'example.com'];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* WHEN
|
|
32
|
+
*/
|
|
25
33
|
const { rerender } = render(
|
|
26
34
|
<WebView onMessage={onMessage} allowedHosts={allowedHosts} />
|
|
27
35
|
);
|
|
@@ -34,6 +42,10 @@ describe('WebView performance', () => {
|
|
|
34
42
|
rerender(
|
|
35
43
|
<WebView onMessage={newOnMessage} allowedHosts={allowedHosts} />
|
|
36
44
|
);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* THEN
|
|
48
|
+
*/
|
|
37
49
|
const mockedWebView = jest.mocked(RNWebView);
|
|
38
50
|
// Verify that the onMessage prop of the RNWebView component has changed
|
|
39
51
|
expect(mockedWebView.mock.calls[0][0].onMessage).toBe(
|