Replace AnimationSheetBuilder.display with collate
Summary
AnimationSheetBuilder.display and sheetSize are deprecated, and should be replaced by AnimationSheetBuilder.collate.
Context
AnimationSheetBuilder
is a testing utility
class that records frames of an animating widget,
and later composes the frames into a single
animation sheet for golden testing. The old way
of composing involves display
to list the images
into a table-like widget, adjusting the testing
surface with sheetSize
, and capturing the table
widget for comparison. A new way, collate
, has
been added that directly put the frames together
into an image for comparison, which requires a less
boilerplate and outputs a smaller image without
compromise in quality. APIs for the old way are thus
deprecated.
The reason why collate
outputs a smaller image,
is because the old way captures on a testing surface
with pixel ratio 3.0, which means it uses a 3x3 pixel
block of the exactly same color to represent 1 actual
pixel, making the image 9 times as large as necessary
(before PNG compression).
Description of change
The following changes have been made to the
AnimationSheetBuilder
class:
- ‘display’ is deprecated and shouldn’t be used.
- ‘sheetSize’ is deprecated and shouldn’t be used.
Migration guide
To migrate to the new API, change the process of setting
surface size and displaying the widget into
AnimationSheetBuilder.collate
.
Derive cells per row
The collate
requires an explicit cellsPerRow
argument, which is the number of frames per
row in the output image. It can be manually counted,
or calculated as follows:
- Find the width of frame, specified when constructing
AnimationSheetBuilder
. For example, in the following snippet it’s 80:final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(80, 30));
- Find the width of surface size, specified during
sheetSize
, which defaults to 800. For example, in the following snippet it’s 600:tester.binding.setSurfaceSize(animationSheet.sheetSize(600));
- The frames per row should be the result of the two
numbers divided, rounded down. For example,
600 / 80 = 7 (rounded down), therefore
animationSheet.collate(7)
Migrate code
Code before migration:
testWidgets('Indeterminate CircularProgressIndicator', (WidgetTester tester) async {
final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(40, 40));
await tester.pumpFrames(animationSheet.record(
const Directionality(
textDirection: TextDirection.ltr,
child: Padding(
padding: EdgeInsets.all(4),
child: CircularProgressIndicator(),
),
),
), const Duration(seconds: 2));
// The code starting here needs migration.
tester.binding.setSurfaceSize(animationSheet.sheetSize());
final Widget display = await animationSheet.display();
await tester.pumpWidget(display);
await expectLater(
find.byWidget(display),
matchesGoldenFile('material.circular_progress_indicator.indeterminate.png'),
);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/42767
Code after migration (cellsPerRow
is 20, derived from 800 / 40):
testWidgets('Indeterminate CircularProgressIndicator', (WidgetTester tester) async {
final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(40, 40));
await tester.pumpFrames(animationSheet.record(
const Directionality(
textDirection: TextDirection.ltr,
child: Padding(
padding: EdgeInsets.all(4),
child: CircularProgressIndicator(),
),
),
), const Duration(seconds: 2));
await expectLater(
animationSheet.collate(20),
matchesGoldenFile('material.circular_progress_indicator.indeterminate.png'),
);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/42767
It’s normal that related golden test reference images are invalidated, which should all be updated. The new images should be identical to the old ones except 1/3 in scale.
Timeline
Landed in version: v2.3.0-13.0.pre
In stable release: 2.5
References
API documentation:
Relevant PRs: