Skip to content
Development
Skill

/patrol-e2e-testing

Use when writing E2E/integration tests, testing native interactions like permissions or system dialogs, capturing UI regressions, or validating cross-platform behavior (Patrol 4.x).

From plugin
flutter-ai-skills
63737 skills
Install
$ npx -y skills add evanca/flutter-ai-rules --skill patrol-e2e-testing --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/patrol-e2e-testing

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when writing E2E/integration tests, testing native interactions like permissions or system dialogs, capturing UI regressions, or validating cross-platform behavior (Patrol 4.x).

SKILL.md

patrol-e2e-testing.SKILL.md
name: patrol-e2e-testing
description: "Use when writing E2E/integration tests, testing native interactions like permissions or system dialogs, capturing UI regressions, or validating cross-platform behavior (Patrol 4.x)."
license: MIT

Patrol E2E Testing Skill

Design, implement, and run end-to-end (E2E) tests using Patrol 4.x in Flutter projects.

When to Use

Use this skill when:

  • A new screen or user flow needs E2E test coverage.
  • A feature interacts with native components (permissions, notifications, system dialogs, deep links).
  • A UI bug should be captured as a regression test.
  • Cross-platform behavior (Android / iOS / Web) must be validated.
  • Setting up Patrol in a new or existing Flutter project.

Setup

Follow the official Patrol documentation for installation and project initialization: [https://patrol.leancode.co/documentation#setup](https://patrol.leancode.co/documentation#setup)

Key Patrol conventions:

  • Add `patrol` as a dev dependency.
  • Place tests in `patrol_test/`.
  • Name test files with a `_test.dart` suffix.
  • Execute tests with `patrol test`.

Workflow

Follow these steps 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

6. Stabilization patterns

Flaky tests undermine confidence. Apply these patterns:

// AVOID — arbitrary delay
await Future.delayed(Duration(seconds: 3));

// PREFER — explicit wait condition
await $.waitUntilVisible($(#targetWidget));

// For animations, pump until settled
await $.pumpAndSettle();
  • Never use `Future.delayed` as a synchronization mechanism.
  • Use `waitUntilVisible` or `waitUntilExists` to wait for UI state.
  • Set `settleTimeout` in `PatrolTesterConfig` for slow CI environments.

Output requirements

When applied, this skill produces:

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

**Checkpoint:** Run `patrol test --target <file>` locally to confirm the test passes before committing.

Quality bar

A valid Patrol test must be:

  • **Deterministic** — no arbitrary delays; uses explicit wait conditions.
  • **Readable** — clear test name describing the user journey.
  • **Minimal but complete** — one assertion chain per journey.
  • **Secret-safe** — credentials loaded from `String.fromEnvironment`, never hardcoded.
  • **CI-ready** — passes headless with `--web-headless true` or on emulator.
Read more
Ships withflutter-ai-skills

36 Flutter and Dart skills your coding agent loads by itself, sourced only from official documentation. A skill is a folder with a SKILL.md file.

Get the whole plugin
Stats
637
Stars
66
Forks
Active
Maintenance
Shell
Language
MIT
License
1d ago
Last commit
1y ago
Created

Repo: evanca/flutter-ai-rules

Other skills on flutter-ai-skills.