patrol-e2e-testing

Generates and maintains end-to-end tests for Flutter apps using Patrol. Use when adding E2E coverage for new features, regression tests for UI bugs, or testing native interactions (permissions, system dialogs, deep links)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "patrol-e2e-testing" with this command: npx skills add evanca/flutter-ai-rules/evanca-flutter-ai-rules-patrol-e2e-testing

Patrol E2E Testing Skill

This skill defines how to design, implement, and run end-to-end (E2E) tests using Patrol 4.x in Flutter projects.

It focuses on:

  • Covering new feature flows with deterministic UI tests
  • Converting reproducible UI bugs into regression tests
  • Handling native OS interactions
  • Running tests locally and in CI using correct Patrol CLI commands

When to Use

Use this skill when:

  • A new screen or user flow must be covered with E2E tests.
  • A feature interacts with native components (permissions, notifications, system dialogs).
  • A UI bug should be captured as a regression test.
  • Cross-platform behavior (Android / iOS / Web) must be validated.

Setup

For installation and project initialization, follow the official documentation:

https://patrol.leancode.co/documentation#setup

Key Patrol conventions:

  • patrol is added as a dev dependency.
  • Tests live in patrol_test/.
  • Test files must end with _test.dart.
  • Tests are executed with patrol test.

How to use this skill

Follow the steps below when implementing or updating Patrol tests.

1. Identify the user journey

Break the feature into:

  • Actions: taps, scrolls, input, navigation, deep links.
  • Observable outcomes: visible text, screen changes, enabled buttons, dialogs.

Rules:

  • One test per primary (happy-path) journey.
  • Separate tests for critical edge cases.
  • Avoid combining unrelated flows in a single test.

2. Structure the Patrol test

Basic Patrol structure:

import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';

void main() {
  patrolTest(
    'user can log in successfully',
    ($) async {
      await $.pumpWidgetAndSettle(const MyApp());

      const email = String.fromEnvironment('E2E_EMAIL');
      const password = String.fromEnvironment('E2E_PASSWORD');

      await $(#emailField).enterText(email);
      await $(#passwordField).enterText(password);
      await $(#loginButton).tap();

      await $.waitUntilVisible($(#homeScreenTitle));

      expect($(#homeScreenTitle).text, equals('Welcome'));
    },
  );
}

Key concepts:

  • Use patrolTest() instead of testWidgets().
  • $ is the Patrol tester.
  • Use $(#keyName) to find widgets by Key.
  • Use explicit wait conditions (e.g., waitUntilVisible).

3. Handle native dialogs

For OS-level permission dialogs:

patrolTest('grants camera permission', ($) async {
  await $.pumpWidgetAndSettle(const MyApp());

  await $(#openCameraButton).tap();

  if (await $.native.isPermissionDialogVisible()) {
    await $.native.grantPermission();
  }

  await $.waitUntilVisible($(#cameraPreview));
});

Use native automation only when required by the feature.

4. Selector & interaction quick reference

Finding widgets:

$('some text')        // by text
$(TextField)          // by type
$(Icons.arrow_back)   // by icon

Tapping:

// Tap a widget containing a specific text label
await $(Container).$('click').tap();

// Tap a container that contains an ElevatedButton
await $(Container).containing(ElevatedButton).tap();

// Tap only the enabled ElevatedButton
await $(ElevatedButton)
    .which<ElevatedButton>(
      (b) => b.enabled,
    )
    .tap();

Entering text:

// Enter text into the second TextField on screen
await $(TextField).at(1).enterText('your input');

Scrolling:

await $(widget_you_want_to_scroll_to).scrollTo();

Native interactions:

// Grant permission while app is in use
await $.native.grantPermissionWhenInUse();

// Open notification shade and tap a notification by text
await $.native.openNotifications();
await $.native.tapOnNotificationBySelector(
  Selector(textContains: 'text'),
);

5. Running Patrol tests

Run all tests:

patrol test

Run a specific file with live reload (development mode):

patrol develop -t integration_test/my_test.dart

Run a specific file:

patrol test --target patrol_test/login_test.dart

Run on web:

patrol test --device chrome

Headless web (CI):

patrol test --device chrome --web-headless true

Filter by tags:

patrol test --tags android

Output requirements when this skill is used

When applied, this skill must produce:

  1. Patrol test(s) covering the specified feature.
  2. Any required widget key additions.
  3. Exact patrol test command(s) to execute locally.
  4. Notes explaining stabilization decisions.

Quality bar

A valid Patrol test must be:

  • Deterministic (no arbitrary delays)
  • Readable
  • Minimal but complete
  • Secret-safe (no hardcoded credentials)
  • CI-ready

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

effective-dart

No summary provided by upstream source.

Repository SourceNeeds Review
General

riverpod

No summary provided by upstream source.

Repository SourceNeeds Review
General

architecture-feature-first

No summary provided by upstream source.

Repository SourceNeeds Review