Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Instance Methods | List of all members
FlutterInputPluginTestObjc Class Reference
Inheritance diagram for FlutterInputPluginTestObjc:

Instance Methods

(bool) - testEmptyCompositionRange
 
(bool) - testClearClientDuringComposing
 
(bool) - testSetMarkedTextWithSelectionChange [implementation]
 
(bool) - testSetMarkedTextWithReplacementRange [implementation]
 
(bool) - testComposingRegionRemovedByFramework [implementation]
 
(bool) - testAutocompleteDisabledWhenAutofillNotSet [implementation]
 
(bool) - testAutocompleteEnabledWhenAutofillSet [implementation]
 
(bool) - testAutocompleteEnabledWhenAutofillSetNoHint [implementation]
 
(bool) - testAutocompleteDisabledWhenObscureTextSet [implementation]
 
(bool) - testAutocompleteDisabledWhenPasswordAutofillSet [implementation]
 
(bool) - testAutocompleteDisabledWhenAutofillGroupIncludesPassword [implementation]
 
(bool) - testContentTypeWhenAutofillTypeIsUsername [implementation]
 
(bool) - testContentTypeWhenAutofillTypeIsOneTimeCode [implementation]
 
(bool) - testFirstRectForCharacterRange [implementation]
 
(bool) - testFirstRectForCharacterRangeAtInfinity [implementation]
 
(bool) - testFirstRectForCharacterRangeWithEsotericAffineTransform [implementation]
 
(bool) - testSetEditingStateWithTextEditingDelta [implementation]
 
(bool) - testOperationsThatTriggerDelta [implementation]
 
(bool) - testComposingWithDelta [implementation]
 
(bool) - testComposingWithDeltasWhenSelectionIsActive [implementation]
 
(bool) - testPerformKeyEquivalent [implementation]
 
(bool) - handleArrowKeyWhenImePopoverIsActive [implementation]
 
(bool) - unhandledKeyEquivalent [implementation]
 
(bool) - testInsertNewLine [implementation]
 
(bool) - testSendActionDoNotInsertNewLine [implementation]
 
(bool) - testLocalTextAndSelectionUpdateAfterDelta [implementation]
 
(bool) - testSelectorsAreForwardedToFramework [implementation]
 

Detailed Description

Definition at line 52 of file FlutterTextInputPluginTest.mm.

Method Documentation

◆ handleArrowKeyWhenImePopoverIsActive

- (bool) handleArrowKeyWhenImePopoverIsActive
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1365 {
1366 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1367 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1368 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1369 [engineMock binaryMessenger])
1370 .andReturn(binaryMessengerMock);
1371 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
1372 callback:nil
1373 userData:nil]);
1374
1375 NSTextInputContext* textInputContext = OCMClassMock([NSTextInputContext class]);
1376 OCMStub([textInputContext handleEvent:[OCMArg any]]).andReturn(YES);
1377
1378 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1379 nibName:@""
1380 bundle:nil];
1381
1382 FlutterTextInputPlugin* plugin =
1383 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
1384
1385 plugin.textInputContext = textInputContext;
1386
1387 NSDictionary* setClientConfig = @{
1388 @"inputAction" : @"action",
1389 @"enableDeltaModel" : @"true",
1390 @"inputType" : @{@"name" : @"inputName"},
1391 };
1392 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
1393 arguments:@[ @(1), setClientConfig ]]
1394 result:^(id){
1395 }];
1396
1398 arguments:@[]]
1399 result:^(id){
1400 }];
1401
1402 // Set marked text, simulate active IME popover.
1403 [plugin setMarkedText:@"m"
1404 selectedRange:NSMakeRange(0, 1)
1405 replacementRange:NSMakeRange(NSNotFound, 0)];
1406
1407 // Right arrow key. This, unlike the key below should be handled by the plugin.
1408 NSEvent* event = [NSEvent keyEventWithType:NSEventTypeKeyDown
1409 location:NSZeroPoint
1410 modifierFlags:0xa00100
1411 timestamp:0
1412 windowNumber:0
1413 context:nil
1414 characters:@"\uF702"
1415 charactersIgnoringModifiers:@"\uF702"
1416 isARepeat:NO
1417 keyCode:0x4];
1418
1419 // Plugin should mark the event as key equivalent.
1420 [plugin performKeyEquivalent:event];
1421
1422 if ([plugin handleKeyEvent:event] != true) {
1423 return false;
1424 }
1425
1426 // CTRL+H (delete backwards)
1427 event = [NSEvent keyEventWithType:NSEventTypeKeyDown
1428 location:NSZeroPoint
1429 modifierFlags:0x40101
1430 timestamp:0
1431 windowNumber:0
1432 context:nil
1433 characters:@"\uF702"
1434 charactersIgnoringModifiers:@"\uF702"
1435 isARepeat:NO
1436 keyCode:0x4];
1437
1438 // Plugin should mark the event as key equivalent.
1439 [plugin performKeyEquivalent:event];
1440
1441 if ([plugin handleKeyEvent:event] != false) {
1442 return false;
1443 }
1444
1445 return true;
1446}
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
NSTextInputContext * textInputContext
void handleMethodCall:result:(FlutterMethodCall *call,[result] FlutterResult result)
BOOL performKeyEquivalent:(NSEvent *event)
void setMarkedText:selectedRange:replacementRange:(id string, [selectedRange] NSRange selectedRange, [replacementRange] NSRange replacementRange)
FlutterViewController * viewController
id CreateMockFlutterEngine(NSString *pasteboardString)
SIT bool any(const Vec< 1, T > &x)
Definition SkVx.h:530

◆ testAutocompleteDisabledWhenAutofillGroupIncludesPassword

- (bool) testAutocompleteDisabledWhenAutofillGroupIncludesPassword
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

521 {
522 // Set up FlutterTextInputPlugin.
524 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
525 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
526 [engineMock binaryMessenger])
527 .andReturn(binaryMessengerMock);
528 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
529 nibName:@""
530 bundle:nil];
531 FlutterTextInputPlugin* plugin =
532 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
533
534 // Set input client 1.
535 NSDictionary* setClientConfig = @{
536 @"inputAction" : @"action",
537 @"inputType" : @{@"name" : @"inputName"},
538 @"fields" : @[
539 @{
540 @"inputAction" : @"action",
541 @"inputType" : @{@"name" : @"inputName"},
542 @"autofill" : @{
543 @"uniqueIdentifier" : @"field1",
544 @"hints" : @[ @"password" ],
545 @"editingValue" : @{@"text" : @""},
546 }
547 },
548 @{
549 @"inputAction" : @"action",
550 @"inputType" : @{@"name" : @"inputName"},
551 @"autofill" : @{
552 @"uniqueIdentifier" : @"field2",
553 @"hints" : @[ @"name" ],
554 @"editingValue" : @{@"text" : @""},
555 }
556 }
557 ]
558 };
559 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
560 arguments:@[ @(1), setClientConfig ]]
561 result:^(id){
562 }];
563
564 // Verify autocomplete is disabled.
565 EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]);
566 return true;
567}

◆ testAutocompleteDisabledWhenAutofillNotSet

- (bool) testAutocompleteDisabledWhenAutofillNotSet
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

351 {
352 // Set up FlutterTextInputPlugin.
354 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
355 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
356 [engineMock binaryMessenger])
357 .andReturn(binaryMessengerMock);
358 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
359 nibName:@""
360 bundle:nil];
361 FlutterTextInputPlugin* plugin =
362 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
363
364 // Set input client 1.
365 NSDictionary* setClientConfig = @{
366 @"inputAction" : @"action",
367 @"inputType" : @{@"name" : @"inputName"},
368 };
369 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
370 arguments:@[ @(1), setClientConfig ]]
371 result:^(id){
372 }];
373
374 // Verify autocomplete is disabled.
375 EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]);
376 return true;
377}

