patrolTest function

  1. @isTest
void patrolTest(
  1. String description,
  2. PatrolTesterCallback callback, {
  3. bool? skip,
  4. Timeout? timeout,
  5. bool semanticsEnabled = true,
  6. TestVariant<Object?> variant = const DefaultTestVariant(),
  7. dynamic tags,
  8. PatrolTesterConfig config = const finders.PatrolTesterConfig(printLogs: true),
  9. NativeAutomatorConfig nativeAutomatorConfig = const NativeAutomatorConfig(),
  10. LiveTestWidgetsFlutterBindingFramePolicy framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fadePointers,
})

Like testWidgets, but with support for Patrol custom finders.

To customize the Patrol-specific configuration, set config.

Using the default WidgetTester

If you need to do something using Flutter's WidgetTester, you can access it like this:

patrolTest(
   'increase counter text',
   ($) async {
     await $.tester.tap(find.byIcon(Icons.add));
   },
);

Implementation

@isTest
void patrolTest(
  String description,
  PatrolTesterCallback callback, {
  bool? skip,
  Timeout? timeout,
  bool semanticsEnabled = true,
  TestVariant<Object?> variant = const DefaultTestVariant(),
  dynamic tags,
  finders.PatrolTesterConfig config = const finders.PatrolTesterConfig(
    printLogs: true,
  ),
  NativeAutomatorConfig nativeAutomatorConfig = const NativeAutomatorConfig(),
  LiveTestWidgetsFlutterBindingFramePolicy framePolicy =
      LiveTestWidgetsFlutterBindingFramePolicy.fadePointers,
}) {
  final patrolLog = PatrolLogWriter(config: {'printLogs': config.printLogs});
  final automator = NativeAutomator(config: nativeAutomatorConfig);
  final automator2 = NativeAutomator2(config: nativeAutomatorConfig);
  final patrolBinding = PatrolBinding.ensureInitialized(nativeAutomatorConfig)
    ..framePolicy = framePolicy;

  if (skip ?? false) {
    patrolLog.log(TestEntry(name: description, status: TestEntryStatus.skip));
  }
  testWidgets(
    description,
    skip: skip,
    timeout: timeout,
    semanticsEnabled: semanticsEnabled,
    variant: variant,
    tags: tags,
    (widgetTester) async {
      widgetTester.binding.platformDispatcher.onSemanticsEnabledChanged = () {
        // This callback is empty on purpose. It's a workaround for tests
        // failing on iOS and (from Flutter 3.29.0) on Android.
        //
        // See https://github.com/leancodepl/patrol/issues/1474
      };

      if (!constants.hotRestartEnabled) {
        // If Patrol's native automation feature is enabled, then this test will
        // be executed only if the native side requested it to be executed.
        // Otherwise, it returns early.

        final requestedToExecute = await patrolBinding.patrolAppService
            .waitForExecutionRequest(global_state.currentTestFullName);

        if (!requestedToExecute) {
          return;
        }
      }

      await automator.configure();
      // We don't have to call this line because automator.configure() does the same.
      // await automator2.configure();

      patrolLog.log(
        TestEntry(name: description, status: TestEntryStatus.start),
      );
      final patrolTester = PatrolIntegrationTester(
        tester: widgetTester,
        nativeAutomator: automator,
        nativeAutomator2: automator2,
        config: config,
      );
      await callback(patrolTester);

      // We need to silent this warning to avoid false positive
      // avoid_redundant_argument_values
      // ignore: prefer_const_declarations
      final waitSeconds = const int.fromEnvironment('PATROL_WAIT');
      final waitDuration = Duration(seconds: waitSeconds);

      if (debugDefaultTargetPlatformOverride !=
          patrolBinding.workaroundDebugDefaultTargetPlatformOverride) {
        debugDefaultTargetPlatformOverride =
            patrolBinding.workaroundDebugDefaultTargetPlatformOverride;
      }

      if (waitDuration > Duration.zero) {
        final stopwatch = Stopwatch()..start();
        await Future.doWhile(() async {
          await widgetTester.pump();
          if (stopwatch.elapsed > waitDuration) {
            stopwatch.stop();
            return false;
          }

          return true;
        });
      }
    },
  );
}