@@ -63,7 +63,7 @@ extension Skip<T> on Subject<T> {
63
63
Subject <T > check <T >(T value, {String ? because}) => Subject ._(_TestContext ._root (
64
64
value: _Present (value),
65
65
// TODO - switch between "a" and "an"
66
- label: 'a $T ' ,
66
+ label: () => [ 'a $T ' ] ,
67
67
fail: (f) {
68
68
final which = f.rejection.which;
69
69
throw TestFailure ([
@@ -261,7 +261,8 @@ abstract class Context<T> {
261
261
/// context. The [label] will be used as if it were a single line "clause"
262
262
/// passed to [expect] . If the label is empty, the clause will be omitted. The
263
263
/// label should only be left empty if the value extraction cannot fail.
264
- Subject <R > nest <R >(String label, Extracted <R > Function (T ) extract,
264
+ Subject <R > nest <R >(
265
+ Iterable <String > Function () label, Extracted <R > Function (T ) extract,
265
266
{bool atSameLevel = false });
266
267
267
268
/// Extract an asynchronous property from the value for further checking.
@@ -277,8 +278,8 @@ abstract class Context<T> {
277
278
/// Some context may disallow asynchronous expectations, for instance in
278
279
/// [softCheck] which must synchronously check the value. In those contexts
279
280
/// this method will throw.
280
- Future <Subject <R >> nestAsync <R >(
281
- String label, FutureOr <Extracted <R >> Function (T ) extract);
281
+ Future <Subject <R >> nestAsync <R >(Iterable < String > Function () label,
282
+ FutureOr <Extracted <R >> Function (T ) extract);
282
283
}
283
284
284
285
/// A property extracted from a value being checked, or a rejection.
@@ -363,7 +364,7 @@ class _TestContext<T> implements Context<T>, _ClauseDescription {
363
364
final List <_TestContext > _aliases;
364
365
365
366
// The "a value" in "a value that:".
366
- final String _label;
367
+ final Iterable < String > Function () _label;
367
368
368
369
final void Function (CheckFailure ) _fail;
369
370
@@ -375,9 +376,9 @@ class _TestContext<T> implements Context<T>, _ClauseDescription {
375
376
required void Function (CheckFailure ) fail,
376
377
required bool allowAsync,
377
378
required bool allowUnawaited,
378
- String ? label,
379
+ Iterable < String > Function () ? label,
379
380
}) : _value = value,
380
- _label = label ?? '' ,
381
+ _label = label ?? (() => [ '' ]) ,
381
382
_fail = fail,
382
383
_allowAsync = allowAsync,
383
384
_allowUnawaited = allowUnawaited,
@@ -394,7 +395,7 @@ class _TestContext<T> implements Context<T>, _ClauseDescription {
394
395
_allowUnawaited = original._allowUnawaited,
395
396
// Never read from an aliased context because they are never present in
396
397
// `_clauses`.
397
- _label = '' ;
398
+ _label = (() => [ '' ]) ;
398
399
399
400
_TestContext ._child (this ._value, this ._label, _TestContext <dynamic > parent)
400
401
: _parent = parent,
@@ -444,20 +445,21 @@ class _TestContext<T> implements Context<T>, _ClauseDescription {
444
445
}
445
446
446
447
@override
447
- Subject <R > nest <R >(String label, Extracted <R > Function (T ) extract,
448
+ Subject <R > nest <R >(
449
+ Iterable <String > Function () label, Extracted <R > Function (T ) extract,
448
450
{bool atSameLevel = false }) {
449
451
final result = _value.map ((actual) => extract (actual)._fillActual (actual));
450
452
final rejection = result.rejection;
451
453
if (rejection != null ) {
452
- _clauses.add (_StringClause (() => [ label] ));
454
+ _clauses.add (_StringClause (label));
453
455
_fail (_failure (rejection));
454
456
}
455
457
final value = result.value ?? _Absent <R >();
456
458
final _TestContext <R > context;
457
459
if (atSameLevel) {
458
460
context = _TestContext ._alias (this , value);
459
461
_aliases.add (context);
460
- if (label.isNotEmpty) _clauses.add (_StringClause (() => [ label] ));
462
+ _clauses.add (_StringClause (label));
461
463
} else {
462
464
context = _TestContext ._child (value, label, this );
463
465
_clauses.add (context);
@@ -466,8 +468,8 @@ class _TestContext<T> implements Context<T>, _ClauseDescription {
466
468
}
467
469
468
470
@override
469
- Future <Subject <R >> nestAsync <R >(
470
- String label, FutureOr <Extracted <R >> Function (T ) extract) async {
471
+ Future <Subject <R >> nestAsync <R >(Iterable < String > Function () label,
472
+ FutureOr <Extracted <R >> Function (T ) extract) async {
471
473
if (! _allowAsync) {
472
474
throw StateError (
473
475
'Async expectations cannot be used on a synchronous subject' );
@@ -478,7 +480,7 @@ class _TestContext<T> implements Context<T>, _ClauseDescription {
478
480
outstandingWork.complete ();
479
481
final rejection = result.rejection;
480
482
if (rejection != null ) {
481
- _clauses.add (_StringClause (() => [ label] ));
483
+ _clauses.add (_StringClause (label));
482
484
_fail (_failure (rejection));
483
485
}
484
486
final value = result.value ?? _Absent <R >();
@@ -507,9 +509,9 @@ class _TestContext<T> implements Context<T>, _ClauseDescription {
507
509
var successfulOverlap = 0 ;
508
510
final expected = < String > [];
509
511
if (_clauses.isEmpty) {
510
- expected.add (_label);
512
+ expected.addAll (_label () );
511
513
} else {
512
- expected.add ( '$ _label that:' );
514
+ expected.addAll ( postfixLast ( ' that:', _label ()) );
513
515
for (var clause in _clauses) {
514
516
final details = clause.detail (failingContext);
515
517
expected.addAll (indent (details.expected));
@@ -550,14 +552,15 @@ class _SkippedContext<T> implements Context<T> {
550
552
}
551
553
552
554
@override
553
- Subject <R > nest <R >(String label, Extracted <R > Function (T p1) extract,
555
+ Subject <R > nest <R >(
556
+ Iterable <String > Function () label, Extracted <R > Function (T p1) extract,
554
557
{bool atSameLevel = false }) {
555
558
return Subject ._(_SkippedContext ());
556
559
}
557
560
558
561
@override
559
- Future <Subject <R >> nestAsync <R >(
560
- String label, FutureOr <Extracted <R >> Function (T p1) extract) async {
562
+ Future <Subject <R >> nestAsync <R >(Iterable < String > Function () label,
563
+ FutureOr <Extracted <R >> Function (T p1) extract) async {
561
564
return Subject ._(_SkippedContext ());
562
565
}
563
566
}
@@ -766,7 +769,8 @@ class _ReplayContext<T> implements Context<T>, Condition<T> {
766
769
}
767
770
768
771
@override
769
- Subject <R > nest <R >(String label, Extracted <R > Function (T p1) extract,
772
+ Subject <R > nest <R >(
773
+ Iterable <String > Function () label, Extracted <R > Function (T p1) extract,
770
774
{bool atSameLevel = false }) {
771
775
final nestedContext = _ReplayContext <R >();
772
776
_interactions.add ((c) {
@@ -777,8 +781,8 @@ class _ReplayContext<T> implements Context<T>, Condition<T> {
777
781
}
778
782
779
783
@override
780
- Future <Subject <R >> nestAsync <R >(
781
- String label, FutureOr <Extracted <R >> Function (T ) extract) async {
784
+ Future <Subject <R >> nestAsync <R >(Iterable < String > Function () label,
785
+ FutureOr <Extracted <R >> Function (T ) extract) async {
782
786
final nestedContext = _ReplayContext <R >();
783
787
_interactions.add ((c) async {
784
788
var result = await c.nestAsync (label, extract);
0 commit comments