Skip to content

Commit c84afb8

Browse files
[FEATURE][BUG]: Fixes and improvements when using with follow_the_leader package (#63)
* FIX: Make use of given spacing in GridGoldenSceneLayout * FIX/ADJUSTMENT: Don't paint to Canvas before taking photo with FlutterCamera - this broke nuanced render object and layer behavior in follow_the_leader. Instead, use toImageSync() on the existing RepaintBoundary. * ADJUSTMENT: Changed GridSceneLayout to use default item decorator and background to match existing behavior of FlexSceneLayout. * FEATURE: Add itemSetup to Gallery so that a single setup can be applied to all items. * ADJUSTMENT: When a Gallery is given item constraints, it now sets its physicalSize to match the max bounds. * FEATURE: Timeline now accepts a desired windowSize which it applies to the physicalSize in the test. * ADJUSTMENT: Changed the existing "minimal" Timeline itemScaffold to become the "standard" one, and then created a true "minimal" itemScaffold that makes no decisions about theme, background color, or padding. * ADJUSTMENT: Renamed "pump" method in Timeline to say "builder" because that's more of what it is.
1 parent 8f097bc commit c84afb8

File tree

17 files changed

+388
-190
lines changed

17 files changed

+388
-190
lines changed

doc/marketing_goldens/shadcn_test_tools.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ class ShadcnSingleShotSceneLayout implements SceneLayout {
5757
Widget build(
5858
WidgetTester tester,
5959
BuildContext context,
60-
Map<GoldenSceneScreenshot, GlobalKey<State<StatefulWidget>>> goldens,
60+
SceneLayoutContent content,
6161
) {
62-
final golden = goldens.entries.first;
62+
final golden = content.goldens.entries.first;
6363

6464
return DefaultTextStyle(
6565
style: GoldenSceneTheme.current.defaultTextStyle.copyWith(
@@ -129,9 +129,9 @@ class ShadcnGalleryLayout implements SceneLayout {
129129
Widget build(
130130
WidgetTester tester,
131131
BuildContext context,
132-
Map<GoldenSceneScreenshot, GlobalKey<State<StatefulWidget>>> goldens,
132+
SceneLayoutContent content,
133133
) {
134-
final entries = goldens.entries.toList();
134+
final entries = content.goldens.entries.toList();
135135

136136
return DefaultTextStyle(
137137
style: GoldenSceneTheme.current.defaultTextStyle.copyWith(

doc/website/source/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ how we solve them.
1212

1313
* **Failure Files:** Flutter spreads a single test failure across four different files.
1414
It's frustrating to have to open up multiple files to cross reference. With
15-
`flutter_test_goldes`, your failure output is painted to a single file for easy review.
15+
`flutter_test_goldens`, your failure output is painted to a single file for easy review.
1616
* **Widget Galleries:** Flutter developers often want to verify multiple configurations
1717
of a single widget, or multiple related widgets, at the same time. With
1818
`flutter_test_goldens`, you can easily paint a variety of widgets into a gallery,

doc/website/source/styles/docs_page_layout.scss

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,15 @@ main.page-content {
265265
margin-bottom: 1.5em;
266266
}
267267

268-
code {
269-
padding: 3px 6px;
270-
background: #7f00a6;
271-
border: 1px solid #a218cc;
272-
border-radius: 4px;
273-
274-
color: WHITE;
268+
p, li > {
269+
code {
270+
padding: 3px 6px;
271+
background: #7f00a6;
272+
border: 1px solid #a218cc;
273+
border-radius: 4px;
274+
275+
color: WHITE;
276+
}
275277
}
276278

277279
li {

lib/src/flutter/flutter_camera.dart

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,7 @@ class FlutterCamera {
3434
);
3535
}
3636

37-
final pictureRecorder = PictureRecorder();
38-
final canvas = Canvas(pictureRecorder);
39-
final screenSize = fullscreenRenderObject.size;
40-
41-
final paintingContext = TestRecordingPaintingContext(canvas);
42-
fullscreenRenderObject.paint(paintingContext, Offset.zero);
43-
44-
final fullscreenPhoto = await pictureRecorder.endRecording().toImage(
45-
screenSize.width.round(),
46-
screenSize.height.round(),
47-
);
37+
final fullscreenPhoto = fullscreenRenderObject.toImageSync();
4838

4939
final contentFinder = finder ?? find.byType(GoldenImageBounds);
5040
expect(finder, findsOne);

lib/src/flutter/flutter_golden_matcher.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import 'dart:io';
2-
import 'dart:typed_data';
32

43
import 'package:flutter/foundation.dart';
54
import 'package:flutter_test/flutter_test.dart';

lib/src/scenes/failure_scene.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ Future<(Image, FailureSceneMetadata)> _layoutFailureScene(
186186
return layout.build(
187187
tester,
188188
context,
189-
renderablePhotos,
189+
SceneLayoutContent(goldens: renderablePhotos),
190190
);
191191
},
192192
),

lib/src/scenes/gallery.dart

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@ class Gallery {
3232
BoxConstraints? itemConstraints,
3333
Finder? itemBoundsFinder,
3434
required SceneLayout layout,
35+
GoldenSetup? itemSetup,
3536
}) : _fileName = fileName,
3637
_sceneDescription = sceneDescription,
3738
_itemScaffold = itemScaffold,
3839
_itemConstraints = itemConstraints,
3940
_itemBoundsFinder = itemBoundsFinder,
40-
_layout = layout {
41+
_layout = layout,
42+
_itemSetup = itemSetup {
4143
_directory = directory ?? GoldenSceneTheme.current.directory;
4244
}
4345

@@ -84,6 +86,12 @@ class Gallery {
8486
/// 3. `find.byType(GoldenImageBounds)`.
8587
final Finder? _itemBoundsFinder;
8688

89+
/// An optional setup method that runs after pumping an item's tree, and just before the
90+
/// item is screenshotted.
91+
///
92+
/// This setup runs for every item in the scene unless an individual item overrides it.
93+
final GoldenSetup? _itemSetup;
94+
8795
/// Requests for all screenshots within this scene, by their ID.
8896
final _requests = <String, GalleryGoldenRequest>{};
8997

@@ -329,6 +337,14 @@ class Gallery {
329337
final previousPlatform = debugDefaultTargetPlatformOverride;
330338
debugDefaultTargetPlatformOverride = item.platform ?? previousPlatform;
331339

340+
if (itemConstraints != null && itemConstraints.hasBoundedWidth && itemConstraints.hasBoundedHeight) {
341+
// Some tests may want to control the size of the window. If we're given bounded
342+
// constraints, make the window the biggest allowable size.
343+
final previousSize = tester.view.physicalSize;
344+
tester.view.physicalSize = itemConstraints.biggest;
345+
addTearDown(() => tester.view.physicalSize = previousSize);
346+
}
347+
332348
if (item.pumper != null) {
333349
// Defer to the `pumper` to pump the entire widget tree for this gallery item.
334350
await item.pumper!.call(tester, itemScaffold, item.description);
@@ -353,7 +369,7 @@ class Gallery {
353369
}
354370

355371
// Run the item's setup function, if there is one.
356-
await item.setup?.call(tester);
372+
await (item.setup ?? _itemSetup)?.call(tester);
357373

358374
// Take a screenshot.
359375
expect(item.boundsFinder, findsOne);
@@ -476,8 +492,11 @@ Image.memory(
476492
SceneLayout layout,
477493
Map<String, GoldenSceneScreenshot> goldenScreenshots,
478494
) async {
479-
final goldensAndGlobalKeys = Map<GoldenSceneScreenshot, GlobalKey>.fromEntries(
480-
goldenScreenshots.entries.map((entry) => MapEntry(entry.value, GlobalKey())),
495+
final content = SceneLayoutContent(
496+
description: _sceneDescription,
497+
goldens: Map<GoldenSceneScreenshot, GlobalKey>.fromEntries(
498+
goldenScreenshots.entries.map((entry) => MapEntry(entry.value, GlobalKey())),
499+
),
481500
);
482501

483502
// Layout the gallery scene with the new goldens, check the intrinsic size of the
@@ -487,13 +506,13 @@ Image.memory(
487506
// a corresponding `GlobalKey` already in the tree. Therefore, this layout pass inserts a
488507
// `GlobalKey` for every golden screenshot that we want to render.
489508
await tester.pumpWidgetAndAdjustWindow(
490-
_buildGalleryLayout(tester, goldensAndGlobalKeys),
509+
_buildGalleryLayout(tester, content),
491510
);
492511

493512
// Use Flutter's `precacheImage()` mechanism to get each golden screenshot bitmap to
494513
// render in this widget test.
495514
await tester.runAsync(() async {
496-
for (final entry in goldensAndGlobalKeys.entries) {
515+
for (final entry in content.goldens.entries) {
497516
await precacheImage(
498517
MemoryImage(entry.key.pngBytes),
499518
tester.element(find.byKey(entry.value)),
@@ -506,21 +525,21 @@ Image.memory(
506525
return GoldenSceneMetadata(
507526
description: _sceneDescription,
508527
images: [
509-
for (final golden in goldensAndGlobalKeys.keys)
528+
for (final golden in content.goldens.keys)
510529
GoldenImageMetadata(
511530
id: golden.id,
512531
metadata: golden.metadata,
513-
topLeft: (goldensAndGlobalKeys[golden]!.currentContext!.findRenderObject() as RenderBox)
514-
.localToGlobal(Offset.zero),
515-
size: goldensAndGlobalKeys[golden]!.currentContext!.size!,
532+
topLeft:
533+
(content.goldens[golden]!.currentContext!.findRenderObject() as RenderBox).localToGlobal(Offset.zero),
534+
size: content.goldens[golden]!.currentContext!.size!,
516535
),
517536
],
518537
);
519538
}
520539

521-
Widget _buildGalleryLayout(WidgetTester tester, Map<GoldenSceneScreenshot, GlobalKey> candidatesAndGlobalKeys) {
540+
Widget _buildGalleryLayout(WidgetTester tester, SceneLayoutContent content) {
522541
return Builder(builder: (context) {
523-
return _layout.build(tester, context, candidatesAndGlobalKeys);
542+
return _layout.build(tester, context, content);
524543
});
525544
}
526545

0 commit comments

Comments
 (0)