matcher-to-checks

📁 kevmoo/dash_skills 📅 7 days ago
4
总安装量
4
周安装量
#47895
全站排名
安装命令
npx skills add https://github.com/kevmoo/dash_skills --skill matcher-to-checks

Agent 安装分布

opencode 4
amp 3
kimi-cli 3
codex 3
gemini-cli 3

Skill 文档

When to use this skill

In a Dart or Flutter project. When a user asks to migrate to package:checks or just “checks”.

The Workflow

  1. Analysis:
    • Use grep to identify files using expect or package:matcher.
    • Review custom matchers; these may require manual migration.
  2. Tools & Dependencies:
    • Ensure dev_dependencies includes checks.
    • Run dart pub add --dev checks if missing.
  3. Discovery:
    • Use the Strategies for Discovery below to find candidates.
  4. Replacement:
    • Add import 'package:checks/checks.dart';.
    • Apply the Common Patterns below.
    • Final Step: Replace import 'package:test/test.dart'; with import 'package:test/scaffolding.dart'; ONLY after all expect calls are replaced. This ensures incremental progress.
  5. Verification:
    • Ensure the code analyzes cleanly.
    • Ensure tests pass.
    • Prefer using the Dart MCP server (vs the dart command line) if available.

Strategies for Discovery

Use these commands to find migration candidates:

  • Find usages of expect: grep -r "expect(" test/
  • Find usages of expectLater: grep -r "expectLater(" test/
  • Find specific matchers (e.g. isTrue): grep -r "isTrue" test/

Common Patterns

Legacy expect Modern check
expect(a, equals(b)) check(a).equals(b)
expect(a, isTrue) check(a).isTrue()
expect(a, isFalse) check(a).isFalse()
expect(a, isNull) check(a).isNull()
expect(a, isNotNull) check(a).isNotNull()
expect(() => fn(), throwsA<T>()) check(() => fn()).throws<T>()
expect(list, hasLength(n)) check(list).length.equals(n)
expect(a, closeTo(b, delta)) check(a).isA<num>().isCloseTo(b, delta)
expect(a, greaterThan(b)) check(a).isGreaterThan(b)
expect(a, lessThan(b)) check(a).isLessThan(b)
expect(a, unorderedEquals(b)) check(a).unorderedEquals(b)
expect(list, isEmpty) check(list).isEmpty()
expect(list, isNotEmpty) check(list).isNotEmpty()
expect(list, contains(item)) check(list).contains(item)
expect(map, equals(otherMap)) check(map).deepEquals(otherMap)
expect(list, equals(otherList)) check(list).deepEquals(otherList)
expect(future, completes) await check(future).completes()
expect(stream, emitsInOrder(...)) await check(stream).withQueue.inOrder(...)

Async & Futures (CRITICAL)

  • Checking async functions: check(() => asyncFunc()).throws<T>() causes FALSE POSITIVES because the closure returns a Future, which is a value, so it “completes normally” (as a Future). Correct Usage:

    await check(asyncFunc()).throws<T>();
    
  • Chaining on void returns: Many async check methods (like throws) return Future<void>. You cannot chain directly on them. Use cascades or callbacks. Wrong:

    await check(future).throws<Error>().has((e) => e.message, 'message').equals('foo');
    

    Correct:

    await check(future).throws<Error>((it) => it.has((e) => e.message, 'message').equals('foo'));
    

Complex Examples:

Deep Verification with isA and having:

Legacy:

expect(() => foo(), throwsA(isA<ArgumentError>()
    .having((e) => e.message, 'message', contains('MSG'))));

Modern:

check(() => foo())
    .throws<ArgumentError>()
    .has((e) => e.message, 'message')
    .contains('MSG');

Every Element:

Legacy:

expect(list, everyElement(isA<int>().having((e) => e.isEven, 'isEven', isTrue)));

Modern:

check(list).every((e) => e.isA<int>()
    .has((v) => v.isEven, 'isEven').isTrue());

Property Extraction:

Legacy:

expect(obj.prop, equals(value)); // When checking multiple props

Modern:

check(obj)
  ..has((e) => e.prop, 'prop').equals(value)
  ..has((e) => e.other, 'other').equals(otherValue);

One-line Cascades: Since checks often return void, use cascades for multiple assertions on the same subject.

check(it)..isGreaterThan(10)..isLessThan(20);

Constraints

  • Scope: Only modify files in test/ (and pubspec.yaml).
  • Correctness: One failing test is unacceptable. If a test fails after migration and you cannot fix it immediately, REVERT that specific change.
  • Type Safety: package:checks is stricter about types than matcher. You may need to add explicit as T casts or isA<T>() checks in the chain.