hydrated_bloc: The parameter 'storageDirectory' is required - flutter

I updated hydrated_bloc from 6.1.0 to the latest 7.0.1 and I got a warning in:
HydratedBloc.storage = await HydratedStorage.build(); The parameter 'storageDirectory' is required.
When I changed to what the new documentation suggested
HydratedBloc.storage = await HydratedStorage.build(
storageDirectory: await getTemporaryDirectory(),); The function 'getTemporaryDirectory' isn't defined.
I also tried:
HydratedBloc.storage = await HydratedStorage.build(storageDirectory: await getApplicationDocumentsDirectory(),); The function 'getApplicationDocumentsDirectory' isn't defined

Both getTemporaryDirectory and getApplicationDocumentsDirectory are part of the path_provider package, so, you have to import it in your main.dart file

Yes you need path Provider Flutter package, you might also experience this error "StorageNotFound (Storage was accessed before it was initialized), or The setter 'storage' isn't defined for the type 'HydratedBloc' in Android Studio
instead define it as below: `
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final storage = await HydratedStorage.build(
storageDirectory: await getApplicationDocumentsDirectory(),
);
HydratedBlocOverrides.runZoned(
() => runApp(MyApp(
appRouter: AppRouter(),
connectivity: Connectivity(),
)),
storage: storage,
);
}
`
You can get the full code here

Related

how to run command in Dart correctly?

That's my code. I want to use Process.run to open a command to do something, like git clone or flutter build.
import 'dart:io';
void main() async {
print('build start');
// var res = await Process.run('git clone xxxx', []);
var res = await Process.run('flutter build windows --dart-define=RunEnv=dist', []);
print(res);
print('build end');
}
But it failed.
Unhandled exception:
ProcessException: 系统找不到指定的文件。
Command: flutter
Dart Process can't read global command variable like flutter or git? In nodejs is easy to do that. What should I do?
Your syntaxis is not right. All parameters have to supplied as a list of string, rewrite it to:
final ProcessResult res = await Process.run(
'flutter',
<String>[
'build',
'windows',
'--dart-define=RunEnv=dist'
],
);
[Edit] Link to documentation: https://api.flutter.dev/flutter/dart-io/Process/run.html [/edit]

Flutter integration test running twice on web

GitHub issue
Setup:
Clone repository
Run chromedriver --port=4444 in another terminal
Run flutter drive --driver=test_driver/integration_test.dart --target=integration_test/example_test.dart -d chrome
It seems like the test is running twice as there are two documents inserted into Firestore where there should only be one document inserted.
This behavior is only happening on web, it doesn't produce the same behavior on iOS
If you clone the repo and test it for yourself please change the collection name of examples to something else to not clash with other testers
Code for when the repository is removed
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
final now = DateTime.now();
const String collectionName = 'examples';
String currentMinute = DateFormat.yMd().add_jm().format(now);
documentsInsertedThisMinute() async {
var collection = FirebaseFirestore.instance.collection(collectionName);
var snapshots =
await collection.where('foobar', isEqualTo: currentMinute).get();
return snapshots.size;
}
setUpAll(() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
});
testWidgets(
'Single document created',
(WidgetTester tester) async {
int preExistingDocuments = await documentsInsertedThisMinute();
print('Pre-existing documents: $preExistingDocuments');
await tester.pumpWidget(const MyApp());
await FirebaseFirestore.instance
.collection(collectionName)
.doc()
.set({'foobar': currentMinute});
int documentsAfterSingleInsert = await documentsInsertedThisMinute();
expect(documentsAfterSingleInsert, 1);
},
);
}
I had the same issues with running the code twice when using -d chrome with or without --headless flag.
What I use:
Multiline Linux
flutter drive \
--driver=test_driver/integration_test.dart \
--target=integration_test/sec_rules_test.dart \
--device-id web-server \
--dart-define=PROJECT_ID=someProjectId
Multiline Windows (Powershell)
flutter drive `
--driver=test_driver/integration_test.dart `
--target=integration_test/example_test.dart `
--device-id web-server `
--dart-define=PROJECT_ID=someProjectId
Also documented here, of course it doesn't specify if you run it in -d chrome it will behave as such.

How to solve "error: The method 'lengthSync' and 'openRead' isn't defined for the type 'FilePickerResult'" in flutter?

