Unverified Commit e03f4391 authored by Emmanuel Garcia's avatar Emmanuel Garcia Committed by GitHub

Reland: Skia gold driver test (#49905)

parent 8061894f
...@@ -10,5 +10,5 @@ import 'package:flutter_devicelab/tasks/integration_tests.dart'; ...@@ -10,5 +10,5 @@ import 'package:flutter_devicelab/tasks/integration_tests.dart';
Future<void> main() async { Future<void> main() async {
deviceOperatingSystem = DeviceOperatingSystem.fuchsia; deviceOperatingSystem = DeviceOperatingSystem.fuchsia;
await task(createFlutterDriverScreenshotTest()); await task(createFlutterDriverScreenshotTest(useFlutterGold: true));
} }
...@@ -107,15 +107,22 @@ TaskFunction createAndroidSplashScreenKitchenSinkTest() { ...@@ -107,15 +107,22 @@ TaskFunction createAndroidSplashScreenKitchenSinkTest() {
); );
} }
TaskFunction createFlutterDriverScreenshotTest() { /// Executes a driver test that takes a screenshot and compares it against a golden image.
/// If [useFlutterGold] is true, the golden image is served by Flutter Gold
/// (https://flutter-gold.skia.org/), otherwise the golden image is read from the disk.
TaskFunction createFlutterDriverScreenshotTest({
bool useFlutterGold = false,
}) {
return DriverTest( return DriverTest(
'${flutterDirectory.path}/dev/integration_tests/flutter_driver_screenshot_test', '${flutterDirectory.path}/dev/integration_tests/flutter_driver_screenshot_test',
'lib/main.dart', 'lib/main.dart',
extraOptions: useFlutterGold ? const <String>[
'--driver', 'test_driver/flutter_gold_main_test.dart'
] : const <String>[]
); );
} }
class DriverTest { class DriverTest {
DriverTest( DriverTest(
this.testDirectory, this.testDirectory,
this.testTarget, { this.testTarget, {
......
...@@ -4,7 +4,12 @@ This tests contains an app with a main page and sub pages. ...@@ -4,7 +4,12 @@ This tests contains an app with a main page and sub pages.
The main page contains a list of buttons; each button leads to a designated sub page when tapped on. The main page contains a list of buttons; each button leads to a designated sub page when tapped on.
Each sub page should displays some simple UIs to screenshot tested. Each sub page should displays some simple UIs to screenshot tested.
The flutter driver test runs the app and opens each page to take a screenshot. Then it compares the screenshot against a golden image stored in `test_driver/goldens/<some_test_page_name>/<device_model>.png`. The flutter driver test runs the app and opens each page to take a screenshot.
Use `test_driver/flutter_gold_main_test.dart` to test against golden files stored on Flutter Gold.
Otherwise, use `main_test.dart` to test against golden files stored on `test_driver/goldens/<some_test_page_name>/<device_model>.png`.
Note that new binaries can't be checked in the Flutter repo, so use [Flutter Gold](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter) instead.
# Add a new page to test # Add a new page to test
...@@ -16,6 +21,7 @@ The flutter driver test runs the app and opens each page to take a screenshot. T ...@@ -16,6 +21,7 @@ The flutter driver test runs the app and opens each page to take a screenshot. T
An example of a `Page` subclass can be found in `lib/image_page.dart` An example of a `Page` subclass can be found in `lib/image_page.dart`
# Experiments # Environments
The test currently only runs on device lab ["mac/ios"] which runs the app on iPhone 6s. * Device Lab which runs the app on iPhone 6s.
\ No newline at end of file * LUCI which runs the app on a Fuchsia NUC device.
// 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_driver/flutter_driver.dart';
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
import 'package:flutter_test/src/buffer_matcher.dart';
Future<void> main() async {
FlutterDriver driver;
String deviceModel;
setUpAll(() async {
driver = await FlutterDriver.connect();
deviceModel = await driver.requestData('device_model');
});
tearDownAll(() => driver.close());
test('A page with an image screenshot', () async {
final SerializableFinder imagePageListTile =
find.byValueKey('image_page');
await driver.waitFor(imagePageListTile);
await driver.tap(imagePageListTile);
await driver.waitFor(find.byValueKey('red_square_image'));
await driver.waitUntilNoTransientCallbacks();
// TODO(egarciad): This is currently a no-op on LUCI.
// https://github.com/flutter/flutter/issues/49837
await expectLater(
driver.screenshot(),
bufferMatchesGoldenFile('red_square_driver_screenshot__$deviceModel.png'),
);
await driver.tap(find.byTooltip('Back'));
});
}
...@@ -4,11 +4,8 @@ ...@@ -4,11 +4,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'dart:math' as math;
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/widgets.dart' show Element;
import 'package:image/image.dart'; import 'package:image/image.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
// ignore: deprecated_member_use // ignore: deprecated_member_use
...@@ -166,92 +163,3 @@ class LocalComparisonOutput { ...@@ -166,92 +163,3 @@ class LocalComparisonOutput {
)); ));
} }
} }
/// Returns a [ComparisonResult] to describe the pixel differential of the
/// [test] and [master] image bytes provided.
ComparisonResult compareLists(List<int> test, List<int> master) {
if (identical(test, master))
return ComparisonResult(passed: true);
if (test == null || master == null || test.isEmpty || master.isEmpty) {
return ComparisonResult(
passed: false,
error: 'Pixel test failed, null image provided.',
);
}
final Image testImage = decodePng(test);
final Image masterImage = decodePng(master);
assert(testImage != null);
assert(masterImage != null);
final int width = testImage.width;
final int height = testImage.height;
if (width != masterImage.width || height != masterImage.height) {
return ComparisonResult(
passed: false,
error: 'Pixel test failed, image sizes do not match.\n'
'Master Image: ${masterImage.width} X ${masterImage.height}\n'
'Test Image: ${testImage.width} X ${testImage.height}',
);
}
int pixelDiffCount = 0;
final int totalPixels = width * height;
final Image invertedMaster = invert(Image.from(masterImage));
final Image invertedTest = invert(Image.from(testImage));
final Map<String, Image> diffs = <String, Image>{
'masterImage' : masterImage,
'testImage' : testImage,
'maskedDiff' : Image.from(testImage),
'isolatedDiff' : Image(width, height),
};
for (int x = 0; x < width; x++) {
for (int y =0; y < height; y++) {
final int testPixel = testImage.getPixel(x, y);
final int masterPixel = masterImage.getPixel(x, y);
final int diffPixel = (getRed(testPixel) - getRed(masterPixel)).abs()
+ (getGreen(testPixel) - getGreen(masterPixel)).abs()
+ (getBlue(testPixel) - getBlue(masterPixel)).abs()
+ (getAlpha(testPixel) - getAlpha(masterPixel)).abs();
if (diffPixel != 0 ) {
final int invertedMasterPixel = invertedMaster.getPixel(x, y);
final int invertedTestPixel = invertedTest.getPixel(x, y);
final int maskPixel = math.max(invertedMasterPixel, invertedTestPixel);
diffs['maskedDiff'].setPixel(x, y, maskPixel);
diffs['isolatedDiff'].setPixel(x, y, maskPixel);
pixelDiffCount++;
}
}
}
if (pixelDiffCount > 0) {
return ComparisonResult(
passed: false,
error: 'Pixel test failed, '
'${((pixelDiffCount/totalPixels) * 100).toStringAsFixed(2)}% '
'diff detected.',
diffs: diffs,
);
}
return ComparisonResult(passed: true);
}
/// An unsupported [WebGoldenComparator] that exists for API compatibility.
class DefaultWebGoldenComparator extends WebGoldenComparator {
@override
Future<bool> compare(Element element, Size size, Uri golden) {
throw UnsupportedError('DefaultWebGoldenComparator is only supported on the web.');
}
@override
Future<void> update(Uri golden, Element element, Size size) {
throw UnsupportedError('DefaultWebGoldenComparator is only supported on the web.');
}
}
...@@ -9,6 +9,7 @@ import 'dart:ui'; ...@@ -9,6 +9,7 @@ import 'dart:ui';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:path/path.dart' as path;
// ignore: deprecated_member_use // ignore: deprecated_member_use
import 'package:test_api/test_api.dart' as test_package show TestFailure; import 'package:test_api/test_api.dart' as test_package show TestFailure;
...@@ -35,6 +36,115 @@ ComparisonResult compareLists(List<int> test, List<int> master) { ...@@ -35,6 +36,115 @@ ComparisonResult compareLists(List<int> test, List<int> master) {
throw UnsupportedError('Golden testing is not supported on the web.'); throw UnsupportedError('Golden testing is not supported on the web.');
} }
/// Compares image pixels against a golden image file.
///
/// Instances of this comparator will be used as the backend for
/// [matchesGoldenFile] when tests are running on Flutter Web, and will usually
/// implemented by deferring the screenshot taking and image comparison to a
/// test server.
///
/// Instances of this comparator will be invoked by the test framework in the
/// [TestWidgetsFlutterBinding.runAsync] zone and are thus not subject to the
/// fake async constraints that are normally imposed on widget tests (i.e. the
/// need or the ability to call [WidgetTester.pump] to advance the microtask
/// queue). Prior to the invocation, the test framework will render only the
/// [Element] to be compared on the screen.
///
/// See also:
///
/// * [GoldenFileComparator] for the comparator to be used when the test is
/// not running in a web browser.
/// * [DefaultWebGoldenComparator] for the default [WebGoldenComparator]
/// implementation for `flutter test`.
/// * [matchesGoldenFile], the function from [flutter_test] that invokes the
/// comparator.
abstract class WebGoldenComparator {
/// Compares the rendered pixels of [element] of size [size] that is being
/// rendered on the top left of the screen against the golden file identified
/// by [golden].
///
/// The returned future completes with a boolean value that indicates whether
/// the pixels rendered on screen match the golden file's pixels.
///
/// In the case of comparison mismatch, the comparator may choose to throw a
/// [TestFailure] if it wants to control the failure message, often in the
/// form of a [ComparisonResult] that provides detailed information about the
/// mismatch.
///
/// The method by which [golden] is located and by which its bytes are loaded
/// is left up to the implementation class. For instance, some implementations
/// may load files from the local file system, whereas others may load files
/// over the network or from a remote repository.
Future<bool> compare(Element element, Size size, Uri golden);
/// Updates the golden file identified by [golden] with rendered pixels of
/// [element].
///
/// This will be invoked in lieu of [compare] when [autoUpdateGoldenFiles]
/// is `true` (which gets set automatically by the test framework when the
/// user runs `flutter test --update-goldens --platform=chrome`).
///
/// The method by which [golden] is located and by which its bytes are written
/// is left up to the implementation class.
Future<void> update(Uri golden, Element element, Size size);
/// Returns a new golden file [Uri] to incorporate any [version] number with
/// the [key].
///
/// The [version] is an optional int that can be used to differentiate
/// historical golden files.
///
/// Version numbers are used in golden file tests for package:flutter. You can
/// learn more about these tests [here](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter).
Uri getTestUri(Uri key, int version) {
if (version == null)
return key;
final String keyString = key.toString();
final String extension = path.extension(keyString);
return Uri.parse(
keyString
.split(extension)
.join() + '.' + version.toString() + extension
);
}
}
/// Compares pixels against those of a golden image file.
///
/// This comparator is used as the backend for [matchesGoldenFile] when tests
/// are running in a web browser.
///
/// When using `flutter test --platform=chrome`, a comparator implemented by
/// [DefaultWebGoldenComparator] is used if no other comparator is specified. It
/// will send a request to the test server, which uses [goldenFileComparator]
/// for golden file compatison.
///
/// When using `flutter test --update-goldens`, the [DefaultWebGoldenComparator]
/// updates the files on disk to match the rendering.
///
/// When using `flutter run`, the default comparator
/// ([_TrivialWebGoldenComparator]) is used. It prints a message to the console
/// but otherwise does nothing. This allows tests to be developed visually on a
/// web browser.
///
/// Callers may choose to override the default comparator by setting this to a
/// custom comparator during test set-up (or using directory-level test
/// configuration). For example, some projects may wish to install a comparator
/// with tolerance levels for allowable differences.
///
/// See also:
///
/// * [flutter_test] for more information about how to configure tests at the
/// directory-level.
/// * [goldenFileComparator], the comparator used when tests are not running on
/// a web browser.
WebGoldenComparator get webGoldenComparator => _webGoldenComparator;
WebGoldenComparator _webGoldenComparator = const _TrivialWebGoldenComparator._();
set webGoldenComparator(WebGoldenComparator value) {
assert(value != null);
_webGoldenComparator = value;
}
/// The default [WebGoldenComparator] implementation for `flutter test`. /// The default [WebGoldenComparator] implementation for `flutter test`.
/// ///
/// This comparator will send a request to the test server for golden comparison /// This comparator will send a request to the test server for golden comparison
...@@ -87,3 +197,23 @@ class DefaultWebGoldenComparator extends WebGoldenComparator { ...@@ -87,3 +197,23 @@ class DefaultWebGoldenComparator extends WebGoldenComparator {
await compare(element, size, golden); await compare(element, size, golden);
} }
} }
class _TrivialWebGoldenComparator implements WebGoldenComparator {
const _TrivialWebGoldenComparator._();
@override
Future<bool> compare(Element element, Size size, Uri golden) {
print('Golden comparison requested for "$golden"; skipping...');
return Future<bool>.value(true);
}
@override
Future<void> update(Uri golden, Element element, Size size) {
throw StateError('webGoldenComparator has not been initialized');
}
@override
Uri getTestUri(Uri key, int version) {
return key;
}
}
...@@ -11,6 +11,7 @@ import 'package:test_api/src/frontend/async_matcher.dart'; // ignore: implementa ...@@ -11,6 +11,7 @@ import 'package:test_api/src/frontend/async_matcher.dart'; // ignore: implementa
// ignore: deprecated_member_use // ignore: deprecated_member_use
import 'package:test_api/test_api.dart' hide TypeMatcher, isInstanceOf; import 'package:test_api/test_api.dart' hide TypeMatcher, isInstanceOf;
import '_goldens_web.dart';
import 'binding.dart'; import 'binding.dart';
import 'finders.dart'; import 'finders.dart';
import 'goldens.dart'; import 'goldens.dart';
......
// 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 'dart:typed_data';
import 'package:test_api/src/frontend/async_matcher.dart'; // ignore: implementation_imports
// ignore: deprecated_member_use
import 'package:test_api/test_api.dart' show Description, 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 '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 [matchesGoldenFile].
///
/// ```dart
/// await expectLater(
/// const <int>[],
/// bufferMatchesGoldenFile('sample.png'),
/// );
/// ```
/// {@end-tool}
AsyncMatcher bufferMatchesGoldenFile(String key, {int version}) {
return _BufferGoldenMatcher(Uri.parse(key), version);
}
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:math' as math;
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/foundation.dart'; import 'package:meta/meta.dart';
import 'package:flutter/widgets.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '_goldens_io.dart' if (dart.library.html) '_goldens_web.dart' as _goldens; import 'package:image/image.dart';
/// Compares image pixels against a golden image file. /// Compares image pixels against a golden image file.
/// ///
...@@ -98,7 +98,77 @@ abstract class GoldenFileComparator { ...@@ -98,7 +98,77 @@ abstract class GoldenFileComparator {
/// Returns a [ComparisonResult] to describe the pixel differential of the /// Returns a [ComparisonResult] to describe the pixel differential of the
/// [test] and [master] image bytes provided. /// [test] and [master] image bytes provided.
static ComparisonResult compareLists(List<int> test, List<int> master) { static ComparisonResult compareLists(List<int> test, List<int> master) {
return _goldens.compareLists(test, master); if (identical(test, master))
return ComparisonResult(passed: true);
if (test == null || master == null || test.isEmpty || master.isEmpty) {
return ComparisonResult(
passed: false,
error: 'Pixel test failed, null image provided.',
);
}
final Image testImage = decodePng(test);
final Image masterImage = decodePng(master);
assert(testImage != null);
assert(masterImage != null);
final int width = testImage.width;
final int height = testImage.height;
if (width != masterImage.width || height != masterImage.height) {
return ComparisonResult(
passed: false,
error: 'Pixel test failed, image sizes do not match.\n'
'Master Image: ${masterImage.width} X ${masterImage.height}\n'
'Test Image: ${testImage.width} X ${testImage.height}',
);
}
int pixelDiffCount = 0;
final int totalPixels = width * height;
final Image invertedMaster = invert(Image.from(masterImage));
final Image invertedTest = invert(Image.from(testImage));
final Map<String, Image> diffs = <String, Image>{
'masterImage' : masterImage,
'testImage' : testImage,
'maskedDiff' : Image.from(testImage),
'isolatedDiff' : Image(width, height),
};
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
final int testPixel = testImage.getPixel(x, y);
final int masterPixel = masterImage.getPixel(x, y);
final int diffPixel = (getRed(testPixel) - getRed(masterPixel)).abs()
+ (getGreen(testPixel) - getGreen(masterPixel)).abs()
+ (getBlue(testPixel) - getBlue(masterPixel)).abs()
+ (getAlpha(testPixel) - getAlpha(masterPixel)).abs();
if (diffPixel != 0 ) {
final int invertedMasterPixel = invertedMaster.getPixel(x, y);
final int invertedTestPixel = invertedTest.getPixel(x, y);
final int maskPixel = math.max(invertedMasterPixel, invertedTestPixel);
diffs['maskedDiff'].setPixel(x, y, maskPixel);
diffs['isolatedDiff'].setPixel(x, y, maskPixel);
pixelDiffCount++;
}
}
}
if (pixelDiffCount > 0) {
return ComparisonResult(
passed: false,
error: 'Pixel test failed, '
'${((pixelDiffCount/totalPixels) * 100).toStringAsFixed(2)}% '
'diff detected.',
diffs: diffs,
);
}
return ComparisonResult(passed: true);
} }
} }
...@@ -135,115 +205,6 @@ set goldenFileComparator(GoldenFileComparator value) { ...@@ -135,115 +205,6 @@ set goldenFileComparator(GoldenFileComparator value) {
_goldenFileComparator = value; _goldenFileComparator = value;
} }
/// Compares image pixels against a golden image file.
///
/// Instances of this comparator will be used as the backend for
/// [matchesGoldenFile] when tests are running on Flutter Web, and will usually
/// implemented by deferring the screenshot taking and image comparison to a
/// test server.
///
/// Instances of this comparator will be invoked by the test framework in the
/// [TestWidgetsFlutterBinding.runAsync] zone and are thus not subject to the
/// fake async constraints that are normally imposed on widget tests (i.e. the
/// need or the ability to call [WidgetTester.pump] to advance the microtask
/// queue). Prior to the invocation, the test framework will render only the
/// [Element] to be compared on the screen.
///
/// See also:
///
/// * [GoldenFileComparator] for the comparator to be used when the test is
/// not running in a web browser.
/// * [DefaultWebGoldenComparator] for the default [WebGoldenComparator]
/// implementation for `flutter test`.
/// * [matchesGoldenFile], the function from [flutter_test] that invokes the
/// comparator.
abstract class WebGoldenComparator {
/// Compares the rendered pixels of [element] of size [size] that is being
/// rendered on the top left of the screen against the golden file identified
/// by [golden].
///
/// The returned future completes with a boolean value that indicates whether
/// the pixels rendered on screen match the golden file's pixels.
///
/// In the case of comparison mismatch, the comparator may choose to throw a
/// [TestFailure] if it wants to control the failure message, often in the
/// form of a [ComparisonResult] that provides detailed information about the
/// mismatch.
///
/// The method by which [golden] is located and by which its bytes are loaded
/// is left up to the implementation class. For instance, some implementations
/// may load files from the local file system, whereas others may load files
/// over the network or from a remote repository.
Future<bool> compare(Element element, Size size, Uri golden);
/// Updates the golden file identified by [golden] with rendered pixels of
/// [element].
///
/// This will be invoked in lieu of [compare] when [autoUpdateGoldenFiles]
/// is `true` (which gets set automatically by the test framework when the
/// user runs `flutter test --update-goldens --platform=chrome`).
///
/// The method by which [golden] is located and by which its bytes are written
/// is left up to the implementation class.
Future<void> update(Uri golden, Element element, Size size);
/// Returns a new golden file [Uri] to incorporate any [version] number with
/// the [key].
///
/// The [version] is an optional int that can be used to differentiate
/// historical golden files.
///
/// Version numbers are used in golden file tests for package:flutter. You can
/// learn more about these tests [here](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter).
Uri getTestUri(Uri key, int version) {
if (version == null)
return key;
final String keyString = key.toString();
final String extension = path.extension(keyString);
return Uri.parse(
keyString
.split(extension)
.join() + '.' + version.toString() + extension
);
}
}
/// Compares pixels against those of a golden image file.
///
/// This comparator is used as the backend for [matchesGoldenFile] when tests
/// are running in a web browser.
///
/// When using `flutter test --platform=chrome`, a comparator implemented by
/// [DefaultWebGoldenComparator] is used if no other comparator is specified. It
/// will send a request to the test server, which uses [goldenFileComparator]
/// for golden file compatison.
///
/// When using `flutter test --update-goldens`, the [DefaultWebGoldenComparator]
/// updates the files on disk to match the rendering.
///
/// When using `flutter run`, the default comparator
/// ([_TrivialWebGoldenComparator]) is used. It prints a message to the console
/// but otherwise does nothing. This allows tests to be developed visually on a
/// web browser.
///
/// Callers may choose to override the default comparator by setting this to a
/// custom comparator during test set-up (or using directory-level test
/// configuration). For example, some projects may wish to install a comparator
/// with tolerance levels for allowable differences.
///
/// See also:
///
/// * [flutter_test] for more information about how to configure tests at the
/// directory-level.
/// * [goldenFileComparator], the comparator used when tests are not running on
/// a web browser.
WebGoldenComparator get webGoldenComparator => _webGoldenComparator;
WebGoldenComparator _webGoldenComparator = const _TrivialWebGoldenComparator._();
set webGoldenComparator(WebGoldenComparator value) {
assert(value != null);
_webGoldenComparator = value;
}
/// Whether golden files should be automatically updated during tests rather /// Whether golden files should be automatically updated during tests rather
/// than compared to the image bytes recorded by the tests. /// than compared to the image bytes recorded by the tests.
/// ///
...@@ -280,7 +241,7 @@ class TrivialComparator implements GoldenFileComparator { ...@@ -280,7 +241,7 @@ class TrivialComparator implements GoldenFileComparator {
@override @override
Future<bool> compare(Uint8List imageBytes, Uri golden) { Future<bool> compare(Uint8List imageBytes, Uri golden) {
debugPrint('Golden file comparison requested for "$golden"; skipping...'); print('Golden file comparison requested for "$golden"; skipping...');
return Future<bool>.value(true); return Future<bool>.value(true);
} }
...@@ -295,26 +256,6 @@ class TrivialComparator implements GoldenFileComparator { ...@@ -295,26 +256,6 @@ class TrivialComparator implements GoldenFileComparator {
} }
} }
class _TrivialWebGoldenComparator implements WebGoldenComparator {
const _TrivialWebGoldenComparator._();
@override
Future<bool> compare(Element element, Size size, Uri golden) {
debugPrint('Golden comparison requested for "$golden"; skipping...');
return Future<bool>.value(true);
}
@override
Future<void> update(Uri golden, Element element, Size size) {
throw StateError('webGoldenComparator has not been initialized');
}
@override
Uri getTestUri(Uri key, int version) {
return key;
}
}
/// The result of a pixel comparison test. /// The result of a pixel comparison test.
/// ///
/// The [ComparisonResult] will always indicate if a test has [passed]. The /// The [ComparisonResult] will always indicate if a test has [passed]. The
......
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