@@ -226,7 +226,7 @@ - (void)testTextChangesTriggerUpdateEditingClient {
226226 XCTAssertFalse ([inputView setTextInputState: @{@" text" : @" AFTER" }]);
227227}
228228
229- - (void )testSelectionChangeTriggersUpdateEditingClient {
229+ - (void )testSelectionChangeDoesNotTriggerUpdateEditingClient {
230230 FlutterTextInputView* inputView = [[FlutterTextInputView alloc ] init ];
231231 inputView.textInputDelegate = engine;
232232
@@ -236,23 +236,23 @@ - (void)testSelectionChangeTriggersUpdateEditingClient {
236236
237237 BOOL shouldUpdate = [inputView
238238 setTextInputState: @{@" text" : @" SELECTION" , @" selectionBase" : @0 , @" selectionExtent" : @3 }];
239- XCTAssertTrue (shouldUpdate);
239+ XCTAssertFalse (shouldUpdate);
240240
241241 shouldUpdate = [inputView
242242 setTextInputState: @{@" text" : @" SELECTION" , @" selectionBase" : @1 , @" selectionExtent" : @3 }];
243- XCTAssertTrue (shouldUpdate);
243+ XCTAssertFalse (shouldUpdate);
244244
245245 shouldUpdate = [inputView
246246 setTextInputState: @{@" text" : @" SELECTION" , @" selectionBase" : @1 , @" selectionExtent" : @2 }];
247- XCTAssertTrue (shouldUpdate);
247+ XCTAssertFalse (shouldUpdate);
248248
249249 // Don't send anything if there's nothing new.
250250 shouldUpdate = [inputView
251251 setTextInputState: @{@" text" : @" SELECTION" , @" selectionBase" : @1 , @" selectionExtent" : @2 }];
252252 XCTAssertFalse (shouldUpdate);
253253}
254254
255- - (void )testComposingChangeTriggersUpdateEditingClient {
255+ - (void )testComposingChangeDoesNotTriggerUpdateEditingClient {
256256 FlutterTextInputView* inputView = [[FlutterTextInputView alloc ] init ];
257257 inputView.textInputDelegate = engine;
258258
@@ -263,22 +263,44 @@ - (void)testComposingChangeTriggersUpdateEditingClient {
263263
264264 BOOL shouldUpdate = [inputView
265265 setTextInputState: @{@" text" : @" COMPOSING" , @" composingBase" : @0 , @" composingExtent" : @3 }];
266- XCTAssertTrue (shouldUpdate);
266+ XCTAssertFalse (shouldUpdate);
267267
268268 shouldUpdate = [inputView
269269 setTextInputState: @{@" text" : @" COMPOSING" , @" composingBase" : @1 , @" composingExtent" : @3 }];
270- XCTAssertTrue (shouldUpdate);
270+ XCTAssertFalse (shouldUpdate);
271271
272272 shouldUpdate = [inputView
273273 setTextInputState: @{@" text" : @" COMPOSING" , @" composingBase" : @1 , @" composingExtent" : @2 }];
274- XCTAssertTrue (shouldUpdate);
274+ XCTAssertFalse (shouldUpdate);
275275
276- // Don't send anything if there's nothing new.
277276 shouldUpdate = [inputView
278277 setTextInputState: @{@" text" : @" COMPOSING" , @" composingBase" : @1 , @" composingExtent" : @2 }];
279278 XCTAssertFalse (shouldUpdate);
280279}
281280
281+ - (void )testUITextInputAvoidUnnecessaryUndateEditingClientCalls {
282+ FlutterTextInputView* inputView = [[FlutterTextInputView alloc ] init ];
283+ inputView.textInputDelegate = engine;
284+
285+ __block int updateCount = 0 ;
286+ OCMStub ([engine updateEditingClient: 0 withState: [OCMArg isNotNil ]])
287+ .andDo (^(NSInvocation * invocation) {
288+ updateCount++;
289+ });
290+
291+ [inputView unmarkText ];
292+ // updateEditingClient shouldn't fire as the text is already unmarked.
293+ XCTAssertEqual (updateCount, 0 );
294+
295+ [inputView setMarkedText: @" marked text" selectedRange: NSMakeRange (0 , 1 )];
296+ // updateEditingClient fires in response to setMarkedText.
297+ XCTAssertEqual (updateCount, 1 );
298+
299+ [inputView unmarkText ];
300+ // updateEditingClient fires in response to unmarkText.
301+ XCTAssertEqual (updateCount, 2 );
302+ }
303+
282304- (void )testUpdateEditingClientNegativeSelection {
283305 FlutterTextInputView* inputView = [[FlutterTextInputView alloc ] init ];
284306 inputView.textInputDelegate = engine;
0 commit comments