blob: cc69142d8b90ea4da04528c62ffc4a5a7028fa2e [file] [log] [blame]
// Copyright 2013 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:js_interop';
import 'dart:typed_data';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'package:web_engine_tester/golden_tester.dart';
import '../common/rendering.dart';
import '../common/test_initialization.dart';
export '../common/rendering.dart' show renderScene;
const MethodCodec codec = StandardMethodCodec();
/// Common test setup for all CanvasKit unit-tests.
void setUpCanvasKitTest({bool withImplicitView = false}) {
setUpUnitTests(
withImplicitView: withImplicitView,
emulateTesterEnvironment: false,
setUpTestViewDimensions: false,
);
setUp(() => debugOverrideJsConfiguration(<String, Object?>{
'fontFallbackBaseUrl': 'assets/fallback_fonts/',
}.jsify() as JsFlutterConfiguration?));
}
/// Convenience getter for the implicit view.
ui.FlutterView get implicitView =>
EnginePlatformDispatcher.instance.implicitView!;
/// Utility function for CanvasKit tests to draw pictures without
/// the [CkPictureRecorder] boilerplate.
CkPicture paintPicture(
ui.Rect cullRect, void Function(CkCanvas canvas) painter) {
final CkPictureRecorder recorder = CkPictureRecorder();
final CkCanvas canvas = recorder.beginRecording(cullRect);
painter(canvas);
return recorder.endRecording();
}
Future<void> matchSceneGolden(
String goldenFile,
ui.Scene scene, {
required ui.Rect region,
}) async {
await renderScene(scene);
await matchGoldenFile(goldenFile, region: region);
}
/// Checks that a [picture] matches the [goldenFile].
///
/// The picture is drawn onto the UI at [ui.Offset.zero] with no additional
/// layers.
Future<void> matchPictureGolden(String goldenFile, CkPicture picture,
{required ui.Rect region}) async {
final LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
sb.addPicture(ui.Offset.zero, picture);
await renderScene(sb.build());
await matchGoldenFile(goldenFile, region: region);
}
Future<bool> matchImage(ui.Image left, ui.Image right) async {
if (left.width != right.width || left.height != right.height) {
return false;
}
int getPixel(ByteData data, int x, int y) =>
data.getUint32((x + y * left.width) * 4);
final ByteData leftData = (await left.toByteData())!;
final ByteData rightData = (await right.toByteData())!;
for (int y = 0; y < left.height; y++) {
for (int x = 0; x < left.width; x++) {
if (getPixel(leftData, x, y) != getPixel(rightData, x, y)) {
return false;
}
}
}
return true;
}
/// Sends a platform message to create a Platform View with the given id and viewType.
Future<void> createPlatformView(int id, String viewType) {
final Completer<void> completer = Completer<void>();
ui.PlatformDispatcher.instance.sendPlatformMessage(
'flutter/platform_views',
codec.encodeMethodCall(MethodCall(
'create',
<String, dynamic>{
'id': id,
'viewType': viewType,
},
)),
(dynamic _) => completer.complete(),
);
return completer.future;
}
/// Disposes of the platform view with the given [id].
Future<void> disposePlatformView(int id) {
final Completer<void> completer = Completer<void>();
ui.PlatformDispatcher.instance.sendPlatformMessage(
'flutter/platform_views',
codec.encodeMethodCall(MethodCall('dispose', id)),
(dynamic _) => completer.complete(),
);
return completer.future;
}
/// Creates a pre-laid out one-line paragraph of text.
///
/// Useful in tests that need a simple label to annotate goldens.
CkParagraph makeSimpleText(
String text, {
String? fontFamily,
double? fontSize,
ui.FontStyle? fontStyle,
ui.FontWeight? fontWeight,
ui.Color? color,
}) {
final CkParagraphBuilder builder = CkParagraphBuilder(CkParagraphStyle(
fontFamily: fontFamily ?? 'Roboto',
fontSize: fontSize ?? 14,
fontStyle: fontStyle ?? ui.FontStyle.normal,
fontWeight: fontWeight ?? ui.FontWeight.normal,
));
builder.pushStyle(CkTextStyle(
color: color ?? const ui.Color(0xFF000000),
));
builder.addText(text);
builder.pop();
final CkParagraph paragraph = builder.build();
paragraph.layout(const ui.ParagraphConstraints(width: 10000));
return paragraph;
}