# Unit Testing a Utility function that returns a Widget


Probably not too common a use case, but for me I have a utility function for handling in-app navigation from the in-app web view `webview_flutter` while it does have a generic error handler, I need to be handle errors differently based on what type of URL was selected as custom logic is required to be able to handle links that are not actually valid.

A snippet from the utility mentioned above:

```dart
  dynamic launchURL(BuildContext context, String url) async {
    if (url == 'about:blank') return;

    if (url.startsWith('internal://')) {
      final isGroups = url.contains('/groups');

      if (isGroups) return _handleUnsupported(context);
    }
  }

  void _handleUnsupported(BuildContext context) {
    SnackBarUtil.error(
      context: context,
      message: LocalePathUtils.errorsLocalePath('unknownRoute'),
    );
  }
```

In this case, groups is a URL path that we currently do not support within the flutter app, so there is other logic specifically for groups, but for brevitiy we will reference the generic `_handleUnsupported` function which returns a Snacbar with a localized error message.

Normally with a utility test, one would simply use `expect`, however in this case the functions result would be a visual element, so before we can expect anything, we need to setup a test to allow all the logic to run.

```dart

testWidgets('cant', (tester) async {
  when(mockUrlLauncherHelper.cl(any)).thenAnswer((_) async => false);
  when(mockCoreCubit.state).thenReturn(fixtureCoreCubitLoaded);
          // assert
  const mockUrl = 'https://test.test';

   Future<void> future(BuildContext context) async {
    await Future.delayed(const Duration(seconds: 1));
    return htmlContentUtils.launchURL(context, mockUrl);
  }

  final widget = providedLocalizedWidgetForTesting(
    child: LayoutBuilder(
      builder: (context, _) {
        return FutureBuilder(
          future: future(context),
          builder: (ctx, snapshot) {
            return const SizedBox.shrink();
          },
        );
      },
    ),
  );

  await tester.pumpWidget(widget);
  await tester.pumpAndSettle();
  await tester.pump(const Duration(seconds: 1));

  expect(find.byType(Flushbar), findsOneWidget);
});
```

There are actually quite a few things happening here in this test, but the most important part is the setup on line 13. Here we are setting up a test implementation of the widget, the `provideLocalizedWidgetForTesting` is a test utility I setup, you can read about it [HERE](https://medium.com/wyzetalk-tech/bringing-localization-into-your-widget-testing-121ef7eec7c).

As the resulting `Snackbar` also makes use of context for state access as well as localization I have included the `LayoutBuilder` to get hold of the context from the test utility.

The utility function itself is a `Future` and one of the easiest way to run those inside a widget is with the `FutureBuilder`, which links back up to the `future` function on line 8. Here is simply included a short delay to help manage ui rendering within the test context, otherwise you end up with it failing as `needsBuild` gets called.

So once we have `settled` and `pumped` that additional second, we are now able to expect the `Widget` that should be rendered on the screen.

As mentioned above, not a very common use-case, and when possible one should always keep UI and Utilities separate, and after having written this I had found a better way to deal with it in my use case, a way that did not involve returning a widget from a utility.

I felt however the learning itself was still valuable, and the possibility does exist that this is an unavoidable scenario for someone or even myself at a later stage. #SharingIsCaring

I hope you found this interesting, and if you have any questions, comments, or improvements, feel free to drop a comment. Enjoy your Flutter development journey :D

If you liked it, a like would be awesome, and if you really liked it, a [cup of coffee](https://www.buymeacoffee.com/remelehane) would be great.

Thanks for reading.

If you wish to carry on with the subject of testing, why not take a look at:


[**Widget testing passed in function**
*In this post, we going to go through how, at least in my opinion, one would go about testing that a function is called…*](https://remelehane.hashnode.dev/widget-testing-passed-in-function-169c2633180b)


[**Widget testing when your app needs access to directories.**
*Many times in an application you would have a need to store files, temporarily or even permanently. For this, you are…*](https://remelehane.hashnode.dev/widget-testing-when-your-app-needs-access-to-directories-2c9c7aa73b8a)
