$npx -y skills add flutter/agent-plugins --skill dart-migrate-to-checks-packageReplace the usage of expect and similar functions from package:matcher to package:checks equivalents.
| 1 | # Migrating Dart Tests to Package Checks |
| 2 | |
| 3 | Use this skill when you need to migrate a Dart test suite from the legacy |
| 4 | `package:matcher` (which is exported by default from `package:test/test.dart`) |
| 5 | to the modern, type-safe, and literate `package:checks` assertion library. |
| 6 | |
| 7 | ## Contents |
| 8 | - [When to Use This Skill](#when-to-use-this-skill) |
| 9 | - [How to Use This Skill (The Workflow)](#how-to-use-this-skill-the-workflow) |
| 10 | - [Key Syntax Differences and Pitfalls](#key-syntax-differences-and-pitfalls) |
| 11 | - [Matcher-to-Checks Mapping Table](#matcher-to-checks-mapping-table) |
| 12 | - [Matchers with No Direct Replacements](#matchers-with-no-direct-replacements) |
| 13 | - [Strategies for Discovery](#strategies-for-discovery) |
| 14 | - [Examples](#examples) |
| 15 | |
| 16 | --- |
| 17 | |
| 18 | ## When to Use This Skill |
| 19 | - When asked to "migrate tests to checks", "use package:checks", or |
| 20 | "modernize test assertions". |
| 21 | - When updating legacy test suites where static type safety, better |
| 22 | autocomplete in IDEs, and highly detailed failure diagnostics are desired. |
| 23 | |
| 24 | --- |
| 25 | |
| 26 | ## How to Use This Skill (The Workflow) |
| 27 | |
| 28 | Follow this structured workflow to safely and systematically migrate a test suite: |
| 29 | |
| 30 | ### 1. Dependency Setup |
| 31 | - Add `package:checks` as a `dev_dependency` in `pubspec.yaml`: |
| 32 | ```bash |
| 33 | dart pub add dev:checks |
| 34 | ``` |
| 35 | - Remove `package:matcher` if it is explicitly listed under `dev_dependencies` |
| 36 | (it is typically transitively included by `package:test`, which is fine). |
| 37 | |
| 38 | ### 2. Identify and Plan Target Files |
| 39 | - Use the grep patterns in [Strategies for Discovery](#strategies-for-discovery) |
| 40 | to locate all test files containing legacy `expect` or `expectLater` calls. |
| 41 | - Decide whether to migrate files fully or incrementally. |
| 42 | |
| 43 | ### 3. Migrating a File (Incremental or Full) |
| 44 | For any target test file: |
| 45 | 1. **Update Imports**: |
| 46 | - Replace the generic `import 'package:test/test.dart';` with: |
| 47 | ```dart |
| 48 | import 'package:test/scaffolding.dart'; |
| 49 | import 'package:checks/checks.dart'; |
| 50 | ``` |
| 51 | - **For Incremental Migration**: If you only want to migrate some test cases |
| 52 | in the file, or want to migrate one step at a time, add: |
| 53 | ```dart |
| 54 | import 'package:test/expect.dart'; // Temporarily allows legacy expect() |
| 55 | ``` |
| 56 | 2. **Translate Assertions**: Rewrite legacy `expect` and `expectLater` calls |
| 57 | to `check` syntax following the [Key Syntax Differences and |
| 58 | Pitfalls](#key-syntax-differences-and-pitfalls) and the |
| 59 | [Matcher-to-Checks Mapping Table](#matcher-to-checks-mapping-table). |
| 60 | 3. **Verify via Compiler**: If migrating fully, remove the `import |
| 61 | 'package:test/expect.dart';` line. Any remaining un-migrated `expect` |
| 62 | calls will immediately surface as compiler errors, making them easy to |
| 63 | find and fix. |
| 64 | |
| 65 | ### 4. Verification and Feedback Loops |
| 66 | - **Static Analysis**: Run static analysis on the target package: |
| 67 | ```bash |
| 68 | dart analyze |
| 69 | ``` |
| 70 | Pay close attention to generic type parameters on `.isA<Type>()` and |
| 71 | ensure asynchronous expectations are properly awaited (check for |
| 72 | `unawaited_futures` warnings). |
| 73 | - **Run Tests**: Execute the tests to verify both behavior and correct |
| 74 | assertion runtime logic: |
| 75 | ```bash |
| 76 | dart test |
| 77 | ``` |
| 78 | If a test fails, review the extremely detailed failure output of |
| 79 | `package:checks` to diagnose if the test is genuinely failing or if the |
| 80 | expectation was translated incorrectly. |
| 81 | |
| 82 | --- |
| 83 | |
| 84 | ## Key Syntax Differences and Pitfalls |
| 85 | |
| 86 | > [!IMPORTANT] |
| 87 | > A line-for-line translation can sometimes introduce subtle bugs or false |
| 88 | > passes. Always review these key differences carefully: |
| 89 | |
| 90 | ### 1. Collection Equality Pitfall (`equals` vs `deepEquals`) |
| 91 | - **Legacy Matcher**: `expect(actual, expected)` or `expect(actual, |
| 92 | equals(expected))` performed a **deep equality check** if the arguments |
| 93 | were collections (Lists, Maps, Sets). |
| 94 | - **Package Checks**: `.equals(expected)` corresponds strictly to |
| 95 | `operator ==`. Since Dart collections do not override `operator ==` for |
| 96 | element-wise comparison, using `.equals` on a collection will check for |
| 97 | *identity* and almost certainly fail at runtime. |
| 98 | - **Remediation**: You **must** replace collection equality assertions with |
| 99 | `.deepEquals(expected)`. |
| 100 | ```dart |
| 101 | // BEFORE (Matcher) |
| 102 | expect(myList, [1, 2, 3]); |
| 103 | |
| 104 | // AFTER (Checks) |
| 105 | check(myList).deepEquals([1, 2, 3]); |
| 106 | ``` |
| 107 | |
| 108 | ### 2. The `reason` Parameter is now `because` |
| 109 | - **Legacy Matcher**: The explanation was passed as a trailing named |
| 110 | argument `reason` to `expect`: |
| 111 | ```dart |
| 112 | expect(actual, expectation, reason: 'Explanation'); |
| 113 | ``` |
| 114 | - **Package Checks**: The explanation is passed as the named argument |
| 115 | `because` to the `check` function *before* the actual subject: |
| 116 | ```dart |
| 117 | check(because: 'Explanation', actual).expectation(); |
| 118 | ``` |
| 119 | |
| 120 | ### 3. Regular Expression Matching (`matches` vs `matchesPattern`) |
| 121 | - * |