Call setEditingState when text changes.#47177
Conversation
| _obscureLatestCharIndex = _value.selection.baseOffset; | ||
| } | ||
| } | ||
| _lastKnownRemoteTextEditingValue = value; |
There was a problem hiding this comment.
This is the key piece here - we update this value in the call path of _formatAndSetValue anyway, and if we update it here, a later check that compares the value being passed with _lastKnownRemoteTextEditingValue always returns true.
This is just too early to set the value -we haven't actually notified the remote side yet.
| 'TextInput.setEditingState', | ||
| 'TextInput.setEditingState', | ||
| 'TextInput.show', | ||
| 'TextInput.setEditingState', |
There was a problem hiding this comment.
This line is the key part of this test - without the change, we don't get the last setEditingState, which contains the value ....
| import 'package:flutter/services.dart'; | ||
| import 'package:flutter_test/flutter_test.dart'; | ||
| import 'package:flutter/foundation.dart'; | ||
| import 'package:pedantic/pedantic.dart'; |
There was a problem hiding this comment.
@jonahwilliams is this ok? It's for unawaited.
There was a problem hiding this comment.
This would introduce a new (direct) dependency on package:pedantic. I don't think we want that.
There was a problem hiding this comment.
Removing this, but FWIW it looks like we directly depend on it elsewhere (although our pubspec doesn't indicate that).
| // Someone could have unregistered us by calling | ||
| // `SystemChannels.textInput.setMockMethodCallHandler` in the test. Actually | ||
| // check if we're registered by calling the method, which should work | ||
| // immediately if we are registered since that method does no real async work. | ||
| bool get isRegistered { | ||
| final int oldLogLength = log.length; | ||
| unawaited(SystemChannels.textInput.invokeMethod<void>('__isRegistered')); | ||
| if (log.length == oldLogLength) { | ||
| return false; | ||
| } | ||
| log.removeLast(); | ||
| return true; | ||
| } |
There was a problem hiding this comment.
I can move this to a separate PR if that works better - it's not needed for this issue.
| import 'package:flutter/services.dart'; | ||
| import 'package:flutter_test/flutter_test.dart'; | ||
| import 'package:flutter/foundation.dart'; | ||
| import 'package:pedantic/pedantic.dart'; |
There was a problem hiding this comment.
This would introduce a new (direct) dependency on package:pedantic. I don't think we want that.
| // immediately if we are registered since that method does no real async work. | ||
| bool get isRegistered { | ||
| final int oldLogLength = log.length; | ||
| unawaited(SystemChannels.textInput.invokeMethod<void>('__isRegistered')); |
There was a problem hiding this comment.
This may have unintended side effects if somebody else is currently registered and receives this, no?
There was a problem hiding this comment.
Hmm. Yes. I'm going to back this change out, don't need it for this PR, - will file an issue about it.
| _obscureLatestCharIndex = _value.selection.baseOffset; | ||
| } | ||
| } | ||
| _lastKnownRemoteTextEditingValue = value; |
| return binding.runTest( | ||
| () async { | ||
| debugResetSemanticsIdCounter(); | ||
| tester.testTextInput.register(); |
There was a problem hiding this comment.
Should there maybe be a convenience method and tester (or testTextInput) to reset everything that does both of this?
There was a problem hiding this comment.
I wonder if this is the right place to reset these things, it feels odd here.
There was a problem hiding this comment.
I tried doing it before the binding.runTest and that didn't work. FWIW, this is where we reset the semantics ID counter as well so...
I'll move these to a convenience method.
|
Fixing the test API is breaking one other test, which, IMO is buggy. I'm going to spit out the package:flutter_test changes into a separate PR so we can do a proper breaking change/migration guide for it (and not have to roll this back if it breaks something internally). |
|
No, it's my actual code change in the framework causing the test breakage. Investigating why, but it looks like this may be a breaking change. |
|
This is breaking whether or not I fix the issue in the tester. If I fix the tester issue, it's breaking because the existing test relied on dirty state from the previous test. If I avoid fixing the tester issue, it's still breaking because the existing test now gets different dirty state from the previous test. |
|
Created flutter/website#3430 for migration. |
|
Migration guide has landed. Going ot land this on green. |
…" (flutter#47397)" This reverts commit d51956a.
Description
The removed line prevents us from mutating the tracking variable too early (it gets mutated by a later function anyway, but mutating it this early means we don't end up notifying the engine side of changes). This wasn't a problem before because the engine stayed running when the app was backgrounded, which meant the state was never really lost. Now that the engine detaches, we lose the state and need to have it to send it up again.
This results in #47137.
I also found that some tests were mutating global state, so I updated those, and I updated the
testerharness to reset some global state between tests to make it more useful (this is now asserted by those tests). I also noticed thatisRegisteredwas not trustworthy because of this global state it's connected to, so I tried to make it work better.Related Issues
fixes #47137
Tests
I added the following tests:
Assert the expected textInput method call is made (setEditingState) after mutating the text.
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]). This will ensure a smooth and quick review process.///).flutter analyze --flutter-repo) does not report any problems on my PR.Breaking Change
Did any tests fail when you ran them? Please read Handling breaking changes.