Fix output for multiline clauses in failures (#2646)
In a failure message the parts of the expectation which were checked and
satisfied are represented in both the "Expected" and "Actual" portions.
This is handled by tracking how many lines of the text overlaps.
Previously this tracked the depth of nesting and assumed each level
contributed only a single line, but this assumption is violated by some
expectations which print with multiple lines. Correct the overlap
accounting to include the actual number of lines added by a label.
diff --git a/pkgs/checks/lib/src/checks.dart b/pkgs/checks/lib/src/checks.dart
index c9cad66..1c82228 100644
--- a/pkgs/checks/lib/src/checks.dart
+++ b/pkgs/checks/lib/src/checks.dart
@@ -863,7 +863,9 @@
if (_clauses.isEmpty) {
expected.addAll(_label());
} else {
- expected.addAll(postfixLast(' that:', _label()));
+ final label = postfixLast(' that:', _label());
+ expected.addAll(label);
+ final labelLines = label.length;
for (var clause in _clauses) {
final details = clause.detail(failingContext);
expected.addAll(indent(details.expected));
@@ -871,7 +873,8 @@
assert(foundDepth == -1);
assert(foundOverlap == -1);
foundDepth = details.depth + 1;
- foundOverlap = details._actualOverlap + successfulOverlap + 1;
+ foundOverlap =
+ details._actualOverlap + successfulOverlap + labelLines;
} else {
if (foundDepth == -1) {
successfulOverlap += details.expected.length;
diff --git a/pkgs/checks/test/failure_message_test.dart b/pkgs/checks/test/failure_message_test.dart
index ee5401c..1c64eee 100644
--- a/pkgs/checks/test/failure_message_test.dart
+++ b/pkgs/checks/test/failure_message_test.dart
@@ -27,6 +27,28 @@
Which: are not equal''');
});
+ test('includes matching portions of actual when label is multiline', () {
+ check(() {
+ check({
+ 'foo\nbar': [10],
+ })['foo\nbar'].first
+ ..isGreaterThan(0)
+ ..isLessThan(10);
+ }).throwsFailure().equals('''
+Expected: a Map<String, List<int>> that:
+ contains a value for 'foo
+ bar' that:
+ has first element that:
+ is greater than <0>
+ is less than <10>
+Actual: a Map<String, List<int>> that:
+ contains a value for 'foo
+ bar' that:
+ has first element that:
+ Actual: <10>
+ Which: is not less than <10>''');
+ });
+
test('include a reason when provided', () {
check(() {
check(because: 'Some reason', 1).isGreaterThan(2);