Unverified Commit 00f3f2b1 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

More beautiful linear_gradient sample (#99298)

parent 96426230
......@@ -11,33 +11,41 @@ void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatelessWidget(),
);
return const MaterialApp(home: MoodyGradient());
}
}
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
class MoodyGradient extends StatelessWidget {
const MoodyGradient({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end:
Alignment(0.8, 0.0), // 10% of the width, so there are ten blinds.
colors: <Color>[
Color(0xffee0000),
Color(0xffeeee00)
], // red to yellow
tileMode: TileMode.repeated, // repeats the gradient over the canvas
return Material(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment(0.8, 1),
colors: <Color>[
Color(0xff1f005c),
Color(0xff5b0060),
Color(0xff870160),
Color(0xffac255e),
Color(0xffca485c),
Color(0xffe16b5c),
Color(0xfff39060),
Color(0xffffb56b),
], // Gradient from https://learnui.design/tools/gradient-generator.html
tileMode: TileMode.mirror,
),
),
child: const Center(
child: Text(
'From Night to Day',
style: TextStyle(fontSize: 24, color: Colors.white),
),
),
),
);
......
......@@ -25,6 +25,8 @@ dev_dependencies:
sdk: flutter
flutter_driver:
sdk: flutter
flutter_goldens:
sdk: flutter
flutter_test:
sdk: flutter
test: 1.20.1
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'goldens_io.dart' if (dart.library.html) 'goldens_web.dart' as flutter_goldens;
Future<void> testExecutable(FutureOr<void> Function() testMain) {
// Enable golden file testing using Skia Gold.
return flutter_goldens.testExecutable(testMain, namePrefix: 'api');
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
export 'package:flutter_goldens/flutter_goldens.dart' show testExecutable;
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
// package:flutter_goldens is not used as part of the test process for web.
Future<void> testExecutable(FutureOr<void> Function() testMain) async => testMain();
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_api_samples/painting/gradient/linear_gradient.0.dart'
as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('finds a gradient', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: example.MoodyGradient(),
),
);
expect(find.byType(example.MoodyGradient), findsOneWidget);
});
testWidgets('gradient matches golden', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: SizedBox(
width: 800,
height: 600,
child: RepaintBoundary(
child: example.MoodyGradient(),
),
),
),
);
await expectLater(
find.byType(example.MoodyGradient),
matchesGoldenFile('linear_gradient.0_test.png'),
);
});
}
......@@ -349,8 +349,9 @@ abstract class Gradient {
/// To use a [LinearGradient] to paint on a canvas directly, see [createShader].
///
/// {@tool dartpad}
/// This sample draws a picture that looks like vertical window shades by having
/// a [Container] display a [BoxDecoration] with a [LinearGradient].
/// This sample draws a picture with a gradient sweeping through different
/// colors, by having a [Container] display a [BoxDecoration] with a
/// [LinearGradient].
///
/// ** See code in examples/api/lib/painting/gradient/linear_gradient.0.dart **
/// {@end-tool}
......
......@@ -25,15 +25,18 @@ const String _kFlutterRootKey = 'FLUTTER_ROOT';
/// [goldenFileComparator] to an instance of [FlutterGoldenFileComparator] that
/// works for the current test. _Which_ FlutterGoldenFileComparator is
/// instantiated is based on the current testing environment.
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
///
/// When set, the `namePrefix` is prepended to the names of all gold images.
Future<void> testExecutable(FutureOr<void> Function() testMain, {String? namePrefix}) async {
const Platform platform = LocalPlatform();
if (FlutterPostSubmitFileComparator.isAvailableForEnvironment(platform)) {
goldenFileComparator = await FlutterPostSubmitFileComparator.fromDefaultComparator(platform);
goldenFileComparator = await FlutterPostSubmitFileComparator.fromDefaultComparator(platform, namePrefix: namePrefix);
} else if (FlutterPreSubmitFileComparator.isAvailableForEnvironment(platform)) {
goldenFileComparator = await FlutterPreSubmitFileComparator.fromDefaultComparator(platform);
goldenFileComparator = await FlutterPreSubmitFileComparator.fromDefaultComparator(platform, namePrefix: namePrefix);
} else if (FlutterSkippingFileComparator.isAvailableForEnvironment(platform)) {
goldenFileComparator = FlutterSkippingFileComparator.fromDefaultComparator(
'Golden file testing is not executed on Cirrus, or LUCI environments outside of flutter/flutter.'
'Golden file testing is not executed on Cirrus, or LUCI environments outside of flutter/flutter.',
namePrefix: namePrefix
);
} else {
goldenFileComparator = await FlutterLocalFileComparator.fromDefaultComparator(platform);
......@@ -91,6 +94,7 @@ abstract class FlutterGoldenFileComparator extends GoldenFileComparator {
this.skiaClient, {
this.fs = const LocalFileSystem(),
this.platform = const LocalPlatform(),
this.namePrefix,
});
/// The directory to which golden file URIs will be resolved in [compare] and
......@@ -109,6 +113,9 @@ abstract class FlutterGoldenFileComparator extends GoldenFileComparator {
@visibleForTesting
final Platform platform;
/// The prefix that is added to all golden names.
final String? namePrefix;
@override
Future<void> update(Uri golden, Uint8List imageBytes) async {
final File goldenFile = getGoldenFile(golden);
......@@ -173,8 +180,12 @@ abstract class FlutterGoldenFileComparator extends GoldenFileComparator {
'Golden files in the Flutter framework must end with the file extension '
'.png.'
);
final String prefix = basedir.pathSegments[basedir.pathSegments.length - 2];
return Uri.parse('$prefix.$golden');
return Uri.parse(<String>[
if (namePrefix != null)
namePrefix!,
basedir.pathSegments[basedir.pathSegments.length - 2],
golden.toString(),
].join('.'));
}
}
......@@ -205,11 +216,13 @@ class FlutterPostSubmitFileComparator extends FlutterGoldenFileComparator {
final SkiaGoldClient skiaClient, {
final FileSystem fs = const LocalFileSystem(),
final Platform platform = const LocalPlatform(),
String? namePrefix,
}) : super(
basedir,
skiaClient,
fs: fs,
platform: platform,
namePrefix: namePrefix,
);
/// Creates a new [FlutterPostSubmitFileComparator] that mirrors the relative
......@@ -221,6 +234,7 @@ class FlutterPostSubmitFileComparator extends FlutterGoldenFileComparator {
final Platform platform, {
SkiaGoldClient? goldens,
LocalFileComparator? defaultComparator,
String? namePrefix,
}) async {
defaultComparator ??= goldenFileComparator as LocalFileComparator;
......@@ -233,7 +247,7 @@ class FlutterPostSubmitFileComparator extends FlutterGoldenFileComparator {
goldens ??= SkiaGoldClient(baseDirectory);
await goldens.auth();
return FlutterPostSubmitFileComparator(baseDirectory.uri, goldens);
return FlutterPostSubmitFileComparator(baseDirectory.uri, goldens, namePrefix: namePrefix);
}
@override
......@@ -283,11 +297,13 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator {
final SkiaGoldClient skiaClient, {
final FileSystem fs = const LocalFileSystem(),
final Platform platform = const LocalPlatform(),
final String? namePrefix,
}) : super(
basedir,
skiaClient,
fs: fs,
platform: platform,
namePrefix: namePrefix,
);
/// Creates a new [FlutterPreSubmitFileComparator] that mirrors the
......@@ -300,6 +316,7 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator {
SkiaGoldClient? goldens,
LocalFileComparator? defaultComparator,
Directory? testBasedir,
String? namePrefix,
}) async {
defaultComparator ??= goldenFileComparator as LocalFileComparator;
......@@ -318,6 +335,7 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator {
return FlutterPreSubmitFileComparator(
baseDirectory.uri,
goldens, platform: platform,
namePrefix: namePrefix,
);
}
......@@ -367,8 +385,9 @@ class FlutterSkippingFileComparator extends FlutterGoldenFileComparator {
FlutterSkippingFileComparator(
final Uri basedir,
final SkiaGoldClient skiaClient,
this.reason,
) : super(basedir, skiaClient);
this.reason, {
String? namePrefix,
}) : super(basedir, skiaClient, namePrefix: namePrefix);
/// Describes the reason for using the [FlutterSkippingFileComparator].
///
......@@ -380,12 +399,13 @@ class FlutterSkippingFileComparator extends FlutterGoldenFileComparator {
static FlutterSkippingFileComparator fromDefaultComparator(
String reason, {
LocalFileComparator? defaultComparator,
String? namePrefix,
}) {
defaultComparator ??= goldenFileComparator as LocalFileComparator;
const FileSystem fs = LocalFileSystem();
final Uri basedir = defaultComparator.basedir;
final SkiaGoldClient skiaClient = SkiaGoldClient(fs.directory(basedir));
return FlutterSkippingFileComparator(basedir, skiaClient, reason);
return FlutterSkippingFileComparator(basedir, skiaClient, reason, namePrefix: namePrefix);
}
@override
......
......@@ -466,6 +466,27 @@ void main() {
expect(key, Uri.parse('foo.png'));
});
test('adds namePrefix', () async {
const String libraryName = 'sidedishes';
const String namePrefix = 'tomatosalad';
const String fileName = 'lettuce.png';
final FakeSkiaGoldClient fakeSkiaClient = FakeSkiaGoldClient();
final Directory basedir = fs.directory('flutter/test/$libraryName/')
..createSync(recursive: true);
final FlutterGoldenFileComparator comparator = FlutterPostSubmitFileComparator(
basedir.uri,
fakeSkiaClient,
fs: fs,
platform: platform,
namePrefix: namePrefix,
);
await comparator.compare(
Uint8List.fromList(_kTestPngBytes),
Uri.parse(fileName),
);
expect(fakeSkiaClient.testNames.single, '$namePrefix.$libraryName.$fileName');
});
group('Post-Submit', () {
late FakeSkiaGoldClient fakeSkiaClient;
......@@ -926,11 +947,16 @@ class FakeSkiaGoldClient extends Fake implements SkiaGoldClient {
@override
Future<void> auth() async {}
final List<String> testNames = <String>[];
int initCalls = 0;
@override
Future<void> imgtestInit() async => initCalls += 1;
@override
Future<bool> imgtestAdd(String testName, File goldenFile) async => true;
Future<bool> imgtestAdd(String testName, File goldenFile) async {
testNames.add(testName);
return true;
}
int tryInitCalls = 0;
@override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment