
* Update project.pbxproj files to say Flutter rather than Chromium Also, the templates now have an empty organization so that we don't cause people to give their apps a Flutter copyright. * Update the copyright notice checker to require a standard notice on all files * Update copyrights on Dart files. (This was a mechanical commit.) * Fix weird license headers on Dart files that deviate from our conventions; relicense Shrine. Some were already marked "The Flutter Authors", not clear why. Their dates have been normalized. Some were missing the blank line after the license. Some were randomly different in trivial ways for no apparent reason (e.g. missing the trailing period). * Clean up the copyrights in non-Dart files. (Manual edits.) Also, make sure templates don't have copyrights. * Fix some more ORGANIZATIONNAMEs
251 lines
9.8 KiB
Dart
251 lines
9.8 KiB
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:io' as io;
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:file/memory.dart';
|
|
import 'package:flutter_test/flutter_test.dart' hide test;
|
|
import 'package:flutter_test/flutter_test.dart' as test_package;
|
|
|
|
// 1x1 transparent pixel
|
|
const List<int> _kExpectedPngBytes =
|
|
<int>[137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0,
|
|
1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 11, 73, 68, 65, 84,
|
|
120, 1, 99, 97, 0, 2, 0, 0, 25, 0, 5, 144, 240, 54, 245, 0, 0, 0, 0, 73, 69,
|
|
78, 68, 174, 66, 96, 130];
|
|
|
|
// 1x1 colored pixel
|
|
const List<int> _kColorFailurePngBytes =
|
|
<int>[137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0,
|
|
1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84,
|
|
120, 1, 99, 249, 207, 240, 255, 63, 0, 7, 18, 3, 2, 164, 147, 160, 197, 0,
|
|
0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130];
|
|
|
|
// 1x2 transparent pixel
|
|
const List<int> _kSizeFailurePngBytes =
|
|
<int>[137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0,
|
|
1, 0, 0,0, 2, 8, 6, 0, 0, 0, 153, 129, 182, 39, 0, 0, 0, 14, 73, 68, 65, 84,
|
|
120, 1, 99, 97, 0, 2, 22, 16, 1, 0, 0, 70, 0, 9, 112, 117, 150, 160, 0, 0,
|
|
0, 0, 73, 69, 78, 68, 174, 66, 96, 130];
|
|
|
|
void main() {
|
|
MemoryFileSystem fs;
|
|
|
|
setUp(() {
|
|
final FileSystemStyle style = io.Platform.isWindows
|
|
? FileSystemStyle.windows
|
|
: FileSystemStyle.posix;
|
|
fs = MemoryFileSystem(style: style);
|
|
});
|
|
|
|
/// Converts posix-style paths to the style associated with [fs].
|
|
///
|
|
/// This allows us to deal in posix-style paths in the tests.
|
|
String fix(String path) {
|
|
if (path.startsWith('/')) {
|
|
path = '${fs.style.drive}$path';
|
|
}
|
|
return path.replaceAll('/', fs.path.separator);
|
|
}
|
|
|
|
void test(String description, FutureOr<void> body()) {
|
|
test_package.test(description, () {
|
|
return io.IOOverrides.runZoned<FutureOr<void>>(
|
|
body,
|
|
createDirectory: (String path) => fs.directory(path),
|
|
createFile: (String path) => fs.file(path),
|
|
createLink: (String path) => fs.link(path),
|
|
getCurrentDirectory: () => fs.currentDirectory,
|
|
setCurrentDirectory: (String path) => fs.currentDirectory = path,
|
|
getSystemTempDirectory: () => fs.systemTempDirectory,
|
|
stat: (String path) => fs.stat(path),
|
|
statSync: (String path) => fs.statSync(path),
|
|
fseIdentical: (String p1, String p2) => fs.identical(p1, p2),
|
|
fseIdenticalSync: (String p1, String p2) => fs.identicalSync(p1, p2),
|
|
fseGetType: (String path, bool followLinks) => fs.type(path, followLinks: followLinks),
|
|
fseGetTypeSync: (String path, bool followLinks) => fs.typeSync(path, followLinks: followLinks),
|
|
fsWatch: (String a, int b, bool c) => throw UnsupportedError('unsupported'),
|
|
fsWatchIsSupported: () => fs.isWatchSupported,
|
|
);
|
|
});
|
|
}
|
|
|
|
group('goldenFileComparator', () {
|
|
test('is initialized by test framework', () {
|
|
expect(goldenFileComparator, isNotNull);
|
|
expect(goldenFileComparator, isInstanceOf<LocalFileComparator>());
|
|
final LocalFileComparator comparator = goldenFileComparator as LocalFileComparator;
|
|
expect(comparator.basedir.path, contains('flutter_test'));
|
|
});
|
|
});
|
|
|
|
group('LocalFileComparator', () {
|
|
LocalFileComparator comparator;
|
|
|
|
setUp(() {
|
|
comparator = LocalFileComparator(fs.file(fix('/golden_test.dart')).uri, pathStyle: fs.path.style);
|
|
});
|
|
|
|
test('calculates basedir correctly', () {
|
|
expect(comparator.basedir, fs.file(fix('/')).uri);
|
|
comparator = LocalFileComparator(fs.file(fix('/foo/bar/golden_test.dart')).uri, pathStyle: fs.path.style);
|
|
expect(comparator.basedir, fs.directory(fix('/foo/bar/')).uri);
|
|
});
|
|
|
|
test('can be instantiated with uri that represents file in same folder', () {
|
|
comparator = LocalFileComparator(Uri.parse('foo_test.dart'), pathStyle: fs.path.style);
|
|
expect(comparator.basedir, Uri.parse('./'));
|
|
});
|
|
|
|
group('compare', () {
|
|
Future<bool> doComparison([ String golden = 'golden.png' ]) {
|
|
final Uri uri = fs.file(fix(golden)).uri;
|
|
return comparator.compare(
|
|
Uint8List.fromList(_kExpectedPngBytes),
|
|
uri,
|
|
);
|
|
}
|
|
|
|
group('succeeds', () {
|
|
test('when golden file is in same folder as test', () async {
|
|
fs.file(fix('/golden.png')).writeAsBytesSync(_kExpectedPngBytes);
|
|
final bool success = await doComparison();
|
|
expect(success, isTrue);
|
|
});
|
|
|
|
test('when golden file is in subfolder of test', () async {
|
|
fs.file(fix('/sub/foo.png'))
|
|
..createSync(recursive: true)
|
|
..writeAsBytesSync(_kExpectedPngBytes);
|
|
final bool success = await doComparison('sub/foo.png');
|
|
expect(success, isTrue);
|
|
});
|
|
|
|
group('when comparator instantiated with uri that represents file in same folder', () {
|
|
test('and golden file is in same folder as test', () async {
|
|
fs.file(fix('/foo/bar/golden.png'))
|
|
..createSync(recursive: true)
|
|
..writeAsBytesSync(_kExpectedPngBytes);
|
|
fs.currentDirectory = fix('/foo/bar');
|
|
comparator = LocalFileComparator(Uri.parse('local_test.dart'), pathStyle: fs.path.style);
|
|
final bool success = await doComparison('golden.png');
|
|
expect(success, isTrue);
|
|
});
|
|
|
|
test('and golden file is in subfolder of test', () async {
|
|
fs.file(fix('/foo/bar/baz/golden.png'))
|
|
..createSync(recursive: true)
|
|
..writeAsBytesSync(_kExpectedPngBytes);
|
|
fs.currentDirectory = fix('/foo/bar');
|
|
comparator = LocalFileComparator(Uri.parse('local_test.dart'), pathStyle: fs.path.style);
|
|
final bool success = await doComparison('baz/golden.png');
|
|
expect(success, isTrue);
|
|
});
|
|
});
|
|
});
|
|
|
|
group('fails', () {
|
|
|
|
test('and generates correct output in the correct location', () async {
|
|
comparator = LocalFileComparator(Uri.parse('local_test.dart'), pathStyle: fs.path.style);
|
|
await fs.file(fix('/golden.png')).writeAsBytes(_kColorFailurePngBytes);
|
|
try {
|
|
await doComparison();
|
|
fail('TestFailure expected but not thrown.');
|
|
} on TestFailure catch (error) {
|
|
expect(error.message, contains('% diff detected'));
|
|
final io.File master = fs.file(
|
|
fix('/failures/golden_masterImage.png')
|
|
);
|
|
final io.File test = fs.file(
|
|
fix('/failures/golden_testImage.png')
|
|
);
|
|
final io.File isolated = fs.file(
|
|
fix('/failures/golden_isolatedDiff.png')
|
|
);
|
|
final io.File masked = fs.file(
|
|
fix('/failures/golden_maskedDiff.png')
|
|
);
|
|
expect(master.existsSync(), isTrue);
|
|
expect(test.existsSync(), isTrue);
|
|
expect(isolated.existsSync(), isTrue);
|
|
expect(masked.existsSync(), isTrue);
|
|
}
|
|
});
|
|
|
|
test('when golden file does not exist', () async {
|
|
try {
|
|
await doComparison();
|
|
fail('TestFailure expected but not thrown.');
|
|
} on TestFailure catch (error) {
|
|
expect(error.message, contains('Could not be compared against non-existent file'));
|
|
}
|
|
});
|
|
|
|
test('when images are not the same size', () async{
|
|
await fs.file(fix('/golden.png')).writeAsBytes(_kSizeFailurePngBytes);
|
|
try {
|
|
await doComparison();
|
|
fail('TestFailure expected but not thrown.');
|
|
} on TestFailure catch (error) {
|
|
expect(error.message, contains('image sizes do not match'));
|
|
}
|
|
});
|
|
|
|
test('when pixels do not match', () async{
|
|
await fs.file(fix('/golden.png')).writeAsBytes(_kColorFailurePngBytes);
|
|
try {
|
|
await doComparison();
|
|
fail('TestFailure expected but not thrown.');
|
|
} on TestFailure catch (error) {
|
|
expect(error.message, contains('% diff detected'));
|
|
}
|
|
});
|
|
|
|
test('when golden bytes are empty', () async {
|
|
await fs.file(fix('/golden.png')).writeAsBytes(<int>[]);
|
|
try {
|
|
await doComparison();
|
|
fail('TestFailure expected but not thrown.');
|
|
} on TestFailure catch (error) {
|
|
expect(error.message, contains('null image provided'));
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
group('update', () {
|
|
test('updates existing file', () async {
|
|
fs.file(fix('/golden.png')).writeAsBytesSync(_kExpectedPngBytes);
|
|
const List<int> newBytes = <int>[11, 12, 13];
|
|
await comparator.update(fs.file('golden.png').uri, Uint8List.fromList(newBytes));
|
|
expect(fs.file(fix('/golden.png')).readAsBytesSync(), newBytes);
|
|
});
|
|
|
|
test('creates non-existent file', () async {
|
|
expect(fs.file(fix('/foo.png')).existsSync(), isFalse);
|
|
const List<int> newBytes = <int>[11, 12, 13];
|
|
await comparator.update(fs.file('foo.png').uri, Uint8List.fromList(newBytes));
|
|
expect(fs.file(fix('/foo.png')).existsSync(), isTrue);
|
|
expect(fs.file(fix('/foo.png')).readAsBytesSync(), newBytes);
|
|
});
|
|
});
|
|
|
|
group('getTestUri', () {
|
|
test('updates file name with version number', () {
|
|
final Uri key = Uri.parse('foo.png');
|
|
final Uri key1 = comparator.getTestUri(key, 1);
|
|
expect(key1, Uri.parse('foo.1.png'));
|
|
});
|
|
test('does nothing for null version number', () {
|
|
final Uri key = Uri.parse('foo.png');
|
|
final Uri keyNull = comparator.getTestUri(key, null);
|
|
expect(keyNull, Uri.parse('foo.png'));
|
|
});
|
|
});
|
|
});
|
|
}
|