mirror of
https://github.com/flutter/flutter
synced 2024-08-24 18:36:03 +00:00
[flutter_test] Change KeyEventSimulator default transit mode (#143847)
## Description This PRs changes the default value transit mode for key event simulation. The default transit mode for key event simulation is currently `KeyDataTransitMode.rawKeyData` while on the framework side `KeyDataTransitMode.keyDataThenRawKeyData` is the preferred transit mode. `KeyDataTransitMode.keyDataThenRawKeyData` is more accurate and can help detect issues. For instance the following test will fail with `KeyDataTransitMode.rawKeyData` because raw keyboard logic for modifier keys is less accurate: ```dart testWidgets('Press control left once', (WidgetTester tester) async { debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData; final List<KeyEvent> events = <KeyEvent>[]; final FocusNode focusNode = FocusNode(); addTearDown(focusNode.dispose); await tester.pumpWidget( Focus( focusNode: focusNode, autofocus: true, onKeyEvent: (_, KeyEvent event) { events.add(event); return KeyEventResult.handled; }, child: Container(), ), ); await simulateKeyDownEvent(LogicalKeyboardKey.controlLeft); // This will fail when transit mode is KeyDataTransitMode.rawKeyData // because a down event for controlRight is synthesized. expect(events.length, 1); debugKeyEventSimulatorTransitModeOverride = null; }); ``` And the following this test is ok with `KeyDataTransitMode.rawKeyData` but rightly fails with `KeyDataTransitMode.keyDataThenRawKeyData`: ```dart testWidgets('Simulates consecutive key down events', (WidgetTester tester) async { debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData; // Simulating several key down events without key up in between is tolerated // when transit mode is KeyDataTransitMode.rawKeyData, it will trigger an // assert on KeyDataTransitMode.keyDataThenRawKeyData. await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown); await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown); debugKeyEventSimulatorTransitModeOverride = null; }); ``` ## Related Issue Related to https://github.com/flutter/flutter/issues/143845 ## Tests Adds two tests.
This commit is contained in:
parent
f677027655
commit
8ade81fb20
|
@ -8507,14 +8507,12 @@ void main() {
|
||||||
expect(controller.selection.extentOffset, 20);
|
expect(controller.selection.extentOffset, 20);
|
||||||
|
|
||||||
await tester.pump(kDoubleTapTimeout);
|
await tester.pump(kDoubleTapTimeout);
|
||||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
|
|
||||||
await tester.tapAt(textOffsetToPosition(tester, 23));
|
await tester.tapAt(textOffsetToPosition(tester, 23));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.selection.baseOffset, 13);
|
expect(controller.selection.baseOffset, 13);
|
||||||
expect(controller.selection.extentOffset, 23);
|
expect(controller.selection.extentOffset, 23);
|
||||||
|
|
||||||
await tester.pump(kDoubleTapTimeout);
|
await tester.pump(kDoubleTapTimeout);
|
||||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
|
|
||||||
await tester.tapAt(textOffsetToPosition(tester, 4));
|
await tester.tapAt(textOffsetToPosition(tester, 4));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.selection.baseOffset, 13);
|
expect(controller.selection.baseOffset, 13);
|
||||||
|
|
|
@ -694,7 +694,7 @@ void main() {
|
||||||
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
Finder button0Material = find.descendant(
|
Finder button0Material = find.descendant(
|
||||||
of: find.widgetWithText(MenuItemButton, 'Item 0').last,
|
of: find.widgetWithText(MenuItemButton, 'Item 0').last,
|
||||||
|
@ -705,7 +705,7 @@ void main() {
|
||||||
expect(item0material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
expect(item0material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||||
|
|
||||||
// Press down key one more time, the highlight should move to the next item.
|
// Press down key one more time, the highlight should move to the next item.
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
final Finder button1Material = find.descendant(
|
final Finder button1Material = find.descendant(
|
||||||
of: find.widgetWithText(MenuItemButton, 'Menu 1').last,
|
of: find.widgetWithText(MenuItemButton, 'Menu 1').last,
|
||||||
|
@ -735,7 +735,7 @@ void main() {
|
||||||
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
Finder button5Material = find.descendant(
|
Finder button5Material = find.descendant(
|
||||||
of: find.widgetWithText(MenuItemButton, 'Item 5').last,
|
of: find.widgetWithText(MenuItemButton, 'Item 5').last,
|
||||||
|
@ -746,7 +746,7 @@ void main() {
|
||||||
expect(item5material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
expect(item5material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||||
|
|
||||||
// Press up key one more time, the highlight should move up to the item 4.
|
// Press up key one more time, the highlight should move up to the item 4.
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
final Finder button4Material = find.descendant(
|
final Finder button4Material = find.descendant(
|
||||||
of: find.widgetWithText(MenuItemButton, 'Item 4').last,
|
of: find.widgetWithText(MenuItemButton, 'Item 4').last,
|
||||||
|
@ -779,17 +779,17 @@ void main() {
|
||||||
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(find.widgetWithText(TextField, 'Item 0'), findsOneWidget);
|
expect(find.widgetWithText(TextField, 'Item 0'), findsOneWidget);
|
||||||
|
|
||||||
// Press down key one more time to the next item.
|
// Press down key one more time to the next item.
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(find.widgetWithText(TextField, 'Menu 1'), findsOneWidget);
|
expect(find.widgetWithText(TextField, 'Menu 1'), findsOneWidget);
|
||||||
|
|
||||||
// Press down to the next item.
|
// Press down to the next item.
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(find.widgetWithText(TextField, 'Item 2'), findsOneWidget);
|
expect(find.widgetWithText(TextField, 'Item 2'), findsOneWidget);
|
||||||
}, variant: TargetPlatformVariant.desktop());
|
}, variant: TargetPlatformVariant.desktop());
|
||||||
|
@ -810,17 +810,17 @@ void main() {
|
||||||
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(find.widgetWithText(TextField, 'Item 5'), findsOneWidget);
|
expect(find.widgetWithText(TextField, 'Item 5'), findsOneWidget);
|
||||||
|
|
||||||
// Press up key one more time to the upper item.
|
// Press up key one more time to the upper item.
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(find.widgetWithText(TextField, 'Item 4'), findsOneWidget);
|
expect(find.widgetWithText(TextField, 'Item 4'), findsOneWidget);
|
||||||
|
|
||||||
// Press up to the upper item.
|
// Press up to the upper item.
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(find.widgetWithText(TextField, 'Item 3'), findsOneWidget);
|
expect(find.widgetWithText(TextField, 'Item 3'), findsOneWidget);
|
||||||
}, variant: TargetPlatformVariant.desktop());
|
}, variant: TargetPlatformVariant.desktop());
|
||||||
|
@ -849,7 +849,7 @@ void main() {
|
||||||
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
final Finder button0Material = find.descendant(
|
final Finder button0Material = find.descendant(
|
||||||
of: find.widgetWithText(MenuItemButton, 'Item 0').last,
|
of: find.widgetWithText(MenuItemButton, 'Item 0').last,
|
||||||
|
@ -859,7 +859,7 @@ void main() {
|
||||||
expect(item0Material.color, themeData.colorScheme.onSurface.withOpacity(0.12)); // first item can be highlighted as it's enabled.
|
expect(item0Material.color, themeData.colorScheme.onSurface.withOpacity(0.12)); // first item can be highlighted as it's enabled.
|
||||||
|
|
||||||
// Continue to press down key. Item 3 should be highlighted as Menu 1 and Item 2 are both disabled.
|
// Continue to press down key. Item 3 should be highlighted as Menu 1 and Item 2 are both disabled.
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
|
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
final Finder button3Material = find.descendant(
|
final Finder button3Material = find.descendant(
|
||||||
of: find.widgetWithText(MenuItemButton, 'Item 3').last,
|
of: find.widgetWithText(MenuItemButton, 'Item 3').last,
|
||||||
|
@ -941,6 +941,7 @@ void main() {
|
||||||
|
|
||||||
// Press up to the upper item (Item 0).
|
// Press up to the upper item (Item 0).
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
||||||
|
await simulateKeyUpEvent(LogicalKeyboardKey.arrowUp);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(find.widgetWithText(TextField, 'Item 0'), findsOneWidget);
|
expect(find.widgetWithText(TextField, 'Item 0'), findsOneWidget);
|
||||||
final Finder button0Material = find.descendant(
|
final Finder button0Material = find.descendant(
|
||||||
|
@ -952,6 +953,7 @@ void main() {
|
||||||
|
|
||||||
// Continue to move up to the last item (Item 5).
|
// Continue to move up to the last item (Item 5).
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
|
||||||
|
await simulateKeyUpEvent(LogicalKeyboardKey.arrowUp);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(find.widgetWithText(TextField, 'Item 5'), findsOneWidget);
|
expect(find.widgetWithText(TextField, 'Item 5'), findsOneWidget);
|
||||||
final Finder button5Material = find.descendant(
|
final Finder button5Material = find.descendant(
|
||||||
|
|
|
@ -15933,14 +15933,12 @@ void main() {
|
||||||
expect(controller.selection.extentOffset, 20);
|
expect(controller.selection.extentOffset, 20);
|
||||||
|
|
||||||
await tester.pump(kDoubleTapTimeout);
|
await tester.pump(kDoubleTapTimeout);
|
||||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
|
|
||||||
await tester.tapAt(textOffsetToPosition(tester, 23));
|
await tester.tapAt(textOffsetToPosition(tester, 23));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.selection.baseOffset, 13);
|
expect(controller.selection.baseOffset, 13);
|
||||||
expect(controller.selection.extentOffset, 23);
|
expect(controller.selection.extentOffset, 23);
|
||||||
|
|
||||||
await tester.pump(kDoubleTapTimeout);
|
await tester.pump(kDoubleTapTimeout);
|
||||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
|
|
||||||
await tester.tapAt(textOffsetToPosition(tester, 4));
|
await tester.tapAt(textOffsetToPosition(tester, 4));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(controller.selection.baseOffset, 13);
|
expect(controller.selection.baseOffset, 13);
|
||||||
|
|
|
@ -30,7 +30,7 @@ void main() {
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.backquote, platform: platform);
|
await simulateKeyDownEvent(LogicalKeyboardKey.backquote, platform: platform);
|
||||||
RawKeyboard.instance.removeListener(handleKey);
|
RawKeyboard.instance.removeListener(handleKey);
|
||||||
}
|
}
|
||||||
});
|
}, variant: KeySimulatorTransitModeVariant.rawKeyData());
|
||||||
|
|
||||||
testWidgets('No character is produced for non-printables', (WidgetTester tester) async {
|
testWidgets('No character is produced for non-printables', (WidgetTester tester) async {
|
||||||
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'web', 'ios']) {
|
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'web', 'ios']) {
|
||||||
|
@ -41,7 +41,7 @@ void main() {
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
|
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
|
||||||
RawKeyboard.instance.removeListener(handleKey);
|
RawKeyboard.instance.removeListener(handleKey);
|
||||||
}
|
}
|
||||||
});
|
}, variant: KeySimulatorTransitModeVariant.rawKeyData());
|
||||||
|
|
||||||
testWidgets('keysPressed is maintained', (WidgetTester tester) async {
|
testWidgets('keysPressed is maintained', (WidgetTester tester) async {
|
||||||
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) {
|
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) {
|
||||||
|
@ -147,7 +147,10 @@ void main() {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/61021
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // https://github.com/flutter/flutter/issues/61021
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('keysPressed is correct when modifier is released before key', (WidgetTester tester) async {
|
testWidgets('keysPressed is correct when modifier is released before key', (WidgetTester tester) async {
|
||||||
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) {
|
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) {
|
||||||
|
@ -198,7 +201,10 @@ void main() {
|
||||||
await simulateKeyUpEvent(LogicalKeyboardKey.keyA, platform: platform, physicalKey: PhysicalKeyboardKey.keyA);
|
await simulateKeyUpEvent(LogicalKeyboardKey.keyA, platform: platform, physicalKey: PhysicalKeyboardKey.keyA);
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
||||||
}
|
}
|
||||||
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/76741
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // https://github.com/flutter/flutter/issues/76741
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('keysPressed modifiers are synchronized with key events on macOS', (WidgetTester tester) async {
|
testWidgets('keysPressed modifiers are synchronized with key events on macOS', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
|
@ -222,7 +228,10 @@ void main() {
|
||||||
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is a macOS-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is a macOS-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('keysPressed modifiers are synchronized with key events on iOS', (WidgetTester tester) async {
|
testWidgets('keysPressed modifiers are synchronized with key events on iOS', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
|
@ -246,7 +255,10 @@ void main() {
|
||||||
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is an iOS-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is a iOS-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('keysPressed modifiers are synchronized with key events on Windows', (WidgetTester tester) async {
|
testWidgets('keysPressed modifiers are synchronized with key events on Windows', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
|
@ -270,7 +282,10 @@ void main() {
|
||||||
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is a Windows-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is a Windows-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('keysPressed modifiers are synchronized with key events on android', (WidgetTester tester) async {
|
testWidgets('keysPressed modifiers are synchronized with key events on android', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
|
@ -294,7 +309,10 @@ void main() {
|
||||||
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is an Android-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is an Android-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('keysPressed modifiers are synchronized with key events on fuchsia', (WidgetTester tester) async {
|
testWidgets('keysPressed modifiers are synchronized with key events on fuchsia', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
|
@ -318,7 +336,10 @@ void main() {
|
||||||
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is a Fuchsia-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is a Fuchsia-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('keysPressed modifiers are synchronized with key events on Linux GLFW', (WidgetTester tester) async {
|
testWidgets('keysPressed modifiers are synchronized with key events on Linux GLFW', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
|
@ -348,7 +369,10 @@ void main() {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is a GLFW-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is a GLFW-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> simulateGTKKeyEvent(bool keyDown, int scancode, int keycode, int modifiers) async {
|
Future<void> simulateGTKKeyEvent(bool keyDown, int scancode, int keycode, int modifiers) async {
|
||||||
final Map<String, dynamic> data = <String, dynamic>{
|
final Map<String, dynamic> data = <String, dynamic>{
|
||||||
|
@ -397,7 +421,10 @@ void main() {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is a GTK-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is a GTK-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/114591 .
|
// Regression test for https://github.com/flutter/flutter/issues/114591 .
|
||||||
//
|
//
|
||||||
|
@ -414,7 +441,10 @@ void main() {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is a GTK-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is a GTK-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/114591 .
|
// Regression test for https://github.com/flutter/flutter/issues/114591 .
|
||||||
//
|
//
|
||||||
|
@ -447,7 +477,10 @@ void main() {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: !isBrowser); // [intended] This is a Browser-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: !isBrowser, // [intended] This is a Browser-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('keysPressed modifiers are synchronized with key events on web', (WidgetTester tester) async {
|
testWidgets('keysPressed modifiers are synchronized with key events on web', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
|
@ -572,7 +605,10 @@ void main() {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}, skip: isBrowser); // [intended] This is an Android-specific test.
|
},
|
||||||
|
variant: KeySimulatorTransitModeVariant.rawKeyData(),
|
||||||
|
skip: isBrowser, // [intended] This is a Android-specific test.
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('sided modifiers without a side set return all sides on macOS', (WidgetTester tester) async {
|
testWidgets('sided modifiers without a side set return all sides on macOS', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
|
|
|
@ -684,7 +684,7 @@ abstract final class KeyEventSimulator {
|
||||||
return result!;
|
return result!;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const KeyDataTransitMode _defaultTransitMode = KeyDataTransitMode.rawKeyData;
|
static const KeyDataTransitMode _defaultTransitMode = KeyDataTransitMode.keyDataThenRawKeyData;
|
||||||
|
|
||||||
// The simulation transit mode for [simulateKeyDownEvent], [simulateKeyUpEvent],
|
// The simulation transit mode for [simulateKeyDownEvent], [simulateKeyUpEvent],
|
||||||
// and [simulateKeyRepeatEvent].
|
// and [simulateKeyRepeatEvent].
|
||||||
|
@ -693,8 +693,8 @@ abstract final class KeyEventSimulator {
|
||||||
// and delivered. For detailed introduction, see [KeyDataTransitMode] and
|
// and delivered. For detailed introduction, see [KeyDataTransitMode] and
|
||||||
// its values.
|
// its values.
|
||||||
//
|
//
|
||||||
// The `_transitMode` defaults to [KeyDataTransitMode.rawKeyEvent], and can be
|
// The `_transitMode` defaults to [KeyDataTransitMode.keyDataThenRawKeyData], and can
|
||||||
// overridden with [debugKeyEventSimulatorTransitModeOverride]. In widget tests, it
|
// be overridden with [debugKeyEventSimulatorTransitModeOverride]. In widget tests, it
|
||||||
// is often set with [KeySimulationModeVariant].
|
// is often set with [KeySimulationModeVariant].
|
||||||
static KeyDataTransitMode get _transitMode {
|
static KeyDataTransitMode get _transitMode {
|
||||||
KeyDataTransitMode? result;
|
KeyDataTransitMode? result;
|
||||||
|
@ -705,6 +705,12 @@ abstract final class KeyEventSimulator {
|
||||||
return result ?? _defaultTransitMode;
|
return result ?? _defaultTransitMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the transit mode that simulated key events are constructed
|
||||||
|
/// and delivered. For detailed introduction, see [KeyDataTransitMode]
|
||||||
|
/// and its values.
|
||||||
|
@visibleForTesting
|
||||||
|
static KeyDataTransitMode get transitMode => _transitMode;
|
||||||
|
|
||||||
static String get _defaultPlatform => kIsWeb ? 'web' : Platform.operatingSystem;
|
static String get _defaultPlatform => kIsWeb ? 'web' : Platform.operatingSystem;
|
||||||
|
|
||||||
/// Simulates sending a hardware key down event.
|
/// Simulates sending a hardware key down event.
|
||||||
|
@ -965,6 +971,15 @@ class KeySimulatorTransitModeVariant extends TestVariant<KeyDataTransitMode> {
|
||||||
KeySimulatorTransitModeVariant.keyDataThenRawKeyData()
|
KeySimulatorTransitModeVariant.keyDataThenRawKeyData()
|
||||||
: this(<KeyDataTransitMode>{KeyDataTransitMode.keyDataThenRawKeyData});
|
: this(<KeyDataTransitMode>{KeyDataTransitMode.keyDataThenRawKeyData});
|
||||||
|
|
||||||
|
/// Creates a [KeySimulatorTransitModeVariant] that only contains
|
||||||
|
/// [KeyDataTransitMode.rawKeyData].
|
||||||
|
@Deprecated(
|
||||||
|
'No longer supported. Transit mode is always key data only. '
|
||||||
|
'This feature was deprecated after v3.18.0-2.0.pre.',
|
||||||
|
)
|
||||||
|
KeySimulatorTransitModeVariant.rawKeyData()
|
||||||
|
: this(<KeyDataTransitMode>{KeyDataTransitMode.rawKeyData});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final Set<KeyDataTransitMode> values;
|
final Set<KeyDataTransitMode> values;
|
||||||
|
|
||||||
|
|
|
@ -37,12 +37,25 @@ Future<void> _shouldThrow<T extends Error>(AsyncValueGetter<void> func) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
testWidgets('default transit mode is keyDataThenRawKeyData', (WidgetTester tester) async {
|
||||||
|
expect(KeyEventSimulator.transitMode, KeyDataTransitMode.keyDataThenRawKeyData);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('debugKeyEventSimulatorTransitModeOverride overrides default transit mode', (WidgetTester tester) async {
|
||||||
|
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData;
|
||||||
|
expect(KeyEventSimulator.transitMode, KeyDataTransitMode.rawKeyData);
|
||||||
|
// Unsetting debugKeyEventSimulatorTransitModeOverride can't be called in a
|
||||||
|
// tear down callback because TestWidgetsFlutterBinding._verifyInvariants
|
||||||
|
// is called before tear down callbacks.
|
||||||
|
debugKeyEventSimulatorTransitModeOverride = null;
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('simulates keyboard events (RawEvent)', (WidgetTester tester) async {
|
testWidgets('simulates keyboard events (RawEvent)', (WidgetTester tester) async {
|
||||||
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData;
|
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData;
|
||||||
|
|
||||||
final List<RawKeyEvent> events = <RawKeyEvent>[];
|
final List<RawKeyEvent> events = <RawKeyEvent>[];
|
||||||
|
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
RawKeyboardListener(
|
RawKeyboardListener(
|
||||||
|
@ -80,7 +93,6 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
await tester.pumpWidget(Container());
|
await tester.pumpWidget(Container());
|
||||||
focusNode.dispose();
|
|
||||||
|
|
||||||
debugKeyEventSimulatorTransitModeOverride = null;
|
debugKeyEventSimulatorTransitModeOverride = null;
|
||||||
});
|
});
|
||||||
|
@ -89,8 +101,8 @@ void main() {
|
||||||
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData;
|
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData;
|
||||||
|
|
||||||
final List<KeyEvent> events = <KeyEvent>[];
|
final List<KeyEvent> events = <KeyEvent>[];
|
||||||
|
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
KeyboardListener(
|
KeyboardListener(
|
||||||
|
@ -243,7 +255,6 @@ void main() {
|
||||||
await tester.idle();
|
await tester.idle();
|
||||||
|
|
||||||
await tester.pumpWidget(Container());
|
await tester.pumpWidget(Container());
|
||||||
focusNode.dispose();
|
|
||||||
|
|
||||||
debugKeyEventSimulatorTransitModeOverride = null;
|
debugKeyEventSimulatorTransitModeOverride = null;
|
||||||
});
|
});
|
||||||
|
@ -252,8 +263,9 @@ void main() {
|
||||||
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData;
|
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData;
|
||||||
|
|
||||||
final List<Object> events = <Object>[];
|
final List<Object> events = <Object>[];
|
||||||
|
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Focus(
|
Focus(
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
@ -308,8 +320,9 @@ void main() {
|
||||||
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData;
|
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData;
|
||||||
|
|
||||||
final List<Object> events = <Object>[];
|
final List<Object> events = <Object>[];
|
||||||
|
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Focus(
|
Focus(
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
|
Loading…
Reference in a new issue