Skip to content

Commit 4998763

Browse files
Add reason parameter to waitFor. (#305)
This parameter allows customizing the error message if the waitFor fails.
1 parent ffcd45e commit 4998763

File tree

4 files changed

+38
-9
lines changed

4 files changed

+38
-9
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 3.1.0-wip
2+
3+
* Add a `reason` argument to `Clock.waitFor`.
4+
15
## 3.0.4
26

37
* Require Dart 3.1.

lib/support/async.dart

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import 'dart:async' show Completer, FutureOr;
1616

17-
import 'package:matcher/matcher.dart' as m;
17+
import 'package:matcher/expect.dart' as m;
1818
import 'package:stack_trace/stack_trace.dart' show Chain;
1919

2020
const defaultInterval = Duration(milliseconds: 500);
@@ -25,9 +25,10 @@ const clock = Clock();
2525
Future<T> waitFor<T>(FutureOr<T> Function() condition,
2626
{Object? matcher,
2727
Duration timeout = defaultTimeout,
28-
Duration interval = defaultInterval}) =>
28+
Duration interval = defaultInterval,
29+
String? reason}) =>
2930
clock.waitFor<T>(condition,
30-
matcher: matcher, timeout: timeout, interval: interval);
31+
matcher: matcher, timeout: timeout, interval: interval, reason: reason);
3132

3233
class Clock {
3334
const Clock();
@@ -47,17 +48,22 @@ class Clock {
4748
/// is returned. Otherwise, if [condition] throws, then that exception is
4849
/// rethrown. If [condition] doesn't throw then an [expect] exception is
4950
/// thrown.
51+
///
52+
/// [reason] is optional and is typically not supplied, as a reason is
53+
/// generated from [matcher]; if [reason] is included it is appended to the
54+
/// reason generated by the matcher.
5055
Future<T> waitFor<T>(FutureOr<T> Function() condition,
5156
{Object? matcher,
5257
Duration timeout = defaultTimeout,
53-
Duration interval = defaultInterval}) async {
58+
Duration interval = defaultInterval,
59+
String? reason}) async {
5460
final mMatcher = matcher == null ? null : m.wrapMatcher(matcher);
5561
final endTime = now.add(timeout);
5662
while (true) {
5763
try {
5864
final value = await condition();
5965
if (mMatcher != null) {
60-
_matcherExpect(value, mMatcher);
66+
_matcherExpect(value, mMatcher, reason);
6167
}
6268
return value;
6369
} catch (e) {
@@ -71,7 +77,7 @@ class Clock {
7177
}
7278
}
7379

74-
void _matcherExpect(Object? value, m.Matcher matcher) {
80+
void _matcherExpect(Object? value, m.Matcher matcher, String? reason) {
7581
final matchState = {};
7682
if (matcher.matches(value, matchState)) {
7783
return;
@@ -89,7 +95,12 @@ void _matcherExpect(Object? value, m.Matcher matcher) {
8995
if (mismatchDescription.length > 0) {
9096
desc.add(' Which: $mismatchDescription\n');
9197
}
92-
throw Exception(desc.toString());
98+
99+
if (reason != null) {
100+
desc.add('$reason\n');
101+
}
102+
103+
m.fail(desc.toString());
93104
}
94105

95106
class Lock {

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: webdriver
2-
version: 3.0.4
2+
version: 3.1.0-wip
33
description: >-
44
Provides WebDriver bindings for Dart. Supports WebDriver JSON interface and
55
W3C spec. Requires the use of WebDriver remote server.

test/support/async_test.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ void main() {
106106
expect(result, equals('Google'));
107107
});
108108

109-
test('throws if condition throws and timeouts', () async {
109+
test('throws if condition throws', () async {
110110
Object? exception;
111111

112112
try {
@@ -127,6 +127,20 @@ void main() {
127127
expect(exception, isNotNull);
128128
});
129129

130+
test('throws with passed reason if condition never matches', () async {
131+
Object? exception;
132+
try {
133+
await clock.waitFor(() => null,
134+
matcher: isNotNull, reason: 'some reason');
135+
} catch (e) {
136+
exception = e;
137+
}
138+
expect(
139+
exception,
140+
isA<TestFailure>()
141+
.having((e) => e.message, 'message', contains('some reason')));
142+
});
143+
130144
test('uses Future value', () async {
131145
final result = await clock.waitFor(() => Future.value('a value'),
132146
matcher: 'a value');

0 commit comments

Comments
 (0)