[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-flutter-dart-migrate-to-checks-package":3,"mdc-l345j1-key":32,"related-org-flutter-dart-migrate-to-checks-package":4558,"related-repo-flutter-dart-migrate-to-checks-package":4688},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":22,"repoUrl":23,"updatedAt":24,"license":25,"forks":26,"topics":27,"repo":28,"sourceUrl":30,"mdContent":31},"dart-migrate-to-checks-package","migrate test matchers to checks package","Replace the usage of `expect` and similar functions from `package:matcher`\nto `package:checks` equivalents.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"flutter","Flutter (Google)","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fflutter.png",[12,16,19],{"name":13,"slug":14,"type":15},"Migration","migration","tag",{"name":17,"slug":18,"type":15},"Dart","dart",{"name":20,"slug":21,"type":15},"Testing","testing",2664,"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fagent-plugins","2026-07-15T05:22:31.276564",null,155,[],{"repoUrl":23,"stars":22,"forks":26,"topics":29,"description":25},[],"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fagent-plugins\u002Ftree\u002FHEAD\u002Fskills\u002Fdart-migrate-to-checks-package","---\nname: dart-migrate-to-checks-package\ndescription: |-\n  Replace the usage of `expect` and similar functions from `package:matcher`\n  to `package:checks` equivalents.\nmetadata:\n  model: models\u002Fgemini-3.1-pro-preview\n  last_modified: Tue, 09 Jun 2026 19:30:00 GMT\n---\n# Migrating Dart Tests to Package Checks\n\nUse this skill when you need to migrate a Dart test suite from the legacy\n`package:matcher` (which is exported by default from `package:test\u002Ftest.dart`)\nto the modern, type-safe, and literate `package:checks` assertion library.\n\n## Contents\n- [When to Use This Skill](#when-to-use-this-skill)\n- [How to Use This Skill (The Workflow)](#how-to-use-this-skill-the-workflow)\n- [Key Syntax Differences and Pitfalls](#key-syntax-differences-and-pitfalls)\n- [Matcher-to-Checks Mapping Table](#matcher-to-checks-mapping-table)\n- [Matchers with No Direct Replacements](#matchers-with-no-direct-replacements)\n- [Strategies for Discovery](#strategies-for-discovery)\n- [Examples](#examples)\n\n---\n\n## When to Use This Skill\n- When asked to \"migrate tests to checks\", \"use package:checks\", or\n  \"modernize test assertions\".\n- When updating legacy test suites where static type safety, better\n  autocomplete in IDEs, and highly detailed failure diagnostics are desired.\n\n---\n\n## How to Use This Skill (The Workflow)\n\nFollow this structured workflow to safely and systematically migrate a test suite:\n\n### 1. Dependency Setup\n- Add `package:checks` as a `dev_dependency` in `pubspec.yaml`:\n  ```bash\n  dart pub add dev:checks\n  ```\n- Remove `package:matcher` if it is explicitly listed under `dev_dependencies`\n  (it is typically transitively included by `package:test`, which is fine).\n\n### 2. Identify and Plan Target Files\n- Use the grep patterns in [Strategies for Discovery](#strategies-for-discovery)\n  to locate all test files containing legacy `expect` or `expectLater` calls.\n- Decide whether to migrate files fully or incrementally.\n\n### 3. Migrating a File (Incremental or Full)\nFor any target test file:\n1. **Update Imports**:\n   - Replace the generic `import 'package:test\u002Ftest.dart';` with:\n     ```dart\n     import 'package:test\u002Fscaffolding.dart';\n     import 'package:checks\u002Fchecks.dart';\n     ```\n   - **For Incremental Migration**: If you only want to migrate some test cases\n     in the file, or want to migrate one step at a time, add:\n     ```dart\n     import 'package:test\u002Fexpect.dart'; \u002F\u002F Temporarily allows legacy expect()\n     ```\n2. **Translate Assertions**: Rewrite legacy `expect` and `expectLater` calls\n   to `check` syntax following the [Key Syntax Differences and\n   Pitfalls](#key-syntax-differences-and-pitfalls) and the\n   [Matcher-to-Checks Mapping Table](#matcher-to-checks-mapping-table).\n3. **Verify via Compiler**: If migrating fully, remove the `import\n   'package:test\u002Fexpect.dart';` line. Any remaining un-migrated `expect`\n   calls will immediately surface as compiler errors, making them easy to\n   find and fix.\n\n### 4. Verification and Feedback Loops\n- **Static Analysis**: Run static analysis on the target package:\n  ```bash\n  dart analyze\n  ```\n  Pay close attention to generic type parameters on `.isA\u003CType>()` and\n  ensure asynchronous expectations are properly awaited (check for\n  `unawaited_futures` warnings).\n- **Run Tests**: Execute the tests to verify both behavior and correct\n  assertion runtime logic:\n  ```bash\n  dart test\n  ```\n  If a test fails, review the extremely detailed failure output of\n  `package:checks` to diagnose if the test is genuinely failing or if the\n  expectation was translated incorrectly.\n\n---\n\n## Key Syntax Differences and Pitfalls\n\n> [!IMPORTANT]\n> A line-for-line translation can sometimes introduce subtle bugs or false\n> passes. Always review these key differences carefully:\n\n### 1. Collection Equality Pitfall (`equals` vs `deepEquals`)\n- **Legacy Matcher**: `expect(actual, expected)` or `expect(actual,\n  equals(expected))` performed a **deep equality check** if the arguments\n  were collections (Lists, Maps, Sets).\n- **Package Checks**: `.equals(expected)` corresponds strictly to\n  `operator ==`. Since Dart collections do not override `operator ==` for\n  element-wise comparison, using `.equals` on a collection will check for\n  *identity* and almost certainly fail at runtime.\n- **Remediation**: You **must** replace collection equality assertions with\n  `.deepEquals(expected)`.\n  ```dart\n  \u002F\u002F BEFORE (Matcher)\n  expect(myList, [1, 2, 3]);\n\n  \u002F\u002F AFTER (Checks)\n  check(myList).deepEquals([1, 2, 3]);\n  ```\n\n### 2. The `reason` Parameter is now `because`\n- **Legacy Matcher**: The explanation was passed as a trailing named\n  argument `reason` to `expect`:\n  ```dart\n  expect(actual, expectation, reason: 'Explanation');\n  ```\n- **Package Checks**: The explanation is passed as the named argument\n  `because` to the `check` function *before* the actual subject:\n  ```dart\n  check(because: 'Explanation', actual).expectation();\n  ```\n\n### 3. Regular Expression Matching (`matches` vs `matchesPattern`)\n- **Legacy Matcher**: The `matches(pattern)` matcher automatically converted\n  a `String` argument into a `RegExp` (e.g., `matches(r'\\d')` matched `'1'`).\n- **Package Checks**: `.matchesPattern(pattern)` treats a `String` argument\n  as a literal string pattern.\n- **Remediation**: To match using a regular expression, you must explicitly\n  pass a `RegExp` object:\n  ```dart\n  \u002F\u002F BEFORE (Matcher)\n  expect(someString, matches(r'\\d+'));\n\n  \u002F\u002F AFTER (Checks)\n  check(someString).matchesPattern(RegExp(r'\\d+'));\n  ```\n\n### 4. Property Extraction (`TypeMatcher.having` vs `.has`)\n- **Legacy Matcher**: Chained field\u002Fproperty expectations used\n  `TypeMatcher.having(feature, description, matcher)`:\n  ```dart\n  expect(actual, isA\u003CPerson>().having((p) => p.name, 'name', startsWith('A')));\n  ```\n- **Package Checks**: The `.has(feature, description)` extension is\n  available on all `Subject`s, takes one fewer argument, and returns a new\n  `Subject` representing that property. You chain expectations directly off\n  it:\n  ```dart\n  check(actual).isA\u003CPerson>().has((p) => p.name, 'name').startsWith('A');\n  ```\n\n### 5. Synchronous vs. Asynchronous `throws`\n- **Legacy Matcher**: In `package:matcher`, `throwsA` behaved similarly for both\n  synchronous closures and asynchronous futures when wrapped in `expect` or\n  `expectLater`.\n- **Package Checks**: The `.throws\u003CE>()` expectation behaves differently and\n  has different return types depending on whether the subject is synchronous or\n  asynchronous:\n  - **Synchronous** (`Subject\u003CT Function()>`): `.throws\u003CE>()` returns a\n    `Subject\u003CE>` synchronously. This **does not** accept a callback argument!\n    You chain or cascade expectations directly off the returned `Subject\u003CE>`:\n    ```dart\n    \u002F\u002F YES (Synchronous chaining)\n    check(() => triggerSyncError()).throws\u003CArgumentError>()\n      ..has((e) => e.message, 'message').equals('invalid input');\n\n    \u002F\u002F NO (Passing a callback to sync throws will cause a compiler error!)\n    check(() => triggerSync\").throws\u003CArgumentError>((it) => ...); \u002F\u002F ERROR!\n    ```\n  - **Asynchronous** (`Subject\u003CFuture\u003CT>>`): `.throws\u003CE>()` returns\n    `Future\u003Cvoid>`. Because you cannot chain directly off a `Future\u003Cvoid>`, this\n    **requires** an inspection callback:\n    ```dart\n    \u002F\u002F YES (Asynchronous callback)\n    await check(triggerAsyncError()).throws\u003CArgumentError>((it) => it\n      ..has((e) => e.message, 'message').equals('invalid input'));\n    ```\n  - **Crucial Pitfall**: Trying to chain expectations directly after an awaited\n    asynchronous `.throws\u003CE>()` (e.g.,\n    `await check(future).throws\u003CE>().equals(...)`) will fail to compile\n    because it returns `Future\u003Cvoid>`.\n\n### 6. RegExp \u002F Pattern Equality\n- **Legacy Matcher**: In `package:matcher`, `expect(myPattern,`\n  `equals(RegExp('Hello')))` worked because the matcher comparison rules\n  handled RegExp instances.\n- **Package Checks**: `.equals()` uses strict Dart `==` equality. Since separate\n  `RegExp` instances do not satisfy `==`, using `.equals()` will fail at runtime.\n- **Remediation**: Use `.isA\u003CRegExp>()` type refinement along with cascades to\n  assert on the properties of the `RegExp` object explicitly:\n  ```dart\n  check(myPattern).isA\u003CRegExp>()\n    ..has((r) => r.pattern, 'pattern').equals('Hello')\n    ..has((r) => r.isMultiLine, 'isMultiLine').isTrue();\n  ```\n\n### 7. Strict Nullable Boolean Safety (`bool?` fields)\n- **Legacy Matcher**: Statically, `isTrue` and `isFalse` performed loose\n  dynamic checks at runtime, which silently accepted nullable booleans (`bool?`).\n- **Package Checks**: `.isTrue()` and `.isFalse()` are defined strictly on\n  `Subject\u003Cbool>` (non-nullable). They are **not** available on `Subject\u003Cbool?>`.\n- **Remediation**: For fields declared as `bool?`, you must either refine the\n  subject (e.g., `.isNotNull().isTrue()`) or simply use `.equals(true)` and\n  `.equals(false)` which are generic and work on all types:\n  ```dart\n  \u002F\u002F If options.flagOutdated is a bool?\n  check(options.flagOutdated).equals(true);\n  check(options.flagOutdated).equals(false);\n  ```\n\n### 8. Map Key Containment (`containsKey` vs `contains`)\n- **Legacy Matcher**: In `package:matcher`, `contains(key)` was used to assert\n  that a `Map` contained a specific key.\n- **Package Checks**: Calling `.contains(...)` on a `Subject\u003CMap>` is not\n  defined and will fail compilation.\n- **Remediation**: Use the map-specific `.containsKey(key)` matcher instead:\n  ```dart\n  \u002F\u002F BEFORE (Matcher)\n  expect(myMap, contains('my_key'));\n\n  \u002F\u002F AFTER (Checks)\n  check(myMap).containsKey('my_key');\n  ```\n\n### 9. Explicit Generic Parameters for Extension Types\n- **Legacy Matcher**: `expect(extensionTypeConst, 3)` compiled because of loose\n  dynamic equality.\n- **Package Checks**: If `QrEciValue` is an extension type representation of `int`\n  (e.g., `extension type const QrEciValue(int value) implements int`), calling\n  `.equals(3)` on a `Subject\u003CQrEciValue>` fails because `3` (an `int`) is not\n  assignable to `QrEciValue`. Casting with `as int` will trigger an\n  \"Unnecessary cast\" static analysis warning because `QrEciValue` statically\n  implements `int`.\n- **Remediation**: Explicitly specify the generic type parameter on the `check`\n  function to force checks to treat it as the primitive type:\n  ```dart\n  \u002F\u002F YES (Type-safe and warning-free)\n  check\u003Cint>(QrEciValue.iso8859_1).equals(3);\n  ```\n\n### 10. Dynamic Map \u002F JSON Lookup Casting\n- **Legacy Matcher**: Loose dynamic typing allowed comparing nested json lookups\n  statically typed as `dynamic` directly against lists or maps.\n- **Package Checks**: Strict type safety rejects the implicit assignment of\n  `dynamic` to `Iterable\u003CObject?>` in `.deepEquals(...)`.\n- **Remediation**: Statically cast the dynamic lookup result to a `List` or `Map`:\n  ```dart\n  \u002F\u002F YES (Explicit cast to List)\n  check(myIterable).deepEquals(json['data']['items'] as List);\n  ```\n\n---\n\n## Matcher-to-Checks Mapping Table\n\nUse this table as a quick reference for direct matcher replacements:\n\n| Legacy Matcher | Package Checks Equivalent | Notes |\n| :--- | :--- | :--- |\n| `expect(actual, expected)` | `check(actual).equals(expected)` | Use `.deepEquals` for collections! |\n| `expect(actual, equals(expected))` | `check(actual).equals(expected)` | Use `.deepEquals` for collections! |\n| `isA\u003CT>()` | `check(actual).isA\u003CT>()` | Chaining is supported directly |\n| `same(expected)` | `check(actual).identicalTo(expected)` | Verifies identity |\n| `anyElement(matcher)` | `check(iterable).any(conditionCallback)` | E.g. `check(list).any((e) => e.equals(1))` |\n| `everyElement(matcher)` | `check(iterable).every(conditionCallback)` | E.g. `check(list).every((e) => e.isGreaterThan(0))` |\n| `hasLength(expected)` | `check(actual).length.equals(expected)` | Works on String, Map, Iterable, etc. |\n| `isNot(matcher)` | `check(actual).not(conditionCallback)` | E.g. `check(val).not((it) => it.equals(5))` |\n| `contains(element)` | `check(actual).contains(element)` | Works on String, Iterable (use `containsKey` for Map!) |\n| `contains(key)` (on a Map) | `check(map).containsKey(key)` | Map key containment |\n| `startsWith(prefix)` | `check(string).startsWith(prefix)` | String only |\n| `endsWith(suffix)` | `check(string).endsWith(suffix)` | String only |\n| `isEmpty` | `check(actual).isEmpty()` | Works on String, Map, Iterable |\n| `isNotEmpty` | `check(actual).isNotEmpty()` | Works on String, Map, Iterable |\n| `isNull` | `check(actual).isNull()` | |\n| `isNotNull` | `check(actual).isNotNull()` | |\n| `isTrue` \u002F `true` | `check(actual).isTrue()` | Works on non-nullable `bool` only |\n| `isFalse` \u002F `false` | `check(actual).isFalse()` | Works on non-nullable `bool` only |\n| `completion(matcher)` | `await check(future).completes(conditionCallback)` | Must be awaited! |\n| `throwsA(matcher)` | `await check(future).throws\u003CType>()` | Must be awaited! |\n| `emits(value)` | `await check(streamQueue).emits(conditionCallback)` | Must be awaited! |\n| `emitsThrough(value)` | `await check(streamQueue).emitsThrough(conditionCallback)` | Must be awaited! |\n| `stringContainsInOrder(list)` | `check(string).containsInOrder(list)` | String only |\n| `pairwiseCompare(...)` | `check(actual).pairwiseMatches(...)` | |\n\n---\n\n## Matchers with No Direct Replacements\n\nSome legacy matchers do not have a one-to-one equivalent in `package:checks`\ndue to API cleanup. Use these standard workarounds:\n\n### 1. Specific Error Matchers\n- **Legacy**: `throwsArgumentError`, `throwsStateError`,\n  `throwsUnsupportedError`, etc.\n- **Checks**: Use `.throws\u003CT>()` with the specific error type:\n  ```dart\n  await check(triggerError()).throws\u003CArgumentError>();\n  ```\n\n### 2. The `anything` Matcher\n- **Legacy**: `expect(actual, anything)`\n- **Checks**: Pass an empty condition callback `(_) {}` when a condition is\n  syntactically required:\n  ```dart\n  await check(someFuture).completes((_) {});\n  ```\n\n### 3. Specific Numeric Toggles\n- **Legacy**: `isPositive`, `isNegative`, `isZero`, `isNonPositive`,\n  `isNonNegative`, `isNonZero`\n- **Checks**: Use explicit comparative expectations:\n  - `isPositive` $\\rightarrow$ `isGreaterThan(0)`\n  - `isNegative` $\\rightarrow$ `isLessThan(0)`\n  - `isZero` $\\rightarrow$ `equals(0)`\n  - `isNonNegative` $\\rightarrow$ `isGreaterOrEqual(0)`\n\n### 4. Numeric Ranges\n- **Legacy**: `inClosedOpenRange(min, max)`, `inInclusiveRange(min, max)`,\n  etc.\n- **Checks**: Chain the boundaries using the cascade operator (`..`):\n  ```dart\n  check(actualValue)\n    ..isGreaterOrEqual(min)\n    ..isLessThan(max);\n  ```\n\n---\n\n## Writing Custom Expectations (Replacing Custom Matchers)\n\nWhen migrating from a legacy codebase, you may encounter custom `Matcher`\nsubclasses. In `package:checks`, custom assertions are implemented as\n`extension` methods on `Subject\u003CT>`.\n\nTo write custom expectations, you must import the checks context API:\n```dart\nimport 'package:checks\u002Fcontext.dart';\n```\n\n### 1. Simple Custom Expectations (using `expect`)\nUse `context.expect` to check a property and return a `Rejection` on failure:\n```dart\nextension CustomPersonChecks on Subject\u003CPerson> {\n  void isAdult() {\n    context.expect(\n      () => ['is an adult (age >= 18)'],\n      (actual) {\n        if (actual.age >= 18) return null; \u002F\u002F Pass\n        return Rejection(\n          which: ['is only ${actual.age} years old'],\n        );\n      },\n    );\n  }\n}\n```\n\n### 2. Nested Property Extraction (using `nest` or `has`)\nTo extract a property and allow further chained checks, use `nest` or the\nsimpler `has` helper:\n- **Using `has` (Recommended for simple, non-failing field access)**:\n  ```dart\n  extension CustomPersonChecks on Subject\u003CPerson> {\n    Subject\u003CAddress> get address => has((p) => p.address, 'address');\n  }\n  ```\n- **Using `nest` (For property extraction that can fail or reject)**:\n  ```dart\n  extension CustomPersonChecks on Subject\u003CPerson> {\n    Subject\u003CString> get ssn => context.nest(\n      'has a valid SSN',\n      (actual) {\n        final ssnValue = actual.ssn;\n        if (ssnValue == null) {\n          return Extracted.rejection(which: ['has no SSN']);\n        }\n        return Extracted.value(ssnValue);\n      },\n    );\n  }\n  ```\n\n### 3. Asynchronous Custom Expectations\nIf the expectation is asynchronous (e.g. checking a Future or Stream), use\n`context.expectAsync` or `context.nestAsync` and return the resulting `Future`:\n```dart\nextension CustomFutureChecks\u003CT> on Subject\u003CFuture\u003CT>> {\n  Future\u003Cvoid> completesNormally() {\n    return context.expectAsync(\n      () => ['completes without throwing'],\n      (actual) async {\n        try {\n          await actual;\n          return null; \u002F\u002F Pass\n        } catch (e) {\n          return Rejection(which: ['threw $e']);\n        }\n      },\n    );\n  }\n}\n```\n\n---\n\n## Strategies for Discovery\n\nExecute these commands in the terminal to identify legacy matchers and files\nrequiring migration:\n\n```bash\n# 1. Find all test files containing legacy expect() or expectLater()\ngrep -rn \"expect(\" test\u002F\ngrep -rn \"expectLater(\" test\u002F\n\n# 2. Find potential collection equality pitfalls (literal lists or maps)\ngrep -rn \"expect(.*, \\[\" test\u002F\ngrep -rn \"expect(.*, {\" test\u002F\n\n# 3. Find matches() calls (need conversion to RegExp + matchesPattern)\ngrep -rn \"matches(\" test\u002F\n\n# 4. Find legacy TypeMatcher.having() calls (which need conversion to .has())\ngrep -rn \"having(\" test\u002F\n```\n\n---\n\n## Examples\n\n### Basic Assertions\n**Before (Matcher):**\n```dart\nexpect(someValue, isNotNull);\nexpect(result, isTrue, reason: 'should be successful');\nexpect(myString, startsWith('hello'));\n```\n\n**After (Checks):**\n```dart\ncheck(someValue).isNotNull();\ncheck(because: 'should be successful', result).isTrue();\ncheck(myString).startsWith('hello');\n```\n\n### Collection and Deep Equality\n**Before (Matcher):**\n```dart\nexpect(items, [1, 2, 3]);\nexpect(configMap, equals({'port': 8080}));\n```\n\n**After (Checks):**\n```dart\ncheck(items).deepEquals([1, 2, 3]);\ncheck(configMap).deepEquals({'port': 8080});\n```\n\n### Chaining and Cascades\n**Before (Matcher):**\n```dart\nexpect(someString, allOf([\n  startsWith('a'),\n  contains('b'),\n  endsWith('c'),\n]));\n```\n\n**After (Checks):**\n```dart\ncheck(someString)\n  ..startsWith('a')\n  ..contains('b')\n  ..endsWith('c');\n```\n\n### Complex Property Matching (has)\n**Before (Matcher):**\n```dart\nexpect(response, isA\u003CResponse>()\n    .having((r) => r.statusCode, 'statusCode', 200)\n    .having((r) => r.body, 'body', contains('success')));\n```\n\n**After (Checks):**\n```dart\ncheck(response).isA\u003CResponse>()\n  ..has((r) => r.statusCode, 'statusCode').equals(200)\n  ..has((r) => r.body, 'body').contains('success');\n```\n\n### Asynchronous Futures\n**Before (Matcher):**\n```dart\nexpect(fetchData(), completes);\nexpect(fetchData(), completion(equals('data')));\nexpect(failingCall(), throwsA(isA\u003CStateError>()));\n```\n\n**After (Checks):**\n```dart\nawait check(fetchData()).completes();\nawait check(fetchData()).completes((it) => it.equals('data'));\nawait check(failingCall()).throws\u003CStateError>();\n```\n\n### Asynchronous Streams\n**Before (Matcher):**\n```dart\nvar queue = StreamQueue(Stream.fromIterable([1, 2, 3]));\nawait expectLater(queue, emitsInOrder([1, 2, 3]));\n```\n\n**After (Checks):**\n```dart\nvar queue = StreamQueue(Stream.fromIterable([1, 2, 3]));\nawait check(queue).inOrder([\n  (s) => s.emits((e) => e.equals(1)),\n  (s) => s.emits((e) => e.equals(2)),\n  (s) => s.emits((e) => e.equals(3)),\n]);\n```\n",{"data":33,"body":37},{"name":4,"description":6,"metadata":34},{"model":35,"last_modified":36},"models\u002Fgemini-3.1-pro-preview","Tue, 09 Jun 2026 19:30:00 GMT",{"type":38,"children":39},"root",[40,49,80,87,156,160,165,178,181,186,191,198,295,301,336,342,347,496,502,590,593,598,612,634,793,813,896,916,1051,1071,1149,1161,1428,1434,1565,1579,1728,1748,1867,1873,2022,2028,2122,2125,2130,2135,2840,2843,2848,2860,2866,2932,2945,2993,2999,3124,3130,3204,3207,3213,3248,3253,3267,3279,3299,3417,3437,3456,3620,3626,3654,3779,3782,3787,3792,4027,4030,4035,4041,4049,4080,4088,4119,4125,4132,4155,4162,4185,4191,4198,4245,4252,4291,4297,4304,4335,4342,4373,4379,4386,4417,4424,4455,4461,4468,4491,4498,4552],{"type":41,"tag":42,"props":43,"children":45},"element","h1",{"id":44},"migrating-dart-tests-to-package-checks",[46],{"type":47,"value":48},"text","Migrating Dart Tests to Package Checks",{"type":41,"tag":50,"props":51,"children":52},"p",{},[53,55,62,64,70,72,78],{"type":47,"value":54},"Use this skill when you need to migrate a Dart test suite from the legacy\n",{"type":41,"tag":56,"props":57,"children":59},"code",{"className":58},[],[60],{"type":47,"value":61},"package:matcher",{"type":47,"value":63}," (which is exported by default from ",{"type":41,"tag":56,"props":65,"children":67},{"className":66},[],[68],{"type":47,"value":69},"package:test\u002Ftest.dart",{"type":47,"value":71},")\nto the modern, type-safe, and literate ",{"type":41,"tag":56,"props":73,"children":75},{"className":74},[],[76],{"type":47,"value":77},"package:checks",{"type":47,"value":79}," assertion library.",{"type":41,"tag":81,"props":82,"children":84},"h2",{"id":83},"contents",[85],{"type":47,"value":86},"Contents",{"type":41,"tag":88,"props":89,"children":90},"ul",{},[91,102,111,120,129,138,147],{"type":41,"tag":92,"props":93,"children":94},"li",{},[95],{"type":41,"tag":96,"props":97,"children":99},"a",{"href":98},"#when-to-use-this-skill",[100],{"type":47,"value":101},"When to Use This Skill",{"type":41,"tag":92,"props":103,"children":104},{},[105],{"type":41,"tag":96,"props":106,"children":108},{"href":107},"#how-to-use-this-skill-the-workflow",[109],{"type":47,"value":110},"How to Use This Skill (The Workflow)",{"type":41,"tag":92,"props":112,"children":113},{},[114],{"type":41,"tag":96,"props":115,"children":117},{"href":116},"#key-syntax-differences-and-pitfalls",[118],{"type":47,"value":119},"Key Syntax Differences and Pitfalls",{"type":41,"tag":92,"props":121,"children":122},{},[123],{"type":41,"tag":96,"props":124,"children":126},{"href":125},"#matcher-to-checks-mapping-table",[127],{"type":47,"value":128},"Matcher-to-Checks Mapping Table",{"type":41,"tag":92,"props":130,"children":131},{},[132],{"type":41,"tag":96,"props":133,"children":135},{"href":134},"#matchers-with-no-direct-replacements",[136],{"type":47,"value":137},"Matchers with No Direct Replacements",{"type":41,"tag":92,"props":139,"children":140},{},[141],{"type":41,"tag":96,"props":142,"children":144},{"href":143},"#strategies-for-discovery",[145],{"type":47,"value":146},"Strategies for Discovery",{"type":41,"tag":92,"props":148,"children":149},{},[150],{"type":41,"tag":96,"props":151,"children":153},{"href":152},"#examples",[154],{"type":47,"value":155},"Examples",{"type":41,"tag":157,"props":158,"children":159},"hr",{},[],{"type":41,"tag":81,"props":161,"children":163},{"id":162},"when-to-use-this-skill",[164],{"type":47,"value":101},{"type":41,"tag":88,"props":166,"children":167},{},[168,173],{"type":41,"tag":92,"props":169,"children":170},{},[171],{"type":47,"value":172},"When asked to \"migrate tests to checks\", \"use package:checks\", or\n\"modernize test assertions\".",{"type":41,"tag":92,"props":174,"children":175},{},[176],{"type":47,"value":177},"When updating legacy test suites where static type safety, better\nautocomplete in IDEs, and highly detailed failure diagnostics are desired.",{"type":41,"tag":157,"props":179,"children":180},{},[],{"type":41,"tag":81,"props":182,"children":184},{"id":183},"how-to-use-this-skill-the-workflow",[185],{"type":47,"value":110},{"type":41,"tag":50,"props":187,"children":188},{},[189],{"type":47,"value":190},"Follow this structured workflow to safely and systematically migrate a test suite:",{"type":41,"tag":192,"props":193,"children":195},"h3",{"id":194},"_1-dependency-setup",[196],{"type":47,"value":197},"1. Dependency Setup",{"type":41,"tag":88,"props":199,"children":200},{},[201,267],{"type":41,"tag":92,"props":202,"children":203},{},[204,206,211,213,219,221,227,229],{"type":47,"value":205},"Add ",{"type":41,"tag":56,"props":207,"children":209},{"className":208},[],[210],{"type":47,"value":77},{"type":47,"value":212}," as a ",{"type":41,"tag":56,"props":214,"children":216},{"className":215},[],[217],{"type":47,"value":218},"dev_dependency",{"type":47,"value":220}," in ",{"type":41,"tag":56,"props":222,"children":224},{"className":223},[],[225],{"type":47,"value":226},"pubspec.yaml",{"type":47,"value":228},":\n",{"type":41,"tag":230,"props":231,"children":236},"pre",{"className":232,"code":233,"language":234,"meta":235,"style":235},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","dart pub add dev:checks\n","bash","",[237],{"type":41,"tag":56,"props":238,"children":239},{"__ignoreMap":235},[240],{"type":41,"tag":241,"props":242,"children":245},"span",{"class":243,"line":244},"line",1,[246,251,257,262],{"type":41,"tag":241,"props":247,"children":249},{"style":248},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[250],{"type":47,"value":18},{"type":41,"tag":241,"props":252,"children":254},{"style":253},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[255],{"type":47,"value":256}," pub",{"type":41,"tag":241,"props":258,"children":259},{"style":253},[260],{"type":47,"value":261}," add",{"type":41,"tag":241,"props":263,"children":264},{"style":253},[265],{"type":47,"value":266}," dev:checks\n",{"type":41,"tag":92,"props":268,"children":269},{},[270,272,277,279,285,287,293],{"type":47,"value":271},"Remove ",{"type":41,"tag":56,"props":273,"children":275},{"className":274},[],[276],{"type":47,"value":61},{"type":47,"value":278}," if it is explicitly listed under ",{"type":41,"tag":56,"props":280,"children":282},{"className":281},[],[283],{"type":47,"value":284},"dev_dependencies",{"type":47,"value":286},"\n(it is typically transitively included by ",{"type":41,"tag":56,"props":288,"children":290},{"className":289},[],[291],{"type":47,"value":292},"package:test",{"type":47,"value":294},", which is fine).",{"type":41,"tag":192,"props":296,"children":298},{"id":297},"_2-identify-and-plan-target-files",[299],{"type":47,"value":300},"2. Identify and Plan Target Files",{"type":41,"tag":88,"props":302,"children":303},{},[304,331],{"type":41,"tag":92,"props":305,"children":306},{},[307,309,313,315,321,323,329],{"type":47,"value":308},"Use the grep patterns in ",{"type":41,"tag":96,"props":310,"children":311},{"href":143},[312],{"type":47,"value":146},{"type":47,"value":314},"\nto locate all test files containing legacy ",{"type":41,"tag":56,"props":316,"children":318},{"className":317},[],[319],{"type":47,"value":320},"expect",{"type":47,"value":322}," or ",{"type":41,"tag":56,"props":324,"children":326},{"className":325},[],[327],{"type":47,"value":328},"expectLater",{"type":47,"value":330}," calls.",{"type":41,"tag":92,"props":332,"children":333},{},[334],{"type":47,"value":335},"Decide whether to migrate files fully or incrementally.",{"type":41,"tag":192,"props":337,"children":339},{"id":338},"_3-migrating-a-file-incremental-or-full",[340],{"type":47,"value":341},"3. Migrating a File (Incremental or Full)",{"type":41,"tag":50,"props":343,"children":344},{},[345],{"type":47,"value":346},"For any target test file:",{"type":41,"tag":348,"props":349,"children":350},"ol",{},[351,426,471],{"type":41,"tag":92,"props":352,"children":353},{},[354,360,361],{"type":41,"tag":355,"props":356,"children":357},"strong",{},[358],{"type":47,"value":359},"Update Imports",{"type":47,"value":228},{"type":41,"tag":88,"props":362,"children":363},{},[364,402],{"type":41,"tag":92,"props":365,"children":366},{},[367,369,375,377],{"type":47,"value":368},"Replace the generic ",{"type":41,"tag":56,"props":370,"children":372},{"className":371},[],[373],{"type":47,"value":374},"import 'package:test\u002Ftest.dart';",{"type":47,"value":376}," with:\n",{"type":41,"tag":230,"props":378,"children":381},{"className":379,"code":380,"language":18,"meta":235,"style":235},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import 'package:test\u002Fscaffolding.dart';\nimport 'package:checks\u002Fchecks.dart';\n",[382],{"type":41,"tag":56,"props":383,"children":384},{"__ignoreMap":235},[385,393],{"type":41,"tag":241,"props":386,"children":387},{"class":243,"line":244},[388],{"type":41,"tag":241,"props":389,"children":390},{},[391],{"type":47,"value":392},"import 'package:test\u002Fscaffolding.dart';\n",{"type":41,"tag":241,"props":394,"children":396},{"class":243,"line":395},2,[397],{"type":41,"tag":241,"props":398,"children":399},{},[400],{"type":47,"value":401},"import 'package:checks\u002Fchecks.dart';\n",{"type":41,"tag":92,"props":403,"children":404},{},[405,410,412],{"type":41,"tag":355,"props":406,"children":407},{},[408],{"type":47,"value":409},"For Incremental Migration",{"type":47,"value":411},": If you only want to migrate some test cases\nin the file, or want to migrate one step at a time, add:\n",{"type":41,"tag":230,"props":413,"children":415},{"className":379,"code":414,"language":18,"meta":235,"style":235},"import 'package:test\u002Fexpect.dart'; \u002F\u002F Temporarily allows legacy expect()\n",[416],{"type":41,"tag":56,"props":417,"children":418},{"__ignoreMap":235},[419],{"type":41,"tag":241,"props":420,"children":421},{"class":243,"line":244},[422],{"type":41,"tag":241,"props":423,"children":424},{},[425],{"type":47,"value":414},{"type":41,"tag":92,"props":427,"children":428},{},[429,434,436,441,443,448,450,456,458,463,465,469],{"type":41,"tag":355,"props":430,"children":431},{},[432],{"type":47,"value":433},"Translate Assertions",{"type":47,"value":435},": Rewrite legacy ",{"type":41,"tag":56,"props":437,"children":439},{"className":438},[],[440],{"type":47,"value":320},{"type":47,"value":442}," and ",{"type":41,"tag":56,"props":444,"children":446},{"className":445},[],[447],{"type":47,"value":328},{"type":47,"value":449}," calls\nto ",{"type":41,"tag":56,"props":451,"children":453},{"className":452},[],[454],{"type":47,"value":455},"check",{"type":47,"value":457}," syntax following the ",{"type":41,"tag":96,"props":459,"children":460},{"href":116},[461],{"type":47,"value":462},"Key Syntax Differences and\nPitfalls",{"type":47,"value":464}," and the\n",{"type":41,"tag":96,"props":466,"children":467},{"href":125},[468],{"type":47,"value":128},{"type":47,"value":470},".",{"type":41,"tag":92,"props":472,"children":473},{},[474,479,481,487,489,494],{"type":41,"tag":355,"props":475,"children":476},{},[477],{"type":47,"value":478},"Verify via Compiler",{"type":47,"value":480},": If migrating fully, remove the ",{"type":41,"tag":56,"props":482,"children":484},{"className":483},[],[485],{"type":47,"value":486},"import 'package:test\u002Fexpect.dart';",{"type":47,"value":488}," line. Any remaining un-migrated ",{"type":41,"tag":56,"props":490,"children":492},{"className":491},[],[493],{"type":47,"value":320},{"type":47,"value":495},"\ncalls will immediately surface as compiler errors, making them easy to\nfind and fix.",{"type":41,"tag":192,"props":497,"children":499},{"id":498},"_4-verification-and-feedback-loops",[500],{"type":47,"value":501},"4. Verification and Feedback Loops",{"type":41,"tag":88,"props":503,"children":504},{},[505,552],{"type":41,"tag":92,"props":506,"children":507},{},[508,513,515,534,536,542,544,550],{"type":41,"tag":355,"props":509,"children":510},{},[511],{"type":47,"value":512},"Static Analysis",{"type":47,"value":514},": Run static analysis on the target package:\n",{"type":41,"tag":230,"props":516,"children":518},{"className":232,"code":517,"language":234,"meta":235,"style":235},"dart analyze\n",[519],{"type":41,"tag":56,"props":520,"children":521},{"__ignoreMap":235},[522],{"type":41,"tag":241,"props":523,"children":524},{"class":243,"line":244},[525,529],{"type":41,"tag":241,"props":526,"children":527},{"style":248},[528],{"type":47,"value":18},{"type":41,"tag":241,"props":530,"children":531},{"style":253},[532],{"type":47,"value":533}," analyze\n",{"type":47,"value":535},"\nPay close attention to generic type parameters on ",{"type":41,"tag":56,"props":537,"children":539},{"className":538},[],[540],{"type":47,"value":541},".isA\u003CType>()",{"type":47,"value":543}," and\nensure asynchronous expectations are properly awaited (check for\n",{"type":41,"tag":56,"props":545,"children":547},{"className":546},[],[548],{"type":47,"value":549},"unawaited_futures",{"type":47,"value":551}," warnings).",{"type":41,"tag":92,"props":553,"children":554},{},[555,560,562,581,583,588],{"type":41,"tag":355,"props":556,"children":557},{},[558],{"type":47,"value":559},"Run Tests",{"type":47,"value":561},": Execute the tests to verify both behavior and correct\nassertion runtime logic:\n",{"type":41,"tag":230,"props":563,"children":565},{"className":232,"code":564,"language":234,"meta":235,"style":235},"dart test\n",[566],{"type":41,"tag":56,"props":567,"children":568},{"__ignoreMap":235},[569],{"type":41,"tag":241,"props":570,"children":571},{"class":243,"line":244},[572,576],{"type":41,"tag":241,"props":573,"children":574},{"style":248},[575],{"type":47,"value":18},{"type":41,"tag":241,"props":577,"children":578},{"style":253},[579],{"type":47,"value":580}," test\n",{"type":47,"value":582},"\nIf a test fails, review the extremely detailed failure output of\n",{"type":41,"tag":56,"props":584,"children":586},{"className":585},[],[587],{"type":47,"value":77},{"type":47,"value":589}," to diagnose if the test is genuinely failing or if the\nexpectation was translated incorrectly.",{"type":41,"tag":157,"props":591,"children":592},{},[],{"type":41,"tag":81,"props":594,"children":596},{"id":595},"key-syntax-differences-and-pitfalls",[597],{"type":47,"value":119},{"type":41,"tag":599,"props":600,"children":601},"blockquote",{},[602],{"type":41,"tag":50,"props":603,"children":604},{},[605,610],{"type":41,"tag":241,"props":606,"children":607},{},[608],{"type":47,"value":609},"!IMPORTANT",{"type":47,"value":611},"\nA line-for-line translation can sometimes introduce subtle bugs or false\npasses. Always review these key differences carefully:",{"type":41,"tag":192,"props":613,"children":615},{"id":614},"_1-collection-equality-pitfall-equals-vs-deepequals",[616,618,624,626,632],{"type":47,"value":617},"1. Collection Equality Pitfall (",{"type":41,"tag":56,"props":619,"children":621},{"className":620},[],[622],{"type":47,"value":623},"equals",{"type":47,"value":625}," vs ",{"type":41,"tag":56,"props":627,"children":629},{"className":628},[],[630],{"type":47,"value":631},"deepEquals",{"type":47,"value":633},")",{"type":41,"tag":88,"props":635,"children":636},{},[637,669,717],{"type":41,"tag":92,"props":638,"children":639},{},[640,645,647,653,654,660,662,667],{"type":41,"tag":355,"props":641,"children":642},{},[643],{"type":47,"value":644},"Legacy Matcher",{"type":47,"value":646},": ",{"type":41,"tag":56,"props":648,"children":650},{"className":649},[],[651],{"type":47,"value":652},"expect(actual, expected)",{"type":47,"value":322},{"type":41,"tag":56,"props":655,"children":657},{"className":656},[],[658],{"type":47,"value":659},"expect(actual, equals(expected))",{"type":47,"value":661}," performed a ",{"type":41,"tag":355,"props":663,"children":664},{},[665],{"type":47,"value":666},"deep equality check",{"type":47,"value":668}," if the arguments\nwere collections (Lists, Maps, Sets).",{"type":41,"tag":92,"props":670,"children":671},{},[672,677,678,684,686,692,694,699,701,707,709,715],{"type":41,"tag":355,"props":673,"children":674},{},[675],{"type":47,"value":676},"Package Checks",{"type":47,"value":646},{"type":41,"tag":56,"props":679,"children":681},{"className":680},[],[682],{"type":47,"value":683},".equals(expected)",{"type":47,"value":685}," corresponds strictly to\n",{"type":41,"tag":56,"props":687,"children":689},{"className":688},[],[690],{"type":47,"value":691},"operator ==",{"type":47,"value":693},". Since Dart collections do not override ",{"type":41,"tag":56,"props":695,"children":697},{"className":696},[],[698],{"type":47,"value":691},{"type":47,"value":700}," for\nelement-wise comparison, using ",{"type":41,"tag":56,"props":702,"children":704},{"className":703},[],[705],{"type":47,"value":706},".equals",{"type":47,"value":708}," on a collection will check for\n",{"type":41,"tag":710,"props":711,"children":712},"em",{},[713],{"type":47,"value":714},"identity",{"type":47,"value":716}," and almost certainly fail at runtime.",{"type":41,"tag":92,"props":718,"children":719},{},[720,725,727,732,734,740,742],{"type":41,"tag":355,"props":721,"children":722},{},[723],{"type":47,"value":724},"Remediation",{"type":47,"value":726},": You ",{"type":41,"tag":355,"props":728,"children":729},{},[730],{"type":47,"value":731},"must",{"type":47,"value":733}," replace collection equality assertions with\n",{"type":41,"tag":56,"props":735,"children":737},{"className":736},[],[738],{"type":47,"value":739},".deepEquals(expected)",{"type":47,"value":741},".\n",{"type":41,"tag":230,"props":743,"children":745},{"className":379,"code":744,"language":18,"meta":235,"style":235},"\u002F\u002F BEFORE (Matcher)\nexpect(myList, [1, 2, 3]);\n\n\u002F\u002F AFTER (Checks)\ncheck(myList).deepEquals([1, 2, 3]);\n",[746],{"type":41,"tag":56,"props":747,"children":748},{"__ignoreMap":235},[749,757,765,775,784],{"type":41,"tag":241,"props":750,"children":751},{"class":243,"line":244},[752],{"type":41,"tag":241,"props":753,"children":754},{},[755],{"type":47,"value":756},"\u002F\u002F BEFORE (Matcher)\n",{"type":41,"tag":241,"props":758,"children":759},{"class":243,"line":395},[760],{"type":41,"tag":241,"props":761,"children":762},{},[763],{"type":47,"value":764},"expect(myList, [1, 2, 3]);\n",{"type":41,"tag":241,"props":766,"children":768},{"class":243,"line":767},3,[769],{"type":41,"tag":241,"props":770,"children":772},{"emptyLinePlaceholder":771},true,[773],{"type":47,"value":774},"\n",{"type":41,"tag":241,"props":776,"children":778},{"class":243,"line":777},4,[779],{"type":41,"tag":241,"props":780,"children":781},{},[782],{"type":47,"value":783},"\u002F\u002F AFTER (Checks)\n",{"type":41,"tag":241,"props":785,"children":787},{"class":243,"line":786},5,[788],{"type":41,"tag":241,"props":789,"children":790},{},[791],{"type":47,"value":792},"check(myList).deepEquals([1, 2, 3]);\n",{"type":41,"tag":192,"props":794,"children":796},{"id":795},"_2-the-reason-parameter-is-now-because",[797,799,805,807],{"type":47,"value":798},"2. The ",{"type":41,"tag":56,"props":800,"children":802},{"className":801},[],[803],{"type":47,"value":804},"reason",{"type":47,"value":806}," Parameter is now ",{"type":41,"tag":56,"props":808,"children":810},{"className":809},[],[811],{"type":47,"value":812},"because",{"type":41,"tag":88,"props":814,"children":815},{},[816,852],{"type":41,"tag":92,"props":817,"children":818},{},[819,823,825,830,832,837,838],{"type":41,"tag":355,"props":820,"children":821},{},[822],{"type":47,"value":644},{"type":47,"value":824},": The explanation was passed as a trailing named\nargument ",{"type":41,"tag":56,"props":826,"children":828},{"className":827},[],[829],{"type":47,"value":804},{"type":47,"value":831}," to ",{"type":41,"tag":56,"props":833,"children":835},{"className":834},[],[836],{"type":47,"value":320},{"type":47,"value":228},{"type":41,"tag":230,"props":839,"children":841},{"className":379,"code":840,"language":18,"meta":235,"style":235},"expect(actual, expectation, reason: 'Explanation');\n",[842],{"type":41,"tag":56,"props":843,"children":844},{"__ignoreMap":235},[845],{"type":41,"tag":241,"props":846,"children":847},{"class":243,"line":244},[848],{"type":41,"tag":241,"props":849,"children":850},{},[851],{"type":47,"value":840},{"type":41,"tag":92,"props":853,"children":854},{},[855,859,861,866,868,873,875,880,882],{"type":41,"tag":355,"props":856,"children":857},{},[858],{"type":47,"value":676},{"type":47,"value":860},": The explanation is passed as the named argument\n",{"type":41,"tag":56,"props":862,"children":864},{"className":863},[],[865],{"type":47,"value":812},{"type":47,"value":867}," to the ",{"type":41,"tag":56,"props":869,"children":871},{"className":870},[],[872],{"type":47,"value":455},{"type":47,"value":874}," function ",{"type":41,"tag":710,"props":876,"children":877},{},[878],{"type":47,"value":879},"before",{"type":47,"value":881}," the actual subject:\n",{"type":41,"tag":230,"props":883,"children":885},{"className":379,"code":884,"language":18,"meta":235,"style":235},"check(because: 'Explanation', actual).expectation();\n",[886],{"type":41,"tag":56,"props":887,"children":888},{"__ignoreMap":235},[889],{"type":41,"tag":241,"props":890,"children":891},{"class":243,"line":244},[892],{"type":41,"tag":241,"props":893,"children":894},{},[895],{"type":47,"value":884},{"type":41,"tag":192,"props":897,"children":899},{"id":898},"_3-regular-expression-matching-matches-vs-matchespattern",[900,902,908,909,915],{"type":47,"value":901},"3. Regular Expression Matching (",{"type":41,"tag":56,"props":903,"children":905},{"className":904},[],[906],{"type":47,"value":907},"matches",{"type":47,"value":625},{"type":41,"tag":56,"props":910,"children":912},{"className":911},[],[913],{"type":47,"value":914},"matchesPattern",{"type":47,"value":633},{"type":41,"tag":88,"props":917,"children":918},{},[919,968,991],{"type":41,"tag":92,"props":920,"children":921},{},[922,926,928,934,936,942,944,950,952,958,960,966],{"type":41,"tag":355,"props":923,"children":924},{},[925],{"type":47,"value":644},{"type":47,"value":927},": The ",{"type":41,"tag":56,"props":929,"children":931},{"className":930},[],[932],{"type":47,"value":933},"matches(pattern)",{"type":47,"value":935}," matcher automatically converted\na ",{"type":41,"tag":56,"props":937,"children":939},{"className":938},[],[940],{"type":47,"value":941},"String",{"type":47,"value":943}," argument into a ",{"type":41,"tag":56,"props":945,"children":947},{"className":946},[],[948],{"type":47,"value":949},"RegExp",{"type":47,"value":951}," (e.g., ",{"type":41,"tag":56,"props":953,"children":955},{"className":954},[],[956],{"type":47,"value":957},"matches(r'\\d')",{"type":47,"value":959}," matched ",{"type":41,"tag":56,"props":961,"children":963},{"className":962},[],[964],{"type":47,"value":965},"'1'",{"type":47,"value":967},").",{"type":41,"tag":92,"props":969,"children":970},{},[971,975,976,982,984,989],{"type":41,"tag":355,"props":972,"children":973},{},[974],{"type":47,"value":676},{"type":47,"value":646},{"type":41,"tag":56,"props":977,"children":979},{"className":978},[],[980],{"type":47,"value":981},".matchesPattern(pattern)",{"type":47,"value":983}," treats a ",{"type":41,"tag":56,"props":985,"children":987},{"className":986},[],[988],{"type":47,"value":941},{"type":47,"value":990}," argument\nas a literal string pattern.",{"type":41,"tag":92,"props":992,"children":993},{},[994,998,1000,1005,1007],{"type":41,"tag":355,"props":995,"children":996},{},[997],{"type":47,"value":724},{"type":47,"value":999},": To match using a regular expression, you must explicitly\npass a ",{"type":41,"tag":56,"props":1001,"children":1003},{"className":1002},[],[1004],{"type":47,"value":949},{"type":47,"value":1006}," object:\n",{"type":41,"tag":230,"props":1008,"children":1010},{"className":379,"code":1009,"language":18,"meta":235,"style":235},"\u002F\u002F BEFORE (Matcher)\nexpect(someString, matches(r'\\d+'));\n\n\u002F\u002F AFTER (Checks)\ncheck(someString).matchesPattern(RegExp(r'\\d+'));\n",[1011],{"type":41,"tag":56,"props":1012,"children":1013},{"__ignoreMap":235},[1014,1021,1029,1036,1043],{"type":41,"tag":241,"props":1015,"children":1016},{"class":243,"line":244},[1017],{"type":41,"tag":241,"props":1018,"children":1019},{},[1020],{"type":47,"value":756},{"type":41,"tag":241,"props":1022,"children":1023},{"class":243,"line":395},[1024],{"type":41,"tag":241,"props":1025,"children":1026},{},[1027],{"type":47,"value":1028},"expect(someString, matches(r'\\d+'));\n",{"type":41,"tag":241,"props":1030,"children":1031},{"class":243,"line":767},[1032],{"type":41,"tag":241,"props":1033,"children":1034},{"emptyLinePlaceholder":771},[1035],{"type":47,"value":774},{"type":41,"tag":241,"props":1037,"children":1038},{"class":243,"line":777},[1039],{"type":41,"tag":241,"props":1040,"children":1041},{},[1042],{"type":47,"value":783},{"type":41,"tag":241,"props":1044,"children":1045},{"class":243,"line":786},[1046],{"type":41,"tag":241,"props":1047,"children":1048},{},[1049],{"type":47,"value":1050},"check(someString).matchesPattern(RegExp(r'\\d+'));\n",{"type":41,"tag":192,"props":1052,"children":1054},{"id":1053},"_4-property-extraction-typematcherhaving-vs-has",[1055,1057,1063,1064,1070],{"type":47,"value":1056},"4. Property Extraction (",{"type":41,"tag":56,"props":1058,"children":1060},{"className":1059},[],[1061],{"type":47,"value":1062},"TypeMatcher.having",{"type":47,"value":625},{"type":41,"tag":56,"props":1065,"children":1067},{"className":1066},[],[1068],{"type":47,"value":1069},".has",{"type":47,"value":633},{"type":41,"tag":88,"props":1072,"children":1073},{},[1074,1104],{"type":41,"tag":92,"props":1075,"children":1076},{},[1077,1081,1083,1089,1090],{"type":41,"tag":355,"props":1078,"children":1079},{},[1080],{"type":47,"value":644},{"type":47,"value":1082},": Chained field\u002Fproperty expectations used\n",{"type":41,"tag":56,"props":1084,"children":1086},{"className":1085},[],[1087],{"type":47,"value":1088},"TypeMatcher.having(feature, description, matcher)",{"type":47,"value":228},{"type":41,"tag":230,"props":1091,"children":1093},{"className":379,"code":1092,"language":18,"meta":235,"style":235},"expect(actual, isA\u003CPerson>().having((p) => p.name, 'name', startsWith('A')));\n",[1094],{"type":41,"tag":56,"props":1095,"children":1096},{"__ignoreMap":235},[1097],{"type":41,"tag":241,"props":1098,"children":1099},{"class":243,"line":244},[1100],{"type":41,"tag":241,"props":1101,"children":1102},{},[1103],{"type":47,"value":1092},{"type":41,"tag":92,"props":1105,"children":1106},{},[1107,1111,1112,1118,1120,1126,1128,1133,1135],{"type":41,"tag":355,"props":1108,"children":1109},{},[1110],{"type":47,"value":676},{"type":47,"value":927},{"type":41,"tag":56,"props":1113,"children":1115},{"className":1114},[],[1116],{"type":47,"value":1117},".has(feature, description)",{"type":47,"value":1119}," extension is\navailable on all ",{"type":41,"tag":56,"props":1121,"children":1123},{"className":1122},[],[1124],{"type":47,"value":1125},"Subject",{"type":47,"value":1127},"s, takes one fewer argument, and returns a new\n",{"type":41,"tag":56,"props":1129,"children":1131},{"className":1130},[],[1132],{"type":47,"value":1125},{"type":47,"value":1134}," representing that property. You chain expectations directly off\nit:\n",{"type":41,"tag":230,"props":1136,"children":1138},{"className":379,"code":1137,"language":18,"meta":235,"style":235},"check(actual).isA\u003CPerson>().has((p) => p.name, 'name').startsWith('A');\n",[1139],{"type":41,"tag":56,"props":1140,"children":1141},{"__ignoreMap":235},[1142],{"type":41,"tag":241,"props":1143,"children":1144},{"class":243,"line":244},[1145],{"type":41,"tag":241,"props":1146,"children":1147},{},[1148],{"type":47,"value":1137},{"type":41,"tag":192,"props":1150,"children":1152},{"id":1151},"_5-synchronous-vs-asynchronous-throws",[1153,1155],{"type":47,"value":1154},"5. Synchronous vs. Asynchronous ",{"type":41,"tag":56,"props":1156,"children":1158},{"className":1157},[],[1159],{"type":47,"value":1160},"throws",{"type":41,"tag":88,"props":1162,"children":1163},{},[1164,1201],{"type":41,"tag":92,"props":1165,"children":1166},{},[1167,1171,1173,1178,1180,1186,1188,1193,1195,1200],{"type":41,"tag":355,"props":1168,"children":1169},{},[1170],{"type":47,"value":644},{"type":47,"value":1172},": In ",{"type":41,"tag":56,"props":1174,"children":1176},{"className":1175},[],[1177],{"type":47,"value":61},{"type":47,"value":1179},", ",{"type":41,"tag":56,"props":1181,"children":1183},{"className":1182},[],[1184],{"type":47,"value":1185},"throwsA",{"type":47,"value":1187}," behaved similarly for both\nsynchronous closures and asynchronous futures when wrapped in ",{"type":41,"tag":56,"props":1189,"children":1191},{"className":1190},[],[1192],{"type":47,"value":320},{"type":47,"value":1194}," or\n",{"type":41,"tag":56,"props":1196,"children":1198},{"className":1197},[],[1199],{"type":47,"value":328},{"type":47,"value":470},{"type":41,"tag":92,"props":1202,"children":1203},{},[1204,1208,1209,1215,1217],{"type":41,"tag":355,"props":1205,"children":1206},{},[1207],{"type":47,"value":676},{"type":47,"value":927},{"type":41,"tag":56,"props":1210,"children":1212},{"className":1211},[],[1213],{"type":47,"value":1214},".throws\u003CE>()",{"type":47,"value":1216}," expectation behaves differently and\nhas different return types depending on whether the subject is synchronous or\nasynchronous:\n",{"type":41,"tag":88,"props":1218,"children":1219},{},[1220,1321,1397],{"type":41,"tag":92,"props":1221,"children":1222},{},[1223,1228,1230,1236,1238,1243,1245,1251,1253,1258,1260,1265,1266],{"type":41,"tag":355,"props":1224,"children":1225},{},[1226],{"type":47,"value":1227},"Synchronous",{"type":47,"value":1229}," (",{"type":41,"tag":56,"props":1231,"children":1233},{"className":1232},[],[1234],{"type":47,"value":1235},"Subject\u003CT Function()>",{"type":47,"value":1237},"): ",{"type":41,"tag":56,"props":1239,"children":1241},{"className":1240},[],[1242],{"type":47,"value":1214},{"type":47,"value":1244}," returns a\n",{"type":41,"tag":56,"props":1246,"children":1248},{"className":1247},[],[1249],{"type":47,"value":1250},"Subject\u003CE>",{"type":47,"value":1252}," synchronously. This ",{"type":41,"tag":355,"props":1254,"children":1255},{},[1256],{"type":47,"value":1257},"does not",{"type":47,"value":1259}," accept a callback argument!\nYou chain or cascade expectations directly off the returned ",{"type":41,"tag":56,"props":1261,"children":1263},{"className":1262},[],[1264],{"type":47,"value":1250},{"type":47,"value":228},{"type":41,"tag":230,"props":1267,"children":1269},{"className":379,"code":1268,"language":18,"meta":235,"style":235},"\u002F\u002F YES (Synchronous chaining)\ncheck(() => triggerSyncError()).throws\u003CArgumentError>()\n  ..has((e) => e.message, 'message').equals('invalid input');\n\n\u002F\u002F NO (Passing a callback to sync throws will cause a compiler error!)\ncheck(() => triggerSync\").throws\u003CArgumentError>((it) => ...); \u002F\u002F ERROR!\n",[1270],{"type":41,"tag":56,"props":1271,"children":1272},{"__ignoreMap":235},[1273,1281,1289,1297,1304,1312],{"type":41,"tag":241,"props":1274,"children":1275},{"class":243,"line":244},[1276],{"type":41,"tag":241,"props":1277,"children":1278},{},[1279],{"type":47,"value":1280},"\u002F\u002F YES (Synchronous chaining)\n",{"type":41,"tag":241,"props":1282,"children":1283},{"class":243,"line":395},[1284],{"type":41,"tag":241,"props":1285,"children":1286},{},[1287],{"type":47,"value":1288},"check(() => triggerSyncError()).throws\u003CArgumentError>()\n",{"type":41,"tag":241,"props":1290,"children":1291},{"class":243,"line":767},[1292],{"type":41,"tag":241,"props":1293,"children":1294},{},[1295],{"type":47,"value":1296},"  ..has((e) => e.message, 'message').equals('invalid input');\n",{"type":41,"tag":241,"props":1298,"children":1299},{"class":243,"line":777},[1300],{"type":41,"tag":241,"props":1301,"children":1302},{"emptyLinePlaceholder":771},[1303],{"type":47,"value":774},{"type":41,"tag":241,"props":1305,"children":1306},{"class":243,"line":786},[1307],{"type":41,"tag":241,"props":1308,"children":1309},{},[1310],{"type":47,"value":1311},"\u002F\u002F NO (Passing a callback to sync throws will cause a compiler error!)\n",{"type":41,"tag":241,"props":1313,"children":1315},{"class":243,"line":1314},6,[1316],{"type":41,"tag":241,"props":1317,"children":1318},{},[1319],{"type":47,"value":1320},"check(() => triggerSync\").throws\u003CArgumentError>((it) => ...); \u002F\u002F ERROR!\n",{"type":41,"tag":92,"props":1322,"children":1323},{},[1324,1329,1330,1336,1337,1342,1344,1350,1352,1357,1359,1364,1366],{"type":41,"tag":355,"props":1325,"children":1326},{},[1327],{"type":47,"value":1328},"Asynchronous",{"type":47,"value":1229},{"type":41,"tag":56,"props":1331,"children":1333},{"className":1332},[],[1334],{"type":47,"value":1335},"Subject\u003CFuture\u003CT>>",{"type":47,"value":1237},{"type":41,"tag":56,"props":1338,"children":1340},{"className":1339},[],[1341],{"type":47,"value":1214},{"type":47,"value":1343}," returns\n",{"type":41,"tag":56,"props":1345,"children":1347},{"className":1346},[],[1348],{"type":47,"value":1349},"Future\u003Cvoid>",{"type":47,"value":1351},". Because you cannot chain directly off a ",{"type":41,"tag":56,"props":1353,"children":1355},{"className":1354},[],[1356],{"type":47,"value":1349},{"type":47,"value":1358},", this\n",{"type":41,"tag":355,"props":1360,"children":1361},{},[1362],{"type":47,"value":1363},"requires",{"type":47,"value":1365}," an inspection callback:\n",{"type":41,"tag":230,"props":1367,"children":1369},{"className":379,"code":1368,"language":18,"meta":235,"style":235},"\u002F\u002F YES (Asynchronous callback)\nawait check(triggerAsyncError()).throws\u003CArgumentError>((it) => it\n  ..has((e) => e.message, 'message').equals('invalid input'));\n",[1370],{"type":41,"tag":56,"props":1371,"children":1372},{"__ignoreMap":235},[1373,1381,1389],{"type":41,"tag":241,"props":1374,"children":1375},{"class":243,"line":244},[1376],{"type":41,"tag":241,"props":1377,"children":1378},{},[1379],{"type":47,"value":1380},"\u002F\u002F YES (Asynchronous callback)\n",{"type":41,"tag":241,"props":1382,"children":1383},{"class":243,"line":395},[1384],{"type":41,"tag":241,"props":1385,"children":1386},{},[1387],{"type":47,"value":1388},"await check(triggerAsyncError()).throws\u003CArgumentError>((it) => it\n",{"type":41,"tag":241,"props":1390,"children":1391},{"class":243,"line":767},[1392],{"type":41,"tag":241,"props":1393,"children":1394},{},[1395],{"type":47,"value":1396},"  ..has((e) => e.message, 'message').equals('invalid input'));\n",{"type":41,"tag":92,"props":1398,"children":1399},{},[1400,1405,1407,1412,1414,1420,1422,1427],{"type":41,"tag":355,"props":1401,"children":1402},{},[1403],{"type":47,"value":1404},"Crucial Pitfall",{"type":47,"value":1406},": Trying to chain expectations directly after an awaited\nasynchronous ",{"type":41,"tag":56,"props":1408,"children":1410},{"className":1409},[],[1411],{"type":47,"value":1214},{"type":47,"value":1413}," (e.g.,\n",{"type":41,"tag":56,"props":1415,"children":1417},{"className":1416},[],[1418],{"type":47,"value":1419},"await check(future).throws\u003CE>().equals(...)",{"type":47,"value":1421},") will fail to compile\nbecause it returns ",{"type":41,"tag":56,"props":1423,"children":1425},{"className":1424},[],[1426],{"type":47,"value":1349},{"type":47,"value":470},{"type":41,"tag":192,"props":1429,"children":1431},{"id":1430},"_6-regexp-pattern-equality",[1432],{"type":47,"value":1433},"6. RegExp \u002F Pattern Equality",{"type":41,"tag":88,"props":1435,"children":1436},{},[1437,1465,1510],{"type":41,"tag":92,"props":1438,"children":1439},{},[1440,1444,1445,1450,1451,1457,1463],{"type":41,"tag":355,"props":1441,"children":1442},{},[1443],{"type":47,"value":644},{"type":47,"value":1172},{"type":41,"tag":56,"props":1446,"children":1448},{"className":1447},[],[1449],{"type":47,"value":61},{"type":47,"value":1179},{"type":41,"tag":56,"props":1452,"children":1454},{"className":1453},[],[1455],{"type":47,"value":1456},"expect(myPattern,",{"type":41,"tag":56,"props":1458,"children":1460},{"className":1459},[],[1461],{"type":47,"value":1462},"equals(RegExp('Hello')))",{"type":47,"value":1464}," worked because the matcher comparison rules\nhandled RegExp instances.",{"type":41,"tag":92,"props":1466,"children":1467},{},[1468,1472,1473,1479,1481,1487,1489,1494,1496,1501,1503,1508],{"type":41,"tag":355,"props":1469,"children":1470},{},[1471],{"type":47,"value":676},{"type":47,"value":646},{"type":41,"tag":56,"props":1474,"children":1476},{"className":1475},[],[1477],{"type":47,"value":1478},".equals()",{"type":47,"value":1480}," uses strict Dart ",{"type":41,"tag":56,"props":1482,"children":1484},{"className":1483},[],[1485],{"type":47,"value":1486},"==",{"type":47,"value":1488}," equality. Since separate\n",{"type":41,"tag":56,"props":1490,"children":1492},{"className":1491},[],[1493],{"type":47,"value":949},{"type":47,"value":1495}," instances do not satisfy ",{"type":41,"tag":56,"props":1497,"children":1499},{"className":1498},[],[1500],{"type":47,"value":1486},{"type":47,"value":1502},", using ",{"type":41,"tag":56,"props":1504,"children":1506},{"className":1505},[],[1507],{"type":47,"value":1478},{"type":47,"value":1509}," will fail at runtime.",{"type":41,"tag":92,"props":1511,"children":1512},{},[1513,1517,1519,1525,1527,1532,1534],{"type":41,"tag":355,"props":1514,"children":1515},{},[1516],{"type":47,"value":724},{"type":47,"value":1518},": Use ",{"type":41,"tag":56,"props":1520,"children":1522},{"className":1521},[],[1523],{"type":47,"value":1524},".isA\u003CRegExp>()",{"type":47,"value":1526}," type refinement along with cascades to\nassert on the properties of the ",{"type":41,"tag":56,"props":1528,"children":1530},{"className":1529},[],[1531],{"type":47,"value":949},{"type":47,"value":1533}," object explicitly:\n",{"type":41,"tag":230,"props":1535,"children":1537},{"className":379,"code":1536,"language":18,"meta":235,"style":235},"check(myPattern).isA\u003CRegExp>()\n  ..has((r) => r.pattern, 'pattern').equals('Hello')\n  ..has((r) => r.isMultiLine, 'isMultiLine').isTrue();\n",[1538],{"type":41,"tag":56,"props":1539,"children":1540},{"__ignoreMap":235},[1541,1549,1557],{"type":41,"tag":241,"props":1542,"children":1543},{"class":243,"line":244},[1544],{"type":41,"tag":241,"props":1545,"children":1546},{},[1547],{"type":47,"value":1548},"check(myPattern).isA\u003CRegExp>()\n",{"type":41,"tag":241,"props":1550,"children":1551},{"class":243,"line":395},[1552],{"type":41,"tag":241,"props":1553,"children":1554},{},[1555],{"type":47,"value":1556},"  ..has((r) => r.pattern, 'pattern').equals('Hello')\n",{"type":41,"tag":241,"props":1558,"children":1559},{"class":243,"line":767},[1560],{"type":41,"tag":241,"props":1561,"children":1562},{},[1563],{"type":47,"value":1564},"  ..has((r) => r.isMultiLine, 'isMultiLine').isTrue();\n",{"type":41,"tag":192,"props":1566,"children":1568},{"id":1567},"_7-strict-nullable-boolean-safety-bool-fields",[1569,1571,1577],{"type":47,"value":1570},"7. Strict Nullable Boolean Safety (",{"type":41,"tag":56,"props":1572,"children":1574},{"className":1573},[],[1575],{"type":47,"value":1576},"bool?",{"type":47,"value":1578}," fields)",{"type":41,"tag":88,"props":1580,"children":1581},{},[1582,1612,1657],{"type":41,"tag":92,"props":1583,"children":1584},{},[1585,1589,1591,1597,1598,1604,1606,1611],{"type":41,"tag":355,"props":1586,"children":1587},{},[1588],{"type":47,"value":644},{"type":47,"value":1590},": Statically, ",{"type":41,"tag":56,"props":1592,"children":1594},{"className":1593},[],[1595],{"type":47,"value":1596},"isTrue",{"type":47,"value":442},{"type":41,"tag":56,"props":1599,"children":1601},{"className":1600},[],[1602],{"type":47,"value":1603},"isFalse",{"type":47,"value":1605}," performed loose\ndynamic checks at runtime, which silently accepted nullable booleans (",{"type":41,"tag":56,"props":1607,"children":1609},{"className":1608},[],[1610],{"type":47,"value":1576},{"type":47,"value":967},{"type":41,"tag":92,"props":1613,"children":1614},{},[1615,1619,1620,1626,1627,1633,1635,1641,1643,1648,1650,1656],{"type":41,"tag":355,"props":1616,"children":1617},{},[1618],{"type":47,"value":676},{"type":47,"value":646},{"type":41,"tag":56,"props":1621,"children":1623},{"className":1622},[],[1624],{"type":47,"value":1625},".isTrue()",{"type":47,"value":442},{"type":41,"tag":56,"props":1628,"children":1630},{"className":1629},[],[1631],{"type":47,"value":1632},".isFalse()",{"type":47,"value":1634}," are defined strictly on\n",{"type":41,"tag":56,"props":1636,"children":1638},{"className":1637},[],[1639],{"type":47,"value":1640},"Subject\u003Cbool>",{"type":47,"value":1642}," (non-nullable). They are ",{"type":41,"tag":355,"props":1644,"children":1645},{},[1646],{"type":47,"value":1647},"not",{"type":47,"value":1649}," available on ",{"type":41,"tag":56,"props":1651,"children":1653},{"className":1652},[],[1654],{"type":47,"value":1655},"Subject\u003Cbool?>",{"type":47,"value":470},{"type":41,"tag":92,"props":1658,"children":1659},{},[1660,1664,1666,1671,1673,1679,1681,1687,1689,1695,1697],{"type":41,"tag":355,"props":1661,"children":1662},{},[1663],{"type":47,"value":724},{"type":47,"value":1665},": For fields declared as ",{"type":41,"tag":56,"props":1667,"children":1669},{"className":1668},[],[1670],{"type":47,"value":1576},{"type":47,"value":1672},", you must either refine the\nsubject (e.g., ",{"type":41,"tag":56,"props":1674,"children":1676},{"className":1675},[],[1677],{"type":47,"value":1678},".isNotNull().isTrue()",{"type":47,"value":1680},") or simply use ",{"type":41,"tag":56,"props":1682,"children":1684},{"className":1683},[],[1685],{"type":47,"value":1686},".equals(true)",{"type":47,"value":1688}," and\n",{"type":41,"tag":56,"props":1690,"children":1692},{"className":1691},[],[1693],{"type":47,"value":1694},".equals(false)",{"type":47,"value":1696}," which are generic and work on all types:\n",{"type":41,"tag":230,"props":1698,"children":1700},{"className":379,"code":1699,"language":18,"meta":235,"style":235},"\u002F\u002F If options.flagOutdated is a bool?\ncheck(options.flagOutdated).equals(true);\ncheck(options.flagOutdated).equals(false);\n",[1701],{"type":41,"tag":56,"props":1702,"children":1703},{"__ignoreMap":235},[1704,1712,1720],{"type":41,"tag":241,"props":1705,"children":1706},{"class":243,"line":244},[1707],{"type":41,"tag":241,"props":1708,"children":1709},{},[1710],{"type":47,"value":1711},"\u002F\u002F If options.flagOutdated is a bool?\n",{"type":41,"tag":241,"props":1713,"children":1714},{"class":243,"line":395},[1715],{"type":41,"tag":241,"props":1716,"children":1717},{},[1718],{"type":47,"value":1719},"check(options.flagOutdated).equals(true);\n",{"type":41,"tag":241,"props":1721,"children":1722},{"class":243,"line":767},[1723],{"type":41,"tag":241,"props":1724,"children":1725},{},[1726],{"type":47,"value":1727},"check(options.flagOutdated).equals(false);\n",{"type":41,"tag":192,"props":1729,"children":1731},{"id":1730},"_8-map-key-containment-containskey-vs-contains",[1732,1734,1740,1741,1747],{"type":47,"value":1733},"8. Map Key Containment (",{"type":41,"tag":56,"props":1735,"children":1737},{"className":1736},[],[1738],{"type":47,"value":1739},"containsKey",{"type":47,"value":625},{"type":41,"tag":56,"props":1742,"children":1744},{"className":1743},[],[1745],{"type":47,"value":1746},"contains",{"type":47,"value":633},{"type":41,"tag":88,"props":1749,"children":1750},{},[1751,1781,1806],{"type":41,"tag":92,"props":1752,"children":1753},{},[1754,1758,1759,1764,1765,1771,1773,1779],{"type":41,"tag":355,"props":1755,"children":1756},{},[1757],{"type":47,"value":644},{"type":47,"value":1172},{"type":41,"tag":56,"props":1760,"children":1762},{"className":1761},[],[1763],{"type":47,"value":61},{"type":47,"value":1179},{"type":41,"tag":56,"props":1766,"children":1768},{"className":1767},[],[1769],{"type":47,"value":1770},"contains(key)",{"type":47,"value":1772}," was used to assert\nthat a ",{"type":41,"tag":56,"props":1774,"children":1776},{"className":1775},[],[1777],{"type":47,"value":1778},"Map",{"type":47,"value":1780}," contained a specific key.",{"type":41,"tag":92,"props":1782,"children":1783},{},[1784,1788,1790,1796,1798,1804],{"type":41,"tag":355,"props":1785,"children":1786},{},[1787],{"type":47,"value":676},{"type":47,"value":1789},": Calling ",{"type":41,"tag":56,"props":1791,"children":1793},{"className":1792},[],[1794],{"type":47,"value":1795},".contains(...)",{"type":47,"value":1797}," on a ",{"type":41,"tag":56,"props":1799,"children":1801},{"className":1800},[],[1802],{"type":47,"value":1803},"Subject\u003CMap>",{"type":47,"value":1805}," is not\ndefined and will fail compilation.",{"type":41,"tag":92,"props":1807,"children":1808},{},[1809,1813,1815,1821,1823],{"type":41,"tag":355,"props":1810,"children":1811},{},[1812],{"type":47,"value":724},{"type":47,"value":1814},": Use the map-specific ",{"type":41,"tag":56,"props":1816,"children":1818},{"className":1817},[],[1819],{"type":47,"value":1820},".containsKey(key)",{"type":47,"value":1822}," matcher instead:\n",{"type":41,"tag":230,"props":1824,"children":1826},{"className":379,"code":1825,"language":18,"meta":235,"style":235},"\u002F\u002F BEFORE (Matcher)\nexpect(myMap, contains('my_key'));\n\n\u002F\u002F AFTER (Checks)\ncheck(myMap).containsKey('my_key');\n",[1827],{"type":41,"tag":56,"props":1828,"children":1829},{"__ignoreMap":235},[1830,1837,1845,1852,1859],{"type":41,"tag":241,"props":1831,"children":1832},{"class":243,"line":244},[1833],{"type":41,"tag":241,"props":1834,"children":1835},{},[1836],{"type":47,"value":756},{"type":41,"tag":241,"props":1838,"children":1839},{"class":243,"line":395},[1840],{"type":41,"tag":241,"props":1841,"children":1842},{},[1843],{"type":47,"value":1844},"expect(myMap, contains('my_key'));\n",{"type":41,"tag":241,"props":1846,"children":1847},{"class":243,"line":767},[1848],{"type":41,"tag":241,"props":1849,"children":1850},{"emptyLinePlaceholder":771},[1851],{"type":47,"value":774},{"type":41,"tag":241,"props":1853,"children":1854},{"class":243,"line":777},[1855],{"type":41,"tag":241,"props":1856,"children":1857},{},[1858],{"type":47,"value":783},{"type":41,"tag":241,"props":1860,"children":1861},{"class":243,"line":786},[1862],{"type":41,"tag":241,"props":1863,"children":1864},{},[1865],{"type":47,"value":1866},"check(myMap).containsKey('my_key');\n",{"type":41,"tag":192,"props":1868,"children":1870},{"id":1869},"_9-explicit-generic-parameters-for-extension-types",[1871],{"type":47,"value":1872},"9. Explicit Generic Parameters for Extension Types",{"type":41,"tag":88,"props":1874,"children":1875},{},[1876,1892,1983],{"type":41,"tag":92,"props":1877,"children":1878},{},[1879,1883,1884,1890],{"type":41,"tag":355,"props":1880,"children":1881},{},[1882],{"type":47,"value":644},{"type":47,"value":646},{"type":41,"tag":56,"props":1885,"children":1887},{"className":1886},[],[1888],{"type":47,"value":1889},"expect(extensionTypeConst, 3)",{"type":47,"value":1891}," compiled because of loose\ndynamic equality.",{"type":41,"tag":92,"props":1893,"children":1894},{},[1895,1899,1901,1907,1909,1915,1917,1923,1925,1931,1932,1938,1940,1946,1948,1953,1955,1960,1962,1968,1970,1975,1977,1982],{"type":41,"tag":355,"props":1896,"children":1897},{},[1898],{"type":47,"value":676},{"type":47,"value":1900},": If ",{"type":41,"tag":56,"props":1902,"children":1904},{"className":1903},[],[1905],{"type":47,"value":1906},"QrEciValue",{"type":47,"value":1908}," is an extension type representation of ",{"type":41,"tag":56,"props":1910,"children":1912},{"className":1911},[],[1913],{"type":47,"value":1914},"int",{"type":47,"value":1916},"\n(e.g., ",{"type":41,"tag":56,"props":1918,"children":1920},{"className":1919},[],[1921],{"type":47,"value":1922},"extension type const QrEciValue(int value) implements int",{"type":47,"value":1924},"), calling\n",{"type":41,"tag":56,"props":1926,"children":1928},{"className":1927},[],[1929],{"type":47,"value":1930},".equals(3)",{"type":47,"value":1797},{"type":41,"tag":56,"props":1933,"children":1935},{"className":1934},[],[1936],{"type":47,"value":1937},"Subject\u003CQrEciValue>",{"type":47,"value":1939}," fails because ",{"type":41,"tag":56,"props":1941,"children":1943},{"className":1942},[],[1944],{"type":47,"value":1945},"3",{"type":47,"value":1947}," (an ",{"type":41,"tag":56,"props":1949,"children":1951},{"className":1950},[],[1952],{"type":47,"value":1914},{"type":47,"value":1954},") is not\nassignable to ",{"type":41,"tag":56,"props":1956,"children":1958},{"className":1957},[],[1959],{"type":47,"value":1906},{"type":47,"value":1961},". Casting with ",{"type":41,"tag":56,"props":1963,"children":1965},{"className":1964},[],[1966],{"type":47,"value":1967},"as int",{"type":47,"value":1969}," will trigger an\n\"Unnecessary cast\" static analysis warning because ",{"type":41,"tag":56,"props":1971,"children":1973},{"className":1972},[],[1974],{"type":47,"value":1906},{"type":47,"value":1976}," statically\nimplements ",{"type":41,"tag":56,"props":1978,"children":1980},{"className":1979},[],[1981],{"type":47,"value":1914},{"type":47,"value":470},{"type":41,"tag":92,"props":1984,"children":1985},{},[1986,1990,1992,1997,1999],{"type":41,"tag":355,"props":1987,"children":1988},{},[1989],{"type":47,"value":724},{"type":47,"value":1991},": Explicitly specify the generic type parameter on the ",{"type":41,"tag":56,"props":1993,"children":1995},{"className":1994},[],[1996],{"type":47,"value":455},{"type":47,"value":1998},"\nfunction to force checks to treat it as the primitive type:\n",{"type":41,"tag":230,"props":2000,"children":2002},{"className":379,"code":2001,"language":18,"meta":235,"style":235},"\u002F\u002F YES (Type-safe and warning-free)\ncheck\u003Cint>(QrEciValue.iso8859_1).equals(3);\n",[2003],{"type":41,"tag":56,"props":2004,"children":2005},{"__ignoreMap":235},[2006,2014],{"type":41,"tag":241,"props":2007,"children":2008},{"class":243,"line":244},[2009],{"type":41,"tag":241,"props":2010,"children":2011},{},[2012],{"type":47,"value":2013},"\u002F\u002F YES (Type-safe and warning-free)\n",{"type":41,"tag":241,"props":2015,"children":2016},{"class":243,"line":395},[2017],{"type":41,"tag":241,"props":2018,"children":2019},{},[2020],{"type":47,"value":2021},"check\u003Cint>(QrEciValue.iso8859_1).equals(3);\n",{"type":41,"tag":192,"props":2023,"children":2025},{"id":2024},"_10-dynamic-map-json-lookup-casting",[2026],{"type":47,"value":2027},"10. Dynamic Map \u002F JSON Lookup Casting",{"type":41,"tag":88,"props":2029,"children":2030},{},[2031,2048,2077],{"type":41,"tag":92,"props":2032,"children":2033},{},[2034,2038,2040,2046],{"type":41,"tag":355,"props":2035,"children":2036},{},[2037],{"type":47,"value":644},{"type":47,"value":2039},": Loose dynamic typing allowed comparing nested json lookups\nstatically typed as ",{"type":41,"tag":56,"props":2041,"children":2043},{"className":2042},[],[2044],{"type":47,"value":2045},"dynamic",{"type":47,"value":2047}," directly against lists or maps.",{"type":41,"tag":92,"props":2049,"children":2050},{},[2051,2055,2057,2062,2063,2069,2070,2076],{"type":41,"tag":355,"props":2052,"children":2053},{},[2054],{"type":47,"value":676},{"type":47,"value":2056},": Strict type safety rejects the implicit assignment of\n",{"type":41,"tag":56,"props":2058,"children":2060},{"className":2059},[],[2061],{"type":47,"value":2045},{"type":47,"value":831},{"type":41,"tag":56,"props":2064,"children":2066},{"className":2065},[],[2067],{"type":47,"value":2068},"Iterable\u003CObject?>",{"type":47,"value":220},{"type":41,"tag":56,"props":2071,"children":2073},{"className":2072},[],[2074],{"type":47,"value":2075},".deepEquals(...)",{"type":47,"value":470},{"type":41,"tag":92,"props":2078,"children":2079},{},[2080,2084,2086,2092,2093,2098,2099],{"type":41,"tag":355,"props":2081,"children":2082},{},[2083],{"type":47,"value":724},{"type":47,"value":2085},": Statically cast the dynamic lookup result to a ",{"type":41,"tag":56,"props":2087,"children":2089},{"className":2088},[],[2090],{"type":47,"value":2091},"List",{"type":47,"value":322},{"type":41,"tag":56,"props":2094,"children":2096},{"className":2095},[],[2097],{"type":47,"value":1778},{"type":47,"value":228},{"type":41,"tag":230,"props":2100,"children":2102},{"className":379,"code":2101,"language":18,"meta":235,"style":235},"\u002F\u002F YES (Explicit cast to List)\ncheck(myIterable).deepEquals(json['data']['items'] as List);\n",[2103],{"type":41,"tag":56,"props":2104,"children":2105},{"__ignoreMap":235},[2106,2114],{"type":41,"tag":241,"props":2107,"children":2108},{"class":243,"line":244},[2109],{"type":41,"tag":241,"props":2110,"children":2111},{},[2112],{"type":47,"value":2113},"\u002F\u002F YES (Explicit cast to List)\n",{"type":41,"tag":241,"props":2115,"children":2116},{"class":243,"line":395},[2117],{"type":41,"tag":241,"props":2118,"children":2119},{},[2120],{"type":47,"value":2121},"check(myIterable).deepEquals(json['data']['items'] as List);\n",{"type":41,"tag":157,"props":2123,"children":2124},{},[],{"type":41,"tag":81,"props":2126,"children":2128},{"id":2127},"matcher-to-checks-mapping-table",[2129],{"type":47,"value":128},{"type":41,"tag":50,"props":2131,"children":2132},{},[2133],{"type":47,"value":2134},"Use this table as a quick reference for direct matcher replacements:",{"type":41,"tag":2136,"props":2137,"children":2138},"table",{},[2139,2163],{"type":41,"tag":2140,"props":2141,"children":2142},"thead",{},[2143],{"type":41,"tag":2144,"props":2145,"children":2146},"tr",{},[2147,2153,2158],{"type":41,"tag":2148,"props":2149,"children":2151},"th",{"align":2150},"left",[2152],{"type":47,"value":644},{"type":41,"tag":2148,"props":2154,"children":2155},{"align":2150},[2156],{"type":47,"value":2157},"Package Checks Equivalent",{"type":41,"tag":2148,"props":2159,"children":2160},{"align":2150},[2161],{"type":47,"value":2162},"Notes",{"type":41,"tag":2164,"props":2165,"children":2166},"tbody",{},[2167,2201,2230,2256,2282,2314,2345,2371,2402,2435,2462,2488,2513,2539,2564,2588,2612,2653,2690,2716,2741,2766,2791,2816],{"type":41,"tag":2144,"props":2168,"children":2169},{},[2170,2179,2188],{"type":41,"tag":2171,"props":2172,"children":2173},"td",{"align":2150},[2174],{"type":41,"tag":56,"props":2175,"children":2177},{"className":2176},[],[2178],{"type":47,"value":652},{"type":41,"tag":2171,"props":2180,"children":2181},{"align":2150},[2182],{"type":41,"tag":56,"props":2183,"children":2185},{"className":2184},[],[2186],{"type":47,"value":2187},"check(actual).equals(expected)",{"type":41,"tag":2171,"props":2189,"children":2190},{"align":2150},[2191,2193,2199],{"type":47,"value":2192},"Use ",{"type":41,"tag":56,"props":2194,"children":2196},{"className":2195},[],[2197],{"type":47,"value":2198},".deepEquals",{"type":47,"value":2200}," for collections!",{"type":41,"tag":2144,"props":2202,"children":2203},{},[2204,2212,2220],{"type":41,"tag":2171,"props":2205,"children":2206},{"align":2150},[2207],{"type":41,"tag":56,"props":2208,"children":2210},{"className":2209},[],[2211],{"type":47,"value":659},{"type":41,"tag":2171,"props":2213,"children":2214},{"align":2150},[2215],{"type":41,"tag":56,"props":2216,"children":2218},{"className":2217},[],[2219],{"type":47,"value":2187},{"type":41,"tag":2171,"props":2221,"children":2222},{"align":2150},[2223,2224,2229],{"type":47,"value":2192},{"type":41,"tag":56,"props":2225,"children":2227},{"className":2226},[],[2228],{"type":47,"value":2198},{"type":47,"value":2200},{"type":41,"tag":2144,"props":2231,"children":2232},{},[2233,2242,2251],{"type":41,"tag":2171,"props":2234,"children":2235},{"align":2150},[2236],{"type":41,"tag":56,"props":2237,"children":2239},{"className":2238},[],[2240],{"type":47,"value":2241},"isA\u003CT>()",{"type":41,"tag":2171,"props":2243,"children":2244},{"align":2150},[2245],{"type":41,"tag":56,"props":2246,"children":2248},{"className":2247},[],[2249],{"type":47,"value":2250},"check(actual).isA\u003CT>()",{"type":41,"tag":2171,"props":2252,"children":2253},{"align":2150},[2254],{"type":47,"value":2255},"Chaining is supported directly",{"type":41,"tag":2144,"props":2257,"children":2258},{},[2259,2268,2277],{"type":41,"tag":2171,"props":2260,"children":2261},{"align":2150},[2262],{"type":41,"tag":56,"props":2263,"children":2265},{"className":2264},[],[2266],{"type":47,"value":2267},"same(expected)",{"type":41,"tag":2171,"props":2269,"children":2270},{"align":2150},[2271],{"type":41,"tag":56,"props":2272,"children":2274},{"className":2273},[],[2275],{"type":47,"value":2276},"check(actual).identicalTo(expected)",{"type":41,"tag":2171,"props":2278,"children":2279},{"align":2150},[2280],{"type":47,"value":2281},"Verifies identity",{"type":41,"tag":2144,"props":2283,"children":2284},{},[2285,2294,2303],{"type":41,"tag":2171,"props":2286,"children":2287},{"align":2150},[2288],{"type":41,"tag":56,"props":2289,"children":2291},{"className":2290},[],[2292],{"type":47,"value":2293},"anyElement(matcher)",{"type":41,"tag":2171,"props":2295,"children":2296},{"align":2150},[2297],{"type":41,"tag":56,"props":2298,"children":2300},{"className":2299},[],[2301],{"type":47,"value":2302},"check(iterable).any(conditionCallback)",{"type":41,"tag":2171,"props":2304,"children":2305},{"align":2150},[2306,2308],{"type":47,"value":2307},"E.g. ",{"type":41,"tag":56,"props":2309,"children":2311},{"className":2310},[],[2312],{"type":47,"value":2313},"check(list).any((e) => e.equals(1))",{"type":41,"tag":2144,"props":2315,"children":2316},{},[2317,2326,2335],{"type":41,"tag":2171,"props":2318,"children":2319},{"align":2150},[2320],{"type":41,"tag":56,"props":2321,"children":2323},{"className":2322},[],[2324],{"type":47,"value":2325},"everyElement(matcher)",{"type":41,"tag":2171,"props":2327,"children":2328},{"align":2150},[2329],{"type":41,"tag":56,"props":2330,"children":2332},{"className":2331},[],[2333],{"type":47,"value":2334},"check(iterable).every(conditionCallback)",{"type":41,"tag":2171,"props":2336,"children":2337},{"align":2150},[2338,2339],{"type":47,"value":2307},{"type":41,"tag":56,"props":2340,"children":2342},{"className":2341},[],[2343],{"type":47,"value":2344},"check(list).every((e) => e.isGreaterThan(0))",{"type":41,"tag":2144,"props":2346,"children":2347},{},[2348,2357,2366],{"type":41,"tag":2171,"props":2349,"children":2350},{"align":2150},[2351],{"type":41,"tag":56,"props":2352,"children":2354},{"className":2353},[],[2355],{"type":47,"value":2356},"hasLength(expected)",{"type":41,"tag":2171,"props":2358,"children":2359},{"align":2150},[2360],{"type":41,"tag":56,"props":2361,"children":2363},{"className":2362},[],[2364],{"type":47,"value":2365},"check(actual).length.equals(expected)",{"type":41,"tag":2171,"props":2367,"children":2368},{"align":2150},[2369],{"type":47,"value":2370},"Works on String, Map, Iterable, etc.",{"type":41,"tag":2144,"props":2372,"children":2373},{},[2374,2383,2392],{"type":41,"tag":2171,"props":2375,"children":2376},{"align":2150},[2377],{"type":41,"tag":56,"props":2378,"children":2380},{"className":2379},[],[2381],{"type":47,"value":2382},"isNot(matcher)",{"type":41,"tag":2171,"props":2384,"children":2385},{"align":2150},[2386],{"type":41,"tag":56,"props":2387,"children":2389},{"className":2388},[],[2390],{"type":47,"value":2391},"check(actual).not(conditionCallback)",{"type":41,"tag":2171,"props":2393,"children":2394},{"align":2150},[2395,2396],{"type":47,"value":2307},{"type":41,"tag":56,"props":2397,"children":2399},{"className":2398},[],[2400],{"type":47,"value":2401},"check(val).not((it) => it.equals(5))",{"type":41,"tag":2144,"props":2403,"children":2404},{},[2405,2414,2423],{"type":41,"tag":2171,"props":2406,"children":2407},{"align":2150},[2408],{"type":41,"tag":56,"props":2409,"children":2411},{"className":2410},[],[2412],{"type":47,"value":2413},"contains(element)",{"type":41,"tag":2171,"props":2415,"children":2416},{"align":2150},[2417],{"type":41,"tag":56,"props":2418,"children":2420},{"className":2419},[],[2421],{"type":47,"value":2422},"check(actual).contains(element)",{"type":41,"tag":2171,"props":2424,"children":2425},{"align":2150},[2426,2428,2433],{"type":47,"value":2427},"Works on String, Iterable (use ",{"type":41,"tag":56,"props":2429,"children":2431},{"className":2430},[],[2432],{"type":47,"value":1739},{"type":47,"value":2434}," for Map!)",{"type":41,"tag":2144,"props":2436,"children":2437},{},[2438,2448,2457],{"type":41,"tag":2171,"props":2439,"children":2440},{"align":2150},[2441,2446],{"type":41,"tag":56,"props":2442,"children":2444},{"className":2443},[],[2445],{"type":47,"value":1770},{"type":47,"value":2447}," (on a Map)",{"type":41,"tag":2171,"props":2449,"children":2450},{"align":2150},[2451],{"type":41,"tag":56,"props":2452,"children":2454},{"className":2453},[],[2455],{"type":47,"value":2456},"check(map).containsKey(key)",{"type":41,"tag":2171,"props":2458,"children":2459},{"align":2150},[2460],{"type":47,"value":2461},"Map key containment",{"type":41,"tag":2144,"props":2463,"children":2464},{},[2465,2474,2483],{"type":41,"tag":2171,"props":2466,"children":2467},{"align":2150},[2468],{"type":41,"tag":56,"props":2469,"children":2471},{"className":2470},[],[2472],{"type":47,"value":2473},"startsWith(prefix)",{"type":41,"tag":2171,"props":2475,"children":2476},{"align":2150},[2477],{"type":41,"tag":56,"props":2478,"children":2480},{"className":2479},[],[2481],{"type":47,"value":2482},"check(string).startsWith(prefix)",{"type":41,"tag":2171,"props":2484,"children":2485},{"align":2150},[2486],{"type":47,"value":2487},"String only",{"type":41,"tag":2144,"props":2489,"children":2490},{},[2491,2500,2509],{"type":41,"tag":2171,"props":2492,"children":2493},{"align":2150},[2494],{"type":41,"tag":56,"props":2495,"children":2497},{"className":2496},[],[2498],{"type":47,"value":2499},"endsWith(suffix)",{"type":41,"tag":2171,"props":2501,"children":2502},{"align":2150},[2503],{"type":41,"tag":56,"props":2504,"children":2506},{"className":2505},[],[2507],{"type":47,"value":2508},"check(string).endsWith(suffix)",{"type":41,"tag":2171,"props":2510,"children":2511},{"align":2150},[2512],{"type":47,"value":2487},{"type":41,"tag":2144,"props":2514,"children":2515},{},[2516,2525,2534],{"type":41,"tag":2171,"props":2517,"children":2518},{"align":2150},[2519],{"type":41,"tag":56,"props":2520,"children":2522},{"className":2521},[],[2523],{"type":47,"value":2524},"isEmpty",{"type":41,"tag":2171,"props":2526,"children":2527},{"align":2150},[2528],{"type":41,"tag":56,"props":2529,"children":2531},{"className":2530},[],[2532],{"type":47,"value":2533},"check(actual).isEmpty()",{"type":41,"tag":2171,"props":2535,"children":2536},{"align":2150},[2537],{"type":47,"value":2538},"Works on String, Map, Iterable",{"type":41,"tag":2144,"props":2540,"children":2541},{},[2542,2551,2560],{"type":41,"tag":2171,"props":2543,"children":2544},{"align":2150},[2545],{"type":41,"tag":56,"props":2546,"children":2548},{"className":2547},[],[2549],{"type":47,"value":2550},"isNotEmpty",{"type":41,"tag":2171,"props":2552,"children":2553},{"align":2150},[2554],{"type":41,"tag":56,"props":2555,"children":2557},{"className":2556},[],[2558],{"type":47,"value":2559},"check(actual).isNotEmpty()",{"type":41,"tag":2171,"props":2561,"children":2562},{"align":2150},[2563],{"type":47,"value":2538},{"type":41,"tag":2144,"props":2565,"children":2566},{},[2567,2576,2585],{"type":41,"tag":2171,"props":2568,"children":2569},{"align":2150},[2570],{"type":41,"tag":56,"props":2571,"children":2573},{"className":2572},[],[2574],{"type":47,"value":2575},"isNull",{"type":41,"tag":2171,"props":2577,"children":2578},{"align":2150},[2579],{"type":41,"tag":56,"props":2580,"children":2582},{"className":2581},[],[2583],{"type":47,"value":2584},"check(actual).isNull()",{"type":41,"tag":2171,"props":2586,"children":2587},{"align":2150},[],{"type":41,"tag":2144,"props":2589,"children":2590},{},[2591,2600,2609],{"type":41,"tag":2171,"props":2592,"children":2593},{"align":2150},[2594],{"type":41,"tag":56,"props":2595,"children":2597},{"className":2596},[],[2598],{"type":47,"value":2599},"isNotNull",{"type":41,"tag":2171,"props":2601,"children":2602},{"align":2150},[2603],{"type":41,"tag":56,"props":2604,"children":2606},{"className":2605},[],[2607],{"type":47,"value":2608},"check(actual).isNotNull()",{"type":41,"tag":2171,"props":2610,"children":2611},{"align":2150},[],{"type":41,"tag":2144,"props":2613,"children":2614},{},[2615,2631,2640],{"type":41,"tag":2171,"props":2616,"children":2617},{"align":2150},[2618,2623,2625],{"type":41,"tag":56,"props":2619,"children":2621},{"className":2620},[],[2622],{"type":47,"value":1596},{"type":47,"value":2624}," \u002F ",{"type":41,"tag":56,"props":2626,"children":2628},{"className":2627},[],[2629],{"type":47,"value":2630},"true",{"type":41,"tag":2171,"props":2632,"children":2633},{"align":2150},[2634],{"type":41,"tag":56,"props":2635,"children":2637},{"className":2636},[],[2638],{"type":47,"value":2639},"check(actual).isTrue()",{"type":41,"tag":2171,"props":2641,"children":2642},{"align":2150},[2643,2645,2651],{"type":47,"value":2644},"Works on non-nullable ",{"type":41,"tag":56,"props":2646,"children":2648},{"className":2647},[],[2649],{"type":47,"value":2650},"bool",{"type":47,"value":2652}," only",{"type":41,"tag":2144,"props":2654,"children":2655},{},[2656,2671,2680],{"type":41,"tag":2171,"props":2657,"children":2658},{"align":2150},[2659,2664,2665],{"type":41,"tag":56,"props":2660,"children":2662},{"className":2661},[],[2663],{"type":47,"value":1603},{"type":47,"value":2624},{"type":41,"tag":56,"props":2666,"children":2668},{"className":2667},[],[2669],{"type":47,"value":2670},"false",{"type":41,"tag":2171,"props":2672,"children":2673},{"align":2150},[2674],{"type":41,"tag":56,"props":2675,"children":2677},{"className":2676},[],[2678],{"type":47,"value":2679},"check(actual).isFalse()",{"type":41,"tag":2171,"props":2681,"children":2682},{"align":2150},[2683,2684,2689],{"type":47,"value":2644},{"type":41,"tag":56,"props":2685,"children":2687},{"className":2686},[],[2688],{"type":47,"value":2650},{"type":47,"value":2652},{"type":41,"tag":2144,"props":2691,"children":2692},{},[2693,2702,2711],{"type":41,"tag":2171,"props":2694,"children":2695},{"align":2150},[2696],{"type":41,"tag":56,"props":2697,"children":2699},{"className":2698},[],[2700],{"type":47,"value":2701},"completion(matcher)",{"type":41,"tag":2171,"props":2703,"children":2704},{"align":2150},[2705],{"type":41,"tag":56,"props":2706,"children":2708},{"className":2707},[],[2709],{"type":47,"value":2710},"await check(future).completes(conditionCallback)",{"type":41,"tag":2171,"props":2712,"children":2713},{"align":2150},[2714],{"type":47,"value":2715},"Must be awaited!",{"type":41,"tag":2144,"props":2717,"children":2718},{},[2719,2728,2737],{"type":41,"tag":2171,"props":2720,"children":2721},{"align":2150},[2722],{"type":41,"tag":56,"props":2723,"children":2725},{"className":2724},[],[2726],{"type":47,"value":2727},"throwsA(matcher)",{"type":41,"tag":2171,"props":2729,"children":2730},{"align":2150},[2731],{"type":41,"tag":56,"props":2732,"children":2734},{"className":2733},[],[2735],{"type":47,"value":2736},"await check(future).throws\u003CType>()",{"type":41,"tag":2171,"props":2738,"children":2739},{"align":2150},[2740],{"type":47,"value":2715},{"type":41,"tag":2144,"props":2742,"children":2743},{},[2744,2753,2762],{"type":41,"tag":2171,"props":2745,"children":2746},{"align":2150},[2747],{"type":41,"tag":56,"props":2748,"children":2750},{"className":2749},[],[2751],{"type":47,"value":2752},"emits(value)",{"type":41,"tag":2171,"props":2754,"children":2755},{"align":2150},[2756],{"type":41,"tag":56,"props":2757,"children":2759},{"className":2758},[],[2760],{"type":47,"value":2761},"await check(streamQueue).emits(conditionCallback)",{"type":41,"tag":2171,"props":2763,"children":2764},{"align":2150},[2765],{"type":47,"value":2715},{"type":41,"tag":2144,"props":2767,"children":2768},{},[2769,2778,2787],{"type":41,"tag":2171,"props":2770,"children":2771},{"align":2150},[2772],{"type":41,"tag":56,"props":2773,"children":2775},{"className":2774},[],[2776],{"type":47,"value":2777},"emitsThrough(value)",{"type":41,"tag":2171,"props":2779,"children":2780},{"align":2150},[2781],{"type":41,"tag":56,"props":2782,"children":2784},{"className":2783},[],[2785],{"type":47,"value":2786},"await check(streamQueue).emitsThrough(conditionCallback)",{"type":41,"tag":2171,"props":2788,"children":2789},{"align":2150},[2790],{"type":47,"value":2715},{"type":41,"tag":2144,"props":2792,"children":2793},{},[2794,2803,2812],{"type":41,"tag":2171,"props":2795,"children":2796},{"align":2150},[2797],{"type":41,"tag":56,"props":2798,"children":2800},{"className":2799},[],[2801],{"type":47,"value":2802},"stringContainsInOrder(list)",{"type":41,"tag":2171,"props":2804,"children":2805},{"align":2150},[2806],{"type":41,"tag":56,"props":2807,"children":2809},{"className":2808},[],[2810],{"type":47,"value":2811},"check(string).containsInOrder(list)",{"type":41,"tag":2171,"props":2813,"children":2814},{"align":2150},[2815],{"type":47,"value":2487},{"type":41,"tag":2144,"props":2817,"children":2818},{},[2819,2828,2837],{"type":41,"tag":2171,"props":2820,"children":2821},{"align":2150},[2822],{"type":41,"tag":56,"props":2823,"children":2825},{"className":2824},[],[2826],{"type":47,"value":2827},"pairwiseCompare(...)",{"type":41,"tag":2171,"props":2829,"children":2830},{"align":2150},[2831],{"type":41,"tag":56,"props":2832,"children":2834},{"className":2833},[],[2835],{"type":47,"value":2836},"check(actual).pairwiseMatches(...)",{"type":41,"tag":2171,"props":2838,"children":2839},{"align":2150},[],{"type":41,"tag":157,"props":2841,"children":2842},{},[],{"type":41,"tag":81,"props":2844,"children":2846},{"id":2845},"matchers-with-no-direct-replacements",[2847],{"type":47,"value":137},{"type":41,"tag":50,"props":2849,"children":2850},{},[2851,2853,2858],{"type":47,"value":2852},"Some legacy matchers do not have a one-to-one equivalent in ",{"type":41,"tag":56,"props":2854,"children":2856},{"className":2855},[],[2857],{"type":47,"value":77},{"type":47,"value":2859},"\ndue to API cleanup. Use these standard workarounds:",{"type":41,"tag":192,"props":2861,"children":2863},{"id":2862},"_1-specific-error-matchers",[2864],{"type":47,"value":2865},"1. Specific Error Matchers",{"type":41,"tag":88,"props":2867,"children":2868},{},[2869,2901],{"type":41,"tag":92,"props":2870,"children":2871},{},[2872,2877,2878,2884,2885,2891,2893,2899],{"type":41,"tag":355,"props":2873,"children":2874},{},[2875],{"type":47,"value":2876},"Legacy",{"type":47,"value":646},{"type":41,"tag":56,"props":2879,"children":2881},{"className":2880},[],[2882],{"type":47,"value":2883},"throwsArgumentError",{"type":47,"value":1179},{"type":41,"tag":56,"props":2886,"children":2888},{"className":2887},[],[2889],{"type":47,"value":2890},"throwsStateError",{"type":47,"value":2892},",\n",{"type":41,"tag":56,"props":2894,"children":2896},{"className":2895},[],[2897],{"type":47,"value":2898},"throwsUnsupportedError",{"type":47,"value":2900},", etc.",{"type":41,"tag":92,"props":2902,"children":2903},{},[2904,2909,2910,2916,2918],{"type":41,"tag":355,"props":2905,"children":2906},{},[2907],{"type":47,"value":2908},"Checks",{"type":47,"value":1518},{"type":41,"tag":56,"props":2911,"children":2913},{"className":2912},[],[2914],{"type":47,"value":2915},".throws\u003CT>()",{"type":47,"value":2917}," with the specific error type:\n",{"type":41,"tag":230,"props":2919,"children":2921},{"className":379,"code":2920,"language":18,"meta":235,"style":235},"await check(triggerError()).throws\u003CArgumentError>();\n",[2922],{"type":41,"tag":56,"props":2923,"children":2924},{"__ignoreMap":235},[2925],{"type":41,"tag":241,"props":2926,"children":2927},{"class":243,"line":244},[2928],{"type":41,"tag":241,"props":2929,"children":2930},{},[2931],{"type":47,"value":2920},{"type":41,"tag":192,"props":2933,"children":2935},{"id":2934},"_2-the-anything-matcher",[2936,2937,2943],{"type":47,"value":798},{"type":41,"tag":56,"props":2938,"children":2940},{"className":2939},[],[2941],{"type":47,"value":2942},"anything",{"type":47,"value":2944}," Matcher",{"type":41,"tag":88,"props":2946,"children":2947},{},[2948,2962],{"type":41,"tag":92,"props":2949,"children":2950},{},[2951,2955,2956],{"type":41,"tag":355,"props":2952,"children":2953},{},[2954],{"type":47,"value":2876},{"type":47,"value":646},{"type":41,"tag":56,"props":2957,"children":2959},{"className":2958},[],[2960],{"type":47,"value":2961},"expect(actual, anything)",{"type":41,"tag":92,"props":2963,"children":2964},{},[2965,2969,2971,2977,2979],{"type":41,"tag":355,"props":2966,"children":2967},{},[2968],{"type":47,"value":2908},{"type":47,"value":2970},": Pass an empty condition callback ",{"type":41,"tag":56,"props":2972,"children":2974},{"className":2973},[],[2975],{"type":47,"value":2976},"(_) {}",{"type":47,"value":2978}," when a condition is\nsyntactically required:\n",{"type":41,"tag":230,"props":2980,"children":2982},{"className":379,"code":2981,"language":18,"meta":235,"style":235},"await check(someFuture).completes((_) {});\n",[2983],{"type":41,"tag":56,"props":2984,"children":2985},{"__ignoreMap":235},[2986],{"type":41,"tag":241,"props":2987,"children":2988},{"class":243,"line":244},[2989],{"type":41,"tag":241,"props":2990,"children":2991},{},[2992],{"type":47,"value":2981},{"type":41,"tag":192,"props":2994,"children":2996},{"id":2995},"_3-specific-numeric-toggles",[2997],{"type":47,"value":2998},"3. Specific Numeric Toggles",{"type":41,"tag":88,"props":3000,"children":3001},{},[3002,3051],{"type":41,"tag":92,"props":3003,"children":3004},{},[3005,3009,3010,3016,3017,3023,3024,3030,3031,3037,3038,3044,3045],{"type":41,"tag":355,"props":3006,"children":3007},{},[3008],{"type":47,"value":2876},{"type":47,"value":646},{"type":41,"tag":56,"props":3011,"children":3013},{"className":3012},[],[3014],{"type":47,"value":3015},"isPositive",{"type":47,"value":1179},{"type":41,"tag":56,"props":3018,"children":3020},{"className":3019},[],[3021],{"type":47,"value":3022},"isNegative",{"type":47,"value":1179},{"type":41,"tag":56,"props":3025,"children":3027},{"className":3026},[],[3028],{"type":47,"value":3029},"isZero",{"type":47,"value":1179},{"type":41,"tag":56,"props":3032,"children":3034},{"className":3033},[],[3035],{"type":47,"value":3036},"isNonPositive",{"type":47,"value":2892},{"type":41,"tag":56,"props":3039,"children":3041},{"className":3040},[],[3042],{"type":47,"value":3043},"isNonNegative",{"type":47,"value":1179},{"type":41,"tag":56,"props":3046,"children":3048},{"className":3047},[],[3049],{"type":47,"value":3050},"isNonZero",{"type":41,"tag":92,"props":3052,"children":3053},{},[3054,3058,3060],{"type":41,"tag":355,"props":3055,"children":3056},{},[3057],{"type":47,"value":2908},{"type":47,"value":3059},": Use explicit comparative expectations:\n",{"type":41,"tag":88,"props":3061,"children":3062},{},[3063,3079,3094,3109],{"type":41,"tag":92,"props":3064,"children":3065},{},[3066,3071,3073],{"type":41,"tag":56,"props":3067,"children":3069},{"className":3068},[],[3070],{"type":47,"value":3015},{"type":47,"value":3072}," $\\rightarrow$ ",{"type":41,"tag":56,"props":3074,"children":3076},{"className":3075},[],[3077],{"type":47,"value":3078},"isGreaterThan(0)",{"type":41,"tag":92,"props":3080,"children":3081},{},[3082,3087,3088],{"type":41,"tag":56,"props":3083,"children":3085},{"className":3084},[],[3086],{"type":47,"value":3022},{"type":47,"value":3072},{"type":41,"tag":56,"props":3089,"children":3091},{"className":3090},[],[3092],{"type":47,"value":3093},"isLessThan(0)",{"type":41,"tag":92,"props":3095,"children":3096},{},[3097,3102,3103],{"type":41,"tag":56,"props":3098,"children":3100},{"className":3099},[],[3101],{"type":47,"value":3029},{"type":47,"value":3072},{"type":41,"tag":56,"props":3104,"children":3106},{"className":3105},[],[3107],{"type":47,"value":3108},"equals(0)",{"type":41,"tag":92,"props":3110,"children":3111},{},[3112,3117,3118],{"type":41,"tag":56,"props":3113,"children":3115},{"className":3114},[],[3116],{"type":47,"value":3043},{"type":47,"value":3072},{"type":41,"tag":56,"props":3119,"children":3121},{"className":3120},[],[3122],{"type":47,"value":3123},"isGreaterOrEqual(0)",{"type":41,"tag":192,"props":3125,"children":3127},{"id":3126},"_4-numeric-ranges",[3128],{"type":47,"value":3129},"4. Numeric Ranges",{"type":41,"tag":88,"props":3131,"children":3132},{},[3133,3156],{"type":41,"tag":92,"props":3134,"children":3135},{},[3136,3140,3141,3147,3148,3154],{"type":41,"tag":355,"props":3137,"children":3138},{},[3139],{"type":47,"value":2876},{"type":47,"value":646},{"type":41,"tag":56,"props":3142,"children":3144},{"className":3143},[],[3145],{"type":47,"value":3146},"inClosedOpenRange(min, max)",{"type":47,"value":1179},{"type":41,"tag":56,"props":3149,"children":3151},{"className":3150},[],[3152],{"type":47,"value":3153},"inInclusiveRange(min, max)",{"type":47,"value":3155},",\netc.",{"type":41,"tag":92,"props":3157,"children":3158},{},[3159,3163,3165,3171,3173],{"type":41,"tag":355,"props":3160,"children":3161},{},[3162],{"type":47,"value":2908},{"type":47,"value":3164},": Chain the boundaries using the cascade operator (",{"type":41,"tag":56,"props":3166,"children":3168},{"className":3167},[],[3169],{"type":47,"value":3170},"..",{"type":47,"value":3172},"):\n",{"type":41,"tag":230,"props":3174,"children":3176},{"className":379,"code":3175,"language":18,"meta":235,"style":235},"check(actualValue)\n  ..isGreaterOrEqual(min)\n  ..isLessThan(max);\n",[3177],{"type":41,"tag":56,"props":3178,"children":3179},{"__ignoreMap":235},[3180,3188,3196],{"type":41,"tag":241,"props":3181,"children":3182},{"class":243,"line":244},[3183],{"type":41,"tag":241,"props":3184,"children":3185},{},[3186],{"type":47,"value":3187},"check(actualValue)\n",{"type":41,"tag":241,"props":3189,"children":3190},{"class":243,"line":395},[3191],{"type":41,"tag":241,"props":3192,"children":3193},{},[3194],{"type":47,"value":3195},"  ..isGreaterOrEqual(min)\n",{"type":41,"tag":241,"props":3197,"children":3198},{"class":243,"line":767},[3199],{"type":41,"tag":241,"props":3200,"children":3201},{},[3202],{"type":47,"value":3203},"  ..isLessThan(max);\n",{"type":41,"tag":157,"props":3205,"children":3206},{},[],{"type":41,"tag":81,"props":3208,"children":3210},{"id":3209},"writing-custom-expectations-replacing-custom-matchers",[3211],{"type":47,"value":3212},"Writing Custom Expectations (Replacing Custom Matchers)",{"type":41,"tag":50,"props":3214,"children":3215},{},[3216,3218,3224,3226,3231,3233,3239,3241,3247],{"type":47,"value":3217},"When migrating from a legacy codebase, you may encounter custom ",{"type":41,"tag":56,"props":3219,"children":3221},{"className":3220},[],[3222],{"type":47,"value":3223},"Matcher",{"type":47,"value":3225},"\nsubclasses. In ",{"type":41,"tag":56,"props":3227,"children":3229},{"className":3228},[],[3230],{"type":47,"value":77},{"type":47,"value":3232},", custom assertions are implemented as\n",{"type":41,"tag":56,"props":3234,"children":3236},{"className":3235},[],[3237],{"type":47,"value":3238},"extension",{"type":47,"value":3240}," methods on ",{"type":41,"tag":56,"props":3242,"children":3244},{"className":3243},[],[3245],{"type":47,"value":3246},"Subject\u003CT>",{"type":47,"value":470},{"type":41,"tag":50,"props":3249,"children":3250},{},[3251],{"type":47,"value":3252},"To write custom expectations, you must import the checks context API:",{"type":41,"tag":230,"props":3254,"children":3256},{"className":379,"code":3255,"language":18,"meta":235,"style":235},"import 'package:checks\u002Fcontext.dart';\n",[3257],{"type":41,"tag":56,"props":3258,"children":3259},{"__ignoreMap":235},[3260],{"type":41,"tag":241,"props":3261,"children":3262},{"class":243,"line":244},[3263],{"type":41,"tag":241,"props":3264,"children":3265},{},[3266],{"type":47,"value":3255},{"type":41,"tag":192,"props":3268,"children":3270},{"id":3269},"_1-simple-custom-expectations-using-expect",[3271,3273,3278],{"type":47,"value":3272},"1. Simple Custom Expectations (using ",{"type":41,"tag":56,"props":3274,"children":3276},{"className":3275},[],[3277],{"type":47,"value":320},{"type":47,"value":633},{"type":41,"tag":50,"props":3280,"children":3281},{},[3282,3283,3289,3291,3297],{"type":47,"value":2192},{"type":41,"tag":56,"props":3284,"children":3286},{"className":3285},[],[3287],{"type":47,"value":3288},"context.expect",{"type":47,"value":3290}," to check a property and return a ",{"type":41,"tag":56,"props":3292,"children":3294},{"className":3293},[],[3295],{"type":47,"value":3296},"Rejection",{"type":47,"value":3298}," on failure:",{"type":41,"tag":230,"props":3300,"children":3302},{"className":379,"code":3301,"language":18,"meta":235,"style":235},"extension CustomPersonChecks on Subject\u003CPerson> {\n  void isAdult() {\n    context.expect(\n      () => ['is an adult (age >= 18)'],\n      (actual) {\n        if (actual.age >= 18) return null; \u002F\u002F Pass\n        return Rejection(\n          which: ['is only ${actual.age} years old'],\n        );\n      },\n    );\n  }\n}\n",[3303],{"type":41,"tag":56,"props":3304,"children":3305},{"__ignoreMap":235},[3306,3314,3322,3330,3338,3346,3354,3363,3372,3381,3390,3399,3408],{"type":41,"tag":241,"props":3307,"children":3308},{"class":243,"line":244},[3309],{"type":41,"tag":241,"props":3310,"children":3311},{},[3312],{"type":47,"value":3313},"extension CustomPersonChecks on Subject\u003CPerson> {\n",{"type":41,"tag":241,"props":3315,"children":3316},{"class":243,"line":395},[3317],{"type":41,"tag":241,"props":3318,"children":3319},{},[3320],{"type":47,"value":3321},"  void isAdult() {\n",{"type":41,"tag":241,"props":3323,"children":3324},{"class":243,"line":767},[3325],{"type":41,"tag":241,"props":3326,"children":3327},{},[3328],{"type":47,"value":3329},"    context.expect(\n",{"type":41,"tag":241,"props":3331,"children":3332},{"class":243,"line":777},[3333],{"type":41,"tag":241,"props":3334,"children":3335},{},[3336],{"type":47,"value":3337},"      () => ['is an adult (age >= 18)'],\n",{"type":41,"tag":241,"props":3339,"children":3340},{"class":243,"line":786},[3341],{"type":41,"tag":241,"props":3342,"children":3343},{},[3344],{"type":47,"value":3345},"      (actual) {\n",{"type":41,"tag":241,"props":3347,"children":3348},{"class":243,"line":1314},[3349],{"type":41,"tag":241,"props":3350,"children":3351},{},[3352],{"type":47,"value":3353},"        if (actual.age >= 18) return null; \u002F\u002F Pass\n",{"type":41,"tag":241,"props":3355,"children":3357},{"class":243,"line":3356},7,[3358],{"type":41,"tag":241,"props":3359,"children":3360},{},[3361],{"type":47,"value":3362},"        return Rejection(\n",{"type":41,"tag":241,"props":3364,"children":3366},{"class":243,"line":3365},8,[3367],{"type":41,"tag":241,"props":3368,"children":3369},{},[3370],{"type":47,"value":3371},"          which: ['is only ${actual.age} years old'],\n",{"type":41,"tag":241,"props":3373,"children":3375},{"class":243,"line":3374},9,[3376],{"type":41,"tag":241,"props":3377,"children":3378},{},[3379],{"type":47,"value":3380},"        );\n",{"type":41,"tag":241,"props":3382,"children":3384},{"class":243,"line":3383},10,[3385],{"type":41,"tag":241,"props":3386,"children":3387},{},[3388],{"type":47,"value":3389},"      },\n",{"type":41,"tag":241,"props":3391,"children":3393},{"class":243,"line":3392},11,[3394],{"type":41,"tag":241,"props":3395,"children":3396},{},[3397],{"type":47,"value":3398},"    );\n",{"type":41,"tag":241,"props":3400,"children":3402},{"class":243,"line":3401},12,[3403],{"type":41,"tag":241,"props":3404,"children":3405},{},[3406],{"type":47,"value":3407},"  }\n",{"type":41,"tag":241,"props":3409,"children":3411},{"class":243,"line":3410},13,[3412],{"type":41,"tag":241,"props":3413,"children":3414},{},[3415],{"type":47,"value":3416},"}\n",{"type":41,"tag":192,"props":3418,"children":3420},{"id":3419},"_2-nested-property-extraction-using-nest-or-has",[3421,3423,3429,3430,3436],{"type":47,"value":3422},"2. Nested Property Extraction (using ",{"type":41,"tag":56,"props":3424,"children":3426},{"className":3425},[],[3427],{"type":47,"value":3428},"nest",{"type":47,"value":322},{"type":41,"tag":56,"props":3431,"children":3433},{"className":3432},[],[3434],{"type":47,"value":3435},"has",{"type":47,"value":633},{"type":41,"tag":50,"props":3438,"children":3439},{},[3440,3442,3447,3449,3454],{"type":47,"value":3441},"To extract a property and allow further chained checks, use ",{"type":41,"tag":56,"props":3443,"children":3445},{"className":3444},[],[3446],{"type":47,"value":3428},{"type":47,"value":3448}," or the\nsimpler ",{"type":41,"tag":56,"props":3450,"children":3452},{"className":3451},[],[3453],{"type":47,"value":3435},{"type":47,"value":3455}," helper:",{"type":41,"tag":88,"props":3457,"children":3458},{},[3459,3504],{"type":41,"tag":92,"props":3460,"children":3461},{},[3462,3474,3475],{"type":41,"tag":355,"props":3463,"children":3464},{},[3465,3467,3472],{"type":47,"value":3466},"Using ",{"type":41,"tag":56,"props":3468,"children":3470},{"className":3469},[],[3471],{"type":47,"value":3435},{"type":47,"value":3473}," (Recommended for simple, non-failing field access)",{"type":47,"value":228},{"type":41,"tag":230,"props":3476,"children":3478},{"className":379,"code":3477,"language":18,"meta":235,"style":235},"extension CustomPersonChecks on Subject\u003CPerson> {\n  Subject\u003CAddress> get address => has((p) => p.address, 'address');\n}\n",[3479],{"type":41,"tag":56,"props":3480,"children":3481},{"__ignoreMap":235},[3482,3489,3497],{"type":41,"tag":241,"props":3483,"children":3484},{"class":243,"line":244},[3485],{"type":41,"tag":241,"props":3486,"children":3487},{},[3488],{"type":47,"value":3313},{"type":41,"tag":241,"props":3490,"children":3491},{"class":243,"line":395},[3492],{"type":41,"tag":241,"props":3493,"children":3494},{},[3495],{"type":47,"value":3496},"  Subject\u003CAddress> get address => has((p) => p.address, 'address');\n",{"type":41,"tag":241,"props":3498,"children":3499},{"class":243,"line":767},[3500],{"type":41,"tag":241,"props":3501,"children":3502},{},[3503],{"type":47,"value":3416},{"type":41,"tag":92,"props":3505,"children":3506},{},[3507,3518,3519],{"type":41,"tag":355,"props":3508,"children":3509},{},[3510,3511,3516],{"type":47,"value":3466},{"type":41,"tag":56,"props":3512,"children":3514},{"className":3513},[],[3515],{"type":47,"value":3428},{"type":47,"value":3517}," (For property extraction that can fail or reject)",{"type":47,"value":228},{"type":41,"tag":230,"props":3520,"children":3522},{"className":379,"code":3521,"language":18,"meta":235,"style":235},"extension CustomPersonChecks on Subject\u003CPerson> {\n  Subject\u003CString> get ssn => context.nest(\n    'has a valid SSN',\n    (actual) {\n      final ssnValue = actual.ssn;\n      if (ssnValue == null) {\n        return Extracted.rejection(which: ['has no SSN']);\n      }\n      return Extracted.value(ssnValue);\n    },\n  );\n}\n",[3523],{"type":41,"tag":56,"props":3524,"children":3525},{"__ignoreMap":235},[3526,3533,3541,3549,3557,3565,3573,3581,3589,3597,3605,3613],{"type":41,"tag":241,"props":3527,"children":3528},{"class":243,"line":244},[3529],{"type":41,"tag":241,"props":3530,"children":3531},{},[3532],{"type":47,"value":3313},{"type":41,"tag":241,"props":3534,"children":3535},{"class":243,"line":395},[3536],{"type":41,"tag":241,"props":3537,"children":3538},{},[3539],{"type":47,"value":3540},"  Subject\u003CString> get ssn => context.nest(\n",{"type":41,"tag":241,"props":3542,"children":3543},{"class":243,"line":767},[3544],{"type":41,"tag":241,"props":3545,"children":3546},{},[3547],{"type":47,"value":3548},"    'has a valid SSN',\n",{"type":41,"tag":241,"props":3550,"children":3551},{"class":243,"line":777},[3552],{"type":41,"tag":241,"props":3553,"children":3554},{},[3555],{"type":47,"value":3556},"    (actual) {\n",{"type":41,"tag":241,"props":3558,"children":3559},{"class":243,"line":786},[3560],{"type":41,"tag":241,"props":3561,"children":3562},{},[3563],{"type":47,"value":3564},"      final ssnValue = actual.ssn;\n",{"type":41,"tag":241,"props":3566,"children":3567},{"class":243,"line":1314},[3568],{"type":41,"tag":241,"props":3569,"children":3570},{},[3571],{"type":47,"value":3572},"      if (ssnValue == null) {\n",{"type":41,"tag":241,"props":3574,"children":3575},{"class":243,"line":3356},[3576],{"type":41,"tag":241,"props":3577,"children":3578},{},[3579],{"type":47,"value":3580},"        return Extracted.rejection(which: ['has no SSN']);\n",{"type":41,"tag":241,"props":3582,"children":3583},{"class":243,"line":3365},[3584],{"type":41,"tag":241,"props":3585,"children":3586},{},[3587],{"type":47,"value":3588},"      }\n",{"type":41,"tag":241,"props":3590,"children":3591},{"class":243,"line":3374},[3592],{"type":41,"tag":241,"props":3593,"children":3594},{},[3595],{"type":47,"value":3596},"      return Extracted.value(ssnValue);\n",{"type":41,"tag":241,"props":3598,"children":3599},{"class":243,"line":3383},[3600],{"type":41,"tag":241,"props":3601,"children":3602},{},[3603],{"type":47,"value":3604},"    },\n",{"type":41,"tag":241,"props":3606,"children":3607},{"class":243,"line":3392},[3608],{"type":41,"tag":241,"props":3609,"children":3610},{},[3611],{"type":47,"value":3612},"  );\n",{"type":41,"tag":241,"props":3614,"children":3615},{"class":243,"line":3401},[3616],{"type":41,"tag":241,"props":3617,"children":3618},{},[3619],{"type":47,"value":3416},{"type":41,"tag":192,"props":3621,"children":3623},{"id":3622},"_3-asynchronous-custom-expectations",[3624],{"type":47,"value":3625},"3. Asynchronous Custom Expectations",{"type":41,"tag":50,"props":3627,"children":3628},{},[3629,3631,3637,3638,3644,3646,3652],{"type":47,"value":3630},"If the expectation is asynchronous (e.g. checking a Future or Stream), use\n",{"type":41,"tag":56,"props":3632,"children":3634},{"className":3633},[],[3635],{"type":47,"value":3636},"context.expectAsync",{"type":47,"value":322},{"type":41,"tag":56,"props":3639,"children":3641},{"className":3640},[],[3642],{"type":47,"value":3643},"context.nestAsync",{"type":47,"value":3645}," and return the resulting ",{"type":41,"tag":56,"props":3647,"children":3649},{"className":3648},[],[3650],{"type":47,"value":3651},"Future",{"type":47,"value":3653},":",{"type":41,"tag":230,"props":3655,"children":3657},{"className":379,"code":3656,"language":18,"meta":235,"style":235},"extension CustomFutureChecks\u003CT> on Subject\u003CFuture\u003CT>> {\n  Future\u003Cvoid> completesNormally() {\n    return context.expectAsync(\n      () => ['completes without throwing'],\n      (actual) async {\n        try {\n          await actual;\n          return null; \u002F\u002F Pass\n        } catch (e) {\n          return Rejection(which: ['threw $e']);\n        }\n      },\n    );\n  }\n}\n",[3658],{"type":41,"tag":56,"props":3659,"children":3660},{"__ignoreMap":235},[3661,3669,3677,3685,3693,3701,3709,3717,3725,3733,3741,3749,3756,3763,3771],{"type":41,"tag":241,"props":3662,"children":3663},{"class":243,"line":244},[3664],{"type":41,"tag":241,"props":3665,"children":3666},{},[3667],{"type":47,"value":3668},"extension CustomFutureChecks\u003CT> on Subject\u003CFuture\u003CT>> {\n",{"type":41,"tag":241,"props":3670,"children":3671},{"class":243,"line":395},[3672],{"type":41,"tag":241,"props":3673,"children":3674},{},[3675],{"type":47,"value":3676},"  Future\u003Cvoid> completesNormally() {\n",{"type":41,"tag":241,"props":3678,"children":3679},{"class":243,"line":767},[3680],{"type":41,"tag":241,"props":3681,"children":3682},{},[3683],{"type":47,"value":3684},"    return context.expectAsync(\n",{"type":41,"tag":241,"props":3686,"children":3687},{"class":243,"line":777},[3688],{"type":41,"tag":241,"props":3689,"children":3690},{},[3691],{"type":47,"value":3692},"      () => ['completes without throwing'],\n",{"type":41,"tag":241,"props":3694,"children":3695},{"class":243,"line":786},[3696],{"type":41,"tag":241,"props":3697,"children":3698},{},[3699],{"type":47,"value":3700},"      (actual) async {\n",{"type":41,"tag":241,"props":3702,"children":3703},{"class":243,"line":1314},[3704],{"type":41,"tag":241,"props":3705,"children":3706},{},[3707],{"type":47,"value":3708},"        try {\n",{"type":41,"tag":241,"props":3710,"children":3711},{"class":243,"line":3356},[3712],{"type":41,"tag":241,"props":3713,"children":3714},{},[3715],{"type":47,"value":3716},"          await actual;\n",{"type":41,"tag":241,"props":3718,"children":3719},{"class":243,"line":3365},[3720],{"type":41,"tag":241,"props":3721,"children":3722},{},[3723],{"type":47,"value":3724},"          return null; \u002F\u002F Pass\n",{"type":41,"tag":241,"props":3726,"children":3727},{"class":243,"line":3374},[3728],{"type":41,"tag":241,"props":3729,"children":3730},{},[3731],{"type":47,"value":3732},"        } catch (e) {\n",{"type":41,"tag":241,"props":3734,"children":3735},{"class":243,"line":3383},[3736],{"type":41,"tag":241,"props":3737,"children":3738},{},[3739],{"type":47,"value":3740},"          return Rejection(which: ['threw $e']);\n",{"type":41,"tag":241,"props":3742,"children":3743},{"class":243,"line":3392},[3744],{"type":41,"tag":241,"props":3745,"children":3746},{},[3747],{"type":47,"value":3748},"        }\n",{"type":41,"tag":241,"props":3750,"children":3751},{"class":243,"line":3401},[3752],{"type":41,"tag":241,"props":3753,"children":3754},{},[3755],{"type":47,"value":3389},{"type":41,"tag":241,"props":3757,"children":3758},{"class":243,"line":3410},[3759],{"type":41,"tag":241,"props":3760,"children":3761},{},[3762],{"type":47,"value":3398},{"type":41,"tag":241,"props":3764,"children":3766},{"class":243,"line":3765},14,[3767],{"type":41,"tag":241,"props":3768,"children":3769},{},[3770],{"type":47,"value":3407},{"type":41,"tag":241,"props":3772,"children":3774},{"class":243,"line":3773},15,[3775],{"type":41,"tag":241,"props":3776,"children":3777},{},[3778],{"type":47,"value":3416},{"type":41,"tag":157,"props":3780,"children":3781},{},[],{"type":41,"tag":81,"props":3783,"children":3785},{"id":3784},"strategies-for-discovery",[3786],{"type":47,"value":146},{"type":41,"tag":50,"props":3788,"children":3789},{},[3790],{"type":47,"value":3791},"Execute these commands in the terminal to identify legacy matchers and files\nrequiring migration:",{"type":41,"tag":230,"props":3793,"children":3795},{"className":232,"code":3794,"language":234,"meta":235,"style":235},"# 1. Find all test files containing legacy expect() or expectLater()\ngrep -rn \"expect(\" test\u002F\ngrep -rn \"expectLater(\" test\u002F\n\n# 2. Find potential collection equality pitfalls (literal lists or maps)\ngrep -rn \"expect(.*, \\[\" test\u002F\ngrep -rn \"expect(.*, {\" test\u002F\n\n# 3. Find matches() calls (need conversion to RegExp + matchesPattern)\ngrep -rn \"matches(\" test\u002F\n\n# 4. Find legacy TypeMatcher.having() calls (which need conversion to .has())\ngrep -rn \"having(\" test\u002F\n",[3796],{"type":41,"tag":56,"props":3797,"children":3798},{"__ignoreMap":235},[3799,3808,3842,3870,3877,3885,3913,3941,3948,3956,3984,3991,3999],{"type":41,"tag":241,"props":3800,"children":3801},{"class":243,"line":244},[3802],{"type":41,"tag":241,"props":3803,"children":3805},{"style":3804},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[3806],{"type":47,"value":3807},"# 1. Find all test files containing legacy expect() or expectLater()\n",{"type":41,"tag":241,"props":3809,"children":3810},{"class":243,"line":395},[3811,3816,3821,3827,3832,3837],{"type":41,"tag":241,"props":3812,"children":3813},{"style":248},[3814],{"type":47,"value":3815},"grep",{"type":41,"tag":241,"props":3817,"children":3818},{"style":253},[3819],{"type":47,"value":3820}," -rn",{"type":41,"tag":241,"props":3822,"children":3824},{"style":3823},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[3825],{"type":47,"value":3826}," \"",{"type":41,"tag":241,"props":3828,"children":3829},{"style":253},[3830],{"type":47,"value":3831},"expect(",{"type":41,"tag":241,"props":3833,"children":3834},{"style":3823},[3835],{"type":47,"value":3836},"\"",{"type":41,"tag":241,"props":3838,"children":3839},{"style":253},[3840],{"type":47,"value":3841}," test\u002F\n",{"type":41,"tag":241,"props":3843,"children":3844},{"class":243,"line":767},[3845,3849,3853,3857,3862,3866],{"type":41,"tag":241,"props":3846,"children":3847},{"style":248},[3848],{"type":47,"value":3815},{"type":41,"tag":241,"props":3850,"children":3851},{"style":253},[3852],{"type":47,"value":3820},{"type":41,"tag":241,"props":3854,"children":3855},{"style":3823},[3856],{"type":47,"value":3826},{"type":41,"tag":241,"props":3858,"children":3859},{"style":253},[3860],{"type":47,"value":3861},"expectLater(",{"type":41,"tag":241,"props":3863,"children":3864},{"style":3823},[3865],{"type":47,"value":3836},{"type":41,"tag":241,"props":3867,"children":3868},{"style":253},[3869],{"type":47,"value":3841},{"type":41,"tag":241,"props":3871,"children":3872},{"class":243,"line":777},[3873],{"type":41,"tag":241,"props":3874,"children":3875},{"emptyLinePlaceholder":771},[3876],{"type":47,"value":774},{"type":41,"tag":241,"props":3878,"children":3879},{"class":243,"line":786},[3880],{"type":41,"tag":241,"props":3881,"children":3882},{"style":3804},[3883],{"type":47,"value":3884},"# 2. Find potential collection equality pitfalls (literal lists or maps)\n",{"type":41,"tag":241,"props":3886,"children":3887},{"class":243,"line":1314},[3888,3892,3896,3900,3905,3909],{"type":41,"tag":241,"props":3889,"children":3890},{"style":248},[3891],{"type":47,"value":3815},{"type":41,"tag":241,"props":3893,"children":3894},{"style":253},[3895],{"type":47,"value":3820},{"type":41,"tag":241,"props":3897,"children":3898},{"style":3823},[3899],{"type":47,"value":3826},{"type":41,"tag":241,"props":3901,"children":3902},{"style":253},[3903],{"type":47,"value":3904},"expect(.*, \\[",{"type":41,"tag":241,"props":3906,"children":3907},{"style":3823},[3908],{"type":47,"value":3836},{"type":41,"tag":241,"props":3910,"children":3911},{"style":253},[3912],{"type":47,"value":3841},{"type":41,"tag":241,"props":3914,"children":3915},{"class":243,"line":3356},[3916,3920,3924,3928,3933,3937],{"type":41,"tag":241,"props":3917,"children":3918},{"style":248},[3919],{"type":47,"value":3815},{"type":41,"tag":241,"props":3921,"children":3922},{"style":253},[3923],{"type":47,"value":3820},{"type":41,"tag":241,"props":3925,"children":3926},{"style":3823},[3927],{"type":47,"value":3826},{"type":41,"tag":241,"props":3929,"children":3930},{"style":253},[3931],{"type":47,"value":3932},"expect(.*, {",{"type":41,"tag":241,"props":3934,"children":3935},{"style":3823},[3936],{"type":47,"value":3836},{"type":41,"tag":241,"props":3938,"children":3939},{"style":253},[3940],{"type":47,"value":3841},{"type":41,"tag":241,"props":3942,"children":3943},{"class":243,"line":3365},[3944],{"type":41,"tag":241,"props":3945,"children":3946},{"emptyLinePlaceholder":771},[3947],{"type":47,"value":774},{"type":41,"tag":241,"props":3949,"children":3950},{"class":243,"line":3374},[3951],{"type":41,"tag":241,"props":3952,"children":3953},{"style":3804},[3954],{"type":47,"value":3955},"# 3. Find matches() calls (need conversion to RegExp + matchesPattern)\n",{"type":41,"tag":241,"props":3957,"children":3958},{"class":243,"line":3383},[3959,3963,3967,3971,3976,3980],{"type":41,"tag":241,"props":3960,"children":3961},{"style":248},[3962],{"type":47,"value":3815},{"type":41,"tag":241,"props":3964,"children":3965},{"style":253},[3966],{"type":47,"value":3820},{"type":41,"tag":241,"props":3968,"children":3969},{"style":3823},[3970],{"type":47,"value":3826},{"type":41,"tag":241,"props":3972,"children":3973},{"style":253},[3974],{"type":47,"value":3975},"matches(",{"type":41,"tag":241,"props":3977,"children":3978},{"style":3823},[3979],{"type":47,"value":3836},{"type":41,"tag":241,"props":3981,"children":3982},{"style":253},[3983],{"type":47,"value":3841},{"type":41,"tag":241,"props":3985,"children":3986},{"class":243,"line":3392},[3987],{"type":41,"tag":241,"props":3988,"children":3989},{"emptyLinePlaceholder":771},[3990],{"type":47,"value":774},{"type":41,"tag":241,"props":3992,"children":3993},{"class":243,"line":3401},[3994],{"type":41,"tag":241,"props":3995,"children":3996},{"style":3804},[3997],{"type":47,"value":3998},"# 4. Find legacy TypeMatcher.having() calls (which need conversion to .has())\n",{"type":41,"tag":241,"props":4000,"children":4001},{"class":243,"line":3410},[4002,4006,4010,4014,4019,4023],{"type":41,"tag":241,"props":4003,"children":4004},{"style":248},[4005],{"type":47,"value":3815},{"type":41,"tag":241,"props":4007,"children":4008},{"style":253},[4009],{"type":47,"value":3820},{"type":41,"tag":241,"props":4011,"children":4012},{"style":3823},[4013],{"type":47,"value":3826},{"type":41,"tag":241,"props":4015,"children":4016},{"style":253},[4017],{"type":47,"value":4018},"having(",{"type":41,"tag":241,"props":4020,"children":4021},{"style":3823},[4022],{"type":47,"value":3836},{"type":41,"tag":241,"props":4024,"children":4025},{"style":253},[4026],{"type":47,"value":3841},{"type":41,"tag":157,"props":4028,"children":4029},{},[],{"type":41,"tag":81,"props":4031,"children":4033},{"id":4032},"examples",[4034],{"type":47,"value":155},{"type":41,"tag":192,"props":4036,"children":4038},{"id":4037},"basic-assertions",[4039],{"type":47,"value":4040},"Basic Assertions",{"type":41,"tag":50,"props":4042,"children":4043},{},[4044],{"type":41,"tag":355,"props":4045,"children":4046},{},[4047],{"type":47,"value":4048},"Before (Matcher):",{"type":41,"tag":230,"props":4050,"children":4052},{"className":379,"code":4051,"language":18,"meta":235,"style":235},"expect(someValue, isNotNull);\nexpect(result, isTrue, reason: 'should be successful');\nexpect(myString, startsWith('hello'));\n",[4053],{"type":41,"tag":56,"props":4054,"children":4055},{"__ignoreMap":235},[4056,4064,4072],{"type":41,"tag":241,"props":4057,"children":4058},{"class":243,"line":244},[4059],{"type":41,"tag":241,"props":4060,"children":4061},{},[4062],{"type":47,"value":4063},"expect(someValue, isNotNull);\n",{"type":41,"tag":241,"props":4065,"children":4066},{"class":243,"line":395},[4067],{"type":41,"tag":241,"props":4068,"children":4069},{},[4070],{"type":47,"value":4071},"expect(result, isTrue, reason: 'should be successful');\n",{"type":41,"tag":241,"props":4073,"children":4074},{"class":243,"line":767},[4075],{"type":41,"tag":241,"props":4076,"children":4077},{},[4078],{"type":47,"value":4079},"expect(myString, startsWith('hello'));\n",{"type":41,"tag":50,"props":4081,"children":4082},{},[4083],{"type":41,"tag":355,"props":4084,"children":4085},{},[4086],{"type":47,"value":4087},"After (Checks):",{"type":41,"tag":230,"props":4089,"children":4091},{"className":379,"code":4090,"language":18,"meta":235,"style":235},"check(someValue).isNotNull();\ncheck(because: 'should be successful', result).isTrue();\ncheck(myString).startsWith('hello');\n",[4092],{"type":41,"tag":56,"props":4093,"children":4094},{"__ignoreMap":235},[4095,4103,4111],{"type":41,"tag":241,"props":4096,"children":4097},{"class":243,"line":244},[4098],{"type":41,"tag":241,"props":4099,"children":4100},{},[4101],{"type":47,"value":4102},"check(someValue).isNotNull();\n",{"type":41,"tag":241,"props":4104,"children":4105},{"class":243,"line":395},[4106],{"type":41,"tag":241,"props":4107,"children":4108},{},[4109],{"type":47,"value":4110},"check(because: 'should be successful', result).isTrue();\n",{"type":41,"tag":241,"props":4112,"children":4113},{"class":243,"line":767},[4114],{"type":41,"tag":241,"props":4115,"children":4116},{},[4117],{"type":47,"value":4118},"check(myString).startsWith('hello');\n",{"type":41,"tag":192,"props":4120,"children":4122},{"id":4121},"collection-and-deep-equality",[4123],{"type":47,"value":4124},"Collection and Deep Equality",{"type":41,"tag":50,"props":4126,"children":4127},{},[4128],{"type":41,"tag":355,"props":4129,"children":4130},{},[4131],{"type":47,"value":4048},{"type":41,"tag":230,"props":4133,"children":4135},{"className":379,"code":4134,"language":18,"meta":235,"style":235},"expect(items, [1, 2, 3]);\nexpect(configMap, equals({'port': 8080}));\n",[4136],{"type":41,"tag":56,"props":4137,"children":4138},{"__ignoreMap":235},[4139,4147],{"type":41,"tag":241,"props":4140,"children":4141},{"class":243,"line":244},[4142],{"type":41,"tag":241,"props":4143,"children":4144},{},[4145],{"type":47,"value":4146},"expect(items, [1, 2, 3]);\n",{"type":41,"tag":241,"props":4148,"children":4149},{"class":243,"line":395},[4150],{"type":41,"tag":241,"props":4151,"children":4152},{},[4153],{"type":47,"value":4154},"expect(configMap, equals({'port': 8080}));\n",{"type":41,"tag":50,"props":4156,"children":4157},{},[4158],{"type":41,"tag":355,"props":4159,"children":4160},{},[4161],{"type":47,"value":4087},{"type":41,"tag":230,"props":4163,"children":4165},{"className":379,"code":4164,"language":18,"meta":235,"style":235},"check(items).deepEquals([1, 2, 3]);\ncheck(configMap).deepEquals({'port': 8080});\n",[4166],{"type":41,"tag":56,"props":4167,"children":4168},{"__ignoreMap":235},[4169,4177],{"type":41,"tag":241,"props":4170,"children":4171},{"class":243,"line":244},[4172],{"type":41,"tag":241,"props":4173,"children":4174},{},[4175],{"type":47,"value":4176},"check(items).deepEquals([1, 2, 3]);\n",{"type":41,"tag":241,"props":4178,"children":4179},{"class":243,"line":395},[4180],{"type":41,"tag":241,"props":4181,"children":4182},{},[4183],{"type":47,"value":4184},"check(configMap).deepEquals({'port': 8080});\n",{"type":41,"tag":192,"props":4186,"children":4188},{"id":4187},"chaining-and-cascades",[4189],{"type":47,"value":4190},"Chaining and Cascades",{"type":41,"tag":50,"props":4192,"children":4193},{},[4194],{"type":41,"tag":355,"props":4195,"children":4196},{},[4197],{"type":47,"value":4048},{"type":41,"tag":230,"props":4199,"children":4201},{"className":379,"code":4200,"language":18,"meta":235,"style":235},"expect(someString, allOf([\n  startsWith('a'),\n  contains('b'),\n  endsWith('c'),\n]));\n",[4202],{"type":41,"tag":56,"props":4203,"children":4204},{"__ignoreMap":235},[4205,4213,4221,4229,4237],{"type":41,"tag":241,"props":4206,"children":4207},{"class":243,"line":244},[4208],{"type":41,"tag":241,"props":4209,"children":4210},{},[4211],{"type":47,"value":4212},"expect(someString, allOf([\n",{"type":41,"tag":241,"props":4214,"children":4215},{"class":243,"line":395},[4216],{"type":41,"tag":241,"props":4217,"children":4218},{},[4219],{"type":47,"value":4220},"  startsWith('a'),\n",{"type":41,"tag":241,"props":4222,"children":4223},{"class":243,"line":767},[4224],{"type":41,"tag":241,"props":4225,"children":4226},{},[4227],{"type":47,"value":4228},"  contains('b'),\n",{"type":41,"tag":241,"props":4230,"children":4231},{"class":243,"line":777},[4232],{"type":41,"tag":241,"props":4233,"children":4234},{},[4235],{"type":47,"value":4236},"  endsWith('c'),\n",{"type":41,"tag":241,"props":4238,"children":4239},{"class":243,"line":786},[4240],{"type":41,"tag":241,"props":4241,"children":4242},{},[4243],{"type":47,"value":4244},"]));\n",{"type":41,"tag":50,"props":4246,"children":4247},{},[4248],{"type":41,"tag":355,"props":4249,"children":4250},{},[4251],{"type":47,"value":4087},{"type":41,"tag":230,"props":4253,"children":4255},{"className":379,"code":4254,"language":18,"meta":235,"style":235},"check(someString)\n  ..startsWith('a')\n  ..contains('b')\n  ..endsWith('c');\n",[4256],{"type":41,"tag":56,"props":4257,"children":4258},{"__ignoreMap":235},[4259,4267,4275,4283],{"type":41,"tag":241,"props":4260,"children":4261},{"class":243,"line":244},[4262],{"type":41,"tag":241,"props":4263,"children":4264},{},[4265],{"type":47,"value":4266},"check(someString)\n",{"type":41,"tag":241,"props":4268,"children":4269},{"class":243,"line":395},[4270],{"type":41,"tag":241,"props":4271,"children":4272},{},[4273],{"type":47,"value":4274},"  ..startsWith('a')\n",{"type":41,"tag":241,"props":4276,"children":4277},{"class":243,"line":767},[4278],{"type":41,"tag":241,"props":4279,"children":4280},{},[4281],{"type":47,"value":4282},"  ..contains('b')\n",{"type":41,"tag":241,"props":4284,"children":4285},{"class":243,"line":777},[4286],{"type":41,"tag":241,"props":4287,"children":4288},{},[4289],{"type":47,"value":4290},"  ..endsWith('c');\n",{"type":41,"tag":192,"props":4292,"children":4294},{"id":4293},"complex-property-matching-has",[4295],{"type":47,"value":4296},"Complex Property Matching (has)",{"type":41,"tag":50,"props":4298,"children":4299},{},[4300],{"type":41,"tag":355,"props":4301,"children":4302},{},[4303],{"type":47,"value":4048},{"type":41,"tag":230,"props":4305,"children":4307},{"className":379,"code":4306,"language":18,"meta":235,"style":235},"expect(response, isA\u003CResponse>()\n    .having((r) => r.statusCode, 'statusCode', 200)\n    .having((r) => r.body, 'body', contains('success')));\n",[4308],{"type":41,"tag":56,"props":4309,"children":4310},{"__ignoreMap":235},[4311,4319,4327],{"type":41,"tag":241,"props":4312,"children":4313},{"class":243,"line":244},[4314],{"type":41,"tag":241,"props":4315,"children":4316},{},[4317],{"type":47,"value":4318},"expect(response, isA\u003CResponse>()\n",{"type":41,"tag":241,"props":4320,"children":4321},{"class":243,"line":395},[4322],{"type":41,"tag":241,"props":4323,"children":4324},{},[4325],{"type":47,"value":4326},"    .having((r) => r.statusCode, 'statusCode', 200)\n",{"type":41,"tag":241,"props":4328,"children":4329},{"class":243,"line":767},[4330],{"type":41,"tag":241,"props":4331,"children":4332},{},[4333],{"type":47,"value":4334},"    .having((r) => r.body, 'body', contains('success')));\n",{"type":41,"tag":50,"props":4336,"children":4337},{},[4338],{"type":41,"tag":355,"props":4339,"children":4340},{},[4341],{"type":47,"value":4087},{"type":41,"tag":230,"props":4343,"children":4345},{"className":379,"code":4344,"language":18,"meta":235,"style":235},"check(response).isA\u003CResponse>()\n  ..has((r) => r.statusCode, 'statusCode').equals(200)\n  ..has((r) => r.body, 'body').contains('success');\n",[4346],{"type":41,"tag":56,"props":4347,"children":4348},{"__ignoreMap":235},[4349,4357,4365],{"type":41,"tag":241,"props":4350,"children":4351},{"class":243,"line":244},[4352],{"type":41,"tag":241,"props":4353,"children":4354},{},[4355],{"type":47,"value":4356},"check(response).isA\u003CResponse>()\n",{"type":41,"tag":241,"props":4358,"children":4359},{"class":243,"line":395},[4360],{"type":41,"tag":241,"props":4361,"children":4362},{},[4363],{"type":47,"value":4364},"  ..has((r) => r.statusCode, 'statusCode').equals(200)\n",{"type":41,"tag":241,"props":4366,"children":4367},{"class":243,"line":767},[4368],{"type":41,"tag":241,"props":4369,"children":4370},{},[4371],{"type":47,"value":4372},"  ..has((r) => r.body, 'body').contains('success');\n",{"type":41,"tag":192,"props":4374,"children":4376},{"id":4375},"asynchronous-futures",[4377],{"type":47,"value":4378},"Asynchronous Futures",{"type":41,"tag":50,"props":4380,"children":4381},{},[4382],{"type":41,"tag":355,"props":4383,"children":4384},{},[4385],{"type":47,"value":4048},{"type":41,"tag":230,"props":4387,"children":4389},{"className":379,"code":4388,"language":18,"meta":235,"style":235},"expect(fetchData(), completes);\nexpect(fetchData(), completion(equals('data')));\nexpect(failingCall(), throwsA(isA\u003CStateError>()));\n",[4390],{"type":41,"tag":56,"props":4391,"children":4392},{"__ignoreMap":235},[4393,4401,4409],{"type":41,"tag":241,"props":4394,"children":4395},{"class":243,"line":244},[4396],{"type":41,"tag":241,"props":4397,"children":4398},{},[4399],{"type":47,"value":4400},"expect(fetchData(), completes);\n",{"type":41,"tag":241,"props":4402,"children":4403},{"class":243,"line":395},[4404],{"type":41,"tag":241,"props":4405,"children":4406},{},[4407],{"type":47,"value":4408},"expect(fetchData(), completion(equals('data')));\n",{"type":41,"tag":241,"props":4410,"children":4411},{"class":243,"line":767},[4412],{"type":41,"tag":241,"props":4413,"children":4414},{},[4415],{"type":47,"value":4416},"expect(failingCall(), throwsA(isA\u003CStateError>()));\n",{"type":41,"tag":50,"props":4418,"children":4419},{},[4420],{"type":41,"tag":355,"props":4421,"children":4422},{},[4423],{"type":47,"value":4087},{"type":41,"tag":230,"props":4425,"children":4427},{"className":379,"code":4426,"language":18,"meta":235,"style":235},"await check(fetchData()).completes();\nawait check(fetchData()).completes((it) => it.equals('data'));\nawait check(failingCall()).throws\u003CStateError>();\n",[4428],{"type":41,"tag":56,"props":4429,"children":4430},{"__ignoreMap":235},[4431,4439,4447],{"type":41,"tag":241,"props":4432,"children":4433},{"class":243,"line":244},[4434],{"type":41,"tag":241,"props":4435,"children":4436},{},[4437],{"type":47,"value":4438},"await check(fetchData()).completes();\n",{"type":41,"tag":241,"props":4440,"children":4441},{"class":243,"line":395},[4442],{"type":41,"tag":241,"props":4443,"children":4444},{},[4445],{"type":47,"value":4446},"await check(fetchData()).completes((it) => it.equals('data'));\n",{"type":41,"tag":241,"props":4448,"children":4449},{"class":243,"line":767},[4450],{"type":41,"tag":241,"props":4451,"children":4452},{},[4453],{"type":47,"value":4454},"await check(failingCall()).throws\u003CStateError>();\n",{"type":41,"tag":192,"props":4456,"children":4458},{"id":4457},"asynchronous-streams",[4459],{"type":47,"value":4460},"Asynchronous Streams",{"type":41,"tag":50,"props":4462,"children":4463},{},[4464],{"type":41,"tag":355,"props":4465,"children":4466},{},[4467],{"type":47,"value":4048},{"type":41,"tag":230,"props":4469,"children":4471},{"className":379,"code":4470,"language":18,"meta":235,"style":235},"var queue = StreamQueue(Stream.fromIterable([1, 2, 3]));\nawait expectLater(queue, emitsInOrder([1, 2, 3]));\n",[4472],{"type":41,"tag":56,"props":4473,"children":4474},{"__ignoreMap":235},[4475,4483],{"type":41,"tag":241,"props":4476,"children":4477},{"class":243,"line":244},[4478],{"type":41,"tag":241,"props":4479,"children":4480},{},[4481],{"type":47,"value":4482},"var queue = StreamQueue(Stream.fromIterable([1, 2, 3]));\n",{"type":41,"tag":241,"props":4484,"children":4485},{"class":243,"line":395},[4486],{"type":41,"tag":241,"props":4487,"children":4488},{},[4489],{"type":47,"value":4490},"await expectLater(queue, emitsInOrder([1, 2, 3]));\n",{"type":41,"tag":50,"props":4492,"children":4493},{},[4494],{"type":41,"tag":355,"props":4495,"children":4496},{},[4497],{"type":47,"value":4087},{"type":41,"tag":230,"props":4499,"children":4501},{"className":379,"code":4500,"language":18,"meta":235,"style":235},"var queue = StreamQueue(Stream.fromIterable([1, 2, 3]));\nawait check(queue).inOrder([\n  (s) => s.emits((e) => e.equals(1)),\n  (s) => s.emits((e) => e.equals(2)),\n  (s) => s.emits((e) => e.equals(3)),\n]);\n",[4502],{"type":41,"tag":56,"props":4503,"children":4504},{"__ignoreMap":235},[4505,4512,4520,4528,4536,4544],{"type":41,"tag":241,"props":4506,"children":4507},{"class":243,"line":244},[4508],{"type":41,"tag":241,"props":4509,"children":4510},{},[4511],{"type":47,"value":4482},{"type":41,"tag":241,"props":4513,"children":4514},{"class":243,"line":395},[4515],{"type":41,"tag":241,"props":4516,"children":4517},{},[4518],{"type":47,"value":4519},"await check(queue).inOrder([\n",{"type":41,"tag":241,"props":4521,"children":4522},{"class":243,"line":767},[4523],{"type":41,"tag":241,"props":4524,"children":4525},{},[4526],{"type":47,"value":4527},"  (s) => s.emits((e) => e.equals(1)),\n",{"type":41,"tag":241,"props":4529,"children":4530},{"class":243,"line":777},[4531],{"type":41,"tag":241,"props":4532,"children":4533},{},[4534],{"type":47,"value":4535},"  (s) => s.emits((e) => e.equals(2)),\n",{"type":41,"tag":241,"props":4537,"children":4538},{"class":243,"line":786},[4539],{"type":41,"tag":241,"props":4540,"children":4541},{},[4542],{"type":47,"value":4543},"  (s) => s.emits((e) => e.equals(3)),\n",{"type":41,"tag":241,"props":4545,"children":4546},{"class":243,"line":1314},[4547],{"type":41,"tag":241,"props":4548,"children":4549},{},[4550],{"type":47,"value":4551},"]);\n",{"type":41,"tag":4553,"props":4554,"children":4555},"style",{},[4556],{"type":47,"value":4557},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":4559,"total":4687},[4560,4569,4580,4592,4603,4612,4618,4630,4642,4654,4668,4678],{"slug":4561,"name":4561,"fn":4562,"description":4563,"org":4564,"tags":4565,"stars":22,"repoUrl":23,"updatedAt":4568},"dart-add-unit-test","write unit tests for Dart code","Write and organize unit tests for functions, methods, and classes using `package:test`. Use when creating new logic or fixing bugs to ensure code remains correct and regression-free.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4566,4567],{"name":17,"slug":18,"type":15},{"name":20,"slug":21,"type":15},"2026-07-15T05:22:40.104823",{"slug":4570,"name":4570,"fn":4571,"description":4572,"org":4573,"tags":4574,"stars":22,"repoUrl":23,"updatedAt":4579},"dart-build-cli-app","build Dart command line applications","Entrypoint structure, exit codes, cross-platform scripts. Use when building command line utilities, scripts, or applications.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4575,4578],{"name":4576,"slug":4577,"type":15},"CLI","cli",{"name":17,"slug":18,"type":15},"2026-07-15T05:22:18.863572",{"slug":4581,"name":4581,"fn":4582,"description":4583,"org":4584,"tags":4585,"stars":22,"repoUrl":23,"updatedAt":4591},"dart-collect-coverage","collect Dart test coverage reports","Collect coverage using the coverage packge and create an LCOV report",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4586,4587,4590],{"name":17,"slug":18,"type":15},{"name":4588,"slug":4589,"type":15},"Reporting","reporting",{"name":20,"slug":21,"type":15},"2026-07-15T05:22:21.38636",{"slug":4593,"name":4593,"fn":4594,"description":4595,"org":4596,"tags":4597,"stars":22,"repoUrl":23,"updatedAt":4602},"dart-fix-runtime-errors","debug and fix Dart runtime errors","Uses get_runtime_errors and lsp to fetch an active stack trace, locate the failing line, apply a fix, and verify resolution via hot_reload.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4598,4599],{"name":17,"slug":18,"type":15},{"name":4600,"slug":4601,"type":15},"Debugging","debugging","2026-07-15T05:22:22.622501",{"slug":4604,"name":4604,"fn":4605,"description":4606,"org":4607,"tags":4608,"stars":22,"repoUrl":23,"updatedAt":4611},"dart-generate-test-mocks","generate mock objects for Dart tests","Define and generate mock objects for external dependencies using `package:mockito` and `build_runner`. Use when unit testing classes that depend on complex external services like APIs or databases.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4609,4610],{"name":17,"slug":18,"type":15},{"name":20,"slug":21,"type":15},"2026-07-15T05:22:42.607449",{"slug":4,"name":4,"fn":5,"description":6,"org":4613,"tags":4614,"stars":22,"repoUrl":23,"updatedAt":24},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4615,4616,4617],{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"name":20,"slug":21,"type":15},{"slug":4619,"name":4619,"fn":4620,"description":4621,"org":4622,"tags":4623,"stars":22,"repoUrl":23,"updatedAt":4629},"dart-resolve-package-conflicts","resolve Dart package version conflicts","Workflow for fixing package version conflicts. Use this when `pub get` fails due to incompatible package versions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4624,4625,4626],{"name":17,"slug":18,"type":15},{"name":4600,"slug":4601,"type":15},{"name":4627,"slug":4628,"type":15},"Engineering","engineering","2026-07-15T05:22:30.059335",{"slug":4631,"name":4631,"fn":4632,"description":4633,"org":4634,"tags":4635,"stars":22,"repoUrl":23,"updatedAt":4641},"dart-run-static-analysis","run static analysis and apply fixes","Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4636,4639,4640],{"name":4637,"slug":4638,"type":15},"Code Analysis","code-analysis",{"name":17,"slug":18,"type":15},{"name":4600,"slug":4601,"type":15},"2026-07-15T05:22:23.861119",{"slug":4643,"name":4643,"fn":4644,"description":4645,"org":4646,"tags":4647,"stars":22,"repoUrl":23,"updatedAt":4653},"dart-setup-ffi-assets","package C\u002FC++ assets for Dart","Guides agents in compiling and packaging C\u002FC++ source code into dynamic or static libraries (Code Assets) using Dart's Native Assets hook system (via hook\u002Fbuild.dart and hook\u002Flink.dart utilizing package:hooks and package:native_toolchain_c). Use when a user asks to: 'setup native assets', 'compile C\u002FC++ source code', 'bundle dynamic libraries', 'build native C code', 'link native assets', 'implement build.dart or link.dart hooks', or 'integrate C\u002FC++ interop in Dart\u002FFlutter'. Helps agents avoid manual toolchain orchestration and configures secure hash-validated binary downloads or advanced linker tree-shaking with package:record_use mapping.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4648,4649,4652],{"name":17,"slug":18,"type":15},{"name":4650,"slug":4651,"type":15},"Deployment","deployment",{"name":4627,"slug":4628,"type":15},"2026-07-15T05:22:20.138636",{"slug":4655,"name":4655,"fn":4656,"description":4657,"org":4658,"tags":4659,"stars":22,"repoUrl":23,"updatedAt":4667},"dart-skills-lint-setup","configure dart_skills_lint for Dart projects","Use this skill when you need to set up validation for AI agent skills in a Dart project for the first time.\nAdds the linter as a dev_dependency, creates a configuration file, and generates a baseline for legacy repos.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4660,4661,4664],{"name":17,"slug":18,"type":15},{"name":4662,"slug":4663,"type":15},"Plugin Development","plugin-development",{"name":4665,"slug":4666,"type":15},"QA","qa","2026-07-15T05:22:47.488998",{"slug":4669,"name":4669,"fn":4670,"description":4671,"org":4672,"tags":4673,"stars":22,"repoUrl":23,"updatedAt":4677},"dart-skills-lint-validation","validate agent skills with dart_skills_lint","Use this skill when you need to validate AI agent skills with dart_skills_lint — running the linter, interpreting failures, fixing violations, and authoring custom rules.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4674,4675,4676],{"name":17,"slug":18,"type":15},{"name":4662,"slug":4663,"type":15},{"name":4665,"slug":4666,"type":15},"2026-07-21T05:38:34.451024",{"slug":4679,"name":4679,"fn":4680,"description":4681,"org":4682,"tags":4683,"stars":22,"repoUrl":23,"updatedAt":4686},"dart-use-ffigen","generate FFI bindings with ffigen","Guide agents to use `package:ffigen` to automatically generate FFI bindings instead of writing them manually. Use this skill when a task involves writing new FFI bindings, extending C\u002FObjective-C\u002FSwift integrations, or replacing hand-crafted `dart:ffi` setups.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4684,4685],{"name":17,"slug":18,"type":15},{"name":4627,"slug":4628,"type":15},"2026-07-15T05:22:17.592351",27,{"items":4689,"total":4728},[4690,4695,4700,4706,4711,4716,4722],{"slug":4561,"name":4561,"fn":4562,"description":4563,"org":4691,"tags":4692,"stars":22,"repoUrl":23,"updatedAt":4568},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4693,4694],{"name":17,"slug":18,"type":15},{"name":20,"slug":21,"type":15},{"slug":4570,"name":4570,"fn":4571,"description":4572,"org":4696,"tags":4697,"stars":22,"repoUrl":23,"updatedAt":4579},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4698,4699],{"name":4576,"slug":4577,"type":15},{"name":17,"slug":18,"type":15},{"slug":4581,"name":4581,"fn":4582,"description":4583,"org":4701,"tags":4702,"stars":22,"repoUrl":23,"updatedAt":4591},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4703,4704,4705],{"name":17,"slug":18,"type":15},{"name":4588,"slug":4589,"type":15},{"name":20,"slug":21,"type":15},{"slug":4593,"name":4593,"fn":4594,"description":4595,"org":4707,"tags":4708,"stars":22,"repoUrl":23,"updatedAt":4602},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4709,4710],{"name":17,"slug":18,"type":15},{"name":4600,"slug":4601,"type":15},{"slug":4604,"name":4604,"fn":4605,"description":4606,"org":4712,"tags":4713,"stars":22,"repoUrl":23,"updatedAt":4611},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4714,4715],{"name":17,"slug":18,"type":15},{"name":20,"slug":21,"type":15},{"slug":4,"name":4,"fn":5,"description":6,"org":4717,"tags":4718,"stars":22,"repoUrl":23,"updatedAt":24},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4719,4720,4721],{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"name":20,"slug":21,"type":15},{"slug":4619,"name":4619,"fn":4620,"description":4621,"org":4723,"tags":4724,"stars":22,"repoUrl":23,"updatedAt":4629},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4725,4726,4727],{"name":17,"slug":18,"type":15},{"name":4600,"slug":4601,"type":15},{"name":4627,"slug":4628,"type":15},24]