I'd like to run tests that call multiple Cloud Functions in the emulator that make use of a mocked out external service (getstream.io). That means the mock would have to stay around across function invocations. Is something like this possible?
let mock = new SomethingMock();
exports.resetMock = functions.https.onCall((data, context) => {
mock = new SomethingMock();
});
exports.addActivity = functions.https.onCall(async (data, context) => {
await mock.addActivity(something);
});
exports.getActivities = functions.https.onCall((data, context) => {
// assumes addActivity has been called a few times
return mock.getActivities();
});
This page says gives no guarantees about preservation of global state in production, but says nothing about the emulator:
https://firebase.google.com/docs/functions/tips#use_global_variables_to_reuse_objects_in_future_invocations
The firebase emulator will neither guarantee the preservation of global state.
The answer is in the definition itself:
The Firebase Local Emulator Suite consists of individual service emulators built to accurately mimic the behavior of Firebase services. This means you can connect your app directly to these emulators to perform integration testing or QA without touching production data. They(emulatored firebase services) are built for accuracy, not performance or security, and are not appropriate to use in production.
Having said that, there is not much added value in having an emulator that does not return results as if the service was in production.
Related
I'm currently migrating my project from Vue2+Vuex to Vue3+pinia. The storage of choice is still firebase. To keep my local storage in sync with the remote firebase-database I want to setup a (one-way) binding. I plan to use useFirestore as documented here.
I wrapped in a pinia action:
async bindTodos () {
this.todos = todos = useFirestore(collection(db, 'todos'));
}
with this.todos being defined in pinias state.
How can I maintain a boolean in the pinia state (i.e. todosReady) that get's updated when the todos were received the first time. Vuex/bindFirestoreRef used to return a promise. Or I am supposed to use import {watch} from "vue" and simply watch for changes in the returned Ref? Hope I'm on the right track!
I try to implement a flutter code that will control NIR Spectrometer via BLE.
I have a very long protocol of service and characteristic uuid pair, and I actually did the same in ionic by just using the uuid pairs and it worked fine...
Is there a way in flutter to call read/write/notify with out do all the:
List<BluetoothService> services = await device.discoverServices();
services.forEach((service) {
// do something with service
for(BluetoothCharacteristic c in characteristics) {
// save the characteristic for latter usage if needed
}
});
something like:
c = BluetoothCharacteristic(device, service_uuid, characteristic_uuid); // why there is no constructor!!
It's going to make life more easy for me!
I finally gave up, also some services that I need don't do advertisement.. So I started to use the plugin flutter_reactive_ble which gives me this option
I have an app with a real time listener setup to instantly pick up all updates on a collection. I also have some logic to pick missing documents afterwards in case my app loses its connectivity (in which case the listener would miss some documents).
I want to test this logic using the simulator, but how do I simulate the loss of connectivity? is there built-in function for that?
Actually the following page shows how to proceed in general, be it with the emulator or an actual Firestore instance:
firebase.firestore().disableNetwork()
.then(() => {
// Do offline actions
// ...
});
firebase.firestore().enableNetwork()
.then(() => {
// Do online actions
// ...
});
My app is in 2 parts. It creates a widget tree and populates a Stateful Widget Config.
I then pass this to phase 2 of my app as a static. (I tried various ways).
On a clean emulator it runs fine. When I run it again using Hot Restart my buildSitePath is passed a half-baked instance that did not go thru the proper constructors.
Thus where appCfg is a static Config appCfg
that has been confirmed to be populated properly the log statement in the following will execute after
the populating and yet it will be the half-baked instance that breaks the app. This happens on Hot Restart which supposedly restarts the app from the beginning.
routes:<String,WidgetBuilder>{
"/site":(BuildContext context) {assert(log("site: $appCfg"));
return buildSitePath(context,appCfg,title);}
},
The solution was to not use a static and to use a onGenerateRoute and pass the actual instance as a parameter. Thus, this worked.
onGenerateRoute: (settings) {
log("onGenerateRoute ${settings.name}");
if (settings.name == "/site") {
Config appCfg = settings.arguments;
log("onGenerateRoute $appCfg");
if (isMaterial(contextA)) {
return MaterialPageRoute(builder: (context) => buildSitePath(contextA, appCfg, title));
} else {
return CupertinoPageRoute(builder: (context) => buildSitePath(contextA, appCfg, title));
}
}
return null;
I looked and found no understanding as to what Hot Restart is doing with classes that might explain this.
What am I missing? Thanks.
As I said in my question my suspicion is that Flutter Hot Restart sees the static class instance that is not populated and jams the class in there using a default constructor.
Even if the class was not static but a member of another class the same ailment persisted.
I record this behavior here so that others need not waste as much time as I did to understand the problem.
I try to check if my app has new version. If has new version shows a modal to force to update. I use the firebase remote config package.
The code looks
versionCheck(context) async {
PackageInfo info = await PackageInfo.fromPlatform();
RemoteConfig remoteConfig = await RemoteConfig.instance;
await remoteConfig.fetch();
await remoteConfig.activateFetched();
final currentBuildNumber = int.parse(info.buildNumber);
final requiredBuildNumber = remoteConfig
.getInt('android_app_version');
if (requiredBuildNumber > currentBuildNumber) {
versionDialog(context);
}
}
The problem: currentBuildNumber return the correct number, but the requiredBuildNumber always return '50', so the if conditional doesn´t work as expected. Something is wrong but don't i don't know what. What´s is the rigth way to do this?
If the app fetches so many times in a short period of time it the fetch calls are throttled. Because of the throttling limits, it is not possible for your app to immediately see changes in Remote Config values. Cached values will be used until the next fetch is allowed. The default cache expiration is 12 hours. This is done to optimize the network usage by Remote Config feature.
Keep in mind that this setting should be used for development only,
not for an app running in production. If you're just testing your app
with a small 10-person development team, you are unlikely to hit the
hourly service-side quota limits. But if you pushed your app out to
thousands of test users with a very low minimum fetch interval, your
app would probably hit this quota.