Flutter iOS Embedder
FlutterChannelKeyResponderTest.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #import <Foundation/Foundation.h>
6 #import <OCMock/OCMock.h>
7 #import <XCTest/XCTest.h>
8 
12 
14 
15 #define XCTAssertStrEqual(value, expected) \
16  XCTAssertTrue([value isEqualToString:expected], \
17  @"String \"%@\" not equal to the expected value of \"%@\"", value, expected)
18 
19 using namespace flutter::testing;
20 
21 API_AVAILABLE(ios(13.4))
22 @interface FlutterChannelKeyResponderTest : XCTestCase
23 @property(copy, nonatomic) FlutterUIPressProxy* testKeyDownEvent API_AVAILABLE(ios(13.4));
24 @property(copy, nonatomic) FlutterUIPressProxy* testKeyUpEvent API_AVAILABLE(ios(13.4));
25 @end
26 
27 @implementation FlutterChannelKeyResponderTest
28 
29 - (void)setUp {
30  // All of these tests were designed to run on iOS 13.4 or later.
31  if (@available(iOS 13.4, *)) {
32  } else {
33  XCTSkip(@"Required API not present for test.");
34  }
35  _testKeyDownEvent = keyDownEvent(UIKeyboardHIDUsageKeyboardA, 0x0, 0.0f, "a", "a");
36  _testKeyUpEvent = keyUpEvent(UIKeyboardHIDUsageKeyboardA, 0x0, 0.0f);
37 }
38 
39 - (void)tearDown API_AVAILABLE(ios(13.4)) {
40  _testKeyDownEvent = nil;
41  _testKeyUpEvent = nil;
42 }
43 
44 - (void)testBasicKeyEvent API_AVAILABLE(ios(13.4)) {
45  __block NSMutableArray<id>* messages = [[NSMutableArray<id> alloc] init];
46  __block BOOL next_response = TRUE;
47  __block NSMutableArray<NSNumber*>* responses = [[NSMutableArray<NSNumber*> alloc] init];
48 
49  id mockKeyEventChannel = OCMStrictClassMock([FlutterBasicMessageChannel class]);
50  OCMStub([mockKeyEventChannel sendMessage:[OCMArg any] reply:[OCMArg any]])
51  .andDo((^(NSInvocation* invocation) {
52  [invocation retainArguments];
53  NSDictionary* message;
54  [invocation getArgument:&message atIndex:2];
55  [messages addObject:message];
56 
57  FlutterReply callback;
58  [invocation getArgument:&callback atIndex:3];
59  NSDictionary* keyMessage = @{
60  @"handled" : @(next_response),
61  };
62  callback(keyMessage);
63  }));
64 
65  // Key down
66  FlutterChannelKeyResponder* responder =
67  [[FlutterChannelKeyResponder alloc] initWithChannel:mockKeyEventChannel];
68  [responder handlePress:_testKeyDownEvent
69  callback:^(BOOL handled) {
70  [responses addObject:@(handled)];
71  }];
72 
73  XCTAssertEqual([messages count], 1u);
74  XCTAssertStrEqual([messages lastObject][@"keymap"], @"ios");
75  XCTAssertStrEqual([messages lastObject][@"type"], @"keydown");
76  XCTAssertEqual([[messages lastObject][@"keyCode"] intValue], UIKeyboardHIDUsageKeyboardA);
77  XCTAssertEqual([[messages lastObject][@"modifiers"] intValue], 0x0);
78  XCTAssertStrEqual([messages lastObject][@"characters"], @"a");
79  XCTAssertStrEqual([messages lastObject][@"charactersIgnoringModifiers"], @"a");
80 
81  XCTAssertEqual([responses count], 1u);
82  XCTAssertEqual([[responses lastObject] boolValue], TRUE);
83 
84  [messages removeAllObjects];
85  [responses removeAllObjects];
86 
87  // Key up
88  next_response = FALSE;
89  [responder handlePress:_testKeyUpEvent
90  callback:^(BOOL handled) {
91  [responses addObject:@(handled)];
92  }];
93 
94  XCTAssertEqual([messages count], 1u);
95  XCTAssertStrEqual([messages lastObject][@"keymap"], @"ios");
96  XCTAssertStrEqual([messages lastObject][@"type"], @"keyup");
97  XCTAssertEqual([[messages lastObject][@"keyCode"] intValue], UIKeyboardHIDUsageKeyboardA);
98  XCTAssertEqual([[messages lastObject][@"modifiers"] intValue], 0x0);
99 
100  XCTAssertEqual([responses count], 1u);
101  XCTAssertEqual([[responses lastObject] boolValue], FALSE);
102 
103  [messages removeAllObjects];
104  [responses removeAllObjects];
105 }
106 
107 - (void)testEmptyResponseIsTakenAsHandled API_AVAILABLE(ios(13.4)) {
108  __block NSMutableArray<id>* messages = [[NSMutableArray<id> alloc] init];
109  __block NSMutableArray<NSNumber*>* responses = [[NSMutableArray<NSNumber*> alloc] init];
110 
111  id mockKeyEventChannel = OCMStrictClassMock([FlutterBasicMessageChannel class]);
112  OCMStub([mockKeyEventChannel sendMessage:[OCMArg any] reply:[OCMArg any]])
113  .andDo((^(NSInvocation* invocation) {
114  [invocation retainArguments];
115  NSDictionary* message;
116  [invocation getArgument:&message atIndex:2];
117  [messages addObject:message];
118 
119  FlutterReply callback;
120  [invocation getArgument:&callback atIndex:3];
121  callback(nullptr);
122  }));
123 
124  FlutterChannelKeyResponder* responder =
125  [[FlutterChannelKeyResponder alloc] initWithChannel:mockKeyEventChannel];
126  [responder handlePress:_testKeyDownEvent
127  callback:^(BOOL handled) {
128  [responses addObject:@(handled)];
129  }];
130 
131  XCTAssertEqual([messages count], 1u);
132  XCTAssertStrEqual([messages lastObject][@"keymap"], @"ios");
133  XCTAssertStrEqual([messages lastObject][@"type"], @"keydown");
134  XCTAssertEqual([[messages lastObject][@"keyCode"] intValue], UIKeyboardHIDUsageKeyboardA);
135  XCTAssertEqual([[messages lastObject][@"modifiers"] intValue], 0x0);
136  XCTAssertStrEqual([messages lastObject][@"characters"], @"a");
137  XCTAssertStrEqual([messages lastObject][@"charactersIgnoringModifiers"], @"a");
138 
139  XCTAssertEqual([responses count], 1u);
140  XCTAssertEqual([[responses lastObject] boolValue], TRUE);
141 }
142 
143 @end
FlutterBasicMessageChannel
Definition: FlutterChannels.h:37
flutter::testing::keyDownEvent
FlutterUIPressProxy * keyDownEvent(UIKeyboardHIDUsage keyCode, UIKeyModifierFlags modifierFlags=0x0, NSTimeInterval timestamp=0.0f, const char *characters="", const char *charactersIgnoringModifiers="") API_AVAILABLE(ios(13.4))
Definition: FlutterFakeKeyEvents.mm:90
API_AVAILABLE
UITextSmartQuotesType smartQuotesType API_AVAILABLE(ios(11.0))
XCTAssertStrEqual
#define XCTAssertStrEqual(value, expected)
Definition: FlutterChannelKeyResponderTest.mm:15
flutter::testing
Definition: FlutterFakeKeyEvents.h:51
FlutterChannelKeyResponder.h
-[FlutterKeyPrimaryResponder-p handlePress:callback:]
void handlePress:callback:(nonnull FlutterUIPressProxy *press,[callback] ios(13.4) API_AVAILABLE)
FlutterMacros.h
FlutterFakeKeyEvents.h
FlutterChannelKeyResponder
Definition: FlutterChannelKeyResponder.h:20
FlutterReply
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterReply)(id _Nullable reply)
FLUTTER_ASSERT_ARC
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponderTest.mm:13
FlutterUIPressProxy
Definition: FlutterUIPressProxy.h:17
FlutterChannelKeyResponderTest
Definition: FlutterChannelKeyResponderTest.mm:22
flutter::testing::keyUpEvent
FlutterUIPressProxy * keyUpEvent(UIKeyboardHIDUsage keyCode, UIKeyModifierFlags modifierFlags=0x0, NSTimeInterval timestamp=0.0f, const char *characters="", const char *charactersIgnoringModifiers="") API_AVAILABLE(ios(13.4))
Definition: FlutterFakeKeyEvents.mm:100