How to write test for flutter package Flutter WeChat Assets Picker - flutter

I am trying to write a test on this flutter package https://pub.dev/packages/wechat_assets_picker using the Mocktail package https://pub.dev/packages/mocktail, but this package does not seem to have test in the documentation.
I have included the minimum reproducible example. The test file is currently not working, it is included as an example test code using the flutter Mocktail package.
It is supposed to mock AssetPicker.pickAssets to test whether it is actually called with the correct arguments. I am running in IOS simulator, we will need to add this key in ios/Runer/Info.plist, otherwise the simulator will close unexpectedly after clicking the add button.
main.dart
import 'package:flutter/material.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final List<AssetEntity>? result =
await AssetPicker.pickAssets(context);
},
tooltip: 'Add photo',
child: const Icon(Icons.add),
),
);
}
}
widget_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:wechat/main.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
class _MockAssetPicker extends Mock implements AssetPicker {}
void main() {
testWidgets('It should call the WeChat asset picker',
(WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
final BuildContext context = tester.element(find.byType(MyApp));
final assetPickerMock = _MockAssetPicker();
when(() => assetPickerMock.pickAssets(context)).thenAnswer((_) => Future.value([
const AssetEntity(
id: 'id1',
typeInt: 1,
width: 100,
height: 100,
),
]));
AssetPicker.instance = assetPickerMock;
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
verify(() => assetPickerMock.pickAssets(context)).called(1);
});
}

Mocking the picker is supported by the separated picker delegate: https://github.com/fluttercandies/flutter_wechat_assets_picker/pull/315
TL;DR, build your own delegate first, then set it through AssetPicker.setPickerDelegate(TestAssetPickerDelegate());

Related

Flutter Image picker not working on simulator after installing google maps package

Image picker is not working after installing google maps in my flutter app.
It picks it's images from gallery but doesn't return anything from the pickimage and pickmultiimage function in simulator but works fine on the emulator.
I am using the latest version of image picker 0.8.6 and google maps 2.2.1.
Here is the code...
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Image picker with google maps!!!!'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final ImagePicker _picker = ImagePicker();
void pickImage() async {
final List<XFile> images = await _picker.pickMultiImage();
print(images);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: [
Center(
child: ElevatedButton(
onPressed: () {
pickImage();
},
child: const Text('pick image')),
)
],
),
);
}
}

Playing an asset with 'audioplayers' package in Flutter

Can anybody tell me how to use this latest library to play a single audio file present in the asset folder of the root of flutter? The code sample of this library on pub.dev is quite difficult to understand
First create an instance of AudioPlayer class.
final player = AudioPlayer();
then add asset file in player.setSource method.
await player.setSource(AssetSource('sounds/coin.wav'));
For more Getting Started documentation
It's as simple as the following snippet. Where click.mp3 is inside the assets folder.
final player = AudioPlayer();
player.play(AssetSource('click.mp3')),
A complete example:
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
AudioPlayer? _player;
#override
void dispose() {
_player?.dispose();
super.dispose();
}
void _play() {
_player?.dispose();
final player = _player = AudioPlayer();
player.play(AssetSource('click.mp3'));
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
'Click on the play button to play a sound',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _play,
tooltip: 'Play',
child: const Icon(Icons.volume_up),
),
);
}
}
Below code block worked for me.
TextButton(
onPressed: () async {
final player = AudioPlayer();
player.play(AssetSource('note1.wav'));
},
child: Text('click me'),
),
When you press the Click me button note1.wav audio file will play.

Flutter mocked clock (using withClock) behave inconsistenly when app starts with WidgetsFlutterBinding.ensureInitialized()

If flutter app starts with:
void main() {
WidgetsFlutterBinding.ensureInitialized();
Then clock.now() prints not mocked value if outside of build method.
Since I am using withClock in my tests, it makes my app unable to be properly tested as sometimes clock.now() returns mocked value, and sometimes real current time.
Please find the following example, and note that _printClockNow prints DateTime.now(), but it should print year 1990.
If you removed line WidgetsFlutterBinding.ensureInitialized() then it works as expected.
Minimum reproduceable code:
import 'package:clock/clock.dart';
import 'package:flutter/material.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
withClock(Clock.fixed(DateTime(1990)), () {
runApp(const MyApp());
});
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _printClockNow() {
print('_printClockNow is: ${clock.now()}'); // prints real NOW
setState(() {});
}
#override
Widget build(BuildContext context) {
print('build clock.now() is: ${clock.now()}'); // prints mocked NOW
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Dummy()],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _printClockNow,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class Dummy extends StatelessWidget {
#override
Widget build(Object context) {
return Text('t: ${clock.now()}');
}
}
Try with putting WidgetsFlutterBinding inside withClock.
void main() {
withClock(Clock.fixed(DateTime(1990)), () {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
});
}

Run native code when triggering alarms with flutter

I have an example that implements an example of Android Alarm Manager with flutter, the event is called normal, however, I want that when the alarm goes off, a native code (Java or Kt) is executed.
Example:
As soon as the alarm goes off even in the background or locked screen, the app will execute my code in Java.
In native Java we created a class that inherits from BroadcastReceiver and implements the onReceive method, in Android Native I would open my app even in the background with native code.
How can I get the flutter to call my native code to run when the alarm is triggered?
My code example:
import 'package:flutter/material.dart';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:android_intent/android_intent.dart';
import 'package:android_intent/flag.dart';
import 'package:platform/platform.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await AndroidAlarmManager.initialize();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Alarme app',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Alarme'),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
void _openLinkInGoogleChrome() {
print('entered');
if (const LocalPlatform().isAndroid) {
// **run Native code java here that implemented onReceive on class .java or .kt !!!**
}
}
class _MyHomePageState extends State<MyHomePage> {
void adicionarAlarme(BuildContext context) async {
await AndroidAlarmManager.periodic(
const Duration(seconds: 3), 0, _openLinkInGoogleChrome);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Clique no botão abaixo para adicionar um alarme',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => adicionarAlarme(context),
tooltip: 'Adicionar alarme',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

Flutter application hangs when calling await rootBundle.loadString(...) from main()

I found this answer about storing global configuration into globals.dart.
How can I load configuration into it from assets/config.json?
I've tried like this:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:convert';
import 'globals.dart' as globals;
void main() async {
globals.config = jsonDecode(await rootBundle.loadString('assets/config.json'));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
...
}
The application starts with a white screen. Nothings happens, no errors. I guess that await rootBundle.loadString(...) causes the application to hang.
You can copy paste run full code below
You need to add WidgetsFlutterBinding.ensureInitialized() in main()
without this line will produce white screen
globals.dart
Map<String, dynamic> config = {};
config.json
{
"id": "1",
"name": "abc"
}
code snippet
void main() async{
WidgetsFlutterBinding.ensureInitialized();
globals.config = jsonDecode(await rootBundle.loadString('assets/config.json'));
runApp(MyApp());
}
pubspec.yaml
assets:
- assets/
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:convert';
import 'globals.dart' as globals;
void main() async{
WidgetsFlutterBinding.ensureInitialized();
globals.config = jsonDecode(await rootBundle.loadString('assets/config.json'));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(globals.config["id"]),
Text(globals.config["name"]),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}