My widgets tests work separately but wont work together - flutter

this is my code:
void main() {
testWidgets("Localiza os widgets na home", (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(home: HomeView()));
final Finder drawer = find.byType(IconButton);
await tester.tap(drawer);
expect(drawer, findsOneWidget);
await tester.pumpAndSettle();
final Finder listTileDrawer = find.byType(ListTile);
expect(listTileDrawer, findsNWidgets(5));
final Finder listViewDrawer = find.byType(ListView);
expect(listViewDrawer, findsOneWidget);
});
testWidgets("Valida se snackBar está sendo exibida corretamente", (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
body: BotaoRedirecionamentoExterno(
url: 'url invalida',
texto: 'teste',
))));
final botao = find.byType(BotaoRedirecionamentoExterno);
await tester.tap(botao);
await tester.pumpAndSettle();
final Finder snackBar = find.byType(SnackBar);
expect(snackBar, findsOneWidget);
});
}
When I run: test/view/home/home_widget_test.dart --no-sound-null-safety it works as expected:
I/flutter (11181): 00:01 +1: Valida se snackBar está sendo exibida corretamente
I/flutter (11181): 00:02 +2: All tests passed!
But when I try: flutter test --no-sound-null-safety:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _WidgetTypeFinder:<zero widgets with type "SnackBar" (ignoring offstage widgets)>
Which: means none were found but one was expected
When the exception was thrown, this was the stack:
#4 main.<anonymous closure> (file:///Users/macos/Desktop/portal-agro-sp-master/test/view/home/home_widget_test.dart:33:5)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)
This was caught by the test expectation on the following line:
file:///Users/macos/Desktop/portal-agro-sp-master/test/view/home/home_widget_test.dart line 33
The test description was:
Valida se snackBar está sendo exibida corretamente
════════════════════════════════════════════════════════════════════════════════════════════════════
00:26 +25 -1: /Users/macos/Desktop/portal-agro-sp-master/test/view/home/home_widget_test.dart: Valida se snackBar está sendo exibida corretamente [E]
Test failed. See exception logs above.
The test description was: Valida se snackBar está sendo exibida corretamente
I need to be able to run all my tests together due to a customer requirement. I already have more than 23 tests ready and this is the first time this has happened.
Does anyone know why this is happening and a way to solve it ?

Related

The method 'containsKey' was called on null flutter

