mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Analyze code snippets in flutter_test docs (#132246)
Fixes https://github.com/flutter/flutter/issues/132274.
This commit is contained in:
parent
e11cc35076
commit
64a0683b41
@ -70,7 +70,8 @@ import 'package:path/path.dart' as path;
|
|||||||
import 'package:watcher/watcher.dart';
|
import 'package:watcher/watcher.dart';
|
||||||
|
|
||||||
final String _flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script))));
|
final String _flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script))));
|
||||||
final String _defaultFlutterPackage = path.join(_flutterRoot, 'packages', 'flutter', 'lib');
|
final String _packageFlutter = path.join(_flutterRoot, 'packages', 'flutter', 'lib');
|
||||||
|
final String _packageFlutterTest = path.join(_flutterRoot, 'packages', 'flutter_test', 'lib');
|
||||||
final String _defaultDartUiLocation = path.join(_flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui');
|
final String _defaultDartUiLocation = path.join(_flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui');
|
||||||
final String _flutter = path.join(_flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
|
final String _flutter = path.join(_flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
|
||||||
|
|
||||||
@ -142,12 +143,16 @@ Future<void> main(List<String> arguments) async {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory flutterPackage;
|
List<Directory> flutterPackages;
|
||||||
if (parsedArguments.rest.length == 1) {
|
if (parsedArguments.rest.length == 1) {
|
||||||
// Used for testing.
|
// Used for testing.
|
||||||
flutterPackage = Directory(parsedArguments.rest.single);
|
flutterPackages = <Directory>[Directory(parsedArguments.rest.single)];
|
||||||
} else {
|
} else {
|
||||||
flutterPackage = Directory(_defaultFlutterPackage);
|
flutterPackages = <Directory>[
|
||||||
|
Directory(_packageFlutter),
|
||||||
|
Directory(_packageFlutterTest),
|
||||||
|
// TODO(goderbauer): Add all other packages.
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
final bool includeDartUi = parsedArguments.wasParsed('dart-ui-location') || parsedArguments['include-dart-ui'] as bool;
|
final bool includeDartUi = parsedArguments.wasParsed('dart-ui-location') || parsedArguments['include-dart-ui'] as bool;
|
||||||
@ -165,14 +170,14 @@ Future<void> main(List<String> arguments) async {
|
|||||||
|
|
||||||
if (parsedArguments['interactive'] != null) {
|
if (parsedArguments['interactive'] != null) {
|
||||||
await _runInteractive(
|
await _runInteractive(
|
||||||
flutterPackage: flutterPackage,
|
flutterPackages: flutterPackages,
|
||||||
tempDirectory: parsedArguments['temp'] as String?,
|
tempDirectory: parsedArguments['temp'] as String?,
|
||||||
filePath: parsedArguments['interactive'] as String,
|
filePath: parsedArguments['interactive'] as String,
|
||||||
dartUiLocation: includeDartUi ? dartUiLocation : null,
|
dartUiLocation: includeDartUi ? dartUiLocation : null,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (await _SnippetChecker(
|
if (await _SnippetChecker(
|
||||||
flutterPackage,
|
flutterPackages,
|
||||||
tempDirectory: parsedArguments['temp'] as String?,
|
tempDirectory: parsedArguments['temp'] as String?,
|
||||||
verbose: parsedArguments['verbose'] as bool,
|
verbose: parsedArguments['verbose'] as bool,
|
||||||
dartUiLocation: includeDartUi ? dartUiLocation : null,
|
dartUiLocation: includeDartUi ? dartUiLocation : null,
|
||||||
@ -360,7 +365,7 @@ class _SnippetChecker {
|
|||||||
/// supplied, the default location of the `dart:ui` code in the Flutter
|
/// supplied, the default location of the `dart:ui` code in the Flutter
|
||||||
/// repository is used (i.e. "<flutter repo>/bin/cache/pkg/sky_engine/lib/ui").
|
/// repository is used (i.e. "<flutter repo>/bin/cache/pkg/sky_engine/lib/ui").
|
||||||
_SnippetChecker(
|
_SnippetChecker(
|
||||||
this._flutterPackage, {
|
this._flutterPackages, {
|
||||||
String? tempDirectory,
|
String? tempDirectory,
|
||||||
this.verbose = false,
|
this.verbose = false,
|
||||||
Directory? dartUiLocation,
|
Directory? dartUiLocation,
|
||||||
@ -438,8 +443,8 @@ class _SnippetChecker {
|
|||||||
/// automatically if there are no errors unless _keepTmp is true.
|
/// automatically if there are no errors unless _keepTmp is true.
|
||||||
final Directory _tempDirectory;
|
final Directory _tempDirectory;
|
||||||
|
|
||||||
/// The package directory for the flutter package within the flutter root dir.
|
/// The package directories within the flutter root dir that will be checked.
|
||||||
final Directory _flutterPackage;
|
final List<Directory> _flutterPackages;
|
||||||
|
|
||||||
/// The directory for the dart:ui code to be analyzed with the flutter code.
|
/// The directory for the dart:ui code to be analyzed with the flutter code.
|
||||||
///
|
///
|
||||||
@ -481,7 +486,7 @@ class _SnippetChecker {
|
|||||||
"import 'dart:typed_data';",
|
"import 'dart:typed_data';",
|
||||||
"import 'dart:ui' as ui;",
|
"import 'dart:ui' as ui;",
|
||||||
"import 'package:flutter_test/flutter_test.dart';",
|
"import 'package:flutter_test/flutter_test.dart';",
|
||||||
for (final File file in _listDartFiles(Directory(_defaultFlutterPackage)))
|
for (final File file in _listDartFiles(Directory(_packageFlutter)))
|
||||||
"import 'package:flutter/${path.basename(file.path)}';",
|
"import 'package:flutter/${path.basename(file.path)}';",
|
||||||
].map<_Line>((String code) => _Line.generated(code: code)).toList();
|
].map<_Line>((String code) => _Line.generated(code: code)).toList();
|
||||||
}
|
}
|
||||||
@ -495,7 +500,8 @@ class _SnippetChecker {
|
|||||||
stderr.writeln('Unable to analyze engine dart snippets at ${_dartUiLocation!.path}.');
|
stderr.writeln('Unable to analyze engine dart snippets at ${_dartUiLocation!.path}.');
|
||||||
}
|
}
|
||||||
final List<File> filesToAnalyze = <File>[
|
final List<File> filesToAnalyze = <File>[
|
||||||
..._listDartFiles(_flutterPackage, recursive: true),
|
for (final Directory flutterPackage in _flutterPackages)
|
||||||
|
..._listDartFiles(flutterPackage, recursive: true),
|
||||||
if (_dartUiLocation != null && _dartUiLocation!.existsSync())
|
if (_dartUiLocation != null && _dartUiLocation!.existsSync())
|
||||||
..._listDartFiles(_dartUiLocation!, recursive: true),
|
..._listDartFiles(_dartUiLocation!, recursive: true),
|
||||||
];
|
];
|
||||||
@ -1084,7 +1090,7 @@ class _SnippetFile {
|
|||||||
|
|
||||||
Future<void> _runInteractive({
|
Future<void> _runInteractive({
|
||||||
required String? tempDirectory,
|
required String? tempDirectory,
|
||||||
required Directory flutterPackage,
|
required List<Directory> flutterPackages,
|
||||||
required String filePath,
|
required String filePath,
|
||||||
required Directory? dartUiLocation,
|
required Directory? dartUiLocation,
|
||||||
}) async {
|
}) async {
|
||||||
@ -1106,7 +1112,7 @@ Future<void> _runInteractive({
|
|||||||
print('Starting up in interactive mode on ${path.relative(filePath, from: _flutterRoot)} ...');
|
print('Starting up in interactive mode on ${path.relative(filePath, from: _flutterRoot)} ...');
|
||||||
print('Type "q" to quit, or "r" to force a reload.');
|
print('Type "q" to quit, or "r" to force a reload.');
|
||||||
|
|
||||||
final _SnippetChecker checker = _SnippetChecker(flutterPackage, tempDirectory: tempDirectory)
|
final _SnippetChecker checker = _SnippetChecker(flutterPackages, tempDirectory: tempDirectory)
|
||||||
.._createConfigurationFiles();
|
.._createConfigurationFiles();
|
||||||
|
|
||||||
ProcessSignal.sigint.watch().listen((_) {
|
ProcessSignal.sigint.watch().listen((_) {
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
/// with the following signature:
|
/// with the following signature:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// Future<void> testExecutable(FutureOr<void> Function() testMain);
|
/// Future<void> testExecutable(FutureOr<void> Function() testMain) async { }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The test framework will execute that method and pass it the `main()` method
|
/// The test framework will execute that method and pass it the `main()` method
|
||||||
|
@ -57,6 +57,9 @@ class Evaluation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// typedef HomePage = Placeholder;
|
||||||
|
|
||||||
/// An accessibility guideline describes a recommendation an application should
|
/// An accessibility guideline describes a recommendation an application should
|
||||||
/// meet to be considered accessible.
|
/// meet to be considered accessible.
|
||||||
///
|
///
|
||||||
|
@ -55,14 +55,14 @@ import 'package:flutter/widgets.dart';
|
|||||||
/// // Start recording (`recording` is true)
|
/// // Start recording (`recording` is true)
|
||||||
/// await tester.pumpFrames(animationSheet.record(
|
/// await tester.pumpFrames(animationSheet.record(
|
||||||
/// target,
|
/// target,
|
||||||
/// recording: true,
|
/// recording: true, // ignore: avoid_redundant_argument_values
|
||||||
/// ), const Duration(seconds: 1));
|
/// ), const Duration(seconds: 1));
|
||||||
///
|
///
|
||||||
/// await gesture.up();
|
/// await gesture.up();
|
||||||
///
|
///
|
||||||
/// await tester.pumpFrames(animationSheet.record(
|
/// await tester.pumpFrames(animationSheet.record(
|
||||||
/// target,
|
/// target,
|
||||||
/// recording: true,
|
/// recording: true, // ignore: avoid_redundant_argument_values
|
||||||
/// ), const Duration(seconds: 1));
|
/// ), const Duration(seconds: 1));
|
||||||
///
|
///
|
||||||
/// // Compare against golden file
|
/// // Compare against golden file
|
||||||
|
@ -143,6 +143,10 @@ class CapturedAccessibilityAnnouncement {
|
|||||||
final Assertiveness assertiveness;
|
final Assertiveness assertiveness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// late TestWidgetsFlutterBinding binding;
|
||||||
|
// late Size someSize;
|
||||||
|
|
||||||
/// Base class for bindings used by widgets library tests.
|
/// Base class for bindings used by widgets library tests.
|
||||||
///
|
///
|
||||||
/// The [ensureInitialized] method creates (if necessary) and returns an
|
/// The [ensureInitialized] method creates (if necessary) and returns an
|
||||||
@ -1548,7 +1552,7 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
|
|||||||
/// ```dart
|
/// ```dart
|
||||||
/// TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
|
/// TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
/// if (binding is LiveTestWidgetsFlutterBinding) {
|
/// if (binding is LiveTestWidgetsFlutterBinding) {
|
||||||
/// binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.[thePolicy];
|
/// binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.onlyPumps;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
// 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:typed_data';
|
|
||||||
|
|
||||||
import 'package:matcher/expect.dart' show Description;
|
|
||||||
import 'package:matcher/src/expect/async_matcher.dart'; // ignore: implementation_imports
|
|
||||||
import 'package:test_api/hooks.dart' show TestFailure;
|
|
||||||
|
|
||||||
import 'goldens.dart';
|
|
||||||
|
|
||||||
/// Matcher created by [bufferMatchesGoldenFile].
|
|
||||||
class _BufferGoldenMatcher extends AsyncMatcher {
|
|
||||||
/// Creates an instance of [BufferGoldenMatcher]. Called by [bufferMatchesGoldenFile].
|
|
||||||
const _BufferGoldenMatcher(this.key, this.version);
|
|
||||||
|
|
||||||
/// The [key] to the golden image.
|
|
||||||
final Uri key;
|
|
||||||
|
|
||||||
/// The [version] of the golden image.
|
|
||||||
final int? version;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String?> matchAsync(dynamic item) async {
|
|
||||||
Uint8List buffer;
|
|
||||||
if (item is List<int>) {
|
|
||||||
buffer = Uint8List.fromList(item);
|
|
||||||
} else if (item is Future<List<int>>) {
|
|
||||||
buffer = Uint8List.fromList(await item);
|
|
||||||
} else {
|
|
||||||
throw AssertionError('Expected `List<int>` or `Future<List<int>>`, instead found: ${item.runtimeType}');
|
|
||||||
}
|
|
||||||
final Uri testNameUri = goldenFileComparator.getTestUri(key, version);
|
|
||||||
if (autoUpdateGoldenFiles) {
|
|
||||||
await goldenFileComparator.update(testNameUri, buffer);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
final bool success = await goldenFileComparator.compare(buffer, testNameUri);
|
|
||||||
return success ? null : 'does not match';
|
|
||||||
} on TestFailure catch (ex) {
|
|
||||||
return ex.message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Description describe(Description description) {
|
|
||||||
final Uri testNameUri = goldenFileComparator.getTestUri(key, version);
|
|
||||||
return description.add('Byte buffer matches golden image "$testNameUri"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that a [Future<List<int>>], or [List<int] matches the
|
|
||||||
/// golden image file identified by [key], with an optional [version] number.
|
|
||||||
///
|
|
||||||
/// The [key] is the [String] representation of a URL.
|
|
||||||
///
|
|
||||||
/// The [version] is a number that can be used to differentiate historical
|
|
||||||
/// golden files. This parameter is optional.
|
|
||||||
///
|
|
||||||
/// {@tool snippet}
|
|
||||||
/// Sample invocations of [bufferMatchesGoldenFile].
|
|
||||||
///
|
|
||||||
/// ```dart
|
|
||||||
/// await expectLater(
|
|
||||||
/// const <int>[ /* bytes... */ ],
|
|
||||||
/// bufferMatchesGoldenFile('sample.png'),
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
/// {@end-tool}
|
|
||||||
AsyncMatcher bufferMatchesGoldenFile(String key, {int? version}) {
|
|
||||||
return _BufferGoldenMatcher(Uri.parse(key), version);
|
|
||||||
}
|
|
@ -24,6 +24,9 @@ const double kDragSlopDefault = 20.0;
|
|||||||
|
|
||||||
const String _defaultPlatform = kIsWeb ? 'web' : 'android';
|
const String _defaultPlatform = kIsWeb ? 'web' : 'android';
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// typedef MyWidget = Placeholder;
|
||||||
|
|
||||||
/// Class that programmatically interacts with the [Semantics] tree.
|
/// Class that programmatically interacts with the [Semantics] tree.
|
||||||
///
|
///
|
||||||
/// Allows for testing of the [Semantics] tree, which is used by assistive
|
/// Allows for testing of the [Semantics] tree, which is used by assistive
|
||||||
@ -123,13 +126,13 @@ class SemanticsController {
|
|||||||
///
|
///
|
||||||
/// ## Sample Code
|
/// ## Sample Code
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```dart
|
||||||
/// testWidgets('MyWidget', (WidgetTester tester) async {
|
/// testWidgets('MyWidget', (WidgetTester tester) async {
|
||||||
/// await tester.pumpWidget(MyWidget());
|
/// await tester.pumpWidget(const MyWidget());
|
||||||
///
|
///
|
||||||
/// expect(
|
/// expect(
|
||||||
/// tester.semantics.simulatedAccessibilityTraversal(),
|
/// tester.semantics.simulatedAccessibilityTraversal(),
|
||||||
/// containsAllInOrder([
|
/// containsAllInOrder(<Matcher>[
|
||||||
/// containsSemantics(label: 'My Widget'),
|
/// containsSemantics(label: 'My Widget'),
|
||||||
/// containsSemantics(label: 'is awesome!', isChecked: true),
|
/// containsSemantics(label: 'is awesome!', isChecked: true),
|
||||||
/// ]),
|
/// ]),
|
||||||
|
@ -17,6 +17,12 @@ typedef ElementPredicate = bool Function(Element element);
|
|||||||
/// Some frequently used widget [Finder]s.
|
/// Some frequently used widget [Finder]s.
|
||||||
const CommonFinders find = CommonFinders._();
|
const CommonFinders find = CommonFinders._();
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// typedef Button = Placeholder;
|
||||||
|
// late WidgetTester tester;
|
||||||
|
// late String filePath;
|
||||||
|
// late Key backKey;
|
||||||
|
|
||||||
/// Provides lightweight syntax for getting frequently used widget [Finder]s.
|
/// Provides lightweight syntax for getting frequently used widget [Finder]s.
|
||||||
///
|
///
|
||||||
/// This class is instantiated once, as [find].
|
/// This class is instantiated once, as [find].
|
||||||
@ -116,9 +122,9 @@ class CommonFinders {
|
|||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// // Suppose you have a button with text 'Update' in it:
|
/// // Suppose you have a button with text 'Update' in it:
|
||||||
/// Button(
|
/// const Button(
|
||||||
/// child: Text('Update')
|
/// child: Text('Update')
|
||||||
/// )
|
/// );
|
||||||
///
|
///
|
||||||
/// // You can find and tap on it like this:
|
/// // You can find and tap on it like this:
|
||||||
/// tester.tap(find.widgetWithText(Button, 'Update'));
|
/// tester.tap(find.widgetWithText(Button, 'Update'));
|
||||||
@ -217,9 +223,9 @@ class CommonFinders {
|
|||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// // Suppose you have a button with icon 'arrow_forward' in it:
|
/// // Suppose you have a button with icon 'arrow_forward' in it:
|
||||||
/// Button(
|
/// const Button(
|
||||||
/// child: Icon(Icons.arrow_forward)
|
/// child: Icon(Icons.arrow_forward)
|
||||||
/// )
|
/// );
|
||||||
///
|
///
|
||||||
/// // You can find and tap on it like this:
|
/// // You can find and tap on it like this:
|
||||||
/// tester.tap(find.widgetWithIcon(Button, Icons.arrow_forward));
|
/// tester.tap(find.widgetWithIcon(Button, Icons.arrow_forward));
|
||||||
@ -242,11 +248,11 @@ class CommonFinders {
|
|||||||
/// ```dart
|
/// ```dart
|
||||||
/// // Suppose you have a button with image in it:
|
/// // Suppose you have a button with image in it:
|
||||||
/// Button(
|
/// Button(
|
||||||
/// child: Image.file(filePath)
|
/// child: Image.file(File(filePath))
|
||||||
/// )
|
/// );
|
||||||
///
|
///
|
||||||
/// // You can find and tap on it like this:
|
/// // You can find and tap on it like this:
|
||||||
/// tester.tap(find.widgetWithImage(Button, FileImage(filePath)));
|
/// tester.tap(find.widgetWithImage(Button, FileImage(File(filePath))));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||||
@ -283,7 +289,7 @@ class CommonFinders {
|
|||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// // Suppose you have a button created like this:
|
/// // Suppose you have a button created like this:
|
||||||
/// Widget myButton = Button(
|
/// Widget myButton = const Button(
|
||||||
/// child: Text('Update')
|
/// child: Text('Update')
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
@ -396,7 +402,7 @@ class CommonFinders {
|
|||||||
/// tester.widget<Opacity>(
|
/// tester.widget<Opacity>(
|
||||||
/// find.ancestor(
|
/// find.ancestor(
|
||||||
/// of: find.text('faded'),
|
/// of: find.text('faded'),
|
||||||
/// matching: find.byType('Opacity'),
|
/// matching: find.byType(Opacity),
|
||||||
/// )
|
/// )
|
||||||
/// ).opacity,
|
/// ).opacity,
|
||||||
/// 0.5
|
/// 0.5
|
||||||
|
@ -331,6 +331,13 @@ Matcher isMethodCall(String name, { required dynamic arguments }) {
|
|||||||
Matcher coversSameAreaAs(Path expectedPath, { required Rect areaToCompare, int sampleSize = 20 })
|
Matcher coversSameAreaAs(Path expectedPath, { required Rect areaToCompare, int sampleSize = 20 })
|
||||||
=> _CoversSameAreaAs(expectedPath, areaToCompare: areaToCompare, sampleSize: sampleSize);
|
=> _CoversSameAreaAs(expectedPath, areaToCompare: areaToCompare, sampleSize: sampleSize);
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// late Image image;
|
||||||
|
// late Future<Image> imageFuture;
|
||||||
|
// typedef MyWidget = Placeholder;
|
||||||
|
// late Future<ByteData> someFont;
|
||||||
|
// late WidgetTester tester;
|
||||||
|
|
||||||
/// Asserts that a [Finder], [Future<ui.Image>], or [ui.Image] matches the
|
/// Asserts that a [Finder], [Future<ui.Image>], or [ui.Image] matches the
|
||||||
/// golden image file identified by [key], with an optional [version] number.
|
/// golden image file identified by [key], with an optional [version] number.
|
||||||
///
|
///
|
||||||
@ -404,18 +411,18 @@ Matcher coversSameAreaAs(Path expectedPath, { required Rect areaToCompare, int s
|
|||||||
/// {@tool snippet}
|
/// {@tool snippet}
|
||||||
/// How to load a custom font for golden images.
|
/// How to load a custom font for golden images.
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// testWidgets('Creating a golden image with a custom font', (tester) async {
|
/// testWidgets('Creating a golden image with a custom font', (WidgetTester tester) async {
|
||||||
/// // Assuming the 'Roboto.ttf' file is declared in the pubspec.yaml file
|
/// // Assuming the 'Roboto.ttf' file is declared in the pubspec.yaml file
|
||||||
/// final font = rootBundle.load('path/to/font-file/Roboto.ttf');
|
/// final Future<ByteData> font = rootBundle.load('path/to/font-file/Roboto.ttf');
|
||||||
///
|
///
|
||||||
/// final fontLoader = FontLoader('Roboto')..addFont(font);
|
/// final FontLoader fontLoader = FontLoader('Roboto')..addFont(font);
|
||||||
/// await fontLoader.load();
|
/// await fontLoader.load();
|
||||||
///
|
///
|
||||||
/// await tester.pumpWidget(const SomeWidget());
|
/// await tester.pumpWidget(const MyWidget());
|
||||||
///
|
///
|
||||||
/// await expectLater(
|
/// await expectLater(
|
||||||
/// find.byType(SomeWidget),
|
/// find.byType(MyWidget),
|
||||||
/// matchesGoldenFile('someWidget.png'),
|
/// matchesGoldenFile('myWidget.png'),
|
||||||
/// );
|
/// );
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
@ -431,7 +438,7 @@ Matcher coversSameAreaAs(Path expectedPath, { required Rect areaToCompare, int s
|
|||||||
/// ```dart
|
/// ```dart
|
||||||
/// Future<void> testExecutable(FutureOr<void> Function() testMain) async {
|
/// Future<void> testExecutable(FutureOr<void> Function() testMain) async {
|
||||||
/// setUpAll(() async {
|
/// setUpAll(() async {
|
||||||
/// final fontLoader = FontLoader('SomeFont')..addFont(someFont);
|
/// final FontLoader fontLoader = FontLoader('SomeFont')..addFont(someFont);
|
||||||
/// await fontLoader.load();
|
/// await fontLoader.load();
|
||||||
/// });
|
/// });
|
||||||
///
|
///
|
||||||
@ -473,18 +480,20 @@ AsyncMatcher matchesGoldenFile(Object key, {int? version}) {
|
|||||||
/// ## Sample code
|
/// ## Sample code
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final ui.Paint paint = ui.Paint()
|
/// testWidgets('matchesReferenceImage', (WidgetTester tester) async {
|
||||||
/// ..style = ui.PaintingStyle.stroke
|
/// final ui.Paint paint = ui.Paint()
|
||||||
/// ..strokeWidth = 1.0;
|
/// ..style = ui.PaintingStyle.stroke
|
||||||
/// final ui.PictureRecorder recorder = ui.PictureRecorder();
|
/// ..strokeWidth = 1.0;
|
||||||
/// final ui.Canvas pictureCanvas = ui.Canvas(recorder);
|
/// final ui.PictureRecorder recorder = ui.PictureRecorder();
|
||||||
/// pictureCanvas.drawCircle(Offset.zero, 20.0, paint);
|
/// final ui.Canvas pictureCanvas = ui.Canvas(recorder);
|
||||||
/// final ui.Picture picture = recorder.endRecording();
|
/// pictureCanvas.drawCircle(Offset.zero, 20.0, paint);
|
||||||
/// ui.Image referenceImage = picture.toImage(50, 50);
|
/// final ui.Picture picture = recorder.endRecording();
|
||||||
|
/// ui.Image referenceImage = await picture.toImage(50, 50);
|
||||||
///
|
///
|
||||||
/// await expectLater(find.text('Save'), matchesReferenceImage(referenceImage));
|
/// await expectLater(find.text('Save'), matchesReferenceImage(referenceImage));
|
||||||
/// await expectLater(image, matchesReferenceImage(referenceImage);
|
/// await expectLater(image, matchesReferenceImage(referenceImage));
|
||||||
/// await expectLater(imageFuture, matchesReferenceImage(referenceImage));
|
/// await expectLater(imageFuture, matchesReferenceImage(referenceImage));
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
@ -508,9 +517,12 @@ AsyncMatcher matchesReferenceImage(ui.Image image) {
|
|||||||
/// ## Sample code
|
/// ## Sample code
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final SemanticsHandle handle = tester.ensureSemantics();
|
/// testWidgets('matchesSemantics', (WidgetTester tester) async {
|
||||||
/// expect(tester.getSemantics(find.text('hello')), matchesSemantics(label: 'hello'));
|
/// final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
/// handle.dispose();
|
/// // ...
|
||||||
|
/// expect(tester.getSemantics(find.text('hello')), matchesSemantics(label: 'hello'));
|
||||||
|
/// handle.dispose();
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
@ -685,9 +697,12 @@ Matcher matchesSemantics({
|
|||||||
/// ## Sample code
|
/// ## Sample code
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final SemanticsHandle handle = tester.ensureSemantics();
|
/// testWidgets('containsSemantics', (WidgetTester tester) async {
|
||||||
/// expect(tester.getSemantics(find.text('hello')), hasSemantics(label: 'hello'));
|
/// final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
/// handle.dispose();
|
/// // ...
|
||||||
|
/// expect(tester.getSemantics(find.text('hello')), containsSemantics(label: 'hello'));
|
||||||
|
/// handle.dispose();
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
@ -859,9 +874,12 @@ Matcher containsSemantics({
|
|||||||
/// ## Sample code
|
/// ## Sample code
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final SemanticsHandle handle = tester.ensureSemantics();
|
/// testWidgets('containsSemantics', (WidgetTester tester) async {
|
||||||
/// await expectLater(tester, meetsGuideline(textContrastGuideline));
|
/// final SemanticsHandle handle = tester.ensureSemantics();
|
||||||
/// handle.dispose();
|
/// // ...
|
||||||
|
/// await expectLater(tester, meetsGuideline(textContrastGuideline));
|
||||||
|
/// handle.dispose();
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Supported accessibility guidelines:
|
/// Supported accessibility guidelines:
|
||||||
|
@ -12,6 +12,10 @@ import 'finders.dart';
|
|||||||
import 'recording_canvas.dart';
|
import 'recording_canvas.dart';
|
||||||
import 'test_async_utils.dart';
|
import 'test_async_utils.dart';
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// late RenderObject myRenderObject;
|
||||||
|
// late Symbol methodName;
|
||||||
|
|
||||||
/// Matches objects or functions that paint a display list that matches the
|
/// Matches objects or functions that paint a display list that matches the
|
||||||
/// canvas calls described by the pattern.
|
/// canvas calls described by the pattern.
|
||||||
///
|
///
|
||||||
@ -20,8 +24,8 @@ import 'test_async_utils.dart';
|
|||||||
/// following signatures:
|
/// following signatures:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// void function(PaintingContext context, Offset offset);
|
/// void exampleOne(PaintingContext context, Offset offset) { }
|
||||||
/// void function(Canvas canvas);
|
/// void exampleTwo(Canvas canvas) { }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// In the case of functions that take a [PaintingContext] and an [Offset], the
|
/// In the case of functions that take a [PaintingContext] and an [Offset], the
|
||||||
@ -65,7 +69,9 @@ Matcher paintsExactlyCountTimes(Symbol methodName, int count) {
|
|||||||
/// literal syntax, for example:
|
/// literal syntax, for example:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// if (methodName == #drawCircle) { ... }
|
/// if (methodName == #drawCircle) {
|
||||||
|
/// // ...
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
typedef PaintPatternPredicate = bool Function(Symbol methodName, List<dynamic> arguments);
|
typedef PaintPatternPredicate = bool Function(Symbol methodName, List<dynamic> arguments);
|
||||||
|
|
||||||
|
@ -8,15 +8,15 @@
|
|||||||
/// ```dart
|
/// ```dart
|
||||||
/// class A {
|
/// class A {
|
||||||
/// const A(this.i);
|
/// const A(this.i);
|
||||||
/// int i;
|
/// final int? i;
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// main () {
|
/// void main () {
|
||||||
/// // prevent prefer_const_constructors lint
|
/// // prevent prefer_const_constructors lint
|
||||||
/// A(nonconst(null));
|
/// A(nonconst(null));
|
||||||
///
|
///
|
||||||
/// // prevent prefer_const_declarations lint
|
/// // prevent prefer_const_declarations lint
|
||||||
/// final int $null = nonconst(null);
|
/// final int? $null = nonconst(null);
|
||||||
/// final A a = nonconst(const A(null));
|
/// final A a = nonconst(const A(null));
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -35,6 +35,9 @@ class RecordedInvocation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// late WidgetTester tester;
|
||||||
|
|
||||||
/// A [Canvas] for tests that records its method calls.
|
/// A [Canvas] for tests that records its method calls.
|
||||||
///
|
///
|
||||||
/// This class can be used in conjunction with [TestRecordingPaintingContext]
|
/// This class can be used in conjunction with [TestRecordingPaintingContext]
|
||||||
|
@ -12,6 +12,9 @@ class _AsyncScope {
|
|||||||
final Zone zone;
|
final Zone zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// late WidgetTester tester;
|
||||||
|
|
||||||
/// Utility class for all the async APIs in the `flutter_test` library.
|
/// Utility class for all the async APIs in the `flutter_test` library.
|
||||||
///
|
///
|
||||||
/// This class provides checking for asynchronous APIs, allowing the library to
|
/// This class provides checking for asynchronous APIs, allowing the library to
|
||||||
|
@ -81,6 +81,9 @@ E? _lastWhereOrNull<E>(Iterable<E> list, bool Function(E) test) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Examples can assume:
|
||||||
|
// typedef MyWidget = Placeholder;
|
||||||
|
|
||||||
/// Runs the [callback] inside the Flutter test environment.
|
/// Runs the [callback] inside the Flutter test environment.
|
||||||
///
|
///
|
||||||
/// Use this function for testing custom [StatelessWidget]s and
|
/// Use this function for testing custom [StatelessWidget]s and
|
||||||
@ -117,7 +120,7 @@ E? _lastWhereOrNull<E>(Iterable<E> list, bool Function(E) test) {
|
|||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// testWidgets('MyWidget', (WidgetTester tester) async {
|
/// testWidgets('MyWidget', (WidgetTester tester) async {
|
||||||
/// await tester.pumpWidget(MyWidget());
|
/// await tester.pumpWidget(const MyWidget());
|
||||||
/// await tester.tap(find.text('Save'));
|
/// await tester.tap(find.text('Save'));
|
||||||
/// expect(find.text('Success'), findsOneWidget);
|
/// expect(find.text('Success'), findsOneWidget);
|
||||||
/// });
|
/// });
|
||||||
@ -319,12 +322,13 @@ class TargetPlatformVariant extends TestVariant<TargetPlatform> {
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// final ValueVariant<TestScenario> variants = ValueVariant<TestScenario>(
|
/// final ValueVariant<TestScenario> variants = ValueVariant<TestScenario>(
|
||||||
/// <TestScenario>{value1, value2},
|
/// <TestScenario>{TestScenario.value1, TestScenario.value2},
|
||||||
/// );
|
/// );
|
||||||
///
|
/// void main() {
|
||||||
/// testWidgets('Test handling of TestScenario', (WidgetTester tester) {
|
/// testWidgets('Test handling of TestScenario', (WidgetTester tester) async {
|
||||||
/// expect(variants.currentValue, equals(value1));
|
/// expect(variants.currentValue, equals(TestScenario.value1));
|
||||||
/// }, variant: variants);
|
/// }, variant: variants);
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
class ValueVariant<T> extends TestVariant<T> {
|
class ValueVariant<T> extends TestVariant<T> {
|
||||||
@ -507,7 +511,7 @@ Future<void> expectLater(
|
|||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// testWidgets('MyWidget', (WidgetTester tester) async {
|
/// testWidgets('MyWidget', (WidgetTester tester) async {
|
||||||
/// await tester.pumpWidget(MyWidget());
|
/// await tester.pumpWidget(const MyWidget());
|
||||||
/// await tester.tap(find.text('Save'));
|
/// await tester.tap(find.text('Save'));
|
||||||
/// await tester.pump(); // allow the application to handle
|
/// await tester.pump(); // allow the application to handle
|
||||||
/// await tester.pump(const Duration(seconds: 1)); // skip past the animation
|
/// await tester.pump(const Duration(seconds: 1)); // skip past the animation
|
||||||
@ -555,7 +559,7 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
|||||||
/// {@tool snippet}
|
/// {@tool snippet}
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// testWidgets('MyWidget asserts invalid bounds', (WidgetTester tester) async {
|
/// testWidgets('MyWidget asserts invalid bounds', (WidgetTester tester) async {
|
||||||
/// await tester.pumpWidget(MyWidget(-1));
|
/// await tester.pumpWidget(const MyWidget());
|
||||||
/// expect(tester.takeException(), isAssertionError); // or isNull, as appropriate.
|
/// expect(tester.takeException(), isAssertionError); // or isNull, as appropriate.
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1173,7 +1173,7 @@ class _UnsupportedDisplay implements TestDisplay {
|
|||||||
/// // Fake the desired properties of the TestWindow. All code running
|
/// // Fake the desired properties of the TestWindow. All code running
|
||||||
/// // within this test will perceive the following fake text scale
|
/// // within this test will perceive the following fake text scale
|
||||||
/// // factor as the real text scale factor of the window.
|
/// // factor as the real text scale factor of the window.
|
||||||
/// testBinding.window.textScaleFactorFakeValue = 2.5;
|
/// testBinding.window.textScaleFactorTestValue = 2.5; // ignore: deprecated_member_use
|
||||||
///
|
///
|
||||||
/// // Test code that depends on text scale factor here.
|
/// // Test code that depends on text scale factor here.
|
||||||
/// });
|
/// });
|
||||||
|
Loading…
Reference in New Issue
Block a user