478 lines
10 KiB
Dart
478 lines
10 KiB
Dart
import 'dart:io';
|
|
import 'dart:ui';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:lottie/lottie.dart';
|
|
import 'utils.dart';
|
|
|
|
void main() {
|
|
void testGolden(
|
|
String description,
|
|
ValueDelegate delegate, {
|
|
double? progress,
|
|
String? filePath,
|
|
}) {
|
|
filePath ??= 'Tests/Shapes.json';
|
|
|
|
var screenshotName = description
|
|
.toLowerCase()
|
|
.replaceAll(RegExp('[^a-z0-9 ]'), '')
|
|
.replaceAll(' ', '_');
|
|
|
|
testWidgets(description, (tester) async {
|
|
var composition = await LottieComposition.fromBytes(
|
|
File('example/assets/$filePath').readAsBytesSync(),
|
|
);
|
|
|
|
var animation = AnimationController(
|
|
vsync: tester,
|
|
duration: composition.duration,
|
|
);
|
|
if (progress != null) {
|
|
animation.value = progress;
|
|
}
|
|
|
|
await tester.pumpWidget(
|
|
Lottie(
|
|
composition: composition,
|
|
controller: animation,
|
|
delegates: LottieDelegates(values: [delegate]),
|
|
addRepaintBoundary: false,
|
|
),
|
|
);
|
|
await tester.pump();
|
|
await expectLater(
|
|
find.byType(Lottie),
|
|
matchesGoldenFile('goldens/dynamic/$screenshotName.png'),
|
|
);
|
|
|
|
if (progress == null || progress == 0) {
|
|
await tester.pumpWidget(
|
|
Lottie(
|
|
composition: composition,
|
|
controller: animation,
|
|
delegates: const LottieDelegates(values: []),
|
|
addRepaintBoundary: false,
|
|
),
|
|
);
|
|
await tester.pump();
|
|
}
|
|
});
|
|
}
|
|
|
|
testGolden(
|
|
'Fill color (Green)',
|
|
ValueDelegate.color([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
'Fill 1',
|
|
], value: Colors.green),
|
|
);
|
|
|
|
testGolden(
|
|
'Fill color (Yellow)',
|
|
ValueDelegate.color([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
'Fill 1',
|
|
], value: Colors.yellow),
|
|
);
|
|
|
|
testGolden(
|
|
'Fill opacity',
|
|
ValueDelegate.opacity(['Shape Layer 1', 'Rectangle', 'Fill 1'], value: 50),
|
|
);
|
|
|
|
testGolden(
|
|
'Stroke color',
|
|
ValueDelegate.strokeColor([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
'Stroke 1',
|
|
], value: Colors.green),
|
|
);
|
|
|
|
testGolden(
|
|
'Stroke width',
|
|
ValueDelegate.strokeWidth([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
'Stroke 1',
|
|
], value: 50),
|
|
);
|
|
|
|
testGolden(
|
|
'Stroke opacity',
|
|
ValueDelegate.opacity([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
'Stroke 1',
|
|
], value: 50),
|
|
);
|
|
|
|
testGolden(
|
|
'Transform anchor point',
|
|
ValueDelegate.transformAnchorPoint([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
], value: const Offset(20, 20)),
|
|
);
|
|
|
|
testGolden(
|
|
'Transform position',
|
|
ValueDelegate.transformPosition([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
], value: const Offset(20, 20)),
|
|
);
|
|
|
|
testGolden(
|
|
'Transform position (relative)',
|
|
ValueDelegate.transformPosition([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
], relative: const Offset(20, 20)),
|
|
);
|
|
|
|
testGolden(
|
|
'Transform opacity',
|
|
ValueDelegate.transformOpacity(['Shape Layer 1', 'Rectangle'], value: 50),
|
|
);
|
|
|
|
testGolden(
|
|
'Transform rotation',
|
|
ValueDelegate.transformRotation(['Shape Layer 1', 'Rectangle'], value: 45),
|
|
);
|
|
|
|
testGolden(
|
|
'Transform scale',
|
|
ValueDelegate.transformScale([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
], value: const Offset(0.5, 0.5)),
|
|
);
|
|
|
|
testGolden(
|
|
'Rectangle corner roundedness',
|
|
ValueDelegate.cornerRadius([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
'Rectangle Path 1',
|
|
], value: 7),
|
|
);
|
|
|
|
testGolden(
|
|
'Rectangle position',
|
|
ValueDelegate.position([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
'Rectangle Path 1',
|
|
], relative: const Offset(20, 20)),
|
|
);
|
|
|
|
testGolden(
|
|
'Rectangle size',
|
|
ValueDelegate.rectangleSize([
|
|
'Shape Layer 1',
|
|
'Rectangle',
|
|
'Rectangle Path 1',
|
|
], relative: const Offset(30, 40)),
|
|
);
|
|
|
|
testGolden(
|
|
'Ellipse position',
|
|
ValueDelegate.position([
|
|
'Shape Layer 1',
|
|
'Ellipse',
|
|
'Ellipse Path 1',
|
|
], relative: const Offset(20, 20)),
|
|
);
|
|
|
|
testGolden(
|
|
'Ellipse size',
|
|
ValueDelegate.ellipseSize([
|
|
'Shape Layer 1',
|
|
'Ellipse',
|
|
'Ellipse Path 1',
|
|
], relative: const Offset(40, 60)),
|
|
);
|
|
|
|
testGolden(
|
|
'Star points',
|
|
ValueDelegate.polystarPoints([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 8),
|
|
);
|
|
|
|
testGolden(
|
|
'Star rotation',
|
|
ValueDelegate.polystarRotation([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 10),
|
|
);
|
|
|
|
testGolden(
|
|
'Star position',
|
|
ValueDelegate.position([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], relative: const Offset(20, 20)),
|
|
);
|
|
|
|
testGolden(
|
|
'Star inner radius',
|
|
ValueDelegate.polystarInnerRadius([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 10),
|
|
);
|
|
|
|
testGolden(
|
|
'Star inner roundedness',
|
|
ValueDelegate.polystarInnerRoundedness([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 100),
|
|
);
|
|
|
|
testGolden(
|
|
'Star outer radius',
|
|
ValueDelegate.polystarOuterRadius([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 60),
|
|
);
|
|
|
|
testGolden(
|
|
'Star outer roundedness',
|
|
ValueDelegate.polystarOuterRoundedness([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 100),
|
|
);
|
|
|
|
testGolden(
|
|
'Polygon points',
|
|
ValueDelegate.polystarPoints([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 8),
|
|
);
|
|
|
|
testGolden(
|
|
'Polygon rotation',
|
|
ValueDelegate.polystarRotation([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 10),
|
|
);
|
|
|
|
testGolden(
|
|
'Polygon position',
|
|
ValueDelegate.position([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], relative: const Offset(20, 20)),
|
|
);
|
|
|
|
testGolden(
|
|
'Polygon radius',
|
|
ValueDelegate.polystarOuterRadius([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], relative: 60),
|
|
);
|
|
|
|
testGolden(
|
|
'Polygon roundedness',
|
|
ValueDelegate.polystarOuterRoundedness([
|
|
'Shape Layer 1',
|
|
'Star',
|
|
'Polystar Path 1',
|
|
], value: 100),
|
|
);
|
|
|
|
testGolden(
|
|
'Repeater transform position',
|
|
ValueDelegate.transformPosition([
|
|
'Shape Layer 1',
|
|
'Repeater Shape',
|
|
'Repeater 1',
|
|
], relative: const Offset(100, 100)),
|
|
);
|
|
|
|
testGolden(
|
|
'Repeater transform start opacity',
|
|
ValueDelegate.transformStartOpacity([
|
|
'Shape Layer 1',
|
|
'Repeater Shape',
|
|
'Repeater 1',
|
|
], value: 25),
|
|
);
|
|
|
|
testGolden(
|
|
'Repeater transform end opacity',
|
|
ValueDelegate.transformEndOpacity([
|
|
'Shape Layer 1',
|
|
'Repeater Shape',
|
|
'Repeater 1',
|
|
], value: 25),
|
|
);
|
|
|
|
testGolden(
|
|
'Repeater transform rotation',
|
|
ValueDelegate.transformRotation([
|
|
'Shape Layer 1',
|
|
'Repeater Shape',
|
|
'Repeater 1',
|
|
], value: 45),
|
|
);
|
|
|
|
testGolden(
|
|
'Repeater transform scale',
|
|
ValueDelegate.transformScale([
|
|
'Shape Layer 1',
|
|
'Repeater Shape',
|
|
'Repeater 1',
|
|
], value: const Offset(2, 2)),
|
|
);
|
|
|
|
testGolden(
|
|
'Time remapping',
|
|
ValueDelegate.timeRemap(['Circle 1'], value: 1),
|
|
progress: 0.1,
|
|
);
|
|
|
|
testGolden(
|
|
'Color Filter',
|
|
ValueDelegate.colorFilter([
|
|
'**',
|
|
], value: const ColorFilter.mode(Colors.green, BlendMode.srcATop)),
|
|
);
|
|
|
|
testGolden('Null Color Filter', ValueDelegate.colorFilter(['**']));
|
|
|
|
testGolden(
|
|
'Matte property',
|
|
ValueDelegate.rectangleSize([
|
|
'Shape Layer 1',
|
|
'Rectangle 1',
|
|
'Rectangle Path 1',
|
|
], value: const Offset(50, 50)),
|
|
filePath: 'Tests/TrackMattes.json',
|
|
);
|
|
|
|
testGolden('Blur', ValueDelegate.blurRadius(['**'], value: 10));
|
|
|
|
testGolden(
|
|
'Drop shadow',
|
|
ValueDelegate.dropShadow(
|
|
['Shape Layer 1', '**'],
|
|
value: const DropShadow(
|
|
color: Colors.green,
|
|
direction: 150,
|
|
distance: 20,
|
|
radius: 10,
|
|
),
|
|
),
|
|
);
|
|
|
|
testGolden(
|
|
'Solid Color',
|
|
ValueDelegate.color(['Cyan Solid 1', '**'], value: Colors.yellow),
|
|
filePath: 'Tests/SolidLayerTransform.json',
|
|
);
|
|
|
|
for (var progress in [0.0, 0.5, 1.0]) {
|
|
testGolden(
|
|
'Opacity interpolation ($progress)',
|
|
ValueDelegate.transformOpacity(
|
|
['Shape Layer 1', 'Rectangle'],
|
|
callback: (frameInfo) => lerpDouble(
|
|
10,
|
|
100,
|
|
Curves.linear.transform(frameInfo.overallProgress),
|
|
)!.round(),
|
|
),
|
|
progress: progress,
|
|
);
|
|
}
|
|
|
|
testWidgets('warningShimmer', (tester) async {
|
|
var size = const Size(500, 400);
|
|
tester.view.physicalSize = size;
|
|
tester.view.devicePixelRatio = 1.0;
|
|
|
|
var composition = await LottieComposition.fromBytes(
|
|
File('test/data/warningShimmer.json').readAsBytesSync(),
|
|
);
|
|
|
|
var delegates = <String, List<ValueDelegate>>{
|
|
'1': [
|
|
for (var i in ['1', '2', '5'])
|
|
ValueDelegate.color(['Layer $i Outlines', '**'], value: Colors.red),
|
|
for (var i in ['3', '4'])
|
|
ValueDelegate.color([
|
|
'Layer $i Outlines',
|
|
'**',
|
|
], value: Colors.greenAccent),
|
|
],
|
|
'2': [
|
|
for (var i in ['1', '2', '5'])
|
|
ValueDelegate.color([
|
|
'Layer $i Outlines',
|
|
'Group 1',
|
|
'*',
|
|
], value: Colors.red),
|
|
for (var i in ['3', '4'])
|
|
ValueDelegate.color([
|
|
'Layer $i Outlines',
|
|
'Group 1',
|
|
'*',
|
|
], value: Colors.greenAccent),
|
|
],
|
|
'3': [
|
|
for (var i in ['1', '2', '5'])
|
|
ValueDelegate.color([
|
|
'Layer $i Outlines',
|
|
'Group 1',
|
|
'Fill 1',
|
|
], value: Colors.red),
|
|
for (var i in ['3', '4'])
|
|
ValueDelegate.color([
|
|
'Layer $i Outlines',
|
|
'Group 1',
|
|
'Fill 1',
|
|
], value: Colors.greenAccent),
|
|
],
|
|
};
|
|
|
|
for (var variant in delegates.entries) {
|
|
await tester.pumpWidget(
|
|
FilmStrip(
|
|
composition,
|
|
size: size,
|
|
delegates: LottieDelegates(values: variant.value),
|
|
),
|
|
);
|
|
|
|
await expectLater(
|
|
find.byType(FilmStrip),
|
|
matchesGoldenFile('goldens/warningShimmer_${variant.key}.png'),
|
|
);
|
|
}
|
|
});
|
|
}
|