Sitelet https://github.com/jogboms/flutter_offline/issues/41
Skip to content

Widget testing #41

Description

@cargopete

Hello, do you have a working example of a widget test for this? Because to me it looks like everything in the child of OfflineBuilder doesn't get picked up by widget tests and isn't found with finders. :(

Activity

  1. BenVercammen commented on Aug 26, 2022

    @BenVercammen

    I needed to adjust my widget tests after adding the OfflineBuilder to my widget tree, which now looks like this:

    • MyApp
      • OfflineBuilder
        • ....

    Now for integration testing, running the app on an emulator or an actual device, everything works as normal, but for widget testing that was not the case. In order to fix this, I've done the following in my widget test:

    // imports for creating mock versions...
    import 'package:connectivity_plus/connectivity_plus.dart';
    import 'package:network_info_plus/network_info_plus.dart';
    import 'package:firebase_auth_mocks/firebase_auth_mocks.dart';
    
    // ...
    
      testWidgets('Smoke test', (WidgetTester tester) async {
        // Wrap in `runAsync` in order to do `await Future.delayed`, otherwise infinite loop
        await tester.runAsync(() async {
          final auth = MockFirebaseAuth();
          final connectivityService = TestConnectivityService(ConnectivityResult.wifi);
          final testNetworkInfoService = TestNetworkInfoService();
          // Build our app and trigger a frame.
          await tester.pumpWidget(MyApp(
              firebaseAuth: auth,
              networkInfo: testNetworkInfoService,
              connectivity: connectivityService,
          ));
          // Just a millisecond of delay is enough to give the OfflineBuilder's StreamBuilder 
          // time to load the initial result (wifi), no need to match the (default) debounce duration or anything
          await Future.delayed(const Duration(milliseconds: 1));
          // Pump and settle so the OfflineBuilder can render its child, instead of the empty SizedBox
          await tester.pumpAndSettle();
          // Your first screen should be fully loaded now
          // ...
        });
      });

    Please note that I copied over the TestConnectivityService and TestNetworkInfoService classes from the flutter_offline_test.dart file, as there's no other way to import them (afaik).

    Now the issue I'm currently still having, is the warning for the @visibleForTesting annotated OfflineBuilder.initialize constructor I'm now using in MyApp.

      @override
      Widget build(BuildContext context) {
        // WARNING: The member 'OfflineBuilder.initialize' can only be used within 'package:flutter_offline/src/main.dart' or a test.
        return OfflineBuilder.initialize(
          connectivityBuilder: _buildMyAppStateData,
          connectivityService: widget.connectivity,
          wifiInfo: widget.networkInfo,
          // A dummy child that should never be rendered... (right?)
          child: const Text('Loading...'),
        );
      }
    
      /// Build the child Widget of the [OfflineBuilder], based on the given connectivity state
      Widget _buildMyAppStateData(BuildContext context, ConnectivityResult connectivity, Widget defaultChild) {
        // ...
      }

    So I have a working widget test, but there are 2 main issues I'd still like to solve:

    1. I don't want to duplicate the TestConnectivityService and TestNetworkInfoService classes
    2. I don't want to use the OfflineBuilder.initialize() constructor as it's not meant to be used

    I'm currently still looking for ways to fix this, but in the meanwhile feedback or hints are more than welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions