diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index ef718a216eb33..e992fa9ebbe09 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1665,9 +1665,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterRestora FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterSemanticsScrollView.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterSemanticsScrollView.mm -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.mm -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPluginTest.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index b70bf32632c3c..bfcbaab7fe293 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -79,8 +79,6 @@ source_set("flutter_framework_source") { "framework/Source/FlutterRestorationPlugin.mm", "framework/Source/FlutterSemanticsScrollView.h", "framework/Source/FlutterSemanticsScrollView.mm", - "framework/Source/FlutterSpellCheckPlugin.h", - "framework/Source/FlutterSpellCheckPlugin.mm", "framework/Source/FlutterTextInputDelegate.h", "framework/Source/FlutterTextInputPlugin.h", "framework/Source/FlutterTextInputPlugin.mm", @@ -266,7 +264,6 @@ shared_library("ios_test_flutter") { "framework/Source/FlutterKeyboardManagerTest.mm", "framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm", "framework/Source/FlutterRestorationPluginTest.mm", - "framework/Source/FlutterSpellCheckPluginTest.mm", "framework/Source/FlutterTextInputPluginTest.mm", "framework/Source/FlutterUndoManagerPluginTest.mm", "framework/Source/FlutterViewControllerTest.mm", diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index ecb6ba4be660a..e70a8a235ef98 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -24,7 +24,6 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterIndirectScribbleDelegate.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerDelegate.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPlugin.h" @@ -112,7 +111,6 @@ @implementation FlutterEngine { fml::scoped_nsobject _platformPlugin; fml::scoped_nsobject _textInputPlugin; fml::scoped_nsobject _undoManagerPlugin; - fml::scoped_nsobject _spellCheckPlugin; fml::scoped_nsobject _restorationPlugin; fml::scoped_nsobject _localizationChannel; fml::scoped_nsobject _navigationChannel; @@ -121,7 +119,6 @@ @implementation FlutterEngine { fml::scoped_nsobject _platformViewsChannel; fml::scoped_nsobject _textInputChannel; fml::scoped_nsobject _undoManagerChannel; - fml::scoped_nsobject _spellCheckChannel; fml::scoped_nsobject _lifecycleChannel; fml::scoped_nsobject _systemChannel; fml::scoped_nsobject _settingsChannel; @@ -467,9 +464,6 @@ - (FlutterMethodChannel*)textInputChannel { - (FlutterMethodChannel*)undoManagerChannel { return _undoManagerChannel.get(); } -- (FlutterMethodChannel*)spellCheckChannel { - return _spellCheckChannel.get(); -} - (FlutterBasicMessageChannel*)lifecycleChannel { return _lifecycleChannel.get(); } @@ -499,7 +493,6 @@ - (void)resetChannels { _systemChannel.reset(); _settingsChannel.reset(); _keyEventChannel.reset(); - _spellCheckChannel.reset(); } - (void)startProfiler { @@ -568,11 +561,6 @@ - (void)setupChannels { binaryMessenger:self.binaryMessenger codec:[FlutterJSONMethodCodec sharedInstance]]); - _spellCheckChannel.reset([[FlutterMethodChannel alloc] - initWithName:@"flutter/spellcheck" - binaryMessenger:self.binaryMessenger - codec:[FlutterJSONMethodCodec sharedInstance]]); - _lifecycleChannel.reset([[FlutterBasicMessageChannel alloc] initWithName:@"flutter/lifecycle" binaryMessenger:self.binaryMessenger @@ -607,8 +595,6 @@ - (void)setupChannels { _restorationPlugin.reset([[FlutterRestorationPlugin alloc] initWithChannel:_restorationChannel.get() restorationEnabled:_restorationEnabled]); - _spellCheckPlugin.reset( - [[FlutterSpellCheckPlugin alloc] initWithMethodChannel:_spellCheckChannel.get()]); } - (void)maybeSetupPlatformViewChannels { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h deleted file mode 100644 index 2536d6a5de713..0000000000000 --- a/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERSPELLCHECKPLUGIN_H_ -#define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERSPELLCHECKPLUGIN_H_ - -#include "flutter/fml/memory/weak_ptr.h" - -#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" -#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h" - -@interface FlutterSpellCheckPlugin : NSObject -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; -- (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel - NS_DESIGNATED_INITIALIZER; - -@end - -@interface FlutterSpellCheckResult : NSObject - -@property(nonatomic, copy, readonly) NSArray* suggestions; -@property(nonatomic, assign, readonly) NSRange misspelledRange; - -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; -- (instancetype)initWithMisspelledRange:(NSRange)range - suggestions:(NSArray*)suggestions NS_DESIGNATED_INITIALIZER; -- (NSDictionary*)toDictionary; - -@end - -#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERSPELLCHECKPLUGIN_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.mm deleted file mode 100644 index de4ef81fa1283..0000000000000 --- a/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.mm +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h" - -#import -#import - -#import "flutter/fml/logging.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" - -// Method Channel name to start spell check. -static NSString* const kInitiateSpellCheck = @"SpellCheck.initiateSpellCheck"; - -@interface FlutterSpellCheckPlugin () - -@property(nonatomic, assign) FlutterMethodChannel* methodChannel; -@property(nonatomic, retain) UITextChecker* textChecker; - -@end - -@implementation FlutterSpellCheckPlugin - -- (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel { - self = [super init]; - if (self) { - [_methodChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { - if (!self) { - return; - } - [self handleMethodCall:call result:result]; - }]; - _textChecker = [[UITextChecker alloc] init]; - } - return self; -} - -- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - NSString* method = call.method; - NSArray* args = call.arguments; - if ([method isEqualToString:kInitiateSpellCheck]) { - FML_DCHECK(args.count == 2); - id language = args[0]; - id text = args[1]; - if (language == [NSNull null] || text == [NSNull null]) { - // Bail if null arguments are passed from dart. - result(nil); - return; - } - - NSArray*>* spellCheckResult = - [self findAllSpellCheckSuggestionsForText:text inLanguage:language]; - result(spellCheckResult); - } -} - -// Get all the misspelled words and suggestions in the entire String. -// -// The result will be formatted as am NSArray. -// Each item of the array is a representation of a misspelled word and suggestions. -// The format of each item looks like this: -// { -// @"location": 0, -// @"length" : 5, -// @"suggestions": [@"suggestion1", @"suggestion2"..] -// } -// -// Returns nil if the language is invalid. -// Returns an empty array if no spell check suggestions. -- (NSArray*>*)findAllSpellCheckSuggestionsForText:(NSString*)text - inLanguage:(NSString*)language { - if (![UITextChecker.availableLanguages containsObject:language]) { - return nil; - } - - NSMutableArray* allSpellSuggestions = [[NSMutableArray alloc] init]; - - FlutterSpellCheckResult* nextSpellSuggestion; - NSUInteger nextOffset = 0; - do { - nextSpellSuggestion = [self findSpellCheckSuggestionsForText:text - inLanguage:language - startingOffset:nextOffset]; - if (nextSpellSuggestion != nil) { - [allSpellSuggestions addObject:nextSpellSuggestion]; - nextOffset = - nextSpellSuggestion.misspelledRange.location + nextSpellSuggestion.misspelledRange.length; - } - } while (nextSpellSuggestion != nil && nextOffset < text.length); - - NSMutableArray* methodChannelResult = [[[NSMutableArray alloc] init] autorelease]; - - for (FlutterSpellCheckResult* result in allSpellSuggestions) { - [methodChannelResult addObject:[result toDictionary]]; - } - - [allSpellSuggestions release]; - return methodChannelResult; -} - -// Get the misspelled word and suggestions. -// -// Returns nil if no spell check suggestions. -- (FlutterSpellCheckResult*)findSpellCheckSuggestionsForText:(NSString*)text - inLanguage:(NSString*)language - startingOffset:(NSInteger)startingOffset { - FML_DCHECK([UITextChecker.availableLanguages containsObject:language]); - NSRange misspelledRange = - [self.textChecker rangeOfMisspelledWordInString:text - range:NSMakeRange(0, text.length) - startingAt:startingOffset - wrap:NO - language:language]; - if (misspelledRange.location == NSNotFound) { - // No misspelled word found - return nil; - } - - // If no possible guesses, the API returns an empty array: - // https://developer.apple.com/documentation/uikit/uitextchecker/1621037-guessesforwordrange?language=objc - NSArray* suggestions = [self.textChecker guessesForWordRange:misspelledRange - inString:text - language:language]; - FlutterSpellCheckResult* result = - [[[FlutterSpellCheckResult alloc] initWithMisspelledRange:misspelledRange - suggestions:suggestions] autorelease]; - return result; -} - -- (UITextChecker*)textChecker { - return _textChecker; -} - -- (void)dealloc { - [_textChecker release]; - [super dealloc]; -} - -@end - -@implementation FlutterSpellCheckResult - -- (instancetype)initWithMisspelledRange:(NSRange)range - suggestions:(NSArray*)suggestions { - self = [super init]; - if (self) { - _suggestions = [suggestions copy]; - _misspelledRange = range; - } - return self; -} - -- (NSDictionary*)toDictionary { - NSMutableDictionary* result = [[[NSMutableDictionary alloc] initWithCapacity:3] autorelease]; - result[@"location"] = @(_misspelledRange.location); - result[@"length"] = @(_misspelledRange.length); - result[@"suggestions"] = [[_suggestions copy] autorelease]; - return result; -} - -- (void)dealloc { - [_suggestions release]; - [super dealloc]; -} - -@end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPluginTest.mm deleted file mode 100644 index a17b60b733005..0000000000000 --- a/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPluginTest.mm +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h" - -#import -#import - -#pragma mark - - -// A mock class representing the UITextChecker used in the tests. -// -// Because OCMock doesn't support mocking NSRange as method arguments, -// this is necessary. -@interface MockTextChecker : UITextChecker - -// The range of misspelled word based on the startingIndex. -// -// Key is the starting index, value is the range -@property(strong, nonatomic) NSMutableDictionary* startingIndexToRange; - -// The suggestions of misspelled word based on the starting index of the misspelled word. -// -// Key is a string representing the range of the misspelled word, value is the suggestions. -@property(strong, nonatomic) - NSMutableDictionary*>* rangeToSuggestions; - -// Mock the spell checking results. -// -// When no misspelled word should be detected, pass (NSNotFound, 0) for the `range` parameter, and -// an empty array for `suggestions`. -// -// Call `reset` to remove all the mocks. -- (void)mockResultRange:(NSRange)range - suggestions:(nonnull NSArray*)suggestions - withStartingIndex:(NSInteger)startingIndex; - -// Remove all mocks. -- (void)reset; - -@end - -@implementation MockTextChecker - -- (instancetype)init { - self = [super init]; - if (self) { - _startingIndexToRange = [[NSMutableDictionary alloc] init]; - _rangeToSuggestions = [[NSMutableDictionary alloc] init]; - } - return self; -} - -- (void)mockResultRange:(NSRange)range - suggestions:(NSArray*)suggestions - withStartingIndex:(NSInteger)startingIndex { - NSValue* valueForRange = [NSValue valueWithRange:range]; - self.startingIndexToRange[@(startingIndex)] = valueForRange; - NSString* rangeString = NSStringFromRange(valueForRange.rangeValue); - self.rangeToSuggestions[rangeString] = suggestions; -} - -- (void)reset { - [self.startingIndexToRange removeAllObjects]; - [self.rangeToSuggestions removeAllObjects]; -} - -#pragma mark UITextChecker Overrides - -- (NSRange)rangeOfMisspelledWordInString:(NSString*)stringToCheck - range:(NSRange)range - startingAt:(NSInteger)startingOffset - wrap:(BOOL)wrapFlag - language:(NSString*)language { - return self.startingIndexToRange[@(startingOffset)].rangeValue; -} - -- (NSArray*)guessesForWordRange:(NSRange)range - inString:(NSString*)string - language:(NSString*)language { - return self.rangeToSuggestions[NSStringFromRange(range)]; -} - -@end - -@interface FlutterSpellCheckPlugin () -- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result; -- (UITextChecker*)textChecker; -@end - -@interface FlutterSpellCheckPluginTest : XCTestCase - -@property(strong, nonatomic) id mockMethodChannel; -@property(strong, nonatomic) FlutterSpellCheckPlugin* plugin; -@property(strong, nonatomic) id mockTextChecker; -@property(strong, nonatomic) id partialMockPlugin; - -@end - -#pragma mark - - -@implementation FlutterSpellCheckPluginTest - -- (void)setUp { - [super setUp]; - self.mockMethodChannel = OCMClassMock([FlutterMethodChannel class]); - self.plugin = [[FlutterSpellCheckPlugin alloc] initWithMethodChannel:self.mockMethodChannel]; - __weak FlutterSpellCheckPlugin* weakPlugin = self.plugin; - OCMStub([self.mockMethodChannel invokeMethod:[OCMArg any] - arguments:[OCMArg any] - result:[OCMArg any]]) - .andDo(^(NSInvocation* invocation) { - NSString* name; - id args; - FlutterResult result; - [invocation getArgument:&name atIndex:2]; - [invocation getArgument:&args atIndex:3]; - [invocation getArgument:&result atIndex:4]; - FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:name - arguments:args]; - [weakPlugin handleMethodCall:methodCall result:result]; - }); - self.mockTextChecker = [[MockTextChecker alloc] init]; - self.partialMockPlugin = OCMPartialMock(self.plugin); - OCMStub([self.partialMockPlugin textChecker]).andReturn(self.mockTextChecker); -} - -- (void)tearDown { - self.plugin = nil; - [super tearDown]; -} - -#pragma mark - Tests - -// Test to make sure the while loop that checks all the misspelled word stops when the a -// `NSNotFound` is found. -- (void)testFindAllSpellCheckSuggestionsForText { - id textCheckerClassMock = OCMClassMock([UITextChecker class]); - [[[textCheckerClassMock stub] andReturn:@[ @"en" ]] availableLanguages]; - NSArray* suggestions1 = @[ @"suggestion 1", @"suggestion 2" ]; - NSArray* suggestions2 = @[ @"suggestion 3", @"suggestion 4" ]; - // 0-4 is a misspelled word. - [self mockUITextCheckerWithExpectedMisspelledWordRange:NSMakeRange(0, 5) - startingIndex:0 - suggestions:suggestions1]; - // 5-9 is a misspelled word. - [self mockUITextCheckerWithExpectedMisspelledWordRange:NSMakeRange(5, 5) - startingIndex:5 - suggestions:suggestions2]; - // No misspelled word after index 10. - [self mockUITextCheckerWithExpectedMisspelledWordRange:NSMakeRange(NSNotFound, 0) - startingIndex:10 - suggestions:@[]]; - __block NSArray* capturedResult; - [self.mockMethodChannel invokeMethod:@"SpellCheck.initiateSpellCheck" - arguments:@[ @"en", @"ksajlkdf aslkdfl kasdf asdfjk" ] - result:^(id _Nullable result) { - capturedResult = result; - }]; - XCTAssertTrue(capturedResult.count == 2); - XCTAssertEqualObjects(capturedResult.firstObject[@"location"], @0); - XCTAssertEqualObjects(capturedResult.firstObject[@"length"], @5); - XCTAssertEqualObjects(capturedResult.firstObject[@"suggestions"], suggestions1); - XCTAssertEqualObjects(capturedResult[1][@"location"], @5); - XCTAssertEqualObjects(capturedResult[1][@"length"], @5); - XCTAssertEqualObjects(capturedResult[1][@"suggestions"], suggestions2); - [self.mockTextChecker reset]; - [textCheckerClassMock stopMocking]; -} - -// Test to make sure while loop that checks all the misspelled word stops when the last word is -// misspelled (aka nextIndex is out of bounds) -- (void)testStopFindingMoreWhenTheLastWordIsMisspelled { - id textCheckerClassMock = OCMClassMock([UITextChecker class]); - [[[textCheckerClassMock stub] andReturn:@[ @"en" ]] availableLanguages]; - NSArray* suggestions1 = @[ @"suggestion 1", @"suggestion 2" ]; - NSArray* suggestions2 = @[ @"suggestion 3", @"suggestion 4" ]; - // 0-4 is a misspelled word. - [self mockUITextCheckerWithExpectedMisspelledWordRange:NSMakeRange(0, 5) - startingIndex:0 - suggestions:suggestions1]; - // 5-9 is a misspelled word. - [self mockUITextCheckerWithExpectedMisspelledWordRange:NSMakeRange(6, 4) - startingIndex:5 - suggestions:suggestions2]; - - __block NSArray* capturedResult; - [self.mockMethodChannel invokeMethod:@"SpellCheck.initiateSpellCheck" - arguments:@[ @"en", @"hejjo abcd" ] - result:^(id _Nullable result) { - capturedResult = result; - }]; - XCTAssertTrue(capturedResult.count == 2); - XCTAssertEqualObjects(capturedResult.firstObject[@"location"], @0); - XCTAssertEqualObjects(capturedResult.firstObject[@"length"], @5); - XCTAssertEqualObjects(capturedResult.firstObject[@"suggestions"], suggestions1); - XCTAssertEqualObjects(capturedResult[1][@"location"], @6); - XCTAssertEqualObjects(capturedResult[1][@"length"], @4); - XCTAssertEqualObjects(capturedResult[1][@"suggestions"], suggestions2); - [self.mockTextChecker reset]; - [textCheckerClassMock stopMocking]; -} - -- (void)testStopFindingMoreWhenTheWholeStringIsAMisspelledWord { - id textCheckerClassMock = OCMClassMock([UITextChecker class]); - [[[textCheckerClassMock stub] andReturn:@[ @"en" ]] availableLanguages]; - NSArray* suggestions1 = @[ @"suggestion 1", @"suggestion 2" ]; - // 0-4 is a misspelled word. - [self mockUITextCheckerWithExpectedMisspelledWordRange:NSMakeRange(0, 5) - startingIndex:0 - suggestions:suggestions1]; - - __block NSArray* capturedResult; - [self.mockMethodChannel invokeMethod:@"SpellCheck.initiateSpellCheck" - arguments:@[ @"en", @"hejjo" ] - result:^(id _Nullable result) { - capturedResult = result; - }]; - XCTAssertTrue(capturedResult.count == 1); - XCTAssertEqualObjects(capturedResult.firstObject[@"location"], @0); - XCTAssertEqualObjects(capturedResult.firstObject[@"length"], @5); - XCTAssertEqualObjects(capturedResult.firstObject[@"suggestions"], suggestions1); - [self.mockTextChecker reset]; - [textCheckerClassMock stopMocking]; -} - -- (void)testInitiateSpellCheckWithNoMisspelledWord { - id textCheckerClassMock = OCMClassMock([UITextChecker class]); - [[[textCheckerClassMock stub] andReturn:@[ @"en" ]] availableLanguages]; - [self mockUITextCheckerWithExpectedMisspelledWordRange:NSMakeRange(NSNotFound, 0) - startingIndex:0 - suggestions:@[]]; - __block id capturedResult; - [self.mockMethodChannel invokeMethod:@"SpellCheck.initiateSpellCheck" - arguments:@[ @"en", @"helloo" ] - result:^(id _Nullable result) { - capturedResult = result; - }]; - XCTAssertEqualObjects(capturedResult, @[]); - [textCheckerClassMock stopMocking]; -} - -- (void)testUnsupportedLanguageShouldReturnNil { - id textCheckerClassMock = OCMClassMock([UITextChecker class]); - [[[textCheckerClassMock stub] andReturn:@[ @"en" ]] availableLanguages]; - [self mockUITextCheckerWithExpectedMisspelledWordRange:NSMakeRange(0, 5) - startingIndex:0 - suggestions:@[]]; - __block id capturedResult; - [self.mockMethodChannel invokeMethod:@"SpellCheck.initiateSpellCheck" - arguments:@[ @"xx", @"helloo" ] - result:^(id _Nullable result) { - capturedResult = result; - }]; - XCTAssertNil(capturedResult); - [textCheckerClassMock stopMocking]; -} - -- (void)testEmptyStringShouldReturnEmptyResults { - // Use real UITextChecker for this as we want to rely on the actual behavior of UITextChecker - // to ensure that spell checks on an empty result always return empty. - [self.partialMockPlugin stopMocking]; - - id textCheckerClassMock = OCMClassMock([UITextChecker class]); - [[[textCheckerClassMock stub] andReturn:@[ @"en" ]] availableLanguages]; - __block id capturedResult; - [self.mockMethodChannel invokeMethod:@"SpellCheck.initiateSpellCheck" - arguments:@[ @"en", @"" ] - result:^(id _Nullable result) { - capturedResult = result; - }]; - XCTAssertEqualObjects(capturedResult, @[]); - [textCheckerClassMock stopMocking]; -} - -- (void)testNullStringArgumentShouldReturnNilResults { - id textCheckerClassMock = OCMClassMock([UITextChecker class]); - [[[textCheckerClassMock stub] andReturn:@[ @"en" ]] availableLanguages]; - __block id capturedResult; - [self.mockMethodChannel invokeMethod:@"SpellCheck.initiateSpellCheck" - arguments:@[ @"en", [NSNull null] ] - result:^(id _Nullable result) { - capturedResult = result; - }]; - XCTAssertNil(capturedResult); - [textCheckerClassMock stopMocking]; -} - -- (void)testNullLanguageArgumentShouldReturnNilResults { - id textCheckerClassMock = OCMClassMock([UITextChecker class]); - [[[textCheckerClassMock stub] andReturn:@[ @"en" ]] availableLanguages]; - __block id capturedResult; - [self.mockMethodChannel invokeMethod:@"SpellCheck.initiateSpellCheck" - arguments:@[ [NSNull null], @"some string" ] - result:^(id _Nullable result) { - capturedResult = result; - }]; - XCTAssertNil(capturedResult); - [textCheckerClassMock stopMocking]; -} - -- (void)mockUITextCheckerWithExpectedMisspelledWordRange:(NSRange)expectedRange - startingIndex:(NSInteger)startingIndex - suggestions:(NSArray*)suggestions { - [self.mockTextChecker mockResultRange:expectedRange - suggestions:suggestions - withStartingIndex:startingIndex]; -} - -@end diff --git a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj index 3632c55063a94..d2f9e6ee03f93 100644 --- a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj +++ b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj @@ -69,7 +69,6 @@ 0D6AB6C922BB05E200EEE540 /* IosUnitTestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IosUnitTestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 0D6AB6CF22BB05E200EEE540 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 0D6AB73E22BD8F0200EEE540 /* FlutterEngineConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = FlutterEngineConfig.xcconfig; sourceTree = ""; }; - 689EC1E2281B30D3008FEB58 /* FlutterSpellCheckPluginTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterSpellCheckPluginTest.mm; sourceTree = ""; }; 68B6091227F62F990036AC78 /* VsyncWaiterIosTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = VsyncWaiterIosTest.mm; sourceTree = ""; }; 3DD7D38C27D2B81000DA365C /* FlutterUndoManagerPluginTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterUndoManagerPluginTest.mm; sourceTree = ""; }; F7521D7226BB671E005F15C5 /* libios_test_flutter.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libios_test_flutter.dylib; path = "../../../../out/$(FLUTTER_ENGINE)/libios_test_flutter.dylib"; sourceTree = ""; }; @@ -99,7 +98,6 @@ 0AC232E924BA71D300A85907 /* Source */ = { isa = PBXGroup; children = ( - 689EC1E2281B30D3008FEB58 /* FlutterSpellCheckPluginTest.mm */, 68B6091227F62F990036AC78 /* VsyncWaiterIosTest.mm */, 3DD7D38C27D2B81000DA365C /* FlutterUndoManagerPluginTest.mm */, F7A3FDE026B9E0A300EADD61 /* FlutterAppDelegateTest.mm */,