More beautiful linear_gradient sample (#99298)
This commit is contained in:
parent
96426230af
commit
00f3f2b14f
@ -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
|
||||
|
14
examples/api/test/flutter_test_config.dart
Normal file
14
examples/api/test/flutter_test_config.dart
Normal file
@ -0,0 +1,14 @@
|
||||
// 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');
|
||||
}
|
5
examples/api/test/goldens_io.dart
Normal file
5
examples/api/test/goldens_io.dart
Normal file
@ -0,0 +1,5 @@
|
||||
// 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;
|
8
examples/api/test/goldens_web.dart
Normal file
8
examples/api/test/goldens_web.dart
Normal file
@ -0,0 +1,8 @@
|
||||
// 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();
|
39
examples/api/test/painting/linear_gradient.0_test.dart
Normal file
39
examples/api/test/painting/linear_gradient.0_test.dart
Normal file
@ -0,0 +1,39 @@
|
||||
// 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user