Flutter integration test running twice on web - flutter

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.

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 inappwebview render html file downloaded from

I'm trying to create an application using
flutter_inappwebview: ^6.0.0-beta.14
base on the the following steps:
download html zipfile from internet.
extract on local storage (at path getting from getApplicationDocumentsDirectory())
use flutter_inappwebview to run localhost server and try to set the documentRoot to the path of getApplicationDocumentsDirectory()
but it show the blank screen and it seems like it cannot find the html file that was extracted. I've explored the directory and already see the html files and folder on that path.
But if I create an html file inside assets folder and run localhost server and access http://localhost:8080/index.html, it was success. But what I want is download html from internet
final dir = (await getApplicationDocumentsDirectory()).path;
final zippedFile = File('$dir/html.zip');// downloaded from internet
await zippedFile.writeAsBytes(zip.data);
final bytes = await zippedFile.readAsBytes();
final archive = ZipDecoder().decodeBytes(bytes);
for (final file in archive) {
final fileName = '$dir/${file.name}';
if (file.isFile && !fileName.contains("__MACOSX")) {
debugPrint(fileName);
final outFile = File(fileName);
await outFile.create(recursive: true);
await outFile.writeAsBytes(file.content);
}
}
and here is code to run localhost server
final dir = (await getApplicationDocumentsDirectory()).path;
final localhostServer = InAppLocalhostServer(
port: 8080,
documentRoot: $dir
);
if (!localhostServer.isRunning()) {
await localhostServer.start();
debugPrint('LOCALHOSTSERVER STARTED');
}

flutter web not working due to await statement

I am having issues with Flutter web when I use await statement,
void main() async {
//debugPaintSizeEnabled = true;
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
this will not display anything on the browser and throws and error:
ChromeProxyService: Failed to evaluate expression 'title': InternalError: Expression evaluation in async frames is not supported. No frame with index 39..
I am stuck :(
debugging testing nothing worked
Run flutter channel stable followed by flutter upgrade --force
When using Firebase, you need to initalize it with options for the specific platform that you are using. Here goes and example on how to configure it for Flutter Web:
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
void main() async {
//debugPaintSizeEnabled = true;
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options = FirebaseOptions(
apiKey: 'YOUR API KEY',
appId: 'YOUR APP ID',
messagingSenderId: 'YOUR MESSAGING SENDER ID',
projectId: 'YOUR PROJECT NAME',
authDomain: 'YOUR AUTH DOMAIN (IF YOU HAVE)',
databaseURL: 'YOUR DATABASE URL (IF YOU USE FIREBASEDATABASE)',
storageBucket: 'YOUR STORAGE BUCKET',
)
);
runApp(MyApp());
}
All this information is available on your Firebase Project Console, just search for it. Hope it helps!

hydrated_bloc: The parameter 'storageDirectory' is required

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

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();
}