Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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).
.claude/skills/evanca-patrol-e2e-testing/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 9% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 30% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 5% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 0% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 4% | 0% |
Design, implement, and run end-to-end (E2E) tests using Patrol 4.x in Flutter projects.
Use this skill when:
Follow the official Patrol documentation for installation and project initialization: https://patrol.leancode.co/documentation#setup
Key Patrol conventions:
patrol as a dev dependency.patrol_test/._test.dart suffix.patrol test.Follow these steps when implementing or updating Patrol tests.
Break the feature into:
Rules:
Basic Patrol structure:
dartimport '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:
patrolTest() instead of testWidgets().$ is the Patrol tester.$(#keyName) to find widgets by Key.waitUntilVisible).For OS-level permission dialogs:
dartpatrolTest('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.
Finding widgets:
dart$('some text') // by text $(TextField) // by type $(Icons.arrow_back) // by icon
Tapping:
dart// 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:
dart// Enter text into the second TextField on screen await $(TextField).at(1).enterText('your input');
Scrolling:
dartawait $(widget_you_want_to_scroll_to).scrollTo();
Native interactions:
dart// 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'), );
Run all tests:
bashpatrol test
Run a specific file with live reload (development mode):
bashpatrol develop -t integration_test/my_test.dart
Run a specific file:
bashpatrol test --target patrol_test/login_test.dart
Run on web:
bashpatrol test --device chrome
Headless web (CI):
bashpatrol test --device chrome --web-headless true
Filter by tags:
bashpatrol test --tags android
Flaky tests undermine confidence. Apply these patterns:
dart// AVOID — arbitrary delay await Future.delayed(Duration(seconds: 3)); // PREFER — explicit wait condition await $.waitUntilVisible($(#targetWidget)); // For animations, pump until settled await $.pumpAndSettle();
Future.delayed as a synchronization mechanism.waitUntilVisible or waitUntilExists to wait for UI state.settleTimeout in PatrolTesterConfig for slow CI environments.When applied, this skill produces:
Key additions to production code.patrol test command(s) to execute locally.Checkpoint: Run patrol test --target <file> locally to confirm the test passes before committing.
A valid Patrol test must be:
String.fromEnvironment, never hardcoded.--web-headless true or on emulator.Other measured skills in the registry, with their headline benchmark lift.