@react-native-firebase/app 25.1.0 → 26.1.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/CHANGELOG.md +54 -0
- package/README.md +21 -0
- package/RNFBApp.podspec +20 -15
- package/android/build.gradle +25 -6
- package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppModule.java → NativeRNFBTurboApp.java} +81 -45
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +3 -3
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +2 -2
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboAppSpec.java +136 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboUtilsSpec.java +94 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/CMakeLists.txt +36 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/RNFBAppTurboModules-generated.cpp +170 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/RNFBAppTurboModules.h +39 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/react/renderer/components/RNFBAppTurboModules/RNFBAppTurboModulesJSI-generated.cpp +187 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/react/renderer/components/RNFBAppTurboModules/RNFBAppTurboModulesJSI.h +606 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +3 -3
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +475 -20
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +8 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +8 -0
- package/android/src/reactnative/java/io/invertase/firebase/utils/{ReactNativeFirebaseUtilsModule.java → NativeRNFBTurboUtils.java} +57 -40
- package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +400 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +1823 -0
- package/app.plugin.js +1 -1
- package/dist/module/FirebaseApp.js +0 -9
- package/dist/module/FirebaseApp.js.map +1 -1
- package/dist/module/common/index.js +0 -645
- package/dist/module/common/index.js.map +1 -1
- package/dist/module/common/unitTestUtils.js +18 -54
- package/dist/module/common/unitTestUtils.js.map +1 -1
- package/dist/module/index.js +0 -1
- package/dist/module/index.js.map +1 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js +12 -6
- package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
- package/dist/module/internal/constants.js +2 -2
- package/dist/module/internal/constants.js.map +1 -1
- package/dist/module/internal/index.js +1 -1
- package/dist/module/internal/index.js.map +1 -1
- package/dist/module/internal/nativeModuleAndroidIos.js +50 -10
- package/dist/module/internal/nativeModuleAndroidIos.js.map +1 -1
- package/dist/module/internal/nativeModuleWeb.js +12 -4
- package/dist/module/internal/nativeModuleWeb.js.map +1 -1
- package/dist/module/internal/registry/app.js +20 -12
- package/dist/module/internal/registry/app.js.map +1 -1
- package/dist/module/internal/registry/modular.js +73 -0
- package/dist/module/internal/registry/modular.js.map +1 -0
- package/dist/module/internal/registry/nativeModule.js +116 -95
- package/dist/module/internal/registry/nativeModule.js.map +1 -1
- package/dist/module/internal/web/RNFBAppModule.js +16 -3
- package/dist/module/internal/web/RNFBAppModule.js.map +1 -1
- package/dist/module/internal/web/utils.js +6 -1
- package/dist/module/internal/web/utils.js.map +1 -1
- package/dist/module/modular.js +44 -37
- package/dist/module/modular.js.map +1 -1
- package/dist/module/types/app.js +0 -3
- package/dist/module/types/app.js.map +1 -1
- package/dist/module/types/internal.js +0 -2
- package/dist/module/utils/UtilsStatics.js +2 -2
- package/dist/module/utils/UtilsStatics.js.map +1 -1
- package/dist/module/utils/index.js +21 -17
- package/dist/module/utils/index.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/FirebaseApp.d.ts +1 -2
- package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
- package/dist/typescript/lib/common/index.d.ts +0 -8
- package/dist/typescript/lib/common/index.d.ts.map +1 -1
- package/dist/typescript/lib/common/unitTestUtils.d.ts +1 -4
- package/dist/typescript/lib/common/unitTestUtils.d.ts.map +1 -1
- package/dist/typescript/lib/index.d.ts +0 -1
- package/dist/typescript/lib/index.d.ts.map +1 -1
- package/dist/typescript/lib/internal/NativeFirebaseError.d.ts +1 -1
- package/dist/typescript/lib/internal/NativeFirebaseError.d.ts.map +1 -1
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/constants.d.ts +2 -3
- package/dist/typescript/lib/internal/constants.d.ts.map +1 -1
- package/dist/typescript/lib/internal/index.d.ts +1 -1
- package/dist/typescript/lib/internal/index.d.ts.map +1 -1
- package/dist/typescript/lib/internal/nativeModuleAndroidIos.d.ts +2 -6
- package/dist/typescript/lib/internal/nativeModuleAndroidIos.d.ts.map +1 -1
- package/dist/typescript/lib/internal/nativeModuleWeb.d.ts.map +1 -1
- package/dist/typescript/lib/internal/registry/app.d.ts +2 -2
- package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
- package/dist/typescript/lib/internal/registry/modular.d.ts +22 -0
- package/dist/typescript/lib/internal/registry/modular.d.ts.map +1 -0
- package/dist/typescript/lib/internal/registry/nativeModule.d.ts +3 -11
- package/dist/typescript/lib/internal/registry/nativeModule.d.ts.map +1 -1
- package/dist/typescript/lib/internal/web/RNFBAppModule.d.ts.map +1 -1
- package/dist/typescript/lib/internal/web/utils.d.ts.map +1 -1
- package/dist/typescript/lib/modular.d.ts +21 -7
- package/dist/typescript/lib/modular.d.ts.map +1 -1
- package/dist/typescript/lib/types/app.d.ts +4 -4
- package/dist/typescript/lib/types/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/internal.d.ts +1 -33
- package/dist/typescript/lib/types/internal.d.ts.map +1 -1
- package/dist/typescript/lib/utils/index.d.ts +7 -3
- package/dist/typescript/lib/utils/index.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/firebase-schema.json +5 -1
- package/firebase_spm.rb +1016 -0
- package/ios/RNFBApp/RCTConvert+FIRApp.h +4 -0
- package/ios/RNFBApp/RCTConvert+FIROptions.h +4 -0
- package/ios/RNFBApp/RNFBAppModule.h +1 -3
- package/ios/RNFBApp/{RNFBAppModule.m → RNFBAppModule.mm} +80 -77
- package/ios/RNFBApp/RNFBSharedUtils.h +4 -0
- package/ios/RNFBApp/RNFBUtilsModule.h +1 -3
- package/ios/RNFBApp/{RNFBUtilsModule.m → RNFBUtilsModule.mm} +68 -25
- package/ios/RNFBApp/RNFBVersion.m +1 -1
- package/ios/RNFBApp.xcodeproj/project.pbxproj +12 -12
- package/ios/generated/RCTAppDependencyProvider.h +25 -0
- package/ios/generated/RCTAppDependencyProvider.mm +55 -0
- package/ios/generated/RCTModuleProviders.h +16 -0
- package/ios/generated/RCTModuleProviders.mm +52 -0
- package/ios/generated/RCTModulesConformingToProtocolsProvider.h +18 -0
- package/ios/generated/RCTModulesConformingToProtocolsProvider.mm +33 -0
- package/ios/generated/RCTThirdPartyComponentsProvider.h +16 -0
- package/ios/generated/RCTThirdPartyComponentsProvider.mm +23 -0
- package/ios/generated/RCTUnstableModulesRequiringMainQueueSetupProvider.h +14 -0
- package/ios/generated/RCTUnstableModulesRequiringMainQueueSetupProvider.mm +19 -0
- package/ios/generated/RNFBAppTurboModules/RNFBAppTurboModules-generated.mm +210 -0
- package/ios/generated/RNFBAppTurboModules/RNFBAppTurboModules.h +399 -0
- package/ios/generated/RNFBAppTurboModulesJSI-generated.cpp +187 -0
- package/ios/generated/RNFBAppTurboModulesJSI.h +606 -0
- package/ios/generated/ReactAppDependencyProvider.podspec +34 -0
- package/ios/generated/ReactCodegen.podspec +111 -0
- package/lib/FirebaseApp.ts +1 -10
- package/lib/common/index.ts +0 -742
- package/lib/common/unitTestUtils.ts +17 -73
- package/lib/index.ts +0 -1
- package/lib/internal/NativeFirebaseError.ts +1 -1
- package/lib/internal/RNFBNativeEventEmitter.ts +12 -6
- package/lib/internal/constants.ts +3 -25
- package/lib/internal/global.d.ts +0 -4
- package/lib/internal/index.ts +1 -1
- package/lib/internal/nativeModuleAndroidIos.ts +69 -12
- package/lib/internal/nativeModuleWeb.ts +11 -5
- package/lib/internal/registry/app.ts +24 -22
- package/lib/internal/registry/modular.ts +97 -0
- package/lib/internal/registry/nativeModule.ts +136 -107
- package/lib/internal/web/RNFBAppModule.ts +16 -3
- package/lib/internal/web/utils.ts +6 -1
- package/lib/modular.ts +47 -72
- package/lib/types/app.ts +6 -11
- package/lib/types/internal.ts +1 -46
- package/lib/utils/UtilsStatics.ts +2 -2
- package/lib/utils/index.ts +24 -18
- package/lib/version.ts +1 -1
- package/package.json +45 -6
- package/plugin/build/app.plugin.d.ts +2 -0
- package/plugin/build/app.plugin.js +6 -0
- package/plugin/src/app.plugin.ts +3 -0
- package/plugin/tsconfig.tsbuildinfo +1 -1
- package/react-native.config.js +2 -0
- package/specs/NativeRNFBTurboApp.ts +57 -0
- package/specs/NativeRNFBTurboUtils.ts +34 -0
- package/typedoc.json +1 -2
- package/dist/module/internal/registry/namespace.js +0 -262
- package/dist/module/internal/registry/namespace.js.map +0 -1
- package/dist/module/namespaced.js +0 -25
- package/dist/module/namespaced.js.map +0 -1
- package/dist/typescript/lib/internal/registry/namespace.d.ts +0 -26
- package/dist/typescript/lib/internal/registry/namespace.d.ts.map +0 -1
- package/dist/typescript/lib/namespaced.d.ts +0 -5
- package/dist/typescript/lib/namespaced.d.ts.map +0 -1
- package/lib/internal/registry/namespace.ts +0 -338
- package/lib/namespaced.ts +0 -24
|
@@ -24,16 +24,20 @@ import android.os.Build;
|
|
|
24
24
|
import android.os.Environment;
|
|
25
25
|
import android.provider.Settings;
|
|
26
26
|
import android.util.Log;
|
|
27
|
-
import com.facebook.
|
|
27
|
+
import com.facebook.fbreact.specs.NativeRNFBTurboUtilsSpec;
|
|
28
|
+
import com.facebook.react.bridge.Arguments;
|
|
29
|
+
import com.facebook.react.bridge.Promise;
|
|
30
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
31
|
+
import com.facebook.react.bridge.UiThreadUtil;
|
|
32
|
+
import com.facebook.react.bridge.WritableMap;
|
|
28
33
|
import com.google.android.gms.common.ConnectionResult;
|
|
29
34
|
import com.google.android.gms.common.GoogleApiAvailability;
|
|
30
35
|
import io.invertase.firebase.app.ReactNativeFirebaseApp;
|
|
31
|
-
import io.invertase.firebase.common.ReactNativeFirebaseModule;
|
|
32
36
|
import java.io.File;
|
|
33
37
|
import java.util.HashMap;
|
|
34
38
|
import java.util.Map;
|
|
35
39
|
|
|
36
|
-
public class
|
|
40
|
+
public class NativeRNFBTurboUtils extends NativeRNFBTurboUtilsSpec {
|
|
37
41
|
private static final String TAG = "Utils";
|
|
38
42
|
private static final String KEY_MAIN_BUNDLE = "MAIN_BUNDLE";
|
|
39
43
|
private static final String KEY_DOCUMENT_DIRECTORY = "DOCUMENT_DIRECTORY";
|
|
@@ -46,15 +50,10 @@ public class ReactNativeFirebaseUtilsModule extends ReactNativeFirebaseModule {
|
|
|
46
50
|
private static final String KEY_CACHE_DIRECTORY = "CACHES_DIRECTORY";
|
|
47
51
|
private static final String FIREBASE_TEST_LAB = "firebase.test.lab";
|
|
48
52
|
|
|
49
|
-
public
|
|
50
|
-
super(reactContext
|
|
53
|
+
public NativeRNFBTurboUtils(ReactApplicationContext reactContext) {
|
|
54
|
+
super(reactContext);
|
|
51
55
|
}
|
|
52
56
|
|
|
53
|
-
/**
|
|
54
|
-
* Is this app running in Firebase Test Lab
|
|
55
|
-
*
|
|
56
|
-
* @return Boolean
|
|
57
|
-
*/
|
|
58
57
|
private static Boolean isRunningInTestLab() {
|
|
59
58
|
String testLabSetting =
|
|
60
59
|
Settings.System.getString(
|
|
@@ -63,33 +62,32 @@ public class ReactNativeFirebaseUtilsModule extends ReactNativeFirebaseModule {
|
|
|
63
62
|
return "true".equals(testLabSetting);
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
@
|
|
65
|
+
@Override
|
|
67
66
|
public void androidGetPlayServicesStatus(Promise promise) {
|
|
68
67
|
promise.resolve(getPlayServicesStatusMap());
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
public void androidPromptForPlayServices() {
|
|
70
|
+
@Override
|
|
71
|
+
public void androidPromptForPlayServices(Promise promise) {
|
|
74
72
|
int status = isGooglePlayServicesAvailable();
|
|
75
73
|
GoogleApiAvailability gapi = GoogleApiAvailability.getInstance();
|
|
76
74
|
|
|
77
75
|
if (status != ConnectionResult.SUCCESS && gapi.isUserResolvableError(status)) {
|
|
78
|
-
Activity activity =
|
|
76
|
+
Activity activity = getCurrentActivity();
|
|
79
77
|
if (activity != null) {
|
|
80
78
|
gapi.getErrorDialog(activity, status, status).show();
|
|
81
79
|
}
|
|
82
80
|
}
|
|
81
|
+
promise.resolve(null);
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
public void androidResolutionForPlayServices() {
|
|
84
|
+
@Override
|
|
85
|
+
public void androidResolutionForPlayServices(Promise promise) {
|
|
88
86
|
int status = isGooglePlayServicesAvailable();
|
|
89
87
|
ConnectionResult connectionResult = new ConnectionResult(status);
|
|
90
88
|
|
|
91
89
|
if (!connectionResult.isSuccess() && connectionResult.hasResolution()) {
|
|
92
|
-
Activity activity =
|
|
90
|
+
Activity activity = getCurrentActivity();
|
|
93
91
|
if (activity != null) {
|
|
94
92
|
try {
|
|
95
93
|
connectionResult.startResolutionForResult(activity, status);
|
|
@@ -98,31 +96,55 @@ public class ReactNativeFirebaseUtilsModule extends ReactNativeFirebaseModule {
|
|
|
98
96
|
}
|
|
99
97
|
}
|
|
100
98
|
}
|
|
99
|
+
promise.resolve(null);
|
|
101
100
|
}
|
|
102
101
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
public void androidMakePlayServicesAvailable() {
|
|
102
|
+
@Override
|
|
103
|
+
public void androidMakePlayServicesAvailable(Promise promise) {
|
|
106
104
|
int status = isGooglePlayServicesAvailable();
|
|
107
105
|
|
|
108
106
|
if (status != ConnectionResult.SUCCESS) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
UiThreadUtil.runOnUiThread(
|
|
108
|
+
() -> {
|
|
109
|
+
Activity activity = getCurrentActivity();
|
|
110
|
+
if (activity != null) {
|
|
111
|
+
GoogleApiAvailability.getInstance()
|
|
112
|
+
.makeGooglePlayServicesAvailable(activity)
|
|
113
|
+
.addOnCompleteListener(
|
|
114
|
+
task -> {
|
|
115
|
+
if (task.isSuccessful()) {
|
|
116
|
+
promise.resolve(null);
|
|
117
|
+
} else if (task.isCanceled()) {
|
|
118
|
+
promise.reject(
|
|
119
|
+
"play-services-update-canceled",
|
|
120
|
+
"Play Services update was canceled by the user");
|
|
121
|
+
} else {
|
|
122
|
+
Exception e = task.getException();
|
|
123
|
+
promise.reject(
|
|
124
|
+
"play-services-update-failed",
|
|
125
|
+
e != null ? e.getMessage() : "Unknown error",
|
|
126
|
+
e);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
} else {
|
|
130
|
+
promise.resolve(null);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
promise.resolve(null);
|
|
113
135
|
}
|
|
114
136
|
}
|
|
115
137
|
|
|
116
138
|
private int isGooglePlayServicesAvailable() {
|
|
117
139
|
GoogleApiAvailability gapi = GoogleApiAvailability.getInstance();
|
|
118
|
-
return gapi.isGooglePlayServicesAvailable(
|
|
140
|
+
return gapi.isGooglePlayServicesAvailable(getReactApplicationContext());
|
|
119
141
|
}
|
|
120
142
|
|
|
121
143
|
private WritableMap getPlayServicesStatusMap() {
|
|
122
144
|
WritableMap result = Arguments.createMap();
|
|
123
145
|
GoogleApiAvailability gapi = GoogleApiAvailability.getInstance();
|
|
124
146
|
|
|
125
|
-
int status = gapi.isGooglePlayServicesAvailable(
|
|
147
|
+
int status = gapi.isGooglePlayServicesAvailable(getReactApplicationContext());
|
|
126
148
|
result.putInt("status", status);
|
|
127
149
|
|
|
128
150
|
if (status == ConnectionResult.SUCCESS) {
|
|
@@ -138,11 +160,10 @@ public class ReactNativeFirebaseUtilsModule extends ReactNativeFirebaseModule {
|
|
|
138
160
|
}
|
|
139
161
|
|
|
140
162
|
@Override
|
|
141
|
-
|
|
163
|
+
protected Map<String, Object> getTypedExportedConstants() {
|
|
142
164
|
Map<String, Object> constants = new HashMap<>();
|
|
143
165
|
|
|
144
166
|
constants.put("isRunningInTestLab", isRunningInTestLab());
|
|
145
|
-
constants.put("androidPlayServices", getPlayServicesStatusMap());
|
|
146
167
|
|
|
147
168
|
Context context = getReactApplicationContext();
|
|
148
169
|
constants.put(KEY_MAIN_BUNDLE, "");
|
|
@@ -155,10 +176,6 @@ public class ReactNativeFirebaseUtilsModule extends ReactNativeFirebaseModule {
|
|
|
155
176
|
if (externalDirectory != null) {
|
|
156
177
|
constants.put(KEY_DOCUMENT_DIRECTORY, externalDirectory.getAbsolutePath());
|
|
157
178
|
} else {
|
|
158
|
-
// The external directory may be null if it is truly external *and*
|
|
159
|
-
// the device's external storage environment changes. We will use the regular
|
|
160
|
-
// Files directory as a backup and note in the documentation that the directory may
|
|
161
|
-
// vary under rare conditions
|
|
162
179
|
constants.put(KEY_DOCUMENT_DIRECTORY, context.getFilesDir().getAbsolutePath());
|
|
163
180
|
}
|
|
164
181
|
}
|
|
@@ -167,15 +184,15 @@ public class ReactNativeFirebaseUtilsModule extends ReactNativeFirebaseModule {
|
|
|
167
184
|
constants.put(KEY_DOCUMENT_DIRECTORY, context.getFilesDir().getAbsolutePath());
|
|
168
185
|
}
|
|
169
186
|
|
|
187
|
+
File picturesDirectory =
|
|
188
|
+
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
|
170
189
|
constants.put(
|
|
171
|
-
KEY_PICS_DIRECTORY,
|
|
172
|
-
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
|
|
173
|
-
.getAbsolutePath());
|
|
190
|
+
KEY_PICS_DIRECTORY, picturesDirectory != null ? picturesDirectory.getAbsolutePath() : "");
|
|
174
191
|
|
|
192
|
+
File moviesDirectory =
|
|
193
|
+
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
|
|
175
194
|
constants.put(
|
|
176
|
-
KEY_MOVIES_DIRECTORY,
|
|
177
|
-
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
|
|
178
|
-
.getAbsolutePath());
|
|
195
|
+
KEY_MOVIES_DIRECTORY, moviesDirectory != null ? moviesDirectory.getAbsolutePath() : "");
|
|
179
196
|
|
|
180
197
|
File externalStorageDirectory = Environment.getExternalStorageDirectory();
|
|
181
198
|
if (externalStorageDirectory != null) {
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
package io.invertase.firebase.app;
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this library except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import static org.junit.Assert.assertEquals;
|
|
21
|
+
import static org.junit.Assert.assertFalse;
|
|
22
|
+
import static org.junit.Assert.assertNull;
|
|
23
|
+
import static org.junit.Assert.assertTrue;
|
|
24
|
+
import static org.mockito.Mockito.mock;
|
|
25
|
+
import static org.mockito.Mockito.mockStatic;
|
|
26
|
+
import static org.mockito.Mockito.verify;
|
|
27
|
+
import static org.mockito.Mockito.when;
|
|
28
|
+
|
|
29
|
+
import android.app.Application;
|
|
30
|
+
import com.facebook.react.ReactApplication;
|
|
31
|
+
import com.facebook.react.ReactHost;
|
|
32
|
+
import com.facebook.react.ReactNativeHost;
|
|
33
|
+
import com.facebook.react.bridge.Arguments;
|
|
34
|
+
import com.facebook.react.bridge.Promise;
|
|
35
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
36
|
+
import com.facebook.react.bridge.ReactContext;
|
|
37
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
38
|
+
import com.facebook.react.bridge.WritableMap;
|
|
39
|
+
import com.google.firebase.FirebaseApp;
|
|
40
|
+
import io.invertase.firebase.common.RCTConvertFirebase;
|
|
41
|
+
import io.invertase.firebase.common.ReactNativeFirebaseEventEmitter;
|
|
42
|
+
import io.invertase.firebase.common.ReactNativeFirebaseJSON;
|
|
43
|
+
import io.invertase.firebase.common.ReactNativeFirebaseMeta;
|
|
44
|
+
import io.invertase.firebase.common.ReactNativeFirebasePreferences;
|
|
45
|
+
import java.lang.ref.WeakReference;
|
|
46
|
+
import java.lang.reflect.Constructor;
|
|
47
|
+
import java.lang.reflect.Field;
|
|
48
|
+
import java.lang.reflect.Method;
|
|
49
|
+
import java.util.Collections;
|
|
50
|
+
import java.util.HashMap;
|
|
51
|
+
import java.util.List;
|
|
52
|
+
import java.util.Map;
|
|
53
|
+
import org.junit.Before;
|
|
54
|
+
import org.junit.Test;
|
|
55
|
+
import org.junit.runner.RunWith;
|
|
56
|
+
import org.mockito.MockedStatic;
|
|
57
|
+
import org.robolectric.RobolectricTestRunner;
|
|
58
|
+
import org.robolectric.annotation.Config;
|
|
59
|
+
import org.robolectric.shadows.ShadowLooper;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* JVM LINE coverage for {@link NativeRNFBTurboApp} — lifecycle, constants, app CRUD, events, and
|
|
63
|
+
* preferences bridges.
|
|
64
|
+
*/
|
|
65
|
+
@RunWith(RobolectricTestRunner.class)
|
|
66
|
+
@Config(sdk = 34, application = NativeRNFBTurboAppTest.HostApplication.class)
|
|
67
|
+
public class NativeRNFBTurboAppTest {
|
|
68
|
+
|
|
69
|
+
public static class HostApplication extends Application implements ReactApplication {
|
|
70
|
+
ReactHost reactHost;
|
|
71
|
+
|
|
72
|
+
@Override
|
|
73
|
+
public ReactNativeHost getReactNativeHost() {
|
|
74
|
+
throw new RuntimeException("bridgeless-only test host");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Override
|
|
78
|
+
public ReactHost getReactHost() {
|
|
79
|
+
return reactHost;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private HostApplication application;
|
|
84
|
+
private ReactHost reactHost;
|
|
85
|
+
private ReactApplicationContext reactContext;
|
|
86
|
+
|
|
87
|
+
@Before
|
|
88
|
+
public void setUp() throws Exception {
|
|
89
|
+
application = (HostApplication) org.robolectric.RuntimeEnvironment.getApplication();
|
|
90
|
+
reactHost = mock(ReactHost.class);
|
|
91
|
+
application.reactHost = reactHost;
|
|
92
|
+
|
|
93
|
+
reactContext = mock(ReactApplicationContext.class);
|
|
94
|
+
when(reactContext.getApplicationContext()).thenReturn(application);
|
|
95
|
+
when(reactContext.hasActiveReactInstance()).thenReturn(true);
|
|
96
|
+
when(reactHost.getCurrentReactContext()).thenReturn(reactContext);
|
|
97
|
+
|
|
98
|
+
NativeRNFBTurboApp.authDomains.clear();
|
|
99
|
+
resetEmitterSharedInstance();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@Test
|
|
103
|
+
public void initialize_registersLifecycleListenerAndAttachesEmitter() throws Exception {
|
|
104
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
105
|
+
module.initialize();
|
|
106
|
+
ShadowLooper.idleMainLooper();
|
|
107
|
+
|
|
108
|
+
verify(reactContext).addLifecycleEventListener(module);
|
|
109
|
+
assertEquals(reactContext, attachedContext());
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@Test
|
|
113
|
+
public void invalidate_removesLifecycleListenerAndDetachesEmitter() throws Exception {
|
|
114
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
115
|
+
ReactNativeFirebaseEventEmitter.getSharedInstance().attachReactContext(reactContext);
|
|
116
|
+
ShadowLooper.idleMainLooper();
|
|
117
|
+
|
|
118
|
+
module.invalidate();
|
|
119
|
+
ShadowLooper.idleMainLooper();
|
|
120
|
+
|
|
121
|
+
verify(reactContext).removeLifecycleEventListener(module);
|
|
122
|
+
assertNull(attachedContext());
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@Test
|
|
126
|
+
public void onHostResume_reattachesEmitter() throws Exception {
|
|
127
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
128
|
+
module.onHostResume();
|
|
129
|
+
ShadowLooper.idleMainLooper();
|
|
130
|
+
assertEquals(reactContext, attachedContext());
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@Test
|
|
134
|
+
public void onHostPause_and_onHostDestroy_areNoOps() {
|
|
135
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
136
|
+
module.onHostPause();
|
|
137
|
+
module.onHostDestroy();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@Test
|
|
141
|
+
public void getTypedExportedConstants_includesAppsAndRawJson() throws Exception {
|
|
142
|
+
FirebaseApp firebaseApp = mock(FirebaseApp.class);
|
|
143
|
+
Map<String, Object> appMap = new HashMap<>();
|
|
144
|
+
appMap.put("name", "[DEFAULT]");
|
|
145
|
+
|
|
146
|
+
try (MockedStatic<FirebaseApp> firebaseApps = mockStatic(FirebaseApp.class);
|
|
147
|
+
MockedStatic<RCTConvertFirebase> convert = mockStatic(RCTConvertFirebase.class);
|
|
148
|
+
MockedStatic<ReactNativeFirebaseJSON> jsonStatic =
|
|
149
|
+
mockStatic(ReactNativeFirebaseJSON.class)) {
|
|
150
|
+
firebaseApps
|
|
151
|
+
.when(() -> FirebaseApp.getApps(reactContext))
|
|
152
|
+
.thenReturn(Collections.singletonList(firebaseApp));
|
|
153
|
+
convert.when(() -> RCTConvertFirebase.firebaseAppToMap(firebaseApp)).thenReturn(appMap);
|
|
154
|
+
|
|
155
|
+
ReactNativeFirebaseJSON json = mock(ReactNativeFirebaseJSON.class);
|
|
156
|
+
jsonStatic.when(ReactNativeFirebaseJSON::getSharedInstance).thenReturn(json);
|
|
157
|
+
when(json.getRawJSON()).thenReturn("{}");
|
|
158
|
+
|
|
159
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
160
|
+
Method method = NativeRNFBTurboApp.class.getDeclaredMethod("getTypedExportedConstants");
|
|
161
|
+
method.setAccessible(true);
|
|
162
|
+
@SuppressWarnings("unchecked")
|
|
163
|
+
Map<String, Object> constants = (Map<String, Object>) method.invoke(module);
|
|
164
|
+
|
|
165
|
+
assertEquals("{}", constants.get("FIREBASE_RAW_JSON"));
|
|
166
|
+
@SuppressWarnings("unchecked")
|
|
167
|
+
List<Map<String, Object>> apps =
|
|
168
|
+
(List<Map<String, Object>>) constants.get("NATIVE_FIREBASE_APPS");
|
|
169
|
+
assertEquals(1, apps.size());
|
|
170
|
+
assertEquals("[DEFAULT]", apps.get(0).get("name"));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@Test
|
|
175
|
+
public void initializeApp_configuresAuthDomainAndResolvesPromise() {
|
|
176
|
+
ReadableMap options = mock(ReadableMap.class);
|
|
177
|
+
ReadableMap appConfig = mock(ReadableMap.class);
|
|
178
|
+
Promise promise = mock(Promise.class);
|
|
179
|
+
FirebaseApp firebaseApp = mock(FirebaseApp.class);
|
|
180
|
+
WritableMap writableMap = mock(WritableMap.class);
|
|
181
|
+
|
|
182
|
+
when(appConfig.getString("name")).thenReturn("secondary");
|
|
183
|
+
when(options.getString("authDomain")).thenReturn("example.firebaseapp.com");
|
|
184
|
+
|
|
185
|
+
try (MockedStatic<RCTConvertFirebase> convert = mockStatic(RCTConvertFirebase.class)) {
|
|
186
|
+
convert
|
|
187
|
+
.when(() -> RCTConvertFirebase.readableMapToFirebaseApp(options, appConfig, reactContext))
|
|
188
|
+
.thenReturn(firebaseApp);
|
|
189
|
+
convert
|
|
190
|
+
.when(() -> RCTConvertFirebase.firebaseAppToWritableMap(firebaseApp))
|
|
191
|
+
.thenReturn(writableMap);
|
|
192
|
+
|
|
193
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
194
|
+
module.initializeApp(options, appConfig, promise);
|
|
195
|
+
|
|
196
|
+
assertEquals("example.firebaseapp.com", NativeRNFBTurboApp.authDomains.get("secondary"));
|
|
197
|
+
verify(promise).resolve(writableMap);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@Test
|
|
202
|
+
public void configureAuthDomain_putsAndRemovesEntries() {
|
|
203
|
+
NativeRNFBTurboApp.configureAuthDomain("secondary", "example.firebaseapp.com");
|
|
204
|
+
assertEquals("example.firebaseapp.com", NativeRNFBTurboApp.authDomains.get("secondary"));
|
|
205
|
+
NativeRNFBTurboApp.configureAuthDomain("secondary", null);
|
|
206
|
+
assertFalse(NativeRNFBTurboApp.authDomains.containsKey("secondary"));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
@Test
|
|
210
|
+
public void setAutomaticDataCollectionEnabled_delegatesToFirebaseApp() {
|
|
211
|
+
FirebaseApp firebaseApp = mock(FirebaseApp.class);
|
|
212
|
+
try (MockedStatic<FirebaseApp> firebaseApps = mockStatic(FirebaseApp.class)) {
|
|
213
|
+
firebaseApps.when(() -> FirebaseApp.getInstance("secondary")).thenReturn(firebaseApp);
|
|
214
|
+
|
|
215
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
216
|
+
module.setAutomaticDataCollectionEnabled("secondary", true);
|
|
217
|
+
|
|
218
|
+
verify(firebaseApp).setDataCollectionDefaultEnabled(true);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@Test
|
|
223
|
+
public void deleteApp_deletesWhenInstancePresent() {
|
|
224
|
+
FirebaseApp firebaseApp = mock(FirebaseApp.class);
|
|
225
|
+
Promise promise = mock(Promise.class);
|
|
226
|
+
try (MockedStatic<FirebaseApp> firebaseApps = mockStatic(FirebaseApp.class)) {
|
|
227
|
+
firebaseApps.when(() -> FirebaseApp.getInstance("secondary")).thenReturn(firebaseApp);
|
|
228
|
+
|
|
229
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
230
|
+
module.deleteApp("secondary", promise);
|
|
231
|
+
|
|
232
|
+
verify(firebaseApp).delete();
|
|
233
|
+
verify(promise).resolve(null);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@Test
|
|
238
|
+
public void deleteApp_resolvesWhenInstanceNull() {
|
|
239
|
+
Promise promise = mock(Promise.class);
|
|
240
|
+
try (MockedStatic<FirebaseApp> firebaseApps = mockStatic(FirebaseApp.class)) {
|
|
241
|
+
firebaseApps.when(() -> FirebaseApp.getInstance("missing")).thenReturn(null);
|
|
242
|
+
|
|
243
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
244
|
+
module.deleteApp("missing", promise);
|
|
245
|
+
|
|
246
|
+
verify(promise).resolve(null);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@Test
|
|
251
|
+
public void eventsNotifyReady_forwardsToEmitter() throws Exception {
|
|
252
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
253
|
+
module.eventsNotifyReady(true);
|
|
254
|
+
Field field = ReactNativeFirebaseEventEmitter.class.getDeclaredField("jsReady");
|
|
255
|
+
field.setAccessible(true);
|
|
256
|
+
assertTrue(field.getBoolean(ReactNativeFirebaseEventEmitter.getSharedInstance()));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@Test
|
|
260
|
+
public void eventsGetListeners_resolvesEmitterMap() {
|
|
261
|
+
Promise promise = mock(Promise.class);
|
|
262
|
+
WritableMap listenersMap = mock(WritableMap.class);
|
|
263
|
+
WritableMap eventsMap = mock(WritableMap.class);
|
|
264
|
+
|
|
265
|
+
try (MockedStatic<Arguments> arguments = mockStatic(Arguments.class)) {
|
|
266
|
+
arguments.when(Arguments::createMap).thenReturn(listenersMap, eventsMap);
|
|
267
|
+
|
|
268
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
269
|
+
module.eventsGetListeners(promise);
|
|
270
|
+
|
|
271
|
+
verify(promise).resolve(listenersMap);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
@Test
|
|
276
|
+
public void eventsPing_sendsEventAndResolvesBody() {
|
|
277
|
+
ReadableMap body = mock(ReadableMap.class);
|
|
278
|
+
WritableMap writable = mock(WritableMap.class);
|
|
279
|
+
Promise promise = mock(Promise.class);
|
|
280
|
+
|
|
281
|
+
try (MockedStatic<RCTConvertFirebase> convert = mockStatic(RCTConvertFirebase.class)) {
|
|
282
|
+
convert.when(() -> RCTConvertFirebase.readableMapToWritableMap(body)).thenReturn(writable);
|
|
283
|
+
|
|
284
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
285
|
+
module.eventsPing("ping_event", body, promise);
|
|
286
|
+
|
|
287
|
+
verify(promise).resolve(writable);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
@Test
|
|
292
|
+
public void eventsAddAndRemoveListener_delegateToEmitter() throws Exception {
|
|
293
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
294
|
+
module.eventsAddListener("auth_state_changed");
|
|
295
|
+
ShadowLooper.idleMainLooper();
|
|
296
|
+
|
|
297
|
+
Field field = ReactNativeFirebaseEventEmitter.class.getDeclaredField("jsListeners");
|
|
298
|
+
field.setAccessible(true);
|
|
299
|
+
@SuppressWarnings("unchecked")
|
|
300
|
+
Map<String, Integer> listeners =
|
|
301
|
+
(Map<String, Integer>) field.get(ReactNativeFirebaseEventEmitter.getSharedInstance());
|
|
302
|
+
assertEquals(Integer.valueOf(1), listeners.get("auth_state_changed"));
|
|
303
|
+
|
|
304
|
+
module.eventsRemoveListener("auth_state_changed", true);
|
|
305
|
+
assertFalse(listeners.containsKey("auth_state_changed"));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
@Test
|
|
309
|
+
public void addListener_and_removeListeners_areNoOpsForRnBuiltInEmitter() {
|
|
310
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
311
|
+
module.addListener("rn_builtin");
|
|
312
|
+
module.removeListeners(1);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
@Test
|
|
316
|
+
public void metaGetAll_resolvesMetaSingleton() {
|
|
317
|
+
Promise promise = mock(Promise.class);
|
|
318
|
+
WritableMap all = mock(WritableMap.class);
|
|
319
|
+
ReactNativeFirebaseMeta meta = mock(ReactNativeFirebaseMeta.class);
|
|
320
|
+
when(meta.getAll()).thenReturn(all);
|
|
321
|
+
|
|
322
|
+
try (MockedStatic<ReactNativeFirebaseMeta> metaStatic =
|
|
323
|
+
mockStatic(ReactNativeFirebaseMeta.class)) {
|
|
324
|
+
metaStatic.when(ReactNativeFirebaseMeta::getSharedInstance).thenReturn(meta);
|
|
325
|
+
|
|
326
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
327
|
+
module.metaGetAll(promise);
|
|
328
|
+
verify(promise).resolve(all);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
@Test
|
|
333
|
+
public void jsonGetAll_resolvesJsonSingleton() {
|
|
334
|
+
Promise promise = mock(Promise.class);
|
|
335
|
+
WritableMap all = mock(WritableMap.class);
|
|
336
|
+
ReactNativeFirebaseJSON json = mock(ReactNativeFirebaseJSON.class);
|
|
337
|
+
when(json.getAll()).thenReturn(all);
|
|
338
|
+
|
|
339
|
+
try (MockedStatic<ReactNativeFirebaseJSON> jsonStatic =
|
|
340
|
+
mockStatic(ReactNativeFirebaseJSON.class)) {
|
|
341
|
+
jsonStatic.when(ReactNativeFirebaseJSON::getSharedInstance).thenReturn(json);
|
|
342
|
+
|
|
343
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
344
|
+
module.jsonGetAll(promise);
|
|
345
|
+
verify(promise).resolve(all);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
@Test
|
|
350
|
+
public void preferencesSettersAndGetters_delegateToPreferencesSingleton() {
|
|
351
|
+
Promise promise = mock(Promise.class);
|
|
352
|
+
WritableMap all = mock(WritableMap.class);
|
|
353
|
+
ReactNativeFirebasePreferences prefs = mock(ReactNativeFirebasePreferences.class);
|
|
354
|
+
when(prefs.getAll()).thenReturn(all);
|
|
355
|
+
|
|
356
|
+
try (MockedStatic<ReactNativeFirebasePreferences> prefsStatic =
|
|
357
|
+
mockStatic(ReactNativeFirebasePreferences.class)) {
|
|
358
|
+
prefsStatic.when(ReactNativeFirebasePreferences::getSharedInstance).thenReturn(prefs);
|
|
359
|
+
|
|
360
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
361
|
+
module.preferencesSetBool("k", true, promise);
|
|
362
|
+
verify(prefs).setBooleanValue("k", true);
|
|
363
|
+
verify(promise).resolve(null);
|
|
364
|
+
|
|
365
|
+
module.preferencesSetString("k", "v", promise);
|
|
366
|
+
verify(prefs).setStringValue("k", "v");
|
|
367
|
+
|
|
368
|
+
module.preferencesGetAll(promise);
|
|
369
|
+
verify(promise).resolve(all);
|
|
370
|
+
|
|
371
|
+
module.preferencesClearAll(promise);
|
|
372
|
+
verify(prefs).clearAll();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
@Test
|
|
377
|
+
public void setLogLevel_isNoOp() {
|
|
378
|
+
NativeRNFBTurboApp module = new NativeRNFBTurboApp(reactContext);
|
|
379
|
+
module.setLogLevel("debug");
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
private static void resetEmitterSharedInstance() throws Exception {
|
|
383
|
+
Constructor<ReactNativeFirebaseEventEmitter> ctor =
|
|
384
|
+
ReactNativeFirebaseEventEmitter.class.getDeclaredConstructor();
|
|
385
|
+
ctor.setAccessible(true);
|
|
386
|
+
ReactNativeFirebaseEventEmitter fresh = ctor.newInstance();
|
|
387
|
+
Field shared = ReactNativeFirebaseEventEmitter.class.getDeclaredField("sharedInstance");
|
|
388
|
+
shared.setAccessible(true);
|
|
389
|
+
shared.set(null, fresh);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
@SuppressWarnings("unchecked")
|
|
393
|
+
private static ReactContext attachedContext() throws Exception {
|
|
394
|
+
ReactNativeFirebaseEventEmitter emitter = ReactNativeFirebaseEventEmitter.getSharedInstance();
|
|
395
|
+
Field field = ReactNativeFirebaseEventEmitter.class.getDeclaredField("attachedReactContext");
|
|
396
|
+
field.setAccessible(true);
|
|
397
|
+
WeakReference<ReactContext> ref = (WeakReference<ReactContext>) field.get(emitter);
|
|
398
|
+
return ref.get();
|
|
399
|
+
}
|
|
400
|
+
}
|