Skip to content

Commit 97b1b24

Browse files
Add failure metadata
1 parent e3a3a16 commit 97b1b24

File tree

2 files changed

+107
-15
lines changed

2 files changed

+107
-15
lines changed

lib/src/scenes/failure_scene.dart

Lines changed: 99 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Future<Image> paintGoldenMismatchImages(GoldenMismatch mismatch) async {
8888
}
8989

9090
/// Given a [report], generates that shows all the mismatches found in the report.
91-
Future<Image> paintFailureScene(WidgetTester tester, GoldenSceneReport report) async {
91+
Future<(Image, FailureSceneMetadata)> paintFailureScene(WidgetTester tester, GoldenSceneReport report) async {
9292
final photos = <GoldenFailurePhoto>[];
9393

9494
for (final item in report.items) {
@@ -143,11 +143,12 @@ Future<Image> paintFailureScene(WidgetTester tester, GoldenSceneReport report) a
143143
);
144144
}
145145

146-
return _layoutFailureScene(tester, photos);
146+
return _layoutFailureScene(tester, report, photos);
147147
}
148148

149149
/// Generates a single image that shows all the golden failures.
150-
Future<Image> _layoutFailureScene(WidgetTester tester, List<GoldenFailurePhoto> images) async {
150+
Future<(Image, FailureSceneMetadata)> _layoutFailureScene(
151+
WidgetTester tester, GoldenSceneReport report, List<GoldenFailurePhoto> images) async {
151152
final renderablePhotos = <GoldenFailurePhoto, (Uint8List, GlobalKey)>{};
152153
for (final photo in images) {
153154
final image = await _convertImagePackageToUiImage(photo.pixels);
@@ -161,7 +162,7 @@ Future<Image> _layoutFailureScene(WidgetTester tester, List<GoldenFailurePhoto>
161162
child: IntrinsicHeight(
162163
child: GoldenFailureScene(
163164
key: sceneKey,
164-
direction: Axis.horizontal,
165+
direction: Axis.vertical,
165166
renderablePhotos: renderablePhotos,
166167
background: null,
167168
),
@@ -180,13 +181,29 @@ Future<Image> _layoutFailureScene(WidgetTester tester, List<GoldenFailurePhoto>
180181

181182
final uiImage = await captureImage(find.byKey(sceneKey).evaluate().single);
182183
final bytes = await uiImage.toByteData(format: ui.ImageByteFormat.rawRgba);
183-
final result = Image.fromBytes(
184+
final failureImage = Image.fromBytes(
184185
width: uiImage.width,
185186
height: uiImage.height,
186187
bytes: bytes!.buffer,
187188
order: ChannelOrder.rgba,
188189
);
189-
return result;
190+
191+
// Lookup and return metadata for the position and size of each failure image
192+
// within the scene.
193+
final metadata = FailureSceneMetadata(
194+
description: report.metadata.description,
195+
images: [
196+
for (final golden in renderablePhotos.keys)
197+
FailureImageMetadata(
198+
id: golden.description,
199+
topLeft:
200+
(renderablePhotos[golden]!.$2.currentContext!.findRenderObject() as RenderBox).localToGlobal(Offset.zero),
201+
size: renderablePhotos[golden]!.$2.currentContext!.size!,
202+
),
203+
],
204+
);
205+
206+
return (failureImage, metadata);
190207
}
191208

192209
/// Generates a single image that shows the golden, the candidate, and the
@@ -456,11 +473,15 @@ class GoldenFailureScene extends StatelessWidget {
456473
Container(
457474
color: material.Colors.white,
458475
padding: const EdgeInsets.all(16),
459-
child: Text(
460-
entry.key.description,
461-
style: TextStyle(
462-
color: material.Colors.black,
463-
fontFamily: "packages/flutter_test_goldens/OpenSans",
476+
child: FittedBox(
477+
fit: BoxFit.scaleDown,
478+
child: Text(
479+
entry.key.description,
480+
softWrap: false,
481+
style: TextStyle(
482+
color: material.Colors.black,
483+
fontFamily: "packages/flutter_test_goldens/OpenSans",
484+
),
464485
),
465486
),
466487
),
@@ -485,3 +506,70 @@ class GoldenFailurePhoto {
485506
final String description;
486507
final Image pixels;
487508
}
509+
510+
class FailureSceneMetadata {
511+
static FailureSceneMetadata fromJson(Map<String, dynamic> json) {
512+
return FailureSceneMetadata(
513+
description: json["description"] ?? "",
514+
images: [
515+
for (final photoJson in (json["images"] as List<dynamic>)) //
516+
FailureImageMetadata.fromJson(photoJson),
517+
],
518+
);
519+
}
520+
521+
const FailureSceneMetadata({
522+
required this.description,
523+
required this.images,
524+
});
525+
526+
final String description;
527+
final List<FailureImageMetadata> images;
528+
529+
Map<String, dynamic> toJson() {
530+
return {
531+
"description": description,
532+
"images": images.map((photo) => photo.toJson()).toList(),
533+
};
534+
}
535+
}
536+
537+
class FailureImageMetadata {
538+
static FailureImageMetadata fromJson(Map<String, dynamic> json) {
539+
return FailureImageMetadata(
540+
id: json["id"],
541+
topLeft: ui.Offset(
542+
(json["topLeft"]["x"] as num).toDouble(),
543+
(json["topLeft"]["y"] as num).toDouble(),
544+
),
545+
size: ui.Size(
546+
(json["size"]["width"] as num).toDouble(),
547+
(json["size"]["height"] as num).toDouble(),
548+
),
549+
);
550+
}
551+
552+
FailureImageMetadata({
553+
required this.id,
554+
required this.topLeft,
555+
required this.size,
556+
});
557+
558+
final String id;
559+
final ui.Offset topLeft;
560+
final ui.Size size;
561+
562+
Map<String, dynamic> toJson() {
563+
return {
564+
"id": id,
565+
"topLeft": {
566+
"x": topLeft.dx,
567+
"y": topLeft.dy,
568+
},
569+
"size": {
570+
"width": size.width,
571+
"height": size.height,
572+
},
573+
};
574+
}
575+
}

lib/src/scenes/gallery.dart

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -545,12 +545,16 @@ class Gallery {
545545
Directory(_goldenFailureDirectoryPath).createSync();
546546

547547
await tester.runAsync(() async {
548-
final failureImage = await paintFailureScene(_tester, report);
548+
final (failureImage, metadata) = await paintFailureScene(_tester, report);
549549

550-
await encodePngFile(
551-
"$_goldenFailureDirectoryPath/failure_$existingGoldenFileName.png",
552-
failureImage,
550+
Uint8List pngData = encodePng(failureImage);
551+
pngData = pngData.copyWithTextMetadata(
552+
"flutter_test_goldens_failure",
553+
const JsonEncoder().convert(metadata.toJson()),
553554
);
555+
556+
final file = File("$_goldenFailureDirectoryPath/failure_$existingGoldenFileName.png");
557+
file.writeAsBytesSync(pngData);
554558
});
555559

556560
_printReport(report);

0 commit comments

Comments
 (0)