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. @Deprecated('nativeAutomatorConfig is deprecated and will be removed in a future release. ' 'Please use platformAutomatorConfig instead.') NativeAutomatorConfig? nativeAutomatorConfig,
  10. PlatformAutomatorConfig? platformAutomatorConfig,
  11. LiveTestWidgetsFlutterBindingFramePolicy framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive,
})

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,
  ),
  @Deprecated(
    'nativeAutomatorConfig is deprecated and will be removed in a future release. '
    'Please use platformAutomatorConfig instead.',
  )
  NativeAutomatorConfig? nativeAutomatorConfig,
  PlatformAutomatorConfig? platformAutomatorConfig,
  LiveTestWidgetsFlutterBindingFramePolicy framePolicy =
      LiveTestWidgetsFlutterBindingFramePolicy.fullyLive,
}) {
  final patrolLog = PatrolLogWriter(config: {'printLogs': config.printLogs});
  if (nativeAutomatorConfig != null && platformAutomatorConfig != null) {
    throw StateError(
      'Cannot use both nativeAutomatorConfig and platformAutomatorConfig',
    );
  }
  final platformAutomator = PlatformAutomator(
    config:
        nativeAutomatorConfig?.toPlatformAutomatorConfig() ??
        platformAutomatorConfig ??
        PlatformAutomatorConfig.defaultConfig(),
  );
  final patrolBinding = PatrolBinding.ensureInitialized(platformAutomator)
    ..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 platformAutomator.action.maybe(
        android: platformAutomator.android.configure,
        ios: platformAutomator.ios.configure,
        web: platformAutomator.web.configure,
      );

      patrolLog.log(
        TestEntry(
          name: global_state.currentTestFullName,
          status: TestEntryStatus.start,
        ),
      );
      final patrolTester = PatrolIntegrationTester(
        tester: widgetTester,
        config: config,
        platformAutomator: platformAutomator,
      );
      try {
        await callback(patrolTester);
      } catch (_) {
        if (constants.hotRestartEnabled) {
          patrolLog.log(
            TestEntry(name: description, status: TestEntryStatus.failure),
          );
        }
        rethrow;
      }

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

      if (constants.hotRestartEnabled &&
          global_state.isCurrentTestLastInGroup) {
        // Patrol log that test is finished
        // If test fails this code will not be executed
        patrolLog
          ..log(
            LogEntry(
              message:
                  'All tests were executed. Press "r" to start again or "q" to quit',
            ),
          )
          ..log(ConfigEntry(config: {ConfigEntry.developCompletedKey: true}));
        // Wait indefinitely in develop mode after the last test
        while (true) {
          await widgetTester.pump();
          await Future<void>.delayed(const Duration(milliseconds: 10));
        }
      }
    },
  );
}