How do I run Flutter widget tests with shadows enabled? - flutter

I'd like to render some of my Flutter golden files with shadows. How can I accomplish that?
Shadows are disabled by default:
https://github.com/flutter/flutter/blob/master/packages/flutter_test/lib/src/binding.dart#L942

With the debugDisableShadows flag.
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('my golden test with shadows enabled', (tester) async {
// Enable shadows
debugDisableShadows = false;
await tester.pumpWidget(MyWidget());
await expectLater(find.byType(MyWidget), matchesGoldenFile('..'));
// Set the flag back to normal
debugDisableShadows = true;
});
}
Note that you have to toggle the flag back to normal inside the test case (and not setUp / tearDown) - otherwise, it will fail.
This happens because this check is performed immediately after the body of testWidgets() completes, but before the test case is considered finished. Which is also before tearDown() is executed.

Related

How to Flutter App run continuously fetch data after every 10 sec in background when app is closed/terminated or screen off

How to Flutter App run continuously in the background when the app is closed/terminated. I have to fetch the location continuously when the app is terminated/closed or the screen is locked.
Try work manager
https://pub.dev/packages/workmanager
Create a root level method and use that method to create a background process.
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
print("Native called background task: $backgroundTask"); //simpleTask will be emitted here.
return Future.value(true);
});
}
void main() {
Workmanager().initialize(
callbackDispatcher, // The top level function, aka callbackDispatcher
isInDebugMode: true // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
);
Workmanager().registerOneOffTask("task-identifier", "simpleTask");
runApp(MyApp());
}

How to pass parameters into flutter integration_test?

I used flutter_driver before for integration tests and was able to insert parameters to the test via environment variables from the host, as the test was running from the host.
For another project I am now using the integration_test package.
The test is not running any longer on the host but on the target so when trying to pass arguments via environment variables, the test does not get them.
I saw https://github.com/flutter/flutter/issues/76852 which I think could help but are there other options available right now?
If you're using the integration_test package, the test code can set global variables prior to running your app, and pull them from the environment specified using --dart-define
For example:
// In main.dart
var environment = 'production';
void main() {
if (environment == 'development') {
// setup configuration for you application
}
runApp(const MyApp());
}
// In your integration_test.dart
import 'package:my_app/main.dart' as app;
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() {
var testingEnvironment = const String.fromEnvironment('TESTING_ENVIRONMENT');
if (testingEnvironment != null) {
app.environment = testingEnvironment;
}
});
testWidgets('my test', (WidgetTester tester) async {
app.main();
await tester.pumpAndSettle();
// Perform your test
});
}
then use the command line flutter test integration_test.dart --dart-define TESTING_ENVIRONMENT=development
Alternately, you could pull them from String.fromEnvironment directly in your app code.
I had the same problem running integration_tests on android emulator. A look at the documentation of bool.fromEnvironment() showed:
/// This constructor is only guaranteed to work when invoked as `const`.
/// It may work as a non-constant invocation on some platforms ...
So this works for me testing with android:
const skipFirst = bool.fromEnvironment('SKIP_FIRST');

Dart's Future Interface (doWhile, microtask and sync)

Haven't seen a lot of info about it online...
What are the possible use cases in which I'd want to use, either Future.doWhile, Future.microtask or Future.sync?
Future.sync
A lot of times after a button press for example, I'd want a Future to happen immediately,
but I wouldn't want it to block the UI, is that a good use case for Future.sync or is that better to use Future and let dart handle when thing will get executed?
I'd want a Future to happen immediately...
You can't make Future to happen immediately because it needs some time to be executed. Instead you can block UI thread while future is executing. The pseudo code looks like that:
T runSync<T>(Future<T> future) {
while (future.running) sleep(10);
return future.result;
}
This will block your ui thread. That's why we are using Futures. Futures used for specific tasks that's not resolved immediately (usually I/O tasks, eg: network requests, file read/write) to get notified when future resolves without blocking UI thread.
Here's how I'm handling futures without blocking UI thread:
class MyState extends State<..> {
bool _running = false;
Future<String> doTask() async {
// some long running IO tasks
return 'Hello world';
}
Future handlePress() async {
setState(() { _running = true; });
try {
await doTask();
} finally {
if (mounted) {
setState(() { _running = false; });
}
}
}
Widget build(BuildContext context) {
return FlatButton(
child: Text('Execute'),
// Disable button if task is currently running to block parallel calls (for example sending same http request twice)
onPressed: _running ? null : handlePress,
);
}
}
In this code when user presses FlatButton I'm setting _running to true to disable FlatButton until Future is running.

In Flutter, How to avoid crash screen by replacing problem content with a text object? [duplicate]

Is there a way to display (in production) a custom error widget instead of the red screen of death? I will not change the framework code, plus even though we are trying to program without errors, we can't guarantee it to happen.
It is possible to change the default error rendering by changing ErrorWidget.builder
ErrorWidget.builder = (errorDetails) {
return Container(color: Colors.red);
}
Use ErrorWidget.builder instead main() function, like this
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
ErrorWidget.builder = (FlutterErrorDetails details) => SomethingWrong();
runApp(YourApp());
}
And if you want to show Certain Widget only on Production app, then you can use kReleaseMode-
if (kReleaseMode) {
ErrorWidget.builder = (FlutterErrorDetails details) => SomethingWrong();
}
Note: The top-level kReleaseMode constant is use to determine whether the app was compiled in release mode.

Flutter: Use custom ErrorWidget

Is there a way to display (in production) a custom error widget instead of the red screen of death? I will not change the framework code, plus even though we are trying to program without errors, we can't guarantee it to happen.
It is possible to change the default error rendering by changing ErrorWidget.builder
ErrorWidget.builder = (errorDetails) {
return Container(color: Colors.red);
}
Use ErrorWidget.builder instead main() function, like this
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
ErrorWidget.builder = (FlutterErrorDetails details) => SomethingWrong();
runApp(YourApp());
}
And if you want to show Certain Widget only on Production app, then you can use kReleaseMode-
if (kReleaseMode) {
ErrorWidget.builder = (FlutterErrorDetails details) => SomethingWrong();
}
Note: The top-level kReleaseMode constant is use to determine whether the app was compiled in release mode.