Image for post
Image for post

Something I had been trying to work out for my Flutter project for some time was validating commit messages, initially, I used commit-msg-validate but having a node dependency in a Flutter/Dart project does not seem right and when the team grew to beyond myself I worked on moving all of the automation scripts I had written in JS over to dart and while there are still a few node dependencies left, they are purely for use in the CI pipeline.

For the purpose of executing git-hooks across the team, I added Lefthook to the project and initially only used pre-push for executing the test scripts, but only recently had an idea for how to execute the commit-msg hook. …


Image for post
Image for post

Some would wonder why a company whos development team speaks almost exclusively Javascript would choose flutter to build their next product.

Well, the short answer is, it was, and still is, the best tool for the job.

The beginning

I was brought into Wyzetalk specifically for my experience in React and React Native as that was the preferred direction for the new mobile application. I spent the first few months doing some RnD projects, and at that time I had not heard of Flutter.

After a few months, my boss was quite surprised to have me come back and say that neither React nor React native would be suitable for the project and that it would be best to use Ionic-Angular. …


Image for post
Image for post

Using dependency injection can be great for simplifying your code and keeping it DRY, it can also simplify testing and even improve testability.

If you have not started using dependency injection in your app, you may want to take a look at get_it.

For those already using it, this is how you would go about testing your code that implements these injections.

class DateTimeHelpers {
int nowInMilliseconds() => DateTime.now().millisecondsSinceEpoch;
}

That is a small helper I created for use within various UI’s pull-to-refresh logic to track a last updated value to ensure the spinner goes away incase the API data has not changed. …


Image for post
Image for post

Recently I had to implement image uploading which required form data that cannot be done with the standard http.Clientand instead needs http.MultipartRequest.

We have been doing a big push to implement a proper TDD approach in our products over at Wyzetalk, so one of the first steps was to get this new method tested, however, it was not as easy as it was with testing http.Client.

Unlike with http.Client one needs to provide an instance that includes the 2 required arguments, type, and Uri. With our product being a white label and the file upload being used from multiple widgets I needed to cater for the possibility of different Uri’s. …


Image for post
Image for post

As it stands now flutter web is not ready for production use, to get started however they have provided the required steps at the Flutter Docs.

One thing os note is, and possibly the biggest hindrance in more mature codebase would be the fact that dart:io does not yet support web and you would need to be using dart:html.

There is a way to do this though, as dart does support conditional imports, but the size of your codebase is going to impact the level of refactoring that needs to be done in order to achieve this.

For starters, you would no longer be able to directly reference dart:io in your codebase. You would then not be able to use HttpClient you would need to use Dio or http from http/http.dart. …


Image for post
Image for post

Many times in an application you would have a need to store files, temporarily or even permanently. For this, you are probably going to be using path_provider, however, those methods are not going to simply work when running a widget test.

Thankfully it is quite simply to be able to mock that and provide your own path for use during testing.

There is quite a simple way to do this and it is done with MethodChannel

const TEST_MOCK_STORAGE = './test/fixtures/core';const channel = MethodChannel(
'plugins.flutter.io/path_provider',
);
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return TEST_MOCK_STORAGE;
});

You simply need to provide the channel you wish to mock, in this case, it is pluggins.flutter.io/path_provider and use the setMockMethodCallHandler where you can either provide specific calls and values to return or in this case provide a catch-all response, in this case, what will happen is any request to path provider will return the provided path. …


Image for post
Image for post

The more accurate you make your test, the higher the quality of the test itself.

Many apps these days are built to be more accessible, one thing we do to ensure this is we localize our applications, allowing people who do not speak the same language as we do, to also use the application.

In our application, we have been using easy_localization, I know there are quite a few choices, but for us, this was one of the easier ones to implement and for us, the JSON support was a big win with how we manage our localization.

To ensure we have the most accurate widget tests, we rather use “real” localizations than having to mock the helper classes. …


Image for post
Image for post

In this post, we going to go through how, at least in my opinion, one would go about testing that a function is called within a widget when that function is one of the Widgets arguments.

Take the following overly simplified example…

class SampleWidget extends StatelessWidget {
final Function(String fileId) onDelete;
final String fileId;

const SampleWidget({
@required this.onDelete,
@required this.fileId,
foundation.Key key,
}) : super(key: key);

@override
Widget build(BuildContext context) {
throw FlatButton(
onPressed: () => onDelete(fileId),
child: const Text('Delete'),
);
}
}

As you can see we have a simple “reusable” widget that takes a fileId and a onDelete function. …


Wyzetalk Flutter
Wyzetalk Flutter

Background

When I started building out the new mobile app for Wyztalk there where a few things on my personal ToDo list that obviously had great benefit to the business, one was a CI pipeline (Article) which I recently completed, this one, however, was something I got right quite early on.

With our current Ionic v1 app we needed to roll out a complete app deploy for CSS or Localization updates. While my implementations for both the UI and locale supported simply being hosted, even being small files, not something you want to be sending down the wire unnecessarily.

For the Flutter app, I spent quite a bit of time working on a simple way to implement this, for the localization we are using easy_localization as it was one of the simpler implementations that both supported JSON as well as online locale, something very useful for initial development. …


Image for post
Image for post

Background:

With phase 1 nearing completion, it was time to get the build process into a CI pipeline, this was something that was key for me working at Wyzetalk as we are unable to do that with some of the legacy products. Initially, I looked at codemagic, but from a costing aspect, it would not have been feasible especially when all our Web Apps where already being deployed through Azure Pipelines.

There was not too much info available online as to how to get it to work, specifically iOS, and that which I did find, did not work, so just in case anyone else has a tough time, here is what I ended up doing. …

About

Reme Le Hane

MTBer, Runner, Developer, Gamer. | Front end Architect at Wyzetalk with 10 years Front-End Experience & ~1yr Flutter. | React Flutter Javascript

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store