Before, my integration test works. After I pull an update of another developer my integration test fails with the following error:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following NoSuchMethodError was thrown running a test:
The method 'containsKey' was called on null.
Receiver: null
Tried calling: containsKey("serverStatus")
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
#1 _IndexState._referAFriendEnabled (package:limitless/pages/index.dart:1390:15)
Transition { currentState: HomeInitial(), event: FetchHomeCarousels(), nextState: HomeInitial() }
Transition { currentState: InitialInboxState(), event: InboxFetch(), nextState: InboxFetchingData() }
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
'package:flutter_test/src/binding.dart': Failed assertion: line 1558 pos 12: 'inTest': is not true.
When the exception was thrown, this was the stack:
#2 LiveTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1558:12)
#3 WidgetTester.pumpAndSettle.<anonymous closure> (package:flutter_test/src/widget_tester.dart:668:23)
<asynchronous suspension>
<asynchronous suspension>
(elided 3 frames from class _AssertionError and package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
03:29 +0 -1: end-to-end test limitless non-transactional test
CustomerStart { }
Transition { currentState: CustomerInitial(), event: CustomerStart { }, nextState: CustomerLoading() }
03:31 +0 -1: Some tests failed.
Running the app works fine. It only fails when running integration test.
This is code snippet about containsKey.
void _referAFriendEnabled() async {
bool referralEnabled = false;
PackageInfo packageInfo = await PackageInfo.fromPlatform();
if (prefs.containsKey('serverStatus')) {
Map appSettings = await AppSharedPref.getServerStatus();
limitlessRepo.appVersion = appSettings["app_version"];
limitlessRepo.storeVersion = appSettings["latest_store_app_version"];
referralEnabled = appSettings["referral_code"];
limitlessRepo.version = packageInfo.version;
} else {
await limitlessRepo.isReferralCodeEnabled();
}
newVersionAvailable();
setState(() {
_isReferralEnabled = referralEnabled;
});
Does anyone has an idea about this? Thank you.

Opening deep link in integration test in Flutter

I'm trying to run an integration test which is highly dependent on the user clicking a magic link he got in his email. So far I failed to find a way of doing that. I came across Process.run but it seems like it should be run before the integration test starts and I need to do it during the test.
Any help with either iOS or Android will be highly appreciated. 🙏
This is the code I tried so far to work on iOS but Process.run ends with ProcessException: No such file or directory:
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('login test', (WidgetTester tester) async {
app_sandbox.main();
await tester.pumpAndSettle(Duration(seconds: 5));
expect(find.text('foo'), findsOneWidget);
await Process.run('xcrun', [
'simctl',
'openurl',
'7D6DEC47-C1E2-4F18-A38B-7B4C17558172',
'https://myDeepLink/sign-in',
]);
await tester.pumpAndSettle();
});
}
this might only work with flutter_driver
await Process.run('xcrun', [
'simctl',
'openurl',
'booted',
'https://myDeepLink/sign-in'
]).then((result) {
stdout.write(result.stdout);
stderr.write(result.stderr);
});
not with testWidgets of integration_test
there I got this error:
> Error occured: DriverError: Failed to fulfill RequestData due to
> remote error Original error: ext.flutter.driver: (112) Service has
> disappeared Original stack trace:
> #0 new _OutstandingRequest (package:vm_service/src/vm_service.dart:1746:45)
> #1 VmService._call (package:vm_service/src/vm_service.dart:2262:21)
> #2 VmService.callServiceExtension (package:vm_service/src/vm_service.dart:2233:14)
> #3 VMServiceFlutterDriver.sendCommand (package:flutter_driver/src/driver/vmservice_driver.dart:306:66)
> #4 FlutterDriver.requestData (package:flutter_driver/src/driver/driver.dart:522:45)
> #5 integrationDriver (package:integration_test/integration_test_driver_extended.dart:51:38)
> <asynchronous suspension>

How to mock Socket.io client in Flutter tests

I'm using socket_io_client v0.9.12 in my flutter app (still not using null safety). I am creating a socket connection with my back-end server when the app starts and allow child widgets to access it using a provider.
I am trying to start creating the connection in the constructor so that when I need to use the socket client, it would probably be initialized already.
This is my provider class which has the creation of the socket connection:
class SocketClient {
SocketClient() {
_initializer = initialize();
}
Future _initializer;
/// Socket client
Socket client;
/// Wait until the client is properly connected with the server
Future finishInitializing() => _initializer;
/// Initialize the socket connection with the server
Future initialize() async {
final completer = Completer<Socket>();
final socket = io(
'http://localhost:3000/gateway',
OptionBuilder() //
.setTransports(['websocket'])
.disableAutoConnect()
.setQuery({'token': 'TOKEN'})
.build(),
)..connect();
socket
..onConnect((_) {
completer.complete(socket);
});
client = await completer.future;
}
}
The main app widget I have:
#override
Widget build(BuildContext context) {
return Provider<SocketClient>(
create: (_) => SocketClient(),
builder: (context, _) {
return Scaffold(
...
);
},
);
}
This is how I am trying to use the socket client:
Future<void> foo(SocketClient socketClient) async {
await socketClient.finishInitializing();
final socket = socketClient.client;
socket.on(eventName, (dynamic uploadDrawingEvent) {
...
});
}
Everything works fine up to now. 🎉
However, when I try to run my tests that depend on this socket client, I see the below error:
Pending timers:
Timer (duration: 0:00:20.000000, periodic: false), created:
#0 new FakeTimer._ (package:fake_async/fake_async.dart:284:41)
#1 FakeAsync._createTimer (package:fake_async/fake_async.dart:248:27)
#2 FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:181:19)
#5 Manager.connect (package:socket_io_client/src/manager.dart:232:19)
#6 Manager.open (package:socket_io_client/src/manager.dart:194:41)
#7 Socket.connect (package:socket_io_client/src/socket.dart:104:8)
#8 SocketClient.initialize (package:flutter_app/web/services/socket_provider.dart:48:8)
<asynchronous suspension>
(elided 2 frames from dart:async)
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test:
A Timer is still pending even after the widget tree was disposed.
'package:flutter_test/src/binding.dart':
Failed assertion: line 1241 pos 12: '!timersPending'
When the exception was thrown, this was the stack:
#2 AutomatedTestWidgetsFlutterBinding._verifyInvariants (package:flutter_test/src/binding.dart:1241:12)
#3 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:803:7)
<asynchronous suspension>
(elided 2 frames from class _AssertionError)
...
initialize function keeps hanging after client = await completer.future; line. That future is not resolved even after the test is finished (see the error).
I would like to get ideas on how I can mock this socket client properly to avoid this error.
I'm looking more towards an answer which mocks the functionality of the socket client because I have some more tests to write to cover the event handlers.
Thank you in advance! 🙏
You can use await IOOverrides for override standard Socket method like socketConnect
Exemple:
await IOOverrides.runZoned(() async {
your code
}, socketConnect: (host, port, {sourceAddress, int sourcePort = 0, timeout}) => Future.value(mockSocket));

Flutter Unhandled Exception: Null check operator used on a null value

I am getting the following error Unhandled Exception: Null check operator and I am not sure if it is something wrong in my code or the library I am using. I am trying to test the livequery of the parse_server_sdk used by back4app because I require sending and receiving images in Realtime. Here is the relevant code:
import 'dart:io';
import 'package:filepicker_windows/filepicker_windows.dart';
import 'package:flutter/material.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
void main() async {
final keyApplicationId = 'EPARW6nRAAyp5uehoDE7rBEby4wtehcZf9EayykS';
final keyClientKey = 'fDaL2DjyC9YdwCwZ4RB5c5vhACROaMOO1EjjL4Zn';
final keyParseServerUrl = 'https://parseapi.back4app.com';
final LIVE_QUERY_URL = 'wss://samuraichat.b4a.io';
await Parse().initialize(keyApplicationId, keyParseServerUrl,
clientKey: keyClientKey,
autoSendSessionId: true,
liveQueryUrl: LIVE_QUERY_URL,
coreStore: CoreStoreMemoryImp());
final LiveQuery liveQuery = LiveQuery();
QueryBuilder<ParseObject> query =
QueryBuilder<ParseObject>(ParseObject('FirstClass'))
..whereEqualTo('chatId', 1);
Subscription subscription = await liveQuery.client.subscribe(query);
subscription.on(LiveQueryEvent.create, (value) {
print('*** CREATE ***: ${DateTime.now().toString()}\n $value ');
print((value as ParseObject).objectId);
print((value as ParseObject).get('message'));
});
runApp(MyApp());
}
Here is the error stack:
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Null check operator used on a null value
#0 MethodChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:142:86)
#1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:148:36)
#2 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:331:12)
#3 MethodChannelConnectivity.checkConnectivity (package:connectivity_platform_interface/src/method_channel_connectivity.dart:41:29)
#4 Connectivity.checkConnectivity (package:connectivity/connectivity.dart:46:22)
#5 Parse.checkConnectivity (package:parse_server_sdk_flutter/parse_server_sdk.dart:106:34)
#6 new LiveQueryReconnectingController (package:parse_server_sdk/src/network/parse_live_query.dart:45:28)
#7 new LiveQueryClient._internal (package:parse_server_sdk/src/network/parse_live_query.dart:146:30)
#8 LiveQueryClient._getInstance (package:parse_server_sdk/src/network/parse_live_query.dart:153:35)
#9 new LiveQuery (package:parse_server_sdk/src/network/parse_live_query.dart:416:30)
#10 main (package:chat_app/main.dart:18:37)
<asynchronous suspension>
Thanks.
Try to clean your app cache:
flutter clean
This bug should be fixed with this PR.
You use the current nullsafety branch by overriding the dependency in your pubspec.yaml:
dependency_overrides:
parse_server_sdk_flutter:
git:
url: https://github.com/parse-community/Parse-SDK-Flutter.git
ref: nullsafety
path: packages/flutter
parse_server_sdk:
git:
url: https://github.com/parse-community/Parse-SDK-Flutter.git
ref: nullsafety
path: packages/dart

Hosting an executable within a Flutter application

I have a basic flutter project running on android where when the application starts, I write an executable bundled in my assets.
static String appInternalPath = '/data/data/com.maksimdan.face_merger';
void writeExecutable() async {
var executablePath = join(appInternalPath, 'main');
if (await File(executablePath).exists()) {
File(executablePath).delete();
print('deleted old executable');
} else {
print('not executable exists');
}
ByteData data = await rootBundle.load('lib/py/dist/main');
List<int> bytes =
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(executablePath).writeAsBytes(bytes);
print('wrote new executable');
}
Sometime later in my code I try to run it.
void invokeExecutable() async {
String executablePath = join(appInternalPath, 'main');
Process.run('chmod', ['u+x', executablePath]).then((ProcessResult results) {
Process.run(executablePath, []).then((ProcessResult results) {
print(results.stdout);
});
});
}
But obtain a permission denied error.
E/flutter (31825): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: ProcessException: Permission denied
E/flutter (31825): Command: /data/data/com.maksimdan.flutter_general/main
E/flutter (31825): #0 _ProcessImpl._start (dart:io-patch/process_patch.dart:390:33)
E/flutter (31825): #1 Process.start (dart:io-patch/process_patch.dart:36:20)
E/flutter (31825): #2 _runNonInteractiveProcess (dart:io-patch/process_patch.dart:565:18)
E/flutter (31825): #3 Process.run (dart:io-patch/process_patch.dart:47:12)
E/flutter (31825): #4 _MyHomePageState.invokeExecutable.<anonymous closure> (package:flutter_general/main.dart:51:15)
E/flutter (31825): #5 _rootRunUnary (dart:async/zone.dart:1362:47)
E/flutter (31825): #6 _CustomZone.runUnary (dart:async/zone.dart:1265:19)
E/flutter (31825): <asynchronous suspension>
I've also tried:
Process.run('/system/bin/chmod', ['744', path]).then((ProcessResult results) {
print('shell1 complete');
Process.run(path, []).then((ProcessResult results) {
print('shell2 complete');
print(results.stdout);
});
});
My executable:
// 'Hello World!' program
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
return 0;
}
>> g++ main.cc -o main
Is there a way to run your own executables in flutter with the proper permissions? On native android, there is an option to file.setExecutable(true); using this strategy. (Hosting an executable within Android application)
Or will I have to experiment with method channels?
pubspec.yml
name: face_merger
description: A new Flutter project.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
sqflite: ^1.3.0+2
process_run: ^0.10.10+1
cupertino_icons: ^0.1.3
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- lib/py/dist/main
I also verified that the file was written to the internal memory of on the device that I expected it to be written to using android studio's device explore.
Besides the writable permission you need to have readable permission in your app.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xxx.yyy">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
...
You need to put the .db file extension at the end of the database name (Assuming DB_DIR is for a database). var path = join(DB_DIR, 'main.db');
Then I think you may want to use path_provider package and use
Directory documentsDirectory = await getApplicationDocumentsDirectory();
for the directory where you are accessing the database.