Unverified Commit e5055293 authored by Yegor's avatar Yegor Committed by GitHub

[web] define $flutterDriverResult variable early in driver test initalization (#107337)

parent 6606372a
......@@ -887,7 +887,11 @@ Future<void> _runFrameworkTests() async {
await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'gen_keycodes'));
await _runFlutterTest(path.join(flutterRoot, 'dev', 'benchmarks', 'test_apps', 'stocks'));
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), tests: <String>[path.join('test', 'src', 'real_tests')], options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'integration_test'), options: <String>['--enable-vmservice']);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'integration_test'), options: <String>[
'--enable-vmservice',
// Web-specific tests depend on Chromium, so they run as part of the web_long_running_tests shard.
'--exclude-tags=web',
]);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_goldens'), options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), options: soundNullSafetyOptions);
......@@ -1115,6 +1119,16 @@ Future<void> _runWebLongRunningTests() async {
() => _runWebReleaseTest('lib/sound_mode.dart', additionalArguments: <String>[
'--sound-null-safety',
]),
() => _runFlutterWebTest(
'html',
path.join(flutterRoot, 'packages', 'integration_test'),
<String>['test/web_extension_test.dart'],
),
() => _runFlutterWebTest(
'canvaskit',
path.join(flutterRoot, 'packages', 'integration_test'),
<String>['test/web_extension_test.dart'],
),
];
// Shuffling mixes fast tests with slow tests so shards take roughly the same
......
......@@ -294,6 +294,29 @@ class FlutterWebConnection {
/// Sends command via WebDriver to Flutter web application.
Future<dynamic> sendCommand(String script, Duration? duration) async {
// This code should not be reachable before the VM service extension is
// initialized. The VM service extension is expected to initialize both
// `$flutterDriverResult` and `$flutterDriver` variables before attempting
// to send commands. This part checks that `$flutterDriverResult` is present.
// `$flutterDriver` is not checked because it is covered by the `script`
// that's executed next.
try {
await _driver.execute(r'return $flutterDriverResult', <String>[]);
} catch (error, stackTrace) {
throw DriverError(
'Driver extension has not been initialized correctly.\n'
'If the test uses a custom VM service extension, make sure it conforms '
'to the protocol used by package:integration_test and '
'package:flutter_driver.\n'
'If the test uses VM service extensions provided by the Flutter SDK, '
'then this error is likely caused by a bug in Flutter. Please report it '
'by filing a bug on GitHub:\n'
' https://github.com/flutter/flutter/issues/new?template=2_bug.md',
error,
stackTrace,
);
}
String phase = 'executing';
try {
// Execute the script, which should leave the result in the `$flutterDriverResult` global variable.
......
......@@ -18,6 +18,11 @@ import 'dart:js_util' as js_util;
///
/// * [_extension_io.dart], which has the dart:io implementation
void registerWebServiceExtension(Future<Map<String, dynamic>> Function(Map<String, String>) call) {
// Define the result variable because packages/flutter_driver/lib/src/driver/web_driver.dart
// checks for this value to become non-null when waiting for the result. If this value is
// undefined at the time of the check, WebDriver throws an exception.
context[r'$flutterDriverResult'] = null;
js_util.setProperty(html.window, r'$flutterDriver', allowInterop((dynamic message) async {
final Map<String, String> params = Map<String, String>.from(
jsonDecode(message as String) as Map<String, dynamic>);
......
......@@ -20,7 +20,12 @@ void main() {
test('web_extension should register a function', () {
expect(() => registerWebServiceExtension(call),
returnsNormally);
expect(js.context.hasProperty(r'$flutterDriver'), true);
expect(js.context[r'$flutterDriver'], isNotNull);
expect(js.context.hasProperty(r'$flutterDriverResult'), true);
expect(js.context[r'$flutterDriverResult'], isNull);
});
});
}
......@@ -17,6 +17,11 @@ import 'dart:js_util' as js_util;
///
/// * `_extension_io.dart`, which has the dart:io implementation
void registerWebServiceExtension(Future<Map<String, dynamic>> Function(Map<String, String>) callback) {
// Define the result variable because packages/flutter_driver/lib/src/driver/web_driver.dart
// checks for this value to become non-null when waiting for the result. If this value is
// undefined at the time of the check, WebDriver throws an exception.
context[r'$flutterDriverResult'] = null;
js_util.setProperty(html.window, r'$flutterDriver', allowInterop((dynamic message) async {
try {
final Map<String, dynamic> messageJson = jsonDecode(message as String) as Map<String, dynamic>;
......
// 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.
@Tags(<String>['web'])
import 'dart:js' as js;
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
void main() {
IntegrationTestWidgetsFlutterBinding();
test('IntegrationTestWidgetsFlutterBinding on the web should register certain global properties', () {
expect(js.context.hasProperty(r'$flutterDriver'), true);
expect(js.context[r'$flutterDriver'], isNotNull);
expect(js.context.hasProperty(r'$flutterDriverResult'), true);
expect(js.context[r'$flutterDriverResult'], isNull);
});
}
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