Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 636285d

Browse files
committed
review and add more functional change to match #17493
1 parent 19107aa commit 636285d

File tree

8 files changed

+61
-33
lines changed

8 files changed

+61
-33
lines changed

shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ - (void)showTextInput {
865865
@"must be part of the responder chain to function");
866866
_activeView.textInputDelegate = _textInputDelegate;
867867

868-
if (!_activeView.window) {
868+
if (_activeView.window != keyWindow) {
869869
[keyWindow addSubview:_activeView];
870870
}
871871
[_activeView becomeFirstResponder];
@@ -885,7 +885,7 @@ - (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configur
885885
_activeView = isSecureTextEntry ? _nonAutofillSecureInputView : _nonAutofillInputView;
886886
[FlutterTextInputPlugin setupInputView:_activeView withConfiguration:configuration];
887887

888-
if (!_activeView.window) {
888+
if (_activeView.window != keyWindow) {
889889
[keyWindow addSubview:_activeView];
890890
}
891891
} else {

shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,29 @@ - (void)testSecureInput {
3838
result:^(id _Nullable result){
3939
}];
4040

41-
// Find all input views in the input hider view.
42-
NSArray<FlutterTextInputView*>* inputFields =
43-
[[[textInputPlugin textInputView] superview] subviews];
44-
45-
// Find the inactive autofillable input field.
41+
// Find all the FlutterTextInputViews we created.
42+
NSArray<FlutterTextInputView*>* inputFields = [[[[textInputPlugin textInputView] superview]
43+
subviews]
44+
filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"class == %@",
45+
[FlutterTextInputView class]]];
46+
47+
// There are no autofill and the mock framework requested a secure entry. The first and only
48+
// inserted FlutterTextInputView should be a secure text entry one.
4649
FlutterTextInputView* inputView = inputFields[0];
4750

4851
// Verify secureTextEntry is set to the correct value.
4952
XCTAssertTrue(inputView.secureTextEntry);
5053

51-
// Clean up mocks
54+
// We should have only ever created one FlutterTextInputView.
55+
XCTAssertEqual(inputFields.count, 1);
56+
57+
// The one FlutterTextInputView we inserted into the view hierarchy should be the text input
58+
// plugin's active text input view.
59+
XCTAssertEqual(inputView, textInputPlugin.textInputView);
60+
61+
// Clean up.
5262
[engine stopMocking];
63+
[[[[textInputPlugin textInputView] superview] subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
5364
}
5465
- (void)testAutofillInputViews {
5566
// Setup test.
@@ -94,9 +105,11 @@ - (void)testAutofillInputViews {
94105
result:^(id _Nullable result){
95106
}];
96107

97-
// Find all input views in the input hider view.
98-
NSArray<FlutterTextInputView*>* inputFields =
99-
[[[textInputPlugin textInputView] superview] subviews];
108+
// Find all the FlutterTextInputViews we created.
109+
NSArray<FlutterTextInputView*>* inputFields = [[[[textInputPlugin textInputView] superview]
110+
subviews]
111+
filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"class == %@",
112+
[FlutterTextInputView class]]];
100113

101114
XCTAssertEqual(inputFields.count, 2);
102115

@@ -108,8 +121,9 @@ - (void)testAutofillInputViews {
108121
// Verify behavior.
109122
OCMVerify([engine updateEditingClient:0 withState:[OCMArg isNotNil] withTag:@"field2"]);
110123

111-
// Clean up mocks
124+
// Clean up.
112125
[engine stopMocking];
126+
[[[[textInputPlugin textInputView] superview] subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
113127
}
114128

115129
- (void)testAutocorrectionPromptRectAppears {

shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#import <OCMock/OCMock.h>
66
#import <XCTest/XCTest.h>
7-
#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
7+
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
88
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
99
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
1010

testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#include "AppDelegate.h"
5+
#import "AppDelegate.h"
6+
67
#import "FlutterEngine+ScenariosTest.h"
78
#import "ScreenBeforeFlutter.h"
89
#import "TextPlatformView.h"

testing/scenario_app/ios/Scenarios/ScenariosUITests/TextSemanticsFocusTest.m

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ - (void)testAccessibilityFocusOnTextSemanticsProducesCorrectIosViews {
2020
// frame.
2121
XCUIElement* textInputSemanticsObject =
2222
[[[self.application textFields] matchingIdentifier:@"flutter textfield"] element];
23-
XCTAssertTrue([textInputSemanticsObject waitForExistenceWithTimeout:5]);
24-
XCTAssertEqual([textInputSemanticsObject valueForKey:@"hasKeyboardFocus"], @(NO));
23+
XCTAssertTrue([textInputSemanticsObject waitForExistenceWithTimeout:3]);
24+
XCTAssertEqualObjects([textInputSemanticsObject valueForKey:@"hasKeyboardFocus"], @(NO));
2525

2626
// Since the first mock framework text field isn't focused on, it shouldn't produce a UITextInput
2727
// in the view hierarchy.
2828
XCUIElement* delegateTextInput = [[self.application textViews] element];
29-
XCTAssertFalse([delegateTextInput waitForExistenceWithTimeout:5]);
29+
XCTAssertFalse([delegateTextInput waitForExistenceWithTimeout:3]);
3030

3131
// Nor should there be a keyboard for text entry.
3232
XCUIElement* keyboard = [[self.application keyboards] element];
33-
XCTAssertFalse([keyboard waitForExistenceWithTimeout:5]);
33+
XCTAssertFalse([keyboard waitForExistenceWithTimeout:3]);
3434

3535
// The tap location doesn't matter. The mock framework just sends a focused text field on tap.
3636
[textInputSemanticsObject tap];
@@ -39,18 +39,18 @@ - (void)testAccessibilityFocusOnTextSemanticsProducesCorrectIosViews {
3939
// UI tests on a XCUIElement).
4040
textInputSemanticsObject =
4141
[[[self.application textFields] matchingIdentifier:@"focused flutter textfield"] element];
42-
XCTAssertTrue([textInputSemanticsObject waitForExistenceWithTimeout:5]);
43-
XCTAssertEqual([textInputSemanticsObject valueForKey:@"hasKeyboardFocus"], @(YES));
42+
XCTAssertTrue([textInputSemanticsObject waitForExistenceWithTimeout:3]);
43+
XCTAssertEqualObjects([textInputSemanticsObject valueForKey:@"hasKeyboardFocus"], @(YES));
4444

45-
// The delegate UITextInput is also inserted on the window and also has keyboard focus to delegate
46-
// real text entry events to the framework.
45+
// The delegate UITextInput is also inserted on the window but we make only the
46+
// TextInputSemanticsObject visible and not the FlutterTextInputView to avoid confusing
47+
// accessibility, it shouldn't be visible to the UI test either.
4748
delegateTextInput = [[self.application textViews] element];
48-
XCTAssertTrue([delegateTextInput waitForExistenceWithTimeout:5]);
49-
XCTAssertEqual([delegateTextInput valueForKey:@"hasKeyboardFocus"], @(YES));
49+
XCTAssertFalse([delegateTextInput waitForExistenceWithTimeout:3]);
5050

51-
// Since there is focus, the soft keyboard is visible on the simulator.
51+
// But since there is focus, the soft keyboard is visible on the simulator.
5252
keyboard = [[self.application keyboards] element];
53-
XCTAssertTrue([keyboard waitForExistenceWithTimeout:5]);
53+
XCTAssertTrue([keyboard waitForExistenceWithTimeout:3]);
5454
}
5555

5656
@end

testing/scenario_app/lib/src/channel_util.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'package:meta/meta.dart';
99

1010
/// Util method to replicate the behavior of a `MethodChannel` in the Flutter
1111
/// framework.
12-
void sendMethodCall({
12+
void sendJsonMethodCall({
1313
@required Window window,
1414
@required String channel,
1515
@required String method,
@@ -28,4 +28,4 @@ void sendMethodCall({
2828
).buffer.asByteData(),
2929
callback,
3030
);
31-
}
31+
}

testing/scenario_app/lib/src/poppable_screen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class PoppableScreenScenario extends Scenario with PlatformEchoMixin {
7373
}
7474

7575
void _pop() {
76-
sendMethodCall(
76+
sendJsonMethodCall(
7777
window: window,
7878
// 'flutter/platform' is the hardcoded name of the 'platform'
7979
// `SystemChannel` from the `SystemNavigator` API.

testing/scenario_app/lib/src/send_text_focus_semantics.dart

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
import 'dart:typed_data';
66
import 'dart:ui';
77

8-
import 'package:scenario_app/src/channel_util.dart';
8+
import 'package:vector_math/vector_math_64.dart';
99

10+
import 'channel_util.dart';
1011
import 'scenario.dart';
1112

1213
/// A scenario that sends back messages when touches are received.
@@ -54,7 +55,7 @@ class SendTextFocusScemantics extends Scenario {
5455
currentValueLength: 0,
5556
scrollChildren: 0,
5657
scrollIndex: 0,
57-
transform: Float64List.fromList(<double>[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 366.5, 0.0, 1.0]),
58+
transform: Matrix4.identity().storage,
5859
elevation: 0.0,
5960
thickness: 0.0,
6061
childrenInTraversalOrder: Int32List(0),
@@ -70,7 +71,19 @@ class SendTextFocusScemantics extends Scenario {
7071
void onPointerDataPacket(PointerDataPacket packet) {
7172
// This mimics the framework which shows the FlutterTextInputView before
7273
// updating the TextInputSemanticsObject.
73-
sendMethodCall(
74+
sendJsonMethodCall(
75+
window: window,
76+
channel: 'flutter/textinput',
77+
method: 'TextInput.setClient',
78+
arguments: <dynamic>[
79+
1,
80+
// The arguments are text field configurations. It doesn't really matter
81+
// since we're just testing text field accessibility here.
82+
<String, dynamic>{ 'obscureText': false },
83+
]
84+
);
85+
86+
sendJsonMethodCall(
7487
window: window,
7588
channel: 'flutter/textinput',
7689
method: 'TextInput.show',
@@ -92,7 +105,7 @@ class SendTextFocusScemantics extends Scenario {
92105
currentValueLength: 0,
93106
scrollChildren: 0,
94107
scrollIndex: 0,
95-
transform: Float64List.fromList(<double>[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 231.0, 0.0, 1.0]),
108+
transform: Matrix4.identity().storage,
96109
elevation: 0.0,
97110
thickness: 0.0,
98111
childrenInTraversalOrder: Int32List(0),

0 commit comments

Comments
 (0)