mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[web] Fix multi-reply on message channel. Add test (#17591)
* Fix multi-reply on message channel. Add test * Add check for viewInstanceCount * skip no-headless test
This commit is contained in:
parent
0726621bfa
commit
db644677fa
@ -172,6 +172,7 @@ task:
|
||||
- $FRAMEWORK_PATH/flutter/bin/flutter config --local-engine=host_debug_unopt --no-analytics --enable-web
|
||||
- $FRAMEWORK_PATH/flutter/bin/flutter pub get --local-engine=host_debug_unopt
|
||||
- $FRAMEWORK_PATH/flutter/bin/flutter drive -v --target=test_driver/text_editing_e2e.dart -d web-server --release --browser-name=chrome --local-engine=host_debug_unopt
|
||||
- $FRAMEWORK_PATH/flutter/bin/flutter drive -v --target=test_driver/platform_messages_e2e.dart -d web-server --release --browser-name=chrome --local-engine=host_debug_unopt
|
||||
- $FRAMEWORK_PATH/flutter/bin/flutter drive -v --target=test_driver/treeshaking_e2e.dart -d web-server --profile --browser-name=chrome --local-engine=host_debug_unopt
|
||||
- $FRAMEWORK_PATH/flutter/bin/flutter drive -v --target=test_driver/image_loading_e2e.dart -d web-server --release --browser-name=chrome --local-engine=host_debug_unopt
|
||||
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
// 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 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
void main() => runApp(MyApp());
|
||||
|
||||
Future<ClipboardData> dataFuture;
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
key: const Key('mainapp'),
|
||||
title: 'Integration Test App For Platform Messages',
|
||||
home: MyHomePage(title: 'Integration Test App For Platform Messages'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
MyHomePage({Key key, this.title}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
_MyHomePageState createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
final TextEditingController _controller =
|
||||
TextEditingController(text: 'Text1');
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text('Hello World',
|
||||
),
|
||||
// Create a text form field since we can't test clipboard unless
|
||||
// html document has focus.
|
||||
TextFormField(
|
||||
key: const Key('input'),
|
||||
enabled: true,
|
||||
controller: _controller,
|
||||
//initialValue: 'Text1',
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Text Input Field:',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
// 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:html' as html;
|
||||
// ignore: undefined_shown_name
|
||||
import 'dart:ui' as ui show platformViewRegistry;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:regular_integration_tests/platform_messages_main.dart' as app;
|
||||
|
||||
import 'package:e2e/e2e.dart';
|
||||
|
||||
void main() async {
|
||||
E2EWidgetsFlutterBinding.ensureInitialized() as E2EWidgetsFlutterBinding;
|
||||
|
||||
testWidgets('platform message for Clipboard.setData reply with future',
|
||||
(WidgetTester tester) async {
|
||||
app.main();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// TODO(nurhan): https://github.com/flutter/flutter/issues/51885
|
||||
SystemChannels.textInput.setMockMethodCallHandler(null);
|
||||
// Focus on a TextFormField.
|
||||
final Finder finder = find.byKey(const Key('input'));
|
||||
expect(finder, findsOneWidget);
|
||||
await tester.tap(find.byKey(const Key('input')));
|
||||
// Focus in input, otherwise clipboard will fail with
|
||||
// 'document is not focused' platform exception.
|
||||
html.document.querySelector('input').focus();
|
||||
await Clipboard.setData(const ClipboardData(text: 'sample text'));
|
||||
}, skip: true); // https://github.com/flutter/flutter/issues/54296
|
||||
|
||||
testWidgets('Should create and dispose view embedder',
|
||||
(WidgetTester tester) async {
|
||||
int viewInstanceCount = 0;
|
||||
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
// ignore: undefined_prefixed_name
|
||||
ui.platformViewRegistry.registerViewFactory('MyView', (int viewId) {
|
||||
++viewInstanceCount;
|
||||
return html.DivElement();
|
||||
});
|
||||
|
||||
app.main();
|
||||
await tester.pumpAndSettle();
|
||||
final Map<String, dynamic> createArgs = <String, dynamic>{
|
||||
'id': '567',
|
||||
'viewType': 'MyView',
|
||||
};
|
||||
await SystemChannels.platform_views.invokeMethod<void>('create', createArgs);
|
||||
final Map<String, dynamic> disposeArgs = <String, dynamic>{
|
||||
'id': '567',
|
||||
};
|
||||
await SystemChannels.platform_views.invokeMethod<void>('dispose', disposeArgs);
|
||||
expect(viewInstanceCount, 1);
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
// 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 'package:e2e/e2e_driver.dart' as e2e;
|
||||
|
||||
Future<void> main() async => e2e.main();
|
||||
@ -18,6 +18,7 @@ class ClipboardMessageHandler {
|
||||
void setDataMethodCall(
|
||||
MethodCall methodCall, ui.PlatformMessageResponseCallback callback) {
|
||||
const MethodCodec codec = JSONMethodCodec();
|
||||
bool errorEnvelopeEncoded = false;
|
||||
_copyToClipboardStrategy
|
||||
.setData(methodCall.arguments['text'])
|
||||
.then((bool success) {
|
||||
@ -26,10 +27,15 @@ class ClipboardMessageHandler {
|
||||
} else {
|
||||
callback(codec.encodeErrorEnvelope(
|
||||
code: 'copy_fail', message: 'Clipboard.setData failed'));
|
||||
errorEnvelopeEncoded = true;
|
||||
}
|
||||
}).catchError((dynamic _) {
|
||||
callback(codec.encodeErrorEnvelope(
|
||||
code: 'copy_fail', message: 'Clipboard.setData failed'));
|
||||
// Don't encode a duplicate reply if we already failed and an error
|
||||
// was already encoded.
|
||||
if (!errorEnvelopeEncoded) {
|
||||
callback(codec.encodeErrorEnvelope(
|
||||
code: 'copy_fail', message: 'Clipboard.setData failed'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -69,11 +69,9 @@ class HtmlViewEmbedder {
|
||||
switch (decoded.method) {
|
||||
case 'create':
|
||||
_create(decoded, callback);
|
||||
window._replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
|
||||
return;
|
||||
case 'dispose':
|
||||
_dispose(decoded, callback);
|
||||
window._replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
|
||||
return;
|
||||
}
|
||||
callback(null);
|
||||
|
||||
@ -50,11 +50,9 @@ void handlePlatformViewCall(
|
||||
switch (decoded.method) {
|
||||
case 'create':
|
||||
_createPlatformView(decoded, callback);
|
||||
window._replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
|
||||
return;
|
||||
case 'dispose':
|
||||
_disposePlatformView(decoded, callback);
|
||||
window._replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
|
||||
return;
|
||||
}
|
||||
callback(null);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user