Skip to content

Commit 2cb07a3

Browse files
authored
Rename matches to matchesPattern, accept Pattern (#1907)
This will treat a `String` argument differently from the equivalent matcher in `package:matcher`, which would have converted strings to regex. Document this in the migration guide. Add tests showing the behavior of passing strings, and explicitly choose cases that show the argument is not treated as a regular expression. Expand the doc comment and show examples of both types of arguments.
1 parent ba6fb1c commit 2cb07a3

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

pkgs/checks/CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
- `nestAsync` no longer returns a `Subject`, callers must pass the
1212
followup `Condition` to the nullable argument.
1313
- Remove the `which` extension on `Future<Subject>`.
14-
- Add a constructor for `Condition` which takes a callback to invoke when
15-
`apply` or `applyAsync` is called.
14+
- `matches` renamed to `matchesPattern` and now accepts a `Pattern`
15+
argument, instead of limiting to `RegExp`.
1616
- Added an example.
1717
- Include a stack trace in the failure description for unexpected errors from
1818
Futures or Streams.

pkgs/checks/doc/migrating_from_matcher.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ check(actualCollection).deepEquals(expected);
6666
value to check for equality, a matcher for the emitted value, or a matcher
6767
for the entire queue which would match multiple values. Use `it()..emits()`
6868
to check the emitted elements.
69+
- In `package:matcher` the [`matches` Matcher][matches] converted a `String`
70+
argument into a `Regex`, so `matches(r'\d')` would match the value `'1'`.
71+
This was potentially confusing, because even though `String` is a subtype of
72+
`Pattern`, it wasn't used as a pattern directly.
73+
With `matchesPattern` a `String` argument is used as a `Pattern` and
74+
comparison uses [`String.allMatches`][allMatches].
75+
For backwards compatibility change `matches(regexString)` to
76+
`matchesPattern(RegExp(regexString))`.
77+
78+
[matches]:https://pub.dev/documentation/matcher/latest/matcher/Matcher/matches.html
79+
[allMatches]:https://api.dart.dev/stable/2.19.1/dart-core/Pattern/allMatches.html
6980

7081
## Matchers with replacements under a different name
7182

pkgs/checks/lib/src/extensions/string.dart

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,18 @@ extension StringChecks on Subject<String> {
5959
);
6060
}
6161

62-
/// Expects that the string matches the regular expression [expected].
63-
void matches(RegExp expected) {
62+
/// Expects that the string matches the pattern [expected].
63+
///
64+
/// Fails if [expected] returns an empty result from calling `allMatches` with
65+
/// the value.
66+
///
67+
/// ```
68+
/// check(actual).matchesPattern('abc');
69+
/// check(actual).matchesPattern(RegExp(r'\d'));
70+
/// ```
71+
void matchesPattern(Pattern expected) {
6472
context.expect(() => prefixFirst('matches ', literal(expected)), (actual) {
65-
if (expected.hasMatch(actual)) return null;
73+
if (expected.allMatches(actual).isNotEmpty) return null;
6674
return Rejection(
6775
which: prefixFirst('does not match ', literal(expected)));
6876
});

pkgs/checks/test/extensions/string_test.dart

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,29 @@ void main() {
3737
});
3838

3939
group('matches', () {
40-
test('succeeds for strings that match', () {
41-
check('123').matches(RegExp(r'\d\d\d'));
40+
test('succeeds for strings that match a regex', () {
41+
check('123').matchesPattern(RegExp(r'\d\d\d'));
4242
});
43-
test('fails for non-matching strings', () {
44-
check('abc').isRejectedBy(it()..matches(RegExp(r'\d\d\d')),
43+
test('succeeds for strings that match a string pattern', () {
44+
check(r'\d').matchesPattern(r'\d');
45+
});
46+
test('fails for non-matching regex', () {
47+
check('abc').isRejectedBy(it()..matchesPattern(RegExp(r'\d\d\d')),
4548
which: [r'does not match <RegExp: pattern=\d\d\d flags=>']);
4649
});
50+
test('fails for non-matching string pattern', () {
51+
// A string is _not_ converted to a regex, string patterns must match
52+
// directly.
53+
check('123').isRejectedBy(it()..matchesPattern(r'\d\d\d'),
54+
which: [r"does not match '\\d\\d\\d'"]);
55+
});
4756
test('can be described', () {
48-
check(it<String>()..matches(RegExp(r'\d\d\d')))
57+
check(it<String>()..matchesPattern(RegExp(r'\d\d\d')))
4958
.description
5059
.deepEquals([r' matches <RegExp: pattern=\d\d\d flags=>']);
60+
check(it<String>()..matchesPattern('abc'))
61+
.description
62+
.deepEquals([r" matches 'abc'"]);
5163
});
5264
});
5365

0 commit comments

Comments
 (0)