2046 lines
70 KiB
Dart
2046 lines
70 KiB
Dart
// Copyright 2018 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
@TestOn('!chrome')
|
|
import 'dart:async';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import '../services/fake_platform_views.dart';
|
|
|
|
void main() {
|
|
|
|
group('AndroidView', () {
|
|
testWidgets('Create Android view', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionLtr),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Create Android view with params', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
creationParams: 'creation parameters',
|
|
creationParamsCodec: StringCodec(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final FakeAndroidPlatformView fakeView = viewsController.views.first;
|
|
final Uint8List rawCreationParams = fakeView.creationParams;
|
|
final ByteData byteData = ByteData.view(
|
|
rawCreationParams.buffer,
|
|
rawCreationParams.offsetInBytes,
|
|
rawCreationParams.lengthInBytes,
|
|
);
|
|
final dynamic actualParams = const StringCodec().decodeMessage(byteData);
|
|
|
|
expect(actualParams, 'creation parameters');
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionLtr, fakeView.creationParams),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Zero sized Android view is not created', (WidgetTester tester) async {
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 0.0,
|
|
height: 0.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
isEmpty,
|
|
);
|
|
});
|
|
|
|
testWidgets('Resize Android view', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
viewsController.resizeCompleter = Completer<void>();
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 100.0,
|
|
height: 50.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
final Layer textureParentLayer = tester.layers[tester.layers.length - 2];
|
|
expect(textureParentLayer, isInstanceOf<ClipRectLayer>());
|
|
final ClipRectLayer clipRect = textureParentLayer;
|
|
expect(clipRect.clipRect, const Rect.fromLTWH(0.0, 0.0, 100.0, 50.0));
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionLtr),
|
|
]),
|
|
);
|
|
|
|
viewsController.resizeCompleter.complete();
|
|
await tester.pump();
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(100.0, 50.0),
|
|
AndroidViewController.kAndroidLayoutDirectionLtr),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Change Android view type', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
viewsController.registerViewType('maps');
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'maps', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 2, 'maps', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionLtr),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Dispose Android view', (WidgetTester tester) async {
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
isEmpty,
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view survives widget tree change', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
final GlobalKey key = GlobalKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr, key: key),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Container(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr, key: key),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionLtr),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view gets touch events', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
const Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr,),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
orderedEquals(<FakeAndroidMotionEvent>[
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionUp, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view transparent hit test behavior', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
int numPointerDownsOnParent = 0;
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Stack(
|
|
children: <Widget>[
|
|
Listener(
|
|
behavior: HitTestBehavior.opaque,
|
|
onPointerDown: (PointerDownEvent e) {
|
|
numPointerDownsOnParent++;
|
|
},
|
|
),
|
|
const Positioned(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
hitTestBehavior: PlatformViewHitTestBehavior.transparent,
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.startGesture(const Offset(50.0, 50.0));
|
|
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
isNull,
|
|
);
|
|
expect(
|
|
numPointerDownsOnParent,
|
|
1,
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view translucent hit test behavior', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
int numPointerDownsOnParent = 0;
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Stack(
|
|
children: <Widget>[
|
|
Listener(
|
|
behavior: HitTestBehavior.opaque,
|
|
onPointerDown: (PointerDownEvent e) {
|
|
numPointerDownsOnParent++;
|
|
},
|
|
),
|
|
const Positioned(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
hitTestBehavior: PlatformViewHitTestBehavior.translucent,
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.startGesture(const Offset(50.0, 50.0));
|
|
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
orderedEquals(<FakeAndroidMotionEvent>[
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
]),
|
|
);
|
|
expect(
|
|
numPointerDownsOnParent,
|
|
1,
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view opaque hit test behavior', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
int numPointerDownsOnParent = 0;
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Stack(
|
|
children: <Widget>[
|
|
Listener(
|
|
behavior: HitTestBehavior.opaque,
|
|
onPointerDown: (PointerDownEvent e) {
|
|
numPointerDownsOnParent++;
|
|
},
|
|
),
|
|
const Positioned(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.startGesture(const Offset(50.0, 50.0));
|
|
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
orderedEquals(<FakeAndroidMotionEvent>[
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
]),
|
|
);
|
|
expect(
|
|
numPointerDownsOnParent,
|
|
0,
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view touch events are in virtual display\'s coordinate system', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: Container(
|
|
margin: const EdgeInsets.all(10.0),
|
|
child: const SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
orderedEquals(<FakeAndroidMotionEvent>[
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(40.0, 40.0)]),
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionUp, <int>[0], <Offset>[Offset(40.0, 40.0)]),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view directionality', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('maps');
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'maps', layoutDirection: TextDirection.rtl),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionRtl),
|
|
]),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'maps', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionLtr),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view ambient directionality', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('maps');
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'maps'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionRtl),
|
|
]),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'maps'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeAndroidPlatformView>[
|
|
FakeAndroidPlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0),
|
|
AndroidViewController.kAndroidLayoutDirectionLtr),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view can lose gesture arenas', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
bool verticalDragAcceptedByParent = false;
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: Container(
|
|
margin: const EdgeInsets.all(10.0),
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
child: const SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, true);
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
isNull,
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view gesture recognizers', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
bool verticalDragAcceptedByParent = false;
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<VerticalDragGestureRecognizer>(
|
|
() {
|
|
return VerticalDragGestureRecognizer()
|
|
..onStart = (_) {}; // Add callback to enable recognizer
|
|
},
|
|
),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, false);
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
orderedEquals(<FakeAndroidMotionEvent>[
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionMove, <int>[0], <Offset>[Offset(50.0, 150.0)]),
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionUp, <int>[0], <Offset>[Offset(50.0, 150.0)]),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets(
|
|
'Android view can claim gesture after all pointers are up', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
bool verticalDragAcceptedByParent = false;
|
|
// The long press recognizer rejects the gesture after the AndroidView gets the pointer up event.
|
|
// This test makes sure that the Android view can win the gesture after it got the pointer up event.
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
onLongPress: () { },
|
|
child: const SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, false);
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
orderedEquals(<FakeAndroidMotionEvent>[
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionUp, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view rebuilt during gesture', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
const Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
|
|
await tester.pumpWidget(
|
|
const Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await gesture.up();
|
|
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
orderedEquals(<FakeAndroidMotionEvent>[
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionMove, <int>[0], <Offset>[Offset(50.0, 150.0)]),
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionUp, <int>[0], <Offset>[Offset(50.0, 150.0)]),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Android view with eager gesture recognizer', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) { },
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<OneSequenceGestureRecognizer>(
|
|
() => EagerGestureRecognizer(),
|
|
),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.startGesture(const Offset(50.0, 50.0));
|
|
|
|
// Normally (without the eager gesture recognizer) after just the pointer down event
|
|
// no gesture arena member will claim the arena (so no motion events will be dispatched to
|
|
// the Android view). Here we assert that with the eager recognizer in the gesture team the
|
|
// pointer down event is immediately dispatched.
|
|
expect(
|
|
viewsController.motionEvents[currentViewId + 1],
|
|
orderedEquals(<FakeAndroidMotionEvent>[
|
|
const FakeAndroidMotionEvent(
|
|
AndroidViewController.kActionDown, <int>[0], <Offset>[Offset(50.0, 50.0)]),
|
|
]),
|
|
);
|
|
});
|
|
|
|
// This test makes sure it doesn't crash.
|
|
// https://github.com/flutter/flutter/issues/21514
|
|
testWidgets('RenderAndroidView reconstructed with same gestureRecognizers does not crash', (WidgetTester tester) async {
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
final AndroidView androidView = AndroidView(
|
|
viewType: 'webview',
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<EagerGestureRecognizer>(
|
|
() => EagerGestureRecognizer(),
|
|
),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
);
|
|
|
|
await tester.pumpWidget(androidView);
|
|
await tester.pumpWidget(const SizedBox.shrink());
|
|
await tester.pumpWidget(androidView);
|
|
});
|
|
|
|
testWidgets('AndroidView rebuilt with same gestureRecognizers', (WidgetTester tester) async {
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
int factoryInvocationCount = 0;
|
|
final ValueGetter<EagerGestureRecognizer> constructRecognizer = () {
|
|
factoryInvocationCount += 1;
|
|
return EagerGestureRecognizer();
|
|
};
|
|
|
|
await tester.pumpWidget(
|
|
AndroidView(
|
|
viewType: 'webview',
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<EagerGestureRecognizer>(constructRecognizer),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
AndroidView(
|
|
viewType: 'webview',
|
|
hitTestBehavior: PlatformViewHitTestBehavior.translucent,
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<EagerGestureRecognizer>(constructRecognizer),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
);
|
|
|
|
expect(factoryInvocationCount, 1);
|
|
});
|
|
|
|
testWidgets('AndroidView has correct semantics', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
expect(currentViewId, greaterThanOrEqualTo(0));
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
viewsController.createCompleter = Completer<void>();
|
|
|
|
await tester.pumpWidget(
|
|
Semantics(
|
|
container: true,
|
|
child: const Align(
|
|
alignment: Alignment.bottomRight,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final SemanticsNode semantics = tester.getSemantics(find.byType(AndroidView));
|
|
|
|
// Platform view has not been created yet, no platformViewId.
|
|
expect(semantics.platformViewId, null);
|
|
expect(semantics.rect, const Rect.fromLTWH(0, 0, 200, 100));
|
|
// A 200x100 rect positioned at bottom right of a 800x600 box.
|
|
expect(semantics.transform, Matrix4.translationValues(600, 500, 0));
|
|
expect(semantics.childrenCount, 0);
|
|
|
|
viewsController.createCompleter.complete();
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(semantics.platformViewId, currentViewId + 1);
|
|
expect(semantics.rect, const Rect.fromLTWH(0, 0, 200, 100));
|
|
// A 200x100 rect positioned at bottom right of a 800x600 box.
|
|
expect(semantics.transform, Matrix4.translationValues(600, 500, 0));
|
|
expect(semantics.childrenCount, 0);
|
|
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('AndroidView can take input focus', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
viewsController.createCompleter = Completer<void>();
|
|
|
|
final GlobalKey containerKey = GlobalKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Column(
|
|
children: <Widget>[
|
|
const SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
Focus(
|
|
debugLabel: 'container',
|
|
child: Container(key: containerKey),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
final Focus androidViewFocusWidget =
|
|
tester.widget(
|
|
find.descendant(
|
|
of: find.byType(AndroidView),
|
|
matching: find.byType(Focus)
|
|
)
|
|
);
|
|
final Element containerElement = tester.element(find.byKey(containerKey));
|
|
final FocusNode androidViewFocusNode = androidViewFocusWidget.focusNode;
|
|
final FocusNode containerFocusNode = Focus.of(containerElement);
|
|
|
|
containerFocusNode.requestFocus();
|
|
|
|
await tester.pump();
|
|
|
|
expect(containerFocusNode.hasFocus, isTrue);
|
|
expect(androidViewFocusNode.hasFocus, isFalse);
|
|
|
|
viewsController.invokeViewFocused(currentViewId + 1);
|
|
|
|
await tester.pump();
|
|
|
|
expect(containerFocusNode.hasFocus, isFalse);
|
|
expect(androidViewFocusNode.hasFocus, isTrue);
|
|
});
|
|
|
|
testWidgets('AndroidView sets a platform view text input client when focused', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
viewsController.createCompleter = Completer<void>();
|
|
|
|
final GlobalKey containerKey = GlobalKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Column(
|
|
children: <Widget>[
|
|
const SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
Focus(
|
|
debugLabel: 'container',
|
|
child: Container(key: containerKey),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
viewsController.createCompleter.complete();
|
|
|
|
|
|
final Element containerElement = tester.element(find.byKey(containerKey));
|
|
final FocusNode containerFocusNode = Focus.of(containerElement);
|
|
|
|
containerFocusNode.requestFocus();
|
|
await tester.pump();
|
|
|
|
int lastPlatformViewTextClient;
|
|
SystemChannels.textInput.setMockMethodCallHandler((MethodCall call) {
|
|
if (call.method == 'TextInput.setPlatformViewClient') {
|
|
lastPlatformViewTextClient = call.arguments;
|
|
}
|
|
return null;
|
|
});
|
|
|
|
viewsController.invokeViewFocused(currentViewId + 1);
|
|
await tester.pump();
|
|
|
|
expect(lastPlatformViewTextClient, currentViewId + 1);
|
|
});
|
|
|
|
testWidgets('AndroidView clears platform focus when unfocused', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeAndroidPlatformViewsController viewsController = FakeAndroidPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
viewsController.createCompleter = Completer<void>();
|
|
|
|
final GlobalKey containerKey = GlobalKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Column(
|
|
children: <Widget>[
|
|
const SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
Focus(
|
|
debugLabel: 'container',
|
|
child: Container(key: containerKey),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
viewsController.createCompleter.complete();
|
|
|
|
final Element containerElement = tester.element(find.byKey(containerKey));
|
|
final FocusNode containerFocusNode = Focus.of(containerElement);
|
|
|
|
containerFocusNode.requestFocus();
|
|
await tester.pump();
|
|
|
|
viewsController.invokeViewFocused(currentViewId + 1);
|
|
await tester.pump();
|
|
|
|
viewsController.lastClearedFocusViewId = null;
|
|
|
|
containerFocusNode.requestFocus();
|
|
await tester.pump();
|
|
|
|
expect(viewsController.lastClearedFocusViewId, currentViewId + 1);
|
|
});
|
|
});
|
|
|
|
group('UiKitView', () {
|
|
testWidgets('Create UIView', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeUiKitView>[
|
|
FakeUiKitView(currentViewId + 1, 'webview'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Change UIView view type', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
viewsController.registerViewType('maps');
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'maps', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeUiKitView>[
|
|
FakeUiKitView(currentViewId + 2, 'maps'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Dispose UIView ', (WidgetTester tester) async {
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
isEmpty,
|
|
);
|
|
});
|
|
|
|
testWidgets('Dispose UIView before creation completed ', (WidgetTester tester) async {
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
viewsController.creationDelay = Completer<void>();
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
),
|
|
),
|
|
);
|
|
|
|
viewsController.creationDelay.complete();
|
|
|
|
expect(
|
|
viewsController.views,
|
|
isEmpty,
|
|
);
|
|
});
|
|
|
|
testWidgets('UIView survives widget tree change', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
final GlobalKey key = GlobalKey();
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr, key: key),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Container(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr, key: key),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeUiKitView>[
|
|
FakeUiKitView(currentViewId + 1, 'webview'),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('Create UIView with params', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
creationParams: 'creation parameters',
|
|
creationParamsCodec: StringCodec(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final FakeUiKitView fakeView = viewsController.views.first;
|
|
final Uint8List rawCreationParams = fakeView.creationParams;
|
|
final ByteData byteData = ByteData.view(
|
|
rawCreationParams.buffer,
|
|
rawCreationParams.offsetInBytes,
|
|
rawCreationParams.lengthInBytes,
|
|
);
|
|
final dynamic actualParams = const StringCodec().decodeMessage(byteData);
|
|
|
|
expect(actualParams, 'creation parameters');
|
|
expect(
|
|
viewsController.views,
|
|
unorderedEquals(<FakeUiKitView>[
|
|
FakeUiKitView(currentViewId + 1, 'webview', fakeView.creationParams),
|
|
]),
|
|
);
|
|
});
|
|
|
|
testWidgets('UiKitView accepts gestures', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
await tester.pumpWidget(
|
|
const Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr,),
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 0);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
|
});
|
|
|
|
testWidgets('UiKitView transparent hit test behavior', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
int numPointerDownsOnParent = 0;
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Stack(
|
|
children: <Widget>[
|
|
Listener(
|
|
behavior: HitTestBehavior.opaque,
|
|
onPointerDown: (PointerDownEvent e) {
|
|
numPointerDownsOnParent++;
|
|
},
|
|
),
|
|
const Positioned(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
hitTestBehavior: PlatformViewHitTestBehavior.transparent,
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 0);
|
|
|
|
expect(numPointerDownsOnParent, 1);
|
|
});
|
|
|
|
testWidgets('UiKitView translucent hit test behavior', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
int numPointerDownsOnParent = 0;
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Stack(
|
|
children: <Widget>[
|
|
Listener(
|
|
behavior: HitTestBehavior.opaque,
|
|
onPointerDown: (PointerDownEvent e) {
|
|
numPointerDownsOnParent++;
|
|
},
|
|
),
|
|
const Positioned(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
hitTestBehavior: PlatformViewHitTestBehavior.translucent,
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
|
|
|
expect(numPointerDownsOnParent, 1);
|
|
});
|
|
|
|
testWidgets('UiKitView opaque hit test behavior', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
int numPointerDownsOnParent = 0;
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Stack(
|
|
children: <Widget>[
|
|
Listener(
|
|
behavior: HitTestBehavior.opaque,
|
|
onPointerDown: (PointerDownEvent e) {
|
|
numPointerDownsOnParent++;
|
|
},
|
|
),
|
|
const Positioned(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
|
expect(numPointerDownsOnParent, 0);
|
|
});
|
|
|
|
testWidgets('UiKitView can lose gesture arenas', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
bool verticalDragAcceptedByParent = false;
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: Container(
|
|
margin: const EdgeInsets.all(10.0),
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
child: const SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, true);
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 0);
|
|
expect(viewsController.gesturesRejected[currentViewId + 1], 1);
|
|
});
|
|
|
|
testWidgets('UiKitView gesture recognizers', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
bool verticalDragAcceptedByParent = false;
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<VerticalDragGestureRecognizer>(
|
|
() {
|
|
return VerticalDragGestureRecognizer()
|
|
..onStart = (_) {}; // Add callback to enable recognizer
|
|
},
|
|
),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, false);
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
|
expect(viewsController.gesturesRejected[currentViewId + 1], 0);
|
|
});
|
|
|
|
testWidgets('UiKitView can claim gesture after all pointers are up', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
bool verticalDragAcceptedByParent = false;
|
|
// The long press recognizer rejects the gesture after the AndroidView gets the pointer up event.
|
|
// This test makes sure that the Android view can win the gesture after it got the pointer up event.
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
onLongPress: () { },
|
|
child: const SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, false);
|
|
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
|
expect(viewsController.gesturesRejected[currentViewId + 1], 0);
|
|
});
|
|
|
|
testWidgets('UiKitView rebuilt during gesture', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
const Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
|
|
await tester.pumpWidget(
|
|
const Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await gesture.up();
|
|
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
|
expect(viewsController.gesturesRejected[currentViewId + 1], 0);
|
|
});
|
|
|
|
testWidgets('UiKitView with eager gesture recognizer', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) { },
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<OneSequenceGestureRecognizer>(
|
|
() => EagerGestureRecognizer(),
|
|
),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
await tester.startGesture(const Offset(50.0, 50.0));
|
|
|
|
// Normally (without the eager gesture recognizer) after just the pointer down event
|
|
// no gesture arena member will claim the arena (so no motion events will be dispatched to
|
|
// the Android view). Here we assert that with the eager recognizer in the gesture team the
|
|
// pointer down event is immediately dispatched.
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 1);
|
|
expect(viewsController.gesturesRejected[currentViewId + 1], 0);
|
|
});
|
|
|
|
testWidgets('UiKitView rejects gestures absorbed by siblings', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
await tester.pumpWidget(
|
|
Stack(
|
|
alignment: Alignment.topLeft,
|
|
children: <Widget>[
|
|
const UiKitView(viewType: 'webview', layoutDirection: TextDirection.ltr),
|
|
Container(
|
|
color: const Color.fromARGB(255, 255, 255, 255),
|
|
width: 100,
|
|
height: 100,
|
|
),
|
|
],
|
|
)
|
|
);
|
|
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(viewsController.gesturesRejected[currentViewId + 1], 1);
|
|
expect(viewsController.gesturesAccepted[currentViewId + 1], 0);
|
|
});
|
|
|
|
testWidgets('AndroidView rebuilt with same gestureRecognizers', (WidgetTester tester) async {
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
int factoryInvocationCount = 0;
|
|
final ValueGetter<EagerGestureRecognizer> constructRecognizer = () {
|
|
factoryInvocationCount += 1;
|
|
return EagerGestureRecognizer();
|
|
};
|
|
|
|
await tester.pumpWidget(
|
|
UiKitView(
|
|
viewType: 'webview',
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<EagerGestureRecognizer>(constructRecognizer),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
UiKitView(
|
|
viewType: 'webview',
|
|
hitTestBehavior: PlatformViewHitTestBehavior.translucent,
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<EagerGestureRecognizer>(constructRecognizer),
|
|
},
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
);
|
|
|
|
expect(factoryInvocationCount, 1);
|
|
});
|
|
|
|
testWidgets('UiKitView has correct semantics', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
expect(currentViewId, greaterThanOrEqualTo(0));
|
|
final FakeIosPlatformViewsController viewsController = FakeIosPlatformViewsController();
|
|
viewsController.registerViewType('webview');
|
|
|
|
await tester.pumpWidget(
|
|
Semantics(
|
|
container: true,
|
|
child: const Align(
|
|
alignment: Alignment.bottomRight,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: UiKitView(
|
|
viewType: 'webview',
|
|
layoutDirection: TextDirection.ltr,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
// First frame is before the platform view was created so the render object
|
|
// is not yet in the tree.
|
|
await tester.pump();
|
|
|
|
final SemanticsNode semantics = tester.getSemantics(find.byType(UiKitView));
|
|
|
|
expect(semantics.platformViewId, currentViewId + 1);
|
|
expect(semantics.rect, const Rect.fromLTWH(0, 0, 200, 100));
|
|
// A 200x100 rect positioned at bottom right of a 800x600 box.
|
|
expect(semantics.transform, Matrix4.translationValues(600, 500, 0));
|
|
expect(semantics.childrenCount, 0);
|
|
|
|
handle.dispose();
|
|
});
|
|
});
|
|
|
|
group('Common PlatformView', () {
|
|
FakePlatformViewController controller;
|
|
|
|
setUp((){
|
|
controller = FakePlatformViewController(0);
|
|
});
|
|
|
|
testWidgets('PlatformViewSurface should create platform view layer', (WidgetTester tester) async {
|
|
final PlatformViewSurface surface = PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},);
|
|
await tester.pumpWidget(surface);
|
|
final PlatformViewLayer layer = tester.layers.firstWhere((Layer layer){
|
|
return layer is PlatformViewLayer;
|
|
});
|
|
expect(layer, isNotNull);
|
|
});
|
|
|
|
testWidgets('PlatformViewSurface can lose gesture arenas', (WidgetTester tester) async {
|
|
bool verticalDragAcceptedByParent = false;
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: Container(
|
|
margin: const EdgeInsets.all(10.0),
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: PlatformViewSurface(
|
|
controller: controller,
|
|
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, true);
|
|
expect(
|
|
controller.dispatchedPointerEvents,
|
|
isEmpty,
|
|
);
|
|
});
|
|
|
|
testWidgets('PlatformViewSurface gesture recognizers dispatch events', (WidgetTester tester) async {
|
|
bool verticalDragAcceptedByParent = false;
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<VerticalDragGestureRecognizer>(
|
|
() {
|
|
return VerticalDragGestureRecognizer()
|
|
..onStart = (_) {}; // Add callback to enable recognizer
|
|
},
|
|
),
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, false);
|
|
expect(
|
|
controller.dispatchedPointerEvents.length,
|
|
3,
|
|
);
|
|
|
|
});
|
|
|
|
testWidgets(
|
|
'PlatformViewSurface can claim gesture after all pointers are up', (WidgetTester tester) async {
|
|
bool verticalDragAcceptedByParent = false;
|
|
// The long press recognizer rejects the gesture after the PlatformViewSurface gets the pointer up event.
|
|
// This test makes sure that the PlatformViewSurface can win the gesture after it got the pointer up event.
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) {
|
|
verticalDragAcceptedByParent = true;
|
|
},
|
|
onLongPress: () { },
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.up();
|
|
|
|
expect(verticalDragAcceptedByParent, false);
|
|
expect(
|
|
controller.dispatchedPointerEvents.length,
|
|
2,
|
|
);
|
|
|
|
});
|
|
|
|
testWidgets('PlatformViewSurface rebuilt during gesture', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
|
await gesture.moveBy(const Offset(0.0, 100.0));
|
|
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await gesture.up();
|
|
|
|
expect(
|
|
controller.dispatchedPointerEvents.length,
|
|
3,
|
|
);
|
|
});
|
|
|
|
testWidgets('PlatformViewSurface with eager gesture recognizer', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GestureDetector(
|
|
onVerticalDragStart: (DragStartDetails d) { },
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<OneSequenceGestureRecognizer>(
|
|
() => EagerGestureRecognizer(),
|
|
),
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.startGesture(const Offset(50.0, 50.0));
|
|
|
|
// Normally (without the eager gesture recognizer) after just the pointer down event
|
|
// no gesture arena member will claim the arena (so no motion events will be dispatched to
|
|
// the PlatformViewSurface). Here we assert that with the eager recognizer in the gesture team the
|
|
// pointer down event is immediately dispatched.
|
|
expect(
|
|
controller.dispatchedPointerEvents.length,
|
|
1,
|
|
);
|
|
});
|
|
|
|
testWidgets('PlatformViewRenderBox reconstructed with same gestureRecognizers', (WidgetTester tester) async {
|
|
|
|
int factoryInvocationCount = 0;
|
|
final ValueGetter<EagerGestureRecognizer> constructRecognizer = () {
|
|
++ factoryInvocationCount;
|
|
return EagerGestureRecognizer();
|
|
};
|
|
|
|
final PlatformViewSurface platformViewSurface = PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<OneSequenceGestureRecognizer>(
|
|
constructRecognizer,
|
|
),
|
|
});
|
|
|
|
await tester.pumpWidget(platformViewSurface);
|
|
await tester.pumpWidget(const SizedBox.shrink());
|
|
await tester.pumpWidget(platformViewSurface);
|
|
|
|
expect(factoryInvocationCount, 2);
|
|
});
|
|
|
|
testWidgets('PlatformViewSurface rebuilt with same gestureRecognizers', (WidgetTester tester) async {
|
|
|
|
int factoryInvocationCount = 0;
|
|
final ValueGetter<EagerGestureRecognizer> constructRecognizer = () {
|
|
++ factoryInvocationCount;
|
|
return EagerGestureRecognizer();
|
|
};
|
|
|
|
await tester.pumpWidget(
|
|
PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<OneSequenceGestureRecognizer>(
|
|
constructRecognizer,
|
|
),
|
|
})
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
PlatformViewSurface(
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
|
|
Factory<OneSequenceGestureRecognizer>(
|
|
constructRecognizer,
|
|
),
|
|
})
|
|
);
|
|
expect(factoryInvocationCount, 1);
|
|
});
|
|
|
|
testWidgets('PlatformViewLink Widget init, should create a SizedBox widget before onPlatformViewCreated and a PlatformViewSurface after', (WidgetTester tester) async {
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
int createdPlatformViewId;
|
|
|
|
PlatformViewCreatedCallback onPlatformViewCreatedCallBack;
|
|
|
|
final PlatformViewLink platformViewLink = PlatformViewLink(createPlatformViewController: (PlatformViewCreationParams params){
|
|
onPlatformViewCreatedCallBack = params.onPlatformViewCreated;
|
|
createdPlatformViewId = params.id;
|
|
return FakePlatformViewController(params.id);
|
|
}, surfaceFactory: (BuildContext context, PlatformViewController controller) {
|
|
return PlatformViewSurface(
|
|
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
);
|
|
});
|
|
|
|
await tester.pumpWidget(platformViewLink);
|
|
final SizedBox sizedBox = tester.allWidgets.firstWhere((Widget widget) => widget is SizedBox);
|
|
expect(sizedBox, isNotNull);
|
|
|
|
onPlatformViewCreatedCallBack(createdPlatformViewId);
|
|
|
|
await tester.pump();
|
|
|
|
final PlatformViewSurface surface = tester.allWidgets.firstWhere((Widget widget) => widget is PlatformViewSurface);
|
|
expect(surface, isNotNull);
|
|
|
|
expect(createdPlatformViewId, currentViewId+1);
|
|
});
|
|
|
|
testWidgets('PlatformViewLink Widget dispose', (WidgetTester tester) async {
|
|
FakePlatformViewController disposedController;
|
|
final PlatformViewLink platformViewLink = PlatformViewLink(createPlatformViewController: (PlatformViewCreationParams params){
|
|
params.onPlatformViewCreated(params.id);
|
|
disposedController = FakePlatformViewController(params.id);
|
|
params.onPlatformViewCreated(params.id);
|
|
return disposedController;
|
|
}, surfaceFactory: (BuildContext context,PlatformViewController controller) {
|
|
return PlatformViewSurface(
|
|
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
);
|
|
});
|
|
|
|
await tester.pumpWidget(platformViewLink);
|
|
|
|
await tester.pumpWidget(Container());
|
|
|
|
expect(disposedController.disposed, true);
|
|
});
|
|
|
|
testWidgets('PlatformViewLink widget survives widget tree change', (WidgetTester tester) async {
|
|
final GlobalKey key = GlobalKey();
|
|
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
|
final List<int> ids = <int>[];
|
|
|
|
FakePlatformViewController controller;
|
|
|
|
PlatformViewLink createPlatformViewLink() {
|
|
return PlatformViewLink(
|
|
key: key,
|
|
createPlatformViewController: (PlatformViewCreationParams params){
|
|
ids.add(params.id);
|
|
controller = FakePlatformViewController(params.id);
|
|
params.onPlatformViewCreated(params.id);
|
|
return controller;
|
|
},
|
|
surfaceFactory: (BuildContext context, PlatformViewController controller) {
|
|
return PlatformViewSurface(
|
|
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
|
controller: controller,
|
|
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: createPlatformViewLink(),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
Center(
|
|
child: Container(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
height: 100.0,
|
|
child: createPlatformViewLink(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
ids,
|
|
unorderedEquals(<int>[
|
|
currentViewId+1,
|
|
]),
|
|
);
|
|
});
|
|
});
|
|
}
|