Skip to content

Commit 5e48c80

Browse files
committed
[FTD #6] add golden test file comparer for threshold
1 parent a9e7207 commit 5e48c80

10 files changed

Lines changed: 85 additions & 33 deletions

File tree

.github/workflows/basic_dart_check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
uses: subosito/flutter-action@v2
1818
with:
1919
channel: stable
20-
flutter-version: 3.27.1
20+
flutter-version: 3.22.3
2121
- run: flutter --version
2222

2323
- name: ⚙️ Install dependencies

dart_test.yaml

Lines changed: 0 additions & 2 deletions
This file was deleted.

lib/src/modules/box/painter/bubble_box_painter.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class BubbleBoxPainter extends CustomPainter {
3131
this.tip = const BubbleBoxTip(),
3232
});
3333
final Text text;
34-
final EdgeInsets padding; //! TODO: fix text not being centered
34+
final EdgeInsets padding;
3535
final Color bubbleColor;
3636
final double borderRadius;
3737
final BubbleBoxTip tip;
@@ -59,7 +59,7 @@ class BubbleBoxPainter extends CustomPainter {
5959
final bubbleHeight = availableHeight + padding.vertical;
6060

6161
// Calculate tail size
62-
//! TODO: extract
62+
// !TODO: extract
6363
final tailHeight = bubbleHeight * 0.25;
6464

6565
final path = Path()

lib/src/modules/box/painter/rounded_box_painter.dart

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,8 @@ class RoundedBoxPainter extends CustomPainter {
4444
..strokeWidth = strokeWidth
4545
..style = PaintingStyle.stroke;
4646

47-
// TODO(everyone): Extract and make generic
4847
final textSpan = TextSpan(text: text.data, style: text.style);
49-
final textPainter = TextPainter(
50-
text: textSpan,
51-
textDirection: TextDirection.ltr,
52-
)..layout();
48+
final textPainter = TextPainter(text: textSpan, textDirection: TextDirection.ltr)..layout();
5349

5450
final textWidth = textPainter.width;
5551
final boxWidth = min(textWidth, size.width);
@@ -61,27 +57,9 @@ class RoundedBoxPainter extends CustomPainter {
6157
final nLines = heightFactor.ceil();
6258
boxHeight = nLines * textHeight;
6359

64-
double getOffsetDx() {
65-
var dx = size.width / 2;
66-
if (padding.left != padding.right) {
67-
final diff = (padding.left - padding.right).abs() / 2;
68-
dx = padding.left < padding.right ? dx + diff : dx - diff;
69-
}
70-
return dx;
71-
}
72-
73-
double getOffsetDy() {
74-
var dy = size.height / 2;
75-
if (padding.top != padding.bottom) {
76-
final diff = (padding.top - padding.bottom).abs() / 2;
77-
dy = padding.top < padding.bottom ? dy + diff : dy - diff;
78-
}
79-
return dy;
80-
}
81-
8260
final centerOffset = Offset(
83-
getOffsetDx(),
84-
getOffsetDy(),
61+
_getOffsetDx(size),
62+
_getOffsetDy(size),
8563
);
8664

8765
final rrect = RRect.fromRectAndRadius(
@@ -92,6 +70,24 @@ class RoundedBoxPainter extends CustomPainter {
9270
canvas.drawRRect(rrect, paint);
9371
}
9472

73+
double _getOffsetDx(Size size) {
74+
var dx = size.width / 2;
75+
if (padding.left != padding.right) {
76+
final diff = (padding.left - padding.right).abs() / 2;
77+
dx = padding.left < padding.right ? dx + diff : dx - diff;
78+
}
79+
return dx;
80+
}
81+
82+
double _getOffsetDy(Size size) {
83+
var dy = size.height / 2;
84+
if (padding.top != padding.bottom) {
85+
final diff = (padding.top - padding.bottom).abs() / 2;
86+
dy = padding.top < padding.bottom ? dy + diff : dy - diff;
87+
}
88+
return dy;
89+
}
90+
9591
@override
9692
bool shouldRepaint(covariant CustomPainter oldDelegate) {
9793
return false;

test/flutter_test_config.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'dart:async';
2+
3+
import 'package:flutter_test/flutter_test.dart';
4+
5+
import 'utils/local_file_comparer.dart';
6+
7+
const _kGoldenTestsThreshold = 0.5 / 100;
8+
9+
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
10+
if (goldenFileComparator is LocalFileComparator) {
11+
final testUrl = (goldenFileComparator as LocalFileComparator).basedir;
12+
13+
goldenFileComparator = LocalFileComparatorWithThreshold(
14+
Uri.parse('$testUrl/test.dart'),
15+
_kGoldenTestsThreshold,
16+
);
17+
} else {
18+
throw Exception(
19+
'Expected `goldenFileComparator` to be of type `LocalFileComparator`, '
20+
'but it is of type `${goldenFileComparator.runtimeType}`',
21+
);
22+
}
23+
24+
await testMain();
25+
}
-1 Bytes
Loading
153 Bytes
Loading
11 Bytes
Loading

test/src/widgets/text_decorator_test.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ void main() {
3434
matchesGoldenFile('text_decorator/box/bubble.default.png'),
3535
);
3636
},
37-
tags: ['golden'],
3837
);
3938
testWidgets(
4039
'BoxStyle.rounded renders',
@@ -57,7 +56,6 @@ void main() {
5756
matchesGoldenFile('text_decorator/box/rounded.default.png'),
5857
);
5958
},
60-
tags: ['golden'],
6159
);
6260

6361
testWidgets(
@@ -80,7 +78,6 @@ void main() {
8078
matchesGoldenFile('text_decorator/box/curled.default.png'),
8179
);
8280
},
83-
tags: ['golden'],
8481
);
8582
});
8683
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
4+
/// Works just like [LocalFileComparator] but includes a [threshold] that, when
5+
/// exceeded, marks the test as a failure.
6+
class LocalFileComparatorWithThreshold extends LocalFileComparator {
7+
LocalFileComparatorWithThreshold(super.testFile, this.threshold) : assert(threshold >= 0 && threshold <= 1, 'Threshold must be between 0 and 1');
8+
9+
/// Threshold above which tests will be marked as failing.
10+
/// Ranges from 0 to 1, both inclusive.
11+
final double threshold;
12+
13+
@override
14+
Future<bool> compare(Uint8List imageBytes, Uri golden) async {
15+
final result = await GoldenFileComparator.compareLists(
16+
imageBytes,
17+
await getGoldenBytes(golden),
18+
);
19+
20+
if (!result.passed && result.diffPercent <= threshold) {
21+
debugPrint(
22+
'A difference of ${result.diffPercent * 100}% was found, but it is '
23+
'acceptable since it is not greater than the threshold of '
24+
'${threshold * 100}%',
25+
);
26+
27+
return true;
28+
}
29+
30+
if (!result.passed) {
31+
final error = await generateFailureOutput(result, golden, basedir);
32+
throw FlutterError(error);
33+
}
34+
return result.passed;
35+
}
36+
}

0 commit comments

Comments
 (0)