[web] Make web integration tests shadow DOM aware. (#82926)
This commit is contained in:
parent
fa1c6a2841
commit
c94f0bea65
@ -904,6 +904,7 @@ Future<void> _runFlutterDriverWebTest({
|
||||
await runCommand(
|
||||
flutter,
|
||||
<String>[
|
||||
...?flutterTestArgs,
|
||||
'drive',
|
||||
'--target=$target',
|
||||
'--browser-name=chrome',
|
||||
@ -1080,6 +1081,7 @@ Future<void> _runGalleryE2eWebTest(String buildMode, { bool canvasKit = false })
|
||||
await runCommand(
|
||||
flutter,
|
||||
<String>[
|
||||
...?flutterTestArgs,
|
||||
'drive',
|
||||
if (canvasKit)
|
||||
'--dart-define=FLUTTER_WEB_USE_SKIA=true',
|
||||
@ -1163,6 +1165,7 @@ Future<void> _runWebReleaseTest(String target, {
|
||||
await runCommand(
|
||||
flutter,
|
||||
<String>[
|
||||
...?flutterTestArgs,
|
||||
'build',
|
||||
'web',
|
||||
'--release',
|
||||
|
@ -15,6 +15,15 @@ import 'package:web_e2e_tests/text_editing_main.dart' as app;
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
/// Locate elements in the correct root of the application, whether it is
|
||||
/// `document` or the new `shadowRoot` of `flt-class-pane`.
|
||||
List<Node> findElements(String selector) {
|
||||
final ShadowRoot? shadowRoot = document.querySelector('flt-glass-pane')?.shadowRoot;
|
||||
return (shadowRoot != null) ?
|
||||
shadowRoot.querySelectorAll(selector):
|
||||
document.querySelectorAll(selector);
|
||||
}
|
||||
|
||||
testWidgets('Focused text field creates a native input element',
|
||||
(WidgetTester tester) async {
|
||||
app.main();
|
||||
@ -29,10 +38,9 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('input')));
|
||||
|
||||
// A native input element will be appended to the DOM.
|
||||
final List<Node> nodeList = document.getElementsByTagName('input');
|
||||
final List<Node> nodeList = findElements('input');
|
||||
expect(nodeList.length, equals(1));
|
||||
final InputElement input =
|
||||
document.getElementsByTagName('input')[0] as InputElement;
|
||||
final InputElement input = nodeList[0] as InputElement;
|
||||
// The element's value will be the same as the textFormField's value.
|
||||
expect(input.value, 'Text1');
|
||||
|
||||
@ -57,10 +65,9 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('empty-input')));
|
||||
|
||||
// A native input element will be appended to the DOM.
|
||||
final List<Node> nodeList = document.getElementsByTagName('input');
|
||||
final List<Node> nodeList = findElements('input');
|
||||
expect(nodeList.length, equals(1));
|
||||
final InputElement input =
|
||||
document.getElementsByTagName('input')[0] as InputElement;
|
||||
final InputElement input = nodeList[0] as InputElement;
|
||||
// The element's value will be empty.
|
||||
expect(input.value, '');
|
||||
|
||||
@ -92,8 +99,7 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('input2')));
|
||||
|
||||
// // Press Tab. This should trigger `onFieldSubmitted` of TextField.
|
||||
final InputElement input =
|
||||
document.getElementsByTagName('input')[0] as InputElement;
|
||||
final InputElement input = findElements('input')[0] as InputElement;
|
||||
dispatchKeyboardEvent(input, 'keydown', <String, dynamic>{
|
||||
'keyCode': 13, // Enter.
|
||||
'cancelable': true,
|
||||
@ -121,10 +127,9 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('input')));
|
||||
|
||||
// A native input element will be appended to the DOM.
|
||||
final List<Node> nodeList = document.getElementsByTagName('input');
|
||||
final List<Node> nodeList = findElements('input');
|
||||
expect(nodeList.length, equals(1));
|
||||
final InputElement input =
|
||||
document.getElementsByTagName('input')[0] as InputElement;
|
||||
final InputElement input = nodeList[0] as InputElement;
|
||||
|
||||
// Press Tab. The focus should move to the next TextFormField.
|
||||
dispatchKeyboardEvent(input, 'keydown', <String, dynamic>{
|
||||
@ -132,14 +137,14 @@ void main() {
|
||||
'code': 'Tab',
|
||||
'bubbles': true,
|
||||
'cancelable': true,
|
||||
'composed': true,
|
||||
});
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// A native input element for the next TextField should be attached to the
|
||||
// DOM.
|
||||
final InputElement input2 =
|
||||
document.getElementsByTagName('input')[0] as InputElement;
|
||||
final InputElement input2 = findElements('input')[0] as InputElement;
|
||||
expect(input2.value, 'Text2');
|
||||
}, semanticsEnabled: false);
|
||||
|
||||
@ -156,10 +161,9 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('input')));
|
||||
|
||||
// A native input element will be appended to the DOM.
|
||||
final List<Node> nodeList = document.getElementsByTagName('input');
|
||||
final List<Node> nodeList = findElements('input');
|
||||
expect(nodeList.length, equals(1));
|
||||
final InputElement input =
|
||||
document.getElementsByTagName('input')[0] as InputElement;
|
||||
final InputElement input = nodeList[0] as InputElement;
|
||||
|
||||
// Press and release CapsLock.
|
||||
dispatchKeyboardEvent(input, 'keydown', <String, dynamic>{
|
||||
@ -167,12 +171,14 @@ void main() {
|
||||
'code': 'CapsLock',
|
||||
'bubbles': true,
|
||||
'cancelable': true,
|
||||
'composed': true,
|
||||
});
|
||||
dispatchKeyboardEvent(input, 'keyup', <String, dynamic>{
|
||||
'key': 'CapsLock',
|
||||
'code': 'CapsLock',
|
||||
'bubbles': true,
|
||||
'cancelable': true,
|
||||
'composed': true,
|
||||
});
|
||||
|
||||
// Press Tab. The focus should move to the next TextFormField.
|
||||
@ -181,14 +187,14 @@ void main() {
|
||||
'code': 'Tab',
|
||||
'bubbles': true,
|
||||
'cancelable': true,
|
||||
'composed': true,
|
||||
});
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// A native input element for the next TextField should be attached to the
|
||||
// DOM.
|
||||
final InputElement input2 =
|
||||
document.getElementsByTagName('input')[0] as InputElement;
|
||||
final InputElement input2 = findElements('input')[0] as InputElement;
|
||||
expect(input2.value, 'Text2');
|
||||
}, semanticsEnabled: false);
|
||||
|
||||
@ -216,7 +222,7 @@ void main() {
|
||||
await gesture.up();
|
||||
|
||||
// A native input element will be appended to the DOM.
|
||||
final List<Node> nodeList = document.getElementsByTagName('textarea');
|
||||
final List<Node> nodeList = findElements('textarea');
|
||||
expect(nodeList.length, equals(1));
|
||||
final TextAreaElement input = nodeList[0] as TextAreaElement;
|
||||
// The element's value should contain the selectable text.
|
||||
|
@ -8,6 +8,8 @@ import 'package:flutter_driver/flutter_driver.dart';
|
||||
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
|
||||
import 'package:webdriver/async_io.dart';
|
||||
|
||||
// TODO(web): Migrate this test to a normal integration_test with a WidgetTester.
|
||||
|
||||
/// The following test is used as a simple smoke test for verifying Flutter
|
||||
/// Framework and Flutter Web Engine integration.
|
||||
void main() {
|
||||
@ -35,12 +37,23 @@ void main() {
|
||||
|
||||
await Future<void>.delayed(const Duration(seconds: 2));
|
||||
|
||||
// A flutter web app may be rendered directly on the body of the page, or
|
||||
// inside the shadow root of the flt-glass-pane (after Flutter 2.4). To
|
||||
// make this test backwards compatible, we first need to locate the correct
|
||||
// root for the app.
|
||||
//
|
||||
// It's either the shadowRoot within flt-glass-pane, or [driver.webDriver].
|
||||
final SearchContext appRoot = await driver.webDriver.execute(
|
||||
'return document.querySelector("flt-glass-pane")?.shadowRoot;',
|
||||
<dynamic>[],
|
||||
) as SearchContext? ?? driver.webDriver;
|
||||
|
||||
// Elements with tag "flt-semantics" would show up after enabling
|
||||
// accessibility.
|
||||
//
|
||||
// The tag used here is based on
|
||||
// https://github.com/flutter/engine/blob/master/lib/web_ui/lib/src/engine/semantics/semantics.dart#L534
|
||||
final WebElement element = await driver.webDriver.findElement(const By.tagName('flt-semantics'));
|
||||
final WebElement element = await appRoot.findElement(const By.cssSelector('flt-semantics'));
|
||||
|
||||
expect(element, isNotNull);
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user