◆ testAutocompleteDisabledWhenObscureTextSet

- (bool) testAutocompleteDisabledWhenObscureTextSet
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

450 {
451 // Set up FlutterTextInputPlugin.
453 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
454 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
455 [engineMock binaryMessenger])
456 .andReturn(binaryMessengerMock);
457 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
458 nibName:@""
459 bundle:nil];
460 FlutterTextInputPlugin* plugin =
461 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
462
463 // Set input client 1.
464 NSDictionary* setClientConfig = @{
465 @"inputAction" : @"action",
466 @"inputType" : @{@"name" : @"inputName"},
467 @"obscureText" : @YES,
468 @"autofill" : @{
469 @"uniqueIdentifier" : @"field1",
470 @"editingValue" : @{@"text" : @""},
471 }
472 };
473 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
474 arguments:@[ @(1), setClientConfig ]]
475 result:^(id){
476 }];
477
478 // Verify autocomplete is disabled.
479 EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]);
480 return true;
481}

◆ testAutocompleteDisabledWhenPasswordAutofillSet

- (bool) testAutocompleteDisabledWhenPasswordAutofillSet
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

483 {
484 // Set up FlutterTextInputPlugin.
486 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
487 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
488 [engineMock binaryMessenger])
489 .andReturn(binaryMessengerMock);
490 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
491 nibName:@""
492 bundle:nil];
493 FlutterTextInputPlugin* plugin =
494 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
495
496 // Set input client 1.
497 NSDictionary* setClientConfig = @{
498 @"inputAction" : @"action",
499 @"inputType" : @{@"name" : @"inputName"},
500 @"autofill" : @{
501 @"uniqueIdentifier" : @"field1",
502 @"hints" : @[ @"password" ],
503 @"editingValue" : @{@"text" : @""},
504 }
505 };
506 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
507 arguments:@[ @(1), setClientConfig ]]
508 result:^(id){
509 }];
510
511 // Verify autocomplete is disabled.
512 EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]);
513
514 // Verify content type is password.
515 if (@available(macOS 11.0, *)) {
516 EXPECT_EQ([plugin contentType], NSTextContentTypePassword);
517 }
518 return true;
519}

◆ testAutocompleteEnabledWhenAutofillSet

- (bool) testAutocompleteEnabledWhenAutofillSet
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

379 {
380 // Set up FlutterTextInputPlugin.
382 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
383 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
384 [engineMock binaryMessenger])
385 .andReturn(binaryMessengerMock);
386 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
387 nibName:@""
388 bundle:nil];
389 FlutterTextInputPlugin* plugin =
390 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
391
392 // Set input client 1.
393 NSDictionary* setClientConfig = @{
394 @"inputAction" : @"action",
395 @"inputType" : @{@"name" : @"inputName"},
396 @"autofill" : @{
397 @"uniqueIdentifier" : @"field1",
398 @"hints" : @[ @"name" ],
399 @"editingValue" : @{@"text" : @""},
400 }
401 };
402 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
403 arguments:@[ @(1), setClientConfig ]]
404 result:^(id){
405 }];
406
407 // Verify autocomplete is enabled.
408 EXPECT_TRUE([plugin isAutomaticTextCompletionEnabled]);
409
410 // Verify content type is nil for unsupported content types.
411 if (@available(macOS 11.0, *)) {
412 EXPECT_EQ([plugin contentType], nil);
413 }
414 return true;
415}
#define EXPECT_TRUE(handle)
Definition unit_test.h:685

◆ testAutocompleteEnabledWhenAutofillSetNoHint

- (bool) testAutocompleteEnabledWhenAutofillSetNoHint
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

417 {
418 // Set up FlutterTextInputPlugin.
420 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
421 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
422 [engineMock binaryMessenger])
423 .andReturn(binaryMessengerMock);
424 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
425 nibName:@""
426 bundle:nil];
427 FlutterTextInputPlugin* plugin =
428 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
429
430 // Set input client 1.
431 NSDictionary* setClientConfig = @{
432 @"inputAction" : @"action",
433 @"inputType" : @{@"name" : @"inputName"},
434 @"autofill" : @{
435 @"uniqueIdentifier" : @"field1",
436 @"hints" : @[],
437 @"editingValue" : @{@"text" : @""},
438 }
439 };
440 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
441 arguments:@[ @(1), setClientConfig ]]
442 result:^(id){
443 }];
444
445 // Verify autocomplete is enabled.
446 EXPECT_TRUE([plugin isAutomaticTextCompletionEnabled]);
447 return true;
448}

◆ testClearClientDuringComposing

- (bool) testClearClientDuringComposing

Definition at line 24 of file FlutterTextInputPluginTest.mm.

299 {
300 // Set up FlutterTextInputPlugin.
302 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
303 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
304 [engineMock binaryMessenger])
305 .andReturn(binaryMessengerMock);
306 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
307 nibName:@""
308 bundle:nil];
309 FlutterTextInputPlugin* plugin =
310 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
311
312 // Set input client 1.
313 NSDictionary* setClientConfig = @{
314 @"inputAction" : @"action",
315 @"inputType" : @{@"name" : @"inputName"},
316 };
317 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
318 arguments:@[ @(1), setClientConfig ]]
319 result:^(id){
320 }];
321
322 // Set editing state with an active composing range.
323 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setEditingState"
324 arguments:@{
325 @"text" : @"Text",
326 @"selectionBase" : @(0),
327 @"selectionExtent" : @(0),
328 @"composingBase" : @(0),
329 @"composingExtent" : @(1),
330 }]
331 result:^(id){
332 }];
333
334 // Verify composing range is (0, 1).
335 NSDictionary* editingState = [plugin editingState];
336 EXPECT_EQ([editingState[@"composingBase"] intValue], 0);
337 EXPECT_EQ([editingState[@"composingExtent"] intValue], 1);
338
339 // Clear input client.
340 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.clearClient"
341 arguments:@[]]
342 result:^(id){
343 }];
344
345 // Verify composing range is collapsed.
346 editingState = [plugin editingState];
347 EXPECT_EQ([editingState[@"composingBase"] intValue], [editingState[@"composingExtent"] intValue]);
348 return true;
349}

◆ testComposingRegionRemovedByFramework

- (bool) testComposingRegionRemovedByFramework
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

239 {
241 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
242 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
243 [engineMock binaryMessenger])
244 .andReturn(binaryMessengerMock);
245
246 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
247 nibName:@""
248 bundle:nil];
249
250 FlutterTextInputPlugin* plugin =
251 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
252
253 NSDictionary* setClientConfig = @{
254 @"inputAction" : @"action",
255 @"inputType" : @{@"name" : @"inputName"},
256 };
257 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
258 arguments:@[ @(1), setClientConfig ]]
259 result:^(id){
260 }];
261
263 arguments:@{
264 @"text" : @"Text",
265 @"selectionBase" : @(4),
266 @"selectionExtent" : @(4),
267 @"composingBase" : @(2),
268 @"composingExtent" : @(4),
269 }];
270 [plugin handleMethodCall:call
271 result:^(id){
272 }];
273
274 // Update with the composing region removed.
275 call = [FlutterMethodCall methodCallWithMethodName:@"TextInput.setEditingState"
276 arguments:@{
277 @"text" : @"Te",
278 @"selectionBase" : @(2),
279 @"selectionExtent" : @(2),
280 @"composingBase" : @(-1),
281 @"composingExtent" : @(-1),
282 }];
283 [plugin handleMethodCall:call
284 result:^(id){
285 }];
286
287 // Verify editing state was set.
288 NSDictionary* editingState = [plugin editingState];
289 EXPECT_STREQ([editingState[@"text"] UTF8String], "Te");
290 EXPECT_STREQ([editingState[@"selectionAffinity"] UTF8String], "TextAffinity.upstream");
291 EXPECT_FALSE([editingState[@"selectionIsDirectional"] boolValue]);
292 EXPECT_EQ([editingState[@"selectionBase"] intValue], 2);
293 EXPECT_EQ([editingState[@"selectionExtent"] intValue], 2);
294 EXPECT_EQ([editingState[@"composingBase"] intValue], -1);
295 EXPECT_EQ([editingState[@"composingExtent"] intValue], -1);
296 return true;
297}
call(args)
Definition dom.py:159

