|
23 | 23 |
|
24 | 24 | import 'dart:typed_data'; |
25 | 25 |
|
| 26 | +import 'package:flutter/foundation.dart'; |
26 | 27 | import 'package:flutter/material.dart'; |
27 | 28 | import 'package:flutter/rendering.dart'; |
| 29 | +import 'package:flutter/services.dart'; |
28 | 30 | import 'package:flutter_test/flutter_test.dart'; |
29 | 31 |
|
30 | 32 | import 'package:pyble/app/app.dart'; |
@@ -93,6 +95,108 @@ Future<void> _focusLandscapeBlocks(WidgetTester tester) async { |
93 | 95 |
|
94 | 96 | void main() { |
95 | 97 | group('landscape software keyboard', () { |
| 98 | + for (final TargetPlatform platform in <TargetPlatform>[ |
| 99 | + TargetPlatform.android, |
| 100 | + TargetPlatform.iOS, |
| 101 | + ]) { |
| 102 | + testWidgets('Expand dismisses a native Blocks keyboard on $platform', ( |
| 103 | + WidgetTester tester, |
| 104 | + ) async { |
| 105 | + debugDefaultTargetPlatformOverride = platform; |
| 106 | + addTearDown(() => debugDefaultTargetPlatformOverride = null); |
| 107 | + const MethodChannel keyboard = MethodChannel('dev.pyble/keyboard'); |
| 108 | + final List<MethodCall> requests = <MethodCall>[]; |
| 109 | + tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( |
| 110 | + keyboard, |
| 111 | + (MethodCall call) async => requests.add(call), |
| 112 | + ); |
| 113 | + addTearDown( |
| 114 | + () => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( |
| 115 | + keyboard, |
| 116 | + null, |
| 117 | + ), |
| 118 | + ); |
| 119 | + await pumpShell( |
| 120 | + tester, |
| 121 | + connection: fakeConnection(initial: ConnState.ready), |
| 122 | + surface: androidTabletLandscape, |
| 123 | + ); |
| 124 | + await _focusLandscapeBlocks(tester); |
| 125 | + final Element host = tester.element( |
| 126 | + find.byKey(_blocksWorkspaceHostKey), |
| 127 | + ); |
| 128 | + expect(find.byType(EditableText), findsNothing); |
| 129 | + tester.view.viewInsets = const FakeViewPadding(bottom: 808); |
| 130 | + addTearDown(tester.view.resetViewInsets); |
| 131 | + await tester.pump(); |
| 132 | + |
| 133 | + await tester.tap(find.byKey(kConsoleStripToggleKey)); |
| 134 | + await tester.pump(); |
| 135 | + expect(requests.map((MethodCall call) => call.method), <String>[ |
| 136 | + 'dismissKeyboard', |
| 137 | + ]); |
| 138 | + expect(requests.single.arguments, isNull); |
| 139 | + expect( |
| 140 | + tester |
| 141 | + .widget<ConsoleStripView>(find.byType(ConsoleStripView)) |
| 142 | + .collapsed, |
| 143 | + isTrue, |
| 144 | + reason: 'acknowledging a hide request does not prove IME dismissal', |
| 145 | + ); |
| 146 | + expect(tester.element(find.byKey(_blocksWorkspaceHostKey)), same(host)); |
| 147 | + tester.view.resetViewInsets(); |
| 148 | + await tester.pump(); |
| 149 | + expect( |
| 150 | + tester |
| 151 | + .widget<ConsoleStripView>(find.byType(ConsoleStripView)) |
| 152 | + .collapsed, |
| 153 | + isFalse, |
| 154 | + ); |
| 155 | + expect(tester.element(find.byKey(_blocksWorkspaceHostKey)), same(host)); |
| 156 | + expect(tester.takeException(), isNull); |
| 157 | + }); |
| 158 | + } |
| 159 | + |
| 160 | + testWidgets('Expand preserves a Flutter editor draft and selection', ( |
| 161 | + WidgetTester tester, |
| 162 | + ) async { |
| 163 | + const MethodChannel keyboard = MethodChannel('dev.pyble/keyboard'); |
| 164 | + final List<String> requests = <String>[]; |
| 165 | + tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( |
| 166 | + keyboard, |
| 167 | + (MethodCall call) async => requests.add(call.method), |
| 168 | + ); |
| 169 | + addTearDown( |
| 170 | + () => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( |
| 171 | + keyboard, |
| 172 | + null, |
| 173 | + ), |
| 174 | + ); |
| 175 | + await pumpShell( |
| 176 | + tester, |
| 177 | + connection: fakeConnection(initial: ConnState.ready), |
| 178 | + surface: androidTabletLandscape, |
| 179 | + ); |
| 180 | + final Finder editor = find.byType(EditableText).first; |
| 181 | + await tester.tap(editor); |
| 182 | + await tester.enterText(editor, '# retained draft'); |
| 183 | + final EditableText before = tester.widget<EditableText>(editor); |
| 184 | + before.controller.selection = const TextSelection.collapsed(offset: 5); |
| 185 | + tester.view.viewInsets = const FakeViewPadding(bottom: 808); |
| 186 | + addTearDown(tester.view.resetViewInsets); |
| 187 | + await tester.pump(); |
| 188 | + await tester.tap(find.byKey(kConsoleStripToggleKey)); |
| 189 | + await tester.pump(); |
| 190 | + expect(requests, <String>['dismissKeyboard']); |
| 191 | + expect(before.focusNode.hasFocus, isFalse); |
| 192 | + expect(before.controller.text, '# retained draft'); |
| 193 | + expect( |
| 194 | + before.controller.selection, |
| 195 | + const TextSelection.collapsed(offset: 5), |
| 196 | + ); |
| 197 | + expect(tester.takeException(), isNull); |
| 198 | + }); |
| 199 | + |
96 | 200 | for (final double inset in <double>[404, 440]) { |
97 | 201 | testWidgets('keeps editing and navigation usable with $inset dp inset', ( |
98 | 202 | WidgetTester tester, |
|
0 commit comments