I want to upload multiple image to the google drive. I am using flutter null safety version and using one example
https://www.c-sharpcorner.com/article/google-drive-integration-in-flutter-upload-download-list-files/ .
In above example the writer is using old version of flutter .
I am using file_picker: ^4.2.1 and the code which is throwing error:
var client = GoogleHttpClient(await googleSignInAccount!.authHeaders);
var drive = ga.DriveApi(client);
ga.File fileToUpload = ga.File();
var file = await FilePicker.platform.pickFiles(
type: _pickingType,
allowMultiple: _multiPick,
onFileLoading: (FilePickerStatus status) => print(status),
allowedExtensions: (_extension?.isNotEmpty ?? false)
? _extension?.replaceAll(' ', '').split(',')
: null,
);
fileToUpload.parents = ["appDataFolder"];
fileToUpload.name = path.basename(file!.paths);
var response = await drive.files.create(
fileToUpload,
uploadMedia: ga.Media(file.openRead(), file.lengthSync()),
);
print(response);
_listGoogleDriveFiles();
}```
and errors are:
1. The argument type 'List<String?>' can't be assigned to the parameter type 'String'.
2. The method 'openRead' isn't defined for the type 'FilePickerResult'.
3. The method 'lengthSync' isn't defined for the type 'FilePickerResult'.
Error is mainly because of the different version of file_picker package . Can you please suggest me other package or the change that could done in the code.

authorize camera test in integration testing

I am writing integration tests for Flutter App. The app let's users to take video. When writing test, how can I allow camera permission for my app inside the script for integration testing when the permission dialog appears?
With new integration_test package, you can grant permission in android inside test_driver/integration_test.dart:
// this permission grant workaround works only for android for now
Future<void> main() async {
final Map<String, String> envVars = Platform.environment;
final String adbPath =
envVars['ANDROID_SDK_ROOT']! + '/platform-tools/adb.exe';
await Process.run(adbPath, [
'shell',
'pm',
'grant',
'com.app.name',
'android.permission.CAMERA'
]);
await Process.run(adbPath, [
'shell',
'pm',
'grant',
'com.app.name',
'android.permission.RECORD_AUDIO'
]);
await integrationDriver();
}

How to test flutter url_launcher that email app opens?

I do have a Snackbar with a SnackbarAction which should open the default email app with a default subject and body on tap. I am wondering if there is somehow the possibility to verify if this really happens with some unit tests.
My Snackbar code looks like this:
SnackBar get snackbar =>
SnackBar(
content: Text(message),
action: SnackBarAction(
key: const Key('ErrorSnackbarAction'),
label: AppLocalizations
.of(_context)
.report,
onPressed: () async => await launch('mailto:test#test.com?subject=TestSubject&body=TestBody')));
I am already verifying the appearance which works fine:
group('ErrorSnackbar', () {
testWidgets('appearance test', (WidgetTester tester) async {
await tester.pumpWidget(_generateSnackbarApp());
await _showSnackbar(tester);
expect(find.text(userMessage), findsOneWidget);
expect(find.byWidgetPredicate((Widget widget) =>
widget is SnackBarAction && widget.label == 'Report'), findsOneWidget);
});
testWidgets('error report test', (WidgetTester tester) async {
await tester.pumpWidget(_generateSnackbarApp());
await _showSnackbar(tester);
tester.tap(find.byKey(errorSnackbarAction));
await tester.pump();
// how to verify that the default email app was opened
// with expected subject and body?
});
});
Short answer: You can't.
The launch with mailto is handled by the OS of the device and is out of context of the flutter app.
As the flutter test package focuses on the flutter app, what happens on the OS is out of reach.
You can ensure that launchUrl is called and the expected parameters were passed. The url_launcher package should be tested. Therefore, we can expect that the email app opens, when we call launchUrl with the mailto: schema.
Here is a short introduction on how to test the url_launcher package:
Add plugin_platform_interface and url_launcher_platform_interface to your dev dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
plugin_platform_interface: any
url_launcher_platform_interface: any
Copy the mock_url_launcher_platform.dart from the url_launcher package: https://github.com/flutter/plugins/blob/main/packages/url_launcher/url_launcher/test/mocks/mock_url_launcher_platform.dart
Now you can test the launchUrl calls like this:
void main() {
late MockUrlLauncher mock;
setUp(() {
mock = MockUrlLauncher();
UrlLauncherPlatform.instance = mock;
});
group('$Link', () {
testWidgets('calls url_launcher for external URLs with blank target',
(WidgetTester tester) async {
FollowLink? followLink;
await tester.pumpWidget(Link(
uri: Uri.parse('http://example.com/foobar'),
target: LinkTarget.blank,
builder: (BuildContext context, FollowLink? followLink2) {
followLink = followLink2;
return Container();
},
));
mock
..setLaunchExpectations(
url: 'http://example.com/foobar',
useSafariVC: false,
useWebView: false,
universalLinksOnly: false,
enableJavaScript: true,
enableDomStorage: true,
headers: <String, String>{},
webOnlyWindowName: null,
)
..setResponse(true);
await followLink!();
expect(mock.canLaunchCalled, isTrue);
expect(mock.launchCalled, isTrue);
});
});
}
Copied the test from https://github.com/flutter/plugins/blob/main/packages/url_launcher/url_launcher/test/link_test.dart
Unit test wise
I think the best way to test it is to wrap url launcher with your own class.
This way you can mock it and check that your logic calls your wrapper class function to launch the mail app. This should be enough.
As for the actual mail app or browser (in my case) you should trust the library todo what it supposed to so no need to unit test it really.