◆ testComposingWithDelta

- (bool) testComposingWithDelta
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1003 {
1004 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1005 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1006 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1007 [engineMock binaryMessenger])
1008 .andReturn(binaryMessengerMock);
1009
1010 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1011 nibName:@""
1012 bundle:nil];
1013
1014 FlutterTextInputPlugin* plugin =
1015 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
1016
1017 NSDictionary* setClientConfig = @{
1018 @"inputAction" : @"action",
1019 @"enableDeltaModel" : @"true",
1020 @"inputType" : @{@"name" : @"inputName"},
1021 };
1022 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
1023 arguments:@[ @(1), setClientConfig ]]
1024 result:^(id){
1025 }];
1026 [plugin setMarkedText:@"m" selectedRange:NSMakeRange(0, 1)];
1027
1028 NSDictionary* deltaToFramework = @{
1029 @"oldText" : @"",
1030 @"deltaText" : @"m",
1031 @"deltaStart" : @(0),
1032 @"deltaEnd" : @(0),
1033 @"selectionBase" : @(0),
1034 @"selectionExtent" : @(1),
1035 @"selectionAffinity" : @"TextAffinity.upstream",
1036 @"selectionIsDirectional" : @(false),
1037 @"composingBase" : @(0),
1038 @"composingExtent" : @(1),
1039 };
1040 NSDictionary* expectedState = @{
1041 @"deltas" : @[ deltaToFramework ],
1042 };
1043
1044 NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance]
1045 encodeMethodCall:[FlutterMethodCall
1046 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1047 arguments:@[ @(1), expectedState ]]];
1048
1049 @try {
1050 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1051 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1052 } @catch (...) {
1053 return false;
1054 }
1055
1056 [plugin setMarkedText:@"ma" selectedRange:NSMakeRange(0, 1)];
1057
1058 deltaToFramework = @{
1059 @"oldText" : @"m",
1060 @"deltaText" : @"ma",
1061 @"deltaStart" : @(0),
1062 @"deltaEnd" : @(1),
1063 @"selectionBase" : @(0),
1064 @"selectionExtent" : @(1),
1065 @"selectionAffinity" : @"TextAffinity.upstream",
1066 @"selectionIsDirectional" : @(false),
1067 @"composingBase" : @(0),
1068 @"composingExtent" : @(2),
1069 };
1070 expectedState = @{
1071 @"deltas" : @[ deltaToFramework ],
1072 };
1073
1075 encodeMethodCall:[FlutterMethodCall
1076 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1077 arguments:@[ @(1), expectedState ]]];
1078
1079 @try {
1080 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1081 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1082 } @catch (...) {
1083 return false;
1084 }
1085
1086 [plugin setMarkedText:@"mar" selectedRange:NSMakeRange(0, 1)];
1087
1088 deltaToFramework = @{
1089 @"oldText" : @"ma",
1090 @"deltaText" : @"mar",
1091 @"deltaStart" : @(0),
1092 @"deltaEnd" : @(2),
1093 @"selectionBase" : @(0),
1094 @"selectionExtent" : @(1),
1095 @"selectionAffinity" : @"TextAffinity.upstream",
1096 @"selectionIsDirectional" : @(false),
1097 @"composingBase" : @(0),
1098 @"composingExtent" : @(3),
1099 };
1100 expectedState = @{
1101 @"deltas" : @[ deltaToFramework ],
1102 };
1103
1105 encodeMethodCall:[FlutterMethodCall
1106 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1107 arguments:@[ @(1), expectedState ]]];
1108
1109 @try {
1110 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1111 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1112 } @catch (...) {
1113 return false;
1114 }
1115
1116 [plugin setMarkedText:@"mark" selectedRange:NSMakeRange(0, 1)];
1117
1118 deltaToFramework = @{
1119 @"oldText" : @"mar",
1120 @"deltaText" : @"mark",
1121 @"deltaStart" : @(0),
1122 @"deltaEnd" : @(3),
1123 @"selectionBase" : @(0),
1124 @"selectionExtent" : @(1),
1125 @"selectionAffinity" : @"TextAffinity.upstream",
1126 @"selectionIsDirectional" : @(false),
1127 @"composingBase" : @(0),
1128 @"composingExtent" : @(4),
1129 };
1130 expectedState = @{
1131 @"deltas" : @[ deltaToFramework ],
1132 };
1133
1135 encodeMethodCall:[FlutterMethodCall
1136 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1137 arguments:@[ @(1), expectedState ]]];
1138
1139 @try {
1140 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1141 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1142 } @catch (...) {
1143 return false;
1144 }
1145
1146 [plugin setMarkedText:@"marke" selectedRange:NSMakeRange(0, 1)];
1147
1148 deltaToFramework = @{
1149 @"oldText" : @"mark",
1150 @"deltaText" : @"marke",
1151 @"deltaStart" : @(0),
1152 @"deltaEnd" : @(4),
1153 @"selectionBase" : @(0),
1154 @"selectionExtent" : @(1),
1155 @"selectionAffinity" : @"TextAffinity.upstream",
1156 @"selectionIsDirectional" : @(false),
1157 @"composingBase" : @(0),
1158 @"composingExtent" : @(5),
1159 };
1160 expectedState = @{
1161 @"deltas" : @[ deltaToFramework ],
1162 };
1163
1165 encodeMethodCall:[FlutterMethodCall
1166 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1167 arguments:@[ @(1), expectedState ]]];
1168
1169 @try {
1170 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1171 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1172 } @catch (...) {
1173 return false;
1174 }
1175
1176 [plugin setMarkedText:@"marked" selectedRange:NSMakeRange(0, 1)];
1177
1178 deltaToFramework = @{
1179 @"oldText" : @"marke",
1180 @"deltaText" : @"marked",
1181 @"deltaStart" : @(0),
1182 @"deltaEnd" : @(5),
1183 @"selectionBase" : @(0),
1184 @"selectionExtent" : @(1),
1185 @"selectionAffinity" : @"TextAffinity.upstream",
1186 @"selectionIsDirectional" : @(false),
1187 @"composingBase" : @(0),
1188 @"composingExtent" : @(6),
1189 };
1190 expectedState = @{
1191 @"deltas" : @[ deltaToFramework ],
1192 };
1193
1195 encodeMethodCall:[FlutterMethodCall
1196 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1197 arguments:@[ @(1), expectedState ]]];
1198
1199 @try {
1200 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1201 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1202 } @catch (...) {
1203 return false;
1204 }
1205
1206 [plugin unmarkText];
1207
1208 deltaToFramework = @{
1209 @"oldText" : @"marked",
1210 @"deltaText" : @"",
1211 @"deltaStart" : @(-1),
1212 @"deltaEnd" : @(-1),
1213 @"selectionBase" : @(6),
1214 @"selectionExtent" : @(6),
1215 @"selectionAffinity" : @"TextAffinity.upstream",
1216 @"selectionIsDirectional" : @(false),
1217 @"composingBase" : @(-1),
1218 @"composingExtent" : @(-1),
1219 };
1220 expectedState = @{
1221 @"deltas" : @[ deltaToFramework ],
1222 };
1223
1225 encodeMethodCall:[FlutterMethodCall
1226 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1227 arguments:@[ @(1), expectedState ]]];
1228
1229 @try {
1230 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1231 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1232 } @catch (...) {
1233 return false;
1234 }
1235 return true;
1236}
instancetype sharedInstance()
Win32Message message

◆ testComposingWithDeltasWhenSelectionIsActive

- (bool) testComposingWithDeltasWhenSelectionIsActive
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1238 {
1239 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1240 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1241 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1242 [engineMock binaryMessenger])
1243 .andReturn(binaryMessengerMock);
1244
1245 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1246 nibName:@""
1247 bundle:nil];
1248
1249 FlutterTextInputPlugin* plugin =
1250 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
1251
1252 NSDictionary* setClientConfig = @{
1253 @"inputAction" : @"action",
1254 @"enableDeltaModel" : @"true",
1255 @"inputType" : @{@"name" : @"inputName"},
1256 };
1257 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
1258 arguments:@[ @(1), setClientConfig ]]
1259 result:^(id){
1260 }];
1261
1262 FlutterMethodCall* call = [FlutterMethodCall methodCallWithMethodName:@"TextInput.setEditingState"
1263 arguments:@{
1264 @"text" : @"Text",
1265 @"selectionBase" : @(0),
1266 @"selectionExtent" : @(4),
1267 @"composingBase" : @(-1),
1268 @"composingExtent" : @(-1),
1269 }];
1270 [plugin handleMethodCall:call
1271 result:^(id){
1272 }];
1273
1274 [plugin setMarkedText:@"~"
1275 selectedRange:NSMakeRange(1, 0)
1276 replacementRange:NSMakeRange(NSNotFound, 0)];
1277
1278 NSDictionary* deltaToFramework = @{
1279 @"oldText" : @"Text",
1280 @"deltaText" : @"~",
1281 @"deltaStart" : @(0),
1282 @"deltaEnd" : @(4),
1283 @"selectionBase" : @(1),
1284 @"selectionExtent" : @(1),
1285 @"selectionAffinity" : @"TextAffinity.upstream",
1286 @"selectionIsDirectional" : @(false),
1287 @"composingBase" : @(0),
1288 @"composingExtent" : @(1),
1289 };
1290 NSDictionary* expectedState = @{
1291 @"deltas" : @[ deltaToFramework ],
1292 };
1293
1294 NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance]
1295 encodeMethodCall:[FlutterMethodCall
1296 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1297 arguments:@[ @(1), expectedState ]]];
1298
1299 @try {
1300 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1301 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1302 } @catch (...) {
1303 return false;
1304 }
1305 return true;
1306}

◆ testContentTypeWhenAutofillTypeIsOneTimeCode

- (bool) testContentTypeWhenAutofillTypeIsOneTimeCode
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

607 {
608 // Set up FlutterTextInputPlugin.
610 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
611 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
612 [engineMock binaryMessenger])
613 .andReturn(binaryMessengerMock);
614 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
615 nibName:@""
616 bundle:nil];
617 FlutterTextInputPlugin* plugin =
618 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
619
620 // Set input client 1.
621 NSDictionary* setClientConfig = @{
622 @"inputAction" : @"action",
623 @"inputType" : @{@"name" : @"inputName"},
624 @"autofill" : @{
625 @"uniqueIdentifier" : @"field1",
626 @"hints" : @[ @"oneTimeCode" ],
627 @"editingValue" : @{@"text" : @""},
628 }
629 };
630 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
631 arguments:@[ @(1), setClientConfig ]]
632 result:^(id){
633 }];
634
635 // Verify autocomplete is disabled.
636 EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]);
637
638 // Verify content type is username.
639 if (@available(macOS 11.0, *)) {
640 EXPECT_EQ([plugin contentType], NSTextContentTypeOneTimeCode);
641 }
642 return true;
643}

◆ testContentTypeWhenAutofillTypeIsUsername

- (bool) testContentTypeWhenAutofillTypeIsUsername
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

569 {
570 // Set up FlutterTextInputPlugin.
572 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
573 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
574 [engineMock binaryMessenger])
575 .andReturn(binaryMessengerMock);
576 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
577 nibName:@""
578 bundle:nil];
579 FlutterTextInputPlugin* plugin =
580 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
581
582 // Set input client 1.
583 NSDictionary* setClientConfig = @{
584 @"inputAction" : @"action",
585 @"inputType" : @{@"name" : @"inputName"},
586 @"autofill" : @{
587 @"uniqueIdentifier" : @"field1",
588 @"hints" : @[ @"name" ],
589 @"editingValue" : @{@"text" : @""},
590 }
591 };
592 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
593 arguments:@[ @(1), setClientConfig ]]
594 result:^(id){
595 }];
596
597 // Verify autocomplete is disabled.
598 EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]);
599
600 // Verify content type is username.
601 if (@available(macOS 11.0, *)) {
602 EXPECT_EQ([plugin contentType], NSTextContentTypeUsername);
603 }
604 return true;
605}

◆ testEmptyCompositionRange

- (bool) testEmptyCompositionRange

Definition at line 24 of file FlutterTextInputPluginTest.mm.

59 {
61 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
62 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
63 [engineMock binaryMessenger])
64 .andReturn(binaryMessengerMock);
65
66 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
67 nibName:@""
68 bundle:nil];
69
71 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
72
73 NSDictionary* setClientConfig = @{
74 @"inputAction" : @"action",
75 @"inputType" : @{@"name" : @"inputName"},
76 };
77 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
78 arguments:@[ @(1), setClientConfig ]]
79 result:^(id){
80 }];
81
83 arguments:@{
84 @"text" : @"Text",
85 @"selectionBase" : @(0),
86 @"selectionExtent" : @(0),
87 @"composingBase" : @(-1),
88 @"composingExtent" : @(-1),
89 }];
90
91 [plugin handleMethodCall:call
92 result:^(id){
93 }];
94
95 // Verify editing state was set.
96 NSDictionary* editingState = [plugin editingState];
97 EXPECT_STREQ([editingState[@"text"] UTF8String], "Text");
98 EXPECT_STREQ([editingState[@"selectionAffinity"] UTF8String], "TextAffinity.upstream");
99 EXPECT_FALSE([editingState[@"selectionIsDirectional"] boolValue]);
100 EXPECT_EQ([editingState[@"selectionBase"] intValue], 0);
101 EXPECT_EQ([editingState[@"selectionExtent"] intValue], 0);
102 EXPECT_EQ([editingState[@"composingBase"] intValue], -1);
103 EXPECT_EQ([editingState[@"composingExtent"] intValue], -1);
104 return true;
105}

◆ testFirstRectForCharacterRange

- (bool) testFirstRectForCharacterRange
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

645 {
647 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
648 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
649 [engineMock binaryMessenger])
650 .andReturn(binaryMessengerMock);
651 FlutterViewController* controllerMock =
652 [[TextInputTestViewController alloc] initWithEngine:engineMock nibName:nil bundle:nil];
653 [controllerMock loadView];
654 id viewMock = controllerMock.flutterView;
655 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
656 [viewMock bounds])
657 .andReturn(NSMakeRect(0, 0, 200, 200));
658
659 id windowMock = OCMClassMock([NSWindow class]);
660 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
661 [viewMock window])
662 .andReturn(windowMock);
663
664 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
665 [viewMock convertRect:NSMakeRect(28, 10, 2, 19) toView:nil])
666 .andReturn(NSMakeRect(28, 10, 2, 19));
667
668 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
669 [windowMock convertRectToScreen:NSMakeRect(28, 10, 2, 19)])
670 .andReturn(NSMakeRect(38, 20, 2, 19));
671
672 FlutterTextInputPlugin* plugin =
673 [[FlutterTextInputPlugin alloc] initWithViewController:controllerMock];
674
676 methodCallWithMethodName:@"TextInput.setEditableSizeAndTransform"
677 arguments:@{
678 @"height" : @(20.0),
679 @"transform" : @[
680 @(1.0), @(0.0), @(0.0), @(0.0), @(0.0), @(1.0), @(0.0), @(0.0), @(0.0),
681 @(0.0), @(1.0), @(0.0), @(20.0), @(10.0), @(0.0), @(1.0)
682 ],
683 @"width" : @(400.0),
684 }];
685
686 [plugin handleMethodCall:call
687 result:^(id){
688 }];
689
690 call = [FlutterMethodCall methodCallWithMethodName:@"TextInput.setCaretRect"
691 arguments:@{
692 @"height" : @(19.0),
693 @"width" : @(2.0),
694 @"x" : @(8.0),
695 @"y" : @(0.0),
696 }];
697
698 [plugin handleMethodCall:call
699 result:^(id){
700 }];
701
702 NSRect rect = [plugin firstRectForCharacterRange:NSMakeRange(0, 0) actualRange:nullptr];
703 @try {
704 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
705 [windowMock convertRectToScreen:NSMakeRect(28, 10, 2, 19)]);
706 } @catch (...) {
707 return false;
708 }
709
710 return NSEqualRects(rect, NSMakeRect(38, 20, 2, 19));
711}
GLFWwindow * window
Definition main.cc:45
NSRect firstRectForCharacterRange:actualRange:(NSRange range, [actualRange] NSRangePointer actualRange)
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350

◆ testFirstRectForCharacterRangeAtInfinity

- (bool) testFirstRectForCharacterRangeAtInfinity
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

713 {
715 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
716 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
717 [engineMock binaryMessenger])
718 .andReturn(binaryMessengerMock);
719 FlutterViewController* controllerMock =
720 [[TextInputTestViewController alloc] initWithEngine:engineMock nibName:nil bundle:nil];
721 [controllerMock loadView];
722 id viewMock = controllerMock.flutterView;
723 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
724 [viewMock bounds])
725 .andReturn(NSMakeRect(0, 0, 200, 200));
726
727 id windowMock = OCMClassMock([NSWindow class]);
728 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
729 [viewMock window])
730 .andReturn(windowMock);
731
732 FlutterTextInputPlugin* plugin =
733 [[FlutterTextInputPlugin alloc] initWithViewController:controllerMock];
734
736 methodCallWithMethodName:@"TextInput.setEditableSizeAndTransform"
737 arguments:@{
738 @"height" : @(20.0),
739 // Projects all points to infinity.
740 @"transform" : @[
741 @(1.0), @(0.0), @(0.0), @(0.0), @(0.0), @(1.0), @(0.0), @(0.0), @(0.0),
742 @(0.0), @(1.0), @(0.0), @(20.0), @(10.0), @(0.0), @(0.0)
743 ],
744 @"width" : @(400.0),
745 }];
746
747 [plugin handleMethodCall:call
748 result:^(id){
749 }];
750
751 call = [FlutterMethodCall methodCallWithMethodName:@"TextInput.setCaretRect"
752 arguments:@{
753 @"height" : @(19.0),
754 @"width" : @(2.0),
755 @"x" : @(8.0),
756 @"y" : @(0.0),
757 }];
758
759 [plugin handleMethodCall:call
760 result:^(id){
761 }];
762
763 NSRect rect = [plugin firstRectForCharacterRange:NSMakeRange(0, 0) actualRange:nullptr];
764 return NSEqualRects(rect, CGRectZero);
765}

◆ testFirstRectForCharacterRangeWithEsotericAffineTransform

- (bool) testFirstRectForCharacterRangeWithEsotericAffineTransform
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

767 {
769 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
770 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
771 [engineMock binaryMessenger])
772 .andReturn(binaryMessengerMock);
773 FlutterViewController* controllerMock =
774 [[TextInputTestViewController alloc] initWithEngine:engineMock nibName:nil bundle:nil];
775 [controllerMock loadView];
776 id viewMock = controllerMock.flutterView;
777 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
778 [viewMock bounds])
779 .andReturn(NSMakeRect(0, 0, 200, 200));
780
781 id windowMock = OCMClassMock([NSWindow class]);
782 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
783 [viewMock window])
784 .andReturn(windowMock);
785
786 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
787 [viewMock convertRect:NSMakeRect(-18, 6, 3, 3) toView:nil])
788 .andReturn(NSMakeRect(-18, 6, 3, 3));
789
790 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
791 [windowMock convertRectToScreen:NSMakeRect(-18, 6, 3, 3)])
792 .andReturn(NSMakeRect(-18, 6, 3, 3));
793
794 FlutterTextInputPlugin* plugin =
795 [[FlutterTextInputPlugin alloc] initWithViewController:controllerMock];
796
798 methodCallWithMethodName:@"TextInput.setEditableSizeAndTransform"
799 arguments:@{
800 @"height" : @(20.0),
801 // This matrix can be generated by running this dart code snippet:
802 // Matrix4.identity()..scale(3.0)..rotateZ(math.pi/2)..translate(1.0, 2.0,
803 // 3.0);
804 @"transform" : @[
805 @(0.0), @(3.0), @(0.0), @(0.0), @(-3.0), @(0.0), @(0.0), @(0.0), @(0.0),
806 @(0.0), @(3.0), @(0.0), @(-6.0), @(3.0), @(9.0), @(1.0)
807 ],
808 @"width" : @(400.0),
809 }];
810
811 [plugin handleMethodCall:call
812 result:^(id){
813 }];
814
815 call = [FlutterMethodCall methodCallWithMethodName:@"TextInput.setCaretRect"
816 arguments:@{
817 @"height" : @(1.0),
818 @"width" : @(1.0),
819 @"x" : @(1.0),
820 @"y" : @(3.0),
821 }];
822
823 [plugin handleMethodCall:call
824 result:^(id){
825 }];
826
827 NSRect rect = [plugin firstRectForCharacterRange:NSMakeRange(0, 0) actualRange:nullptr];
828
829 @try {
830 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
831 [windowMock convertRectToScreen:NSMakeRect(-18, 6, 3, 3)]);
832 } @catch (...) {
833 return false;
834 }
835
836 return NSEqualRects(rect, NSMakeRect(-18, 6, 3, 3));
837}

◆ testInsertNewLine

- (bool) testInsertNewLine
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1522 {
1523 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1524 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1525 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1526 [engineMock binaryMessenger])
1527 .andReturn(binaryMessengerMock);
1528 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
1529 callback:nil
1530 userData:nil]);
1531
1532 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1533 nibName:@""
1534 bundle:nil];
1535
1536 FlutterTextInputPlugin* plugin =
1537 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
1538
1539 NSDictionary* setClientConfig = @{
1540 @"inputType" : @{@"name" : @"TextInputType.multiline"},
1541 @"inputAction" : @"TextInputAction.newline",
1542 };
1543 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
1544 arguments:@[ @(1), setClientConfig ]]
1545 result:^(id){
1546 }];
1547
1548 FlutterMethodCall* call = [FlutterMethodCall methodCallWithMethodName:@"TextInput.setEditingState"
1549 arguments:@{
1550 @"text" : @"Text",
1551 @"selectionBase" : @(4),
1552 @"selectionExtent" : @(4),
1553 @"composingBase" : @(-1),
1554 @"composingExtent" : @(-1),
1555 }];
1556
1557 [plugin handleMethodCall:call
1558 result:^(id){
1559 }];
1560
1561 // Verify editing state was set.
1562 NSDictionary* editingState = [plugin editingState];
1563 EXPECT_STREQ([editingState[@"text"] UTF8String], "Text");
1564 EXPECT_STREQ([editingState[@"selectionAffinity"] UTF8String], "TextAffinity.upstream");
1565 EXPECT_FALSE([editingState[@"selectionIsDirectional"] boolValue]);
1566 EXPECT_EQ([editingState[@"selectionBase"] intValue], 4);
1567 EXPECT_EQ([editingState[@"selectionExtent"] intValue], 4);
1568 EXPECT_EQ([editingState[@"composingBase"] intValue], -1);
1569 EXPECT_EQ([editingState[@"composingExtent"] intValue], -1);
1570
1571 [plugin doCommandBySelector:@selector(insertNewline:)];
1572
1573 // Verify editing state was set.
1574 editingState = [plugin editingState];
1575 EXPECT_STREQ([editingState[@"text"] UTF8String], "Text\n");
1576 EXPECT_STREQ([editingState[@"selectionAffinity"] UTF8String], "TextAffinity.upstream");
1577 EXPECT_FALSE([editingState[@"selectionIsDirectional"] boolValue]);
1578 EXPECT_EQ([editingState[@"selectionBase"] intValue], 5);
1579 EXPECT_EQ([editingState[@"selectionExtent"] intValue], 5);
1580 EXPECT_EQ([editingState[@"composingBase"] intValue], -1);
1581 EXPECT_EQ([editingState[@"composingExtent"] intValue], -1);
1582
1583 return true;
1584}
void doCommandBySelector:(SEL selector)

◆ testLocalTextAndSelectionUpdateAfterDelta

- (bool) testLocalTextAndSelectionUpdateAfterDelta
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1685 {
1686 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1687 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1688 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1689 [engineMock binaryMessenger])
1690 .andReturn(binaryMessengerMock);
1691
1692 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1693 nibName:@""
1694 bundle:nil];
1695
1696 FlutterTextInputPlugin* plugin =
1697 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
1698
1699 NSDictionary* setClientConfig = @{
1700 @"inputAction" : @"action",
1701 @"enableDeltaModel" : @"true",
1702 @"inputType" : @{@"name" : @"inputName"},
1703 };
1704 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
1705 arguments:@[ @(1), setClientConfig ]]
1706 result:^(id){
1707 }];
1708 [plugin insertText:@"text to insert"];
1709
1710 NSDictionary* deltaToFramework = @{
1711 @"oldText" : @"",
1712 @"deltaText" : @"text to insert",
1713 @"deltaStart" : @(0),
1714 @"deltaEnd" : @(0),
1715 @"selectionBase" : @(14),
1716 @"selectionExtent" : @(14),
1717 @"selectionAffinity" : @"TextAffinity.upstream",
1718 @"selectionIsDirectional" : @(false),
1719 @"composingBase" : @(-1),
1720 @"composingExtent" : @(-1),
1721 };
1722 NSDictionary* expectedState = @{
1723 @"deltas" : @[ deltaToFramework ],
1724 };
1725
1726 NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance]
1727 encodeMethodCall:[FlutterMethodCall
1728 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
1729 arguments:@[ @(1), expectedState ]]];
1730
1731 @try {
1732 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1733 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1734 } @catch (...) {
1735 return false;
1736 }
1737
1738 bool localTextAndSelectionUpdated = [plugin.string isEqualToString:@"text to insert"] &&
1739 NSEqualRanges(plugin.selectedRange, NSMakeRange(14, 0));
1740
1741 return localTextAndSelectionUpdated;
1742}

◆ testOperationsThatTriggerDelta

- (bool) testOperationsThatTriggerDelta
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

888 {
890 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
891 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
892 [engineMock binaryMessenger])
893 .andReturn(binaryMessengerMock);
894
895 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
896 nibName:@""
897 bundle:nil];
898
899 FlutterTextInputPlugin* plugin =
900 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
901
902 NSDictionary* setClientConfig = @{
903 @"inputAction" : @"action",
904 @"enableDeltaModel" : @"true",
905 @"inputType" : @{@"name" : @"inputName"},
906 };
907 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
908 arguments:@[ @(1), setClientConfig ]]
909 result:^(id){
910 }];
911 [plugin insertText:@"text to insert"];
912
913 NSDictionary* deltaToFramework = @{
914 @"oldText" : @"",
915 @"deltaText" : @"text to insert",
916 @"deltaStart" : @(0),
917 @"deltaEnd" : @(0),
918 @"selectionBase" : @(14),
919 @"selectionExtent" : @(14),
920 @"selectionAffinity" : @"TextAffinity.upstream",
921 @"selectionIsDirectional" : @(false),
922 @"composingBase" : @(-1),
923 @"composingExtent" : @(-1),
924 };
925 NSDictionary* expectedState = @{
926 @"deltas" : @[ deltaToFramework ],
927 };
928
929 NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance]
930 encodeMethodCall:[FlutterMethodCall
931 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
932 arguments:@[ @(1), expectedState ]]];
933
934 @try {
935 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
936 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
937 } @catch (...) {
938 return false;
939 }
940
941 [plugin setMarkedText:@"marked text" selectedRange:NSMakeRange(0, 1)];
942
943 deltaToFramework = @{
944 @"oldText" : @"text to insert",
945 @"deltaText" : @"marked text",
946 @"deltaStart" : @(14),
947 @"deltaEnd" : @(14),
948 @"selectionBase" : @(14),
949 @"selectionExtent" : @(15),
950 @"selectionAffinity" : @"TextAffinity.upstream",
951 @"selectionIsDirectional" : @(false),
952 @"composingBase" : @(14),
953 @"composingExtent" : @(25),
954 };
955 expectedState = @{
956 @"deltas" : @[ deltaToFramework ],
957 };
958
960 encodeMethodCall:[FlutterMethodCall
961 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
962 arguments:@[ @(1), expectedState ]]];
963
964 @try {
965 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
966 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
967 } @catch (...) {
968 return false;
969 }
970
971 [plugin unmarkText];
972
973 deltaToFramework = @{
974 @"oldText" : @"text to insertmarked text",
975 @"deltaText" : @"",
976 @"deltaStart" : @(-1),
977 @"deltaEnd" : @(-1),
978 @"selectionBase" : @(25),
979 @"selectionExtent" : @(25),
980 @"selectionAffinity" : @"TextAffinity.upstream",
981 @"selectionIsDirectional" : @(false),
982 @"composingBase" : @(-1),
983 @"composingExtent" : @(-1),
984 };
985 expectedState = @{
986 @"deltas" : @[ deltaToFramework ],
987 };
988
990 encodeMethodCall:[FlutterMethodCall
991 methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"
992 arguments:@[ @(1), expectedState ]]];
993
994 @try {
995 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
996 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
997 } @catch (...) {
998 return false;
999 }
1000 return true;
1001}

◆ testPerformKeyEquivalent

- (bool) testPerformKeyEquivalent
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1308 {
1309 __block NSEvent* eventBeingDispatchedByKeyboardManager = nil;
1310 FlutterViewController* viewControllerMock = OCMClassMock([FlutterViewController class]);
1311 OCMStub([viewControllerMock isDispatchingKeyEvent:[OCMArg any]])
1312 .andDo(^(NSInvocation* invocation) {
1313 NSEvent* event;
1314 [invocation getArgument:(void*)&event atIndex:2];
1315 BOOL result = event == eventBeingDispatchedByKeyboardManager;
1316 [invocation setReturnValue:&result];
1317 });
1318
1319 NSEvent* event = [NSEvent keyEventWithType:NSEventTypeKeyDown
1320 location:NSZeroPoint
1321 modifierFlags:0x100
1322 timestamp:0
1323 windowNumber:0
1324 context:nil
1325 characters:@""
1326 charactersIgnoringModifiers:@""
1327 isARepeat:NO
1328 keyCode:0x50];
1329
1330 FlutterTextInputPlugin* plugin =
1331 [[FlutterTextInputPlugin alloc] initWithViewController:viewControllerMock];
1332
1333 OCMExpect([viewControllerMock keyDown:event]);
1334
1335 // Require that event is handled (returns YES)
1336 if (![plugin performKeyEquivalent:event]) {
1337 return false;
1338 };
1339
1340 @try {
1341 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1342 [viewControllerMock keyDown:event]);
1343 } @catch (...) {
1344 return false;
1345 }
1346
1347 // performKeyEquivalent must not forward event if it is being
1348 // dispatched by keyboard manager
1349 eventBeingDispatchedByKeyboardManager = event;
1350
1351 OCMReject([viewControllerMock keyDown:event]);
1352 @try {
1353 // Require that event is not handled (returns NO) and not
1354 // forwarded to controller
1355 if ([plugin performKeyEquivalent:event]) {
1356 return false;
1357 };
1358 } @catch (...) {
1359 return false;
1360 }
1361
1362 return true;
1363}
GAsyncResult * result
int BOOL

◆ testSelectorsAreForwardedToFramework

- (bool) testSelectorsAreForwardedToFramework
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1744 {
1745 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1746 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1747 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1748 [engineMock binaryMessenger])
1749 .andReturn(binaryMessengerMock);
1750
1751 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1752 nibName:@""
1753 bundle:nil];
1754
1755 FlutterTextInputPlugin* plugin =
1756 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
1757
1758 NSDictionary* setClientConfig = @{
1759 @"inputAction" : @"action",
1760 @"enableDeltaModel" : @"true",
1761 @"inputType" : @{@"name" : @"inputName"},
1762 };
1763 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
1764 arguments:@[ @(1), setClientConfig ]]
1765 result:^(id){
1766 }];
1767
1768 // Can't run CFRunLoop in default mode because it causes crashes from scheduled
1769 // sources from other tests.
1770 NSString* runLoopMode = @"FlutterTestRunLoopMode";
1771 plugin.customRunLoopMode = runLoopMode;
1772
1773 // Ensure both selectors are grouped in one platform channel call.
1774 [plugin doCommandBySelector:@selector(moveUp:)];
1776
1777 __block bool done = false;
1778 CFRunLoopPerformBlock(CFRunLoopGetMain(), (__bridge CFStringRef)runLoopMode, ^{
1779 done = true;
1780 });
1781
1782 while (!done) {
1783 // Each invocation will handle one source.
1784 CFRunLoopRunInMode((__bridge CFStringRef)runLoopMode, 0, true);
1785 }
1786
1787 NSData* performSelectorCall = [[FlutterJSONMethodCodec sharedInstance]
1788 encodeMethodCall:[FlutterMethodCall
1789 methodCallWithMethodName:@"TextInputClient.performSelectors"
1790 arguments:@[
1791 @(1), @[ @"moveUp:", @"moveRightAndModifySelection:" ]
1792 ]]];
1793
1794 @try {
1795 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1796 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:performSelectorCall]);
1797 } @catch (...) {
1798 return false;
1799 }
1800
1801 return true;
1802}
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition DM.cpp:263

◆ testSendActionDoNotInsertNewLine

- (bool) testSendActionDoNotInsertNewLine
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1586 {
1587 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1588 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1589 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1590 [engineMock binaryMessenger])
1591 .andReturn(binaryMessengerMock);
1592 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
1593 callback:nil
1594 userData:nil]);
1595
1596 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1597 nibName:@""
1598 bundle:nil];
1599
1600 FlutterTextInputPlugin* plugin =
1601 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
1602
1603 NSDictionary* setClientConfig = @{
1604 @"inputType" : @{@"name" : @"TextInputType.multiline"},
1605 @"inputAction" : @"TextInputAction.send",
1606 };
1607 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
1608 arguments:@[ @(1), setClientConfig ]]
1609 result:^(id){
1610 }];
1611
1612 FlutterMethodCall* call = [FlutterMethodCall methodCallWithMethodName:@"TextInput.setEditingState"
1613 arguments:@{
1614 @"text" : @"Text",
1615 @"selectionBase" : @(4),
1616 @"selectionExtent" : @(4),
1617 @"composingBase" : @(-1),
1618 @"composingExtent" : @(-1),
1619 }];
1620
1621 NSDictionary* expectedState = @{
1622 @"selectionBase" : @(4),
1623 @"selectionExtent" : @(4),
1624 @"selectionAffinity" : @"TextAffinity.upstream",
1625 @"selectionIsDirectional" : @(NO),
1626 @"composingBase" : @(-1),
1627 @"composingExtent" : @(-1),
1628 @"text" : @"Text",
1629 };
1630
1631 NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance]
1632 encodeMethodCall:[FlutterMethodCall
1633 methodCallWithMethodName:@"TextInputClient.updateEditingState"
1634 arguments:@[ @(1), expectedState ]]];
1635
1636 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
1637 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1638
1639 [plugin handleMethodCall:call
1640 result:^(id){
1641 }];
1642
1643 [plugin doCommandBySelector:@selector(insertNewline:)];
1644
1645 NSData* performActionCall = [[FlutterJSONMethodCodec sharedInstance]
1646 encodeMethodCall:[FlutterMethodCall
1647 methodCallWithMethodName:@"TextInputClient.performAction"
1648 arguments:@[ @(1), @"TextInputAction.send" ]]];
1649
1650 // Input action should be notified.
1651 @try {
1652 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1653 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:performActionCall]);
1654 } @catch (...) {
1655 return false;
1656 }
1657
1658 NSDictionary* updatedState = @{
1659 @"selectionBase" : @(5),
1660 @"selectionExtent" : @(5),
1661 @"selectionAffinity" : @"TextAffinity.upstream",
1662 @"selectionIsDirectional" : @(NO),
1663 @"composingBase" : @(-1),
1664 @"composingExtent" : @(-1),
1665 @"text" : @"Text\n",
1666 };
1667
1669 encodeMethodCall:[FlutterMethodCall
1670 methodCallWithMethodName:@"TextInputClient.updateEditingState"
1671 arguments:@[ @(1), updatedState ]]];
1672
1673 // Verify that editing state was not be updated.
1674 @try {
1675 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
1676 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
1677 return false;
1678 } @catch (...) {
1679 // Expected.
1680 }
1681
1682 return true;
1683}

◆ testSetEditingStateWithTextEditingDelta

- (bool) testSetEditingStateWithTextEditingDelta
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

839 {
841 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
842 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
843 [engineMock binaryMessenger])
844 .andReturn(binaryMessengerMock);
845
846 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
847 nibName:@""
848 bundle:nil];
849
850 FlutterTextInputPlugin* plugin =
851 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
852
853 NSDictionary* setClientConfig = @{
854 @"inputAction" : @"action",
855 @"enableDeltaModel" : @"true",
856 @"inputType" : @{@"name" : @"inputName"},
857 };
858 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
859 arguments:@[ @(1), setClientConfig ]]
860 result:^(id){
861 }];
862
864 arguments:@{
865 @"text" : @"Text",
866 @"selectionBase" : @(0),
867 @"selectionExtent" : @(0),
868 @"composingBase" : @(-1),
869 @"composingExtent" : @(-1),
870 }];
871
872 [plugin handleMethodCall:call
873 result:^(id){
874 }];
875
876 // Verify editing state was set.
877 NSDictionary* editingState = [plugin editingState];
878 EXPECT_STREQ([editingState[@"text"] UTF8String], "Text");
879 EXPECT_STREQ([editingState[@"selectionAffinity"] UTF8String], "TextAffinity.upstream");
880 EXPECT_FALSE([editingState[@"selectionIsDirectional"] boolValue]);
881 EXPECT_EQ([editingState[@"selectionBase"] intValue], 0);
882 EXPECT_EQ([editingState[@"selectionExtent"] intValue], 0);
883 EXPECT_EQ([editingState[@"composingBase"] intValue], -1);
884 EXPECT_EQ([editingState[@"composingExtent"] intValue], -1);
885 return true;
886}

◆ testSetMarkedTextWithReplacementRange

- (bool) testSetMarkedTextWithReplacementRange
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

173 {
175 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
176 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
177 [engineMock binaryMessenger])
178 .andReturn(binaryMessengerMock);
179
180 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
181 nibName:@""
182 bundle:nil];
183
184 FlutterTextInputPlugin* plugin =
185 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
186
187 NSDictionary* setClientConfig = @{
188 @"inputAction" : @"action",
189 @"inputType" : @{@"name" : @"inputName"},
190 };
191 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
192 arguments:@[ @(1), setClientConfig ]]
193 result:^(id){
194 }];
195
197 arguments:@{
198 @"text" : @"1234",
199 @"selectionBase" : @(3),
200 @"selectionExtent" : @(3),
201 @"composingBase" : @(-1),
202 @"composingExtent" : @(-1),
203 }];
204 [plugin handleMethodCall:call
205 result:^(id){
206 }];
207
208 [plugin setMarkedText:@"marked"
209 selectedRange:NSMakeRange(1, 0)
210 replacementRange:NSMakeRange(1, 2)];
211
212 NSDictionary* expectedState = @{
213 @"selectionBase" : @(2),
214 @"selectionExtent" : @(2),
215 @"selectionAffinity" : @"TextAffinity.upstream",
216 @"selectionIsDirectional" : @(NO),
217 @"composingBase" : @(1),
218 @"composingExtent" : @(7),
219 @"text" : @"1marked4",
220 };
221
222 NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance]
223 encodeMethodCall:[FlutterMethodCall
224 methodCallWithMethodName:@"TextInputClient.updateEditingState"
225 arguments:@[ @(1), expectedState ]]];
226
227 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
228 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
229
230 @try {
231 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
232 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
233 } @catch (...) {
234 return false;
235 }
236 return true;
237}

◆ testSetMarkedTextWithSelectionChange

- (bool) testSetMarkedTextWithSelectionChange
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

107 {
109 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
110 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
111 [engineMock binaryMessenger])
112 .andReturn(binaryMessengerMock);
113
114 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
115 nibName:@""
116 bundle:nil];
117
118 FlutterTextInputPlugin* plugin =
119 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
120
121 NSDictionary* setClientConfig = @{
122 @"inputAction" : @"action",
123 @"inputType" : @{@"name" : @"inputName"},
124 };
125 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
126 arguments:@[ @(1), setClientConfig ]]
127 result:^(id){
128 }];
129
131 arguments:@{
132 @"text" : @"Text",
133 @"selectionBase" : @(4),
134 @"selectionExtent" : @(4),
135 @"composingBase" : @(-1),
136 @"composingExtent" : @(-1),
137 }];
138 [plugin handleMethodCall:call
139 result:^(id){
140 }];
141
142 [plugin setMarkedText:@"marked"
143 selectedRange:NSMakeRange(1, 0)
144 replacementRange:NSMakeRange(NSNotFound, 0)];
145
146 NSDictionary* expectedState = @{
147 @"selectionBase" : @(5),
148 @"selectionExtent" : @(5),
149 @"selectionAffinity" : @"TextAffinity.upstream",
150 @"selectionIsDirectional" : @(NO),
151 @"composingBase" : @(4),
152 @"composingExtent" : @(10),
153 @"text" : @"Textmarked",
154 };
155
156 NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance]
157 encodeMethodCall:[FlutterMethodCall
158 methodCallWithMethodName:@"TextInputClient.updateEditingState"
159 arguments:@[ @(1), expectedState ]]];
160
161 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
162 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
163
164 @try {
165 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
166 [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]);
167 } @catch (...) {
168 return false;
169 }
170 return true;
171}

◆ unhandledKeyEquivalent

- (bool) unhandledKeyEquivalent
implementation

Definition at line 24 of file FlutterTextInputPluginTest.mm.

1448 {
1449 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1450 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1451 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1452 [engineMock binaryMessenger])
1453 .andReturn(binaryMessengerMock);
1454
1455 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1456 nibName:@""
1457 bundle:nil];
1458
1459 FlutterTextInputPlugin* plugin =
1460 [[FlutterTextInputPlugin alloc] initWithViewController:viewController];
1461
1462 NSDictionary* setClientConfig = @{
1463 @"inputAction" : @"action",
1464 @"enableDeltaModel" : @"true",
1465 @"inputType" : @{@"name" : @"inputName"},
1466 };
1467 [plugin handleMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInput.setClient"
1468 arguments:@[ @(1), setClientConfig ]]
1469 result:^(id){
1470 }];
1471
1473 arguments:@[]]
1474 result:^(id){
1475 }];
1476
1477 // CTRL+H (delete backwards)
1478 NSEvent* event = [NSEvent keyEventWithType:NSEventTypeKeyDown
1479 location:NSZeroPoint
1480 modifierFlags:0x40101
1481 timestamp:0
1482 windowNumber:0
1483 context:nil
1484 characters:@""
1485 charactersIgnoringModifiers:@"h"
1486 isARepeat:NO
1487 keyCode:0x4];
1488
1489 // Plugin should mark the event as key equivalent.
1490 [plugin performKeyEquivalent:event];
1491
1492 // Simulate KeyboardManager sending unhandled event to plugin. This must return
1493 // true because it is a known editing command.
1494 if ([plugin handleKeyEvent:event] != true) {
1495 return false;
1496 }
1497
1498 // CMD+W
1499 event = [NSEvent keyEventWithType:NSEventTypeKeyDown
1500 location:NSZeroPoint
1501 modifierFlags:0x100108
1502 timestamp:0
1503 windowNumber:0
1504 context:nil
1505 characters:@"w"
1506 charactersIgnoringModifiers:@"w"
1507 isARepeat:NO
1508 keyCode:0x13];
1509
1510 // Plugin should mark the event as key equivalent.
1511 [plugin performKeyEquivalent:event];
1512
1513 // This is not a valid editing command, plugin must return false so that
1514 // KeyboardManager sends the event to next responder.
1515 if ([plugin handleKeyEvent:event] != false) {
1516 return false;
1517 }
1518
1519 return true;
1520}

The documentation for this class was generated from the following file: