Added equals and hashCode for TextInputConfiguration and AutofillConfiguration (#162238)

- Added equals and hashCode for `TextInputConfiguration` and
`AutofillConfiguration` (fixed
https://github.com/flutter/flutter/issues/139033)
- Fixed copyWith method in `TextInputConfiguration` (fixed
https://github.com/flutter/flutter/issues/162236)
- Added some tests 

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->

*List which issues are fixed by this PR. You must list at least one
issue. An issue is not required if the PR fixes something trivial like a
typo.*

*If you had to change anything in the [flutter/tests] repo, include a
link to the migration guide as per the [breaking change policy].*

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

---------

Co-authored-by: Bruno Leroux <bruno.leroux@gmail.com>
This commit is contained in:
Paulik8 2025-02-05 22:46:56 +01:00 committed by GitHub
parent 211d83d772
commit ce6817b0a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 403 additions and 0 deletions

View File

@ -737,6 +737,45 @@ class AutofillConfiguration {
}
: null;
}
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
return other is AutofillConfiguration &&
other.enabled == enabled &&
other.uniqueIdentifier == uniqueIdentifier &&
listEquals(other.autofillHints, autofillHints) &&
other.currentEditingValue == currentEditingValue &&
other.hintText == hintText;
}
@override
int get hashCode {
return Object.hash(
enabled,
uniqueIdentifier,
Object.hashAll(autofillHints),
currentEditingValue,
hintText,
);
}
@override
String toString() {
final List<String> description = <String>[
'enabled: $enabled',
'uniqueIdentifier: $uniqueIdentifier',
'autofillHints: $autofillHints',
'currentEditingValue: $currentEditingValue',
if (hintText != null) 'hintText: $hintText',
];
return 'AutofillConfiguration(${description.join(', ')})';
}
}
/// An object that represents an autofillable input field in the autofill workflow.

View File

@ -44,6 +44,7 @@ export 'package:vector_math/vector_math_64.dart' show Matrix4;
export 'autofill.dart' show AutofillConfiguration, AutofillScope;
export 'text_editing.dart' show TextSelection;
// TODO(a14n): the following export leads to Segmentation fault, see https://github.com/flutter/flutter/issues/106332
// export 'text_editing_delta.dart' show TextEditingDelta;
@ -713,6 +714,7 @@ class TextInputConfiguration {
smartQuotesType: smartQuotesType ?? this.smartQuotesType,
enableSuggestions: enableSuggestions ?? this.enableSuggestions,
enableInteractiveSelection: enableInteractiveSelection ?? this.enableInteractiveSelection,
actionLabel: actionLabel ?? this.actionLabel,
inputAction: inputAction ?? this.inputAction,
textCapitalization: textCapitalization ?? this.textCapitalization,
keyboardAppearance: keyboardAppearance ?? this.keyboardAppearance,
@ -772,6 +774,81 @@ class TextInputConfiguration {
'enableDeltaModel': enableDeltaModel,
};
}
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
return other is TextInputConfiguration &&
other.viewId == viewId &&
other.inputType == inputType &&
other.readOnly == readOnly &&
other.obscureText == obscureText &&
other.autocorrect == autocorrect &&
other.smartDashesType == smartDashesType &&
other.smartQuotesType == smartQuotesType &&
other.enableSuggestions == enableSuggestions &&
other.enableInteractiveSelection == enableInteractiveSelection &&
other.actionLabel == actionLabel &&
other.inputAction == inputAction &&
other.keyboardAppearance == keyboardAppearance &&
other.textCapitalization == textCapitalization &&
other.autofillConfiguration == autofillConfiguration &&
other.enableIMEPersonalizedLearning == enableIMEPersonalizedLearning &&
listEquals(other.allowedMimeTypes, allowedMimeTypes) &&
other.enableDeltaModel == enableDeltaModel;
}
@override
int get hashCode {
return Object.hash(
viewId,
inputType,
readOnly,
obscureText,
autocorrect,
smartDashesType,
smartQuotesType,
enableSuggestions,
enableInteractiveSelection,
actionLabel,
inputAction,
keyboardAppearance,
textCapitalization,
autofillConfiguration,
enableIMEPersonalizedLearning,
Object.hashAll(allowedMimeTypes),
enableDeltaModel,
);
}
@override
String toString() {
final List<String> description = <String>[
if (viewId != null) 'viewId: $viewId',
'inputType: $inputType',
'readOnly: $readOnly',
'obscureText: $obscureText',
'autocorrect: $autocorrect',
'smartDashesType: $smartDashesType',
'smartQuotesType: $smartQuotesType',
'enableSuggestions: $enableSuggestions',
'enableInteractiveSelection: $enableInteractiveSelection',
if (actionLabel != null) 'actionLabel: $actionLabel',
'inputAction: $inputAction',
'keyboardAppearance: $keyboardAppearance',
'textCapitalization: $textCapitalization',
'autofillConfiguration: $autofillConfiguration',
'enableIMEPersonalizedLearning: $enableIMEPersonalizedLearning',
'allowedMimeTypes: $allowedMimeTypes',
'enableDeltaModel: $enableDeltaModel',
];
return 'TextInputConfiguration(${description.join(', ')})';
}
}
TextAffinity? _toTextAffinity(String? affinity) {

View File

@ -95,6 +95,74 @@ void main() {
},
);
});
group('AutoFillConfiguration', () {
late AutofillConfiguration fakeAutoFillConfiguration;
late AutofillConfiguration fakeAutoFillConfiguration2;
setUp(() {
// If you create two objects with `const` with the same values, the second object will be equal to the first one by reference.
// This means that even without overriding the `equals` method, the test will pass.
// ignore: prefer_const_constructors
fakeAutoFillConfiguration = AutofillConfiguration(
uniqueIdentifier: 'id1',
// ignore: prefer_const_literals_to_create_immutables
autofillHints: <String>['client1'],
currentEditingValue: TextEditingValue.empty,
hintText: 'hint',
);
// ignore: prefer_const_constructors
fakeAutoFillConfiguration2 = AutofillConfiguration(
uniqueIdentifier: 'id1',
// ignore: prefer_const_literals_to_create_immutables
autofillHints: <String>['client1'],
currentEditingValue: TextEditingValue.empty,
hintText: 'hint',
);
});
test('equality operator works correctly', () {
expect(fakeAutoFillConfiguration, equals(fakeAutoFillConfiguration2));
expect(fakeAutoFillConfiguration.enabled, equals(fakeAutoFillConfiguration2.enabled));
expect(
fakeAutoFillConfiguration.uniqueIdentifier,
equals(fakeAutoFillConfiguration2.uniqueIdentifier),
);
expect(
fakeAutoFillConfiguration.autofillHints,
equals(fakeAutoFillConfiguration2.autofillHints),
);
expect(
fakeAutoFillConfiguration.currentEditingValue,
equals(fakeAutoFillConfiguration2.currentEditingValue),
);
expect(fakeAutoFillConfiguration.hintText, equals(fakeAutoFillConfiguration2.hintText));
});
test('hashCode works correctly', () {
expect(fakeAutoFillConfiguration.hashCode, equals(fakeAutoFillConfiguration2.hashCode));
expect(
fakeAutoFillConfiguration.enabled.hashCode,
equals(fakeAutoFillConfiguration2.enabled.hashCode),
);
expect(
fakeAutoFillConfiguration.uniqueIdentifier.hashCode,
equals(fakeAutoFillConfiguration2.uniqueIdentifier.hashCode),
);
expect(
Object.hashAll(fakeAutoFillConfiguration.autofillHints),
equals(Object.hashAll(fakeAutoFillConfiguration2.autofillHints)),
);
expect(
fakeAutoFillConfiguration.currentEditingValue.hashCode,
equals(fakeAutoFillConfiguration2.currentEditingValue.hashCode),
);
expect(
fakeAutoFillConfiguration.hintText.hashCode,
equals(fakeAutoFillConfiguration2.hintText.hashCode),
);
});
});
}
class FakeAutofillClient implements TextInputClient, AutofillClient {

View File

@ -321,10 +321,229 @@ void main() {
});
group('TextInputConfiguration', () {
late TextInputConfiguration fakeTextInputConfiguration;
late TextInputConfiguration fakeTextInputConfiguration2;
setUp(() {
// If you create two objects with `const` with the same values, the second object will be equal to the first one by reference.
// This means that even without overriding the `equals` method, the test will pass.
// ignore: prefer_const_constructors
fakeTextInputConfiguration = TextInputConfiguration(
viewId: 1,
actionLabel: 'label1',
smartDashesType: SmartDashesType.enabled,
smartQuotesType: SmartQuotesType.enabled,
// ignore: prefer_const_literals_to_create_immutables
allowedMimeTypes: <String>['text/plain', 'application/pdf'],
);
fakeTextInputConfiguration2 = fakeTextInputConfiguration.copyWith();
});
tearDown(() {
TextInputConnection.debugResetId();
});
test('equality operator works correctly', () {
expect(fakeTextInputConfiguration, equals(fakeTextInputConfiguration2));
expect(fakeTextInputConfiguration.viewId, equals(fakeTextInputConfiguration2.viewId));
expect(fakeTextInputConfiguration.inputType, equals(fakeTextInputConfiguration2.inputType));
expect(
fakeTextInputConfiguration.inputAction,
equals(fakeTextInputConfiguration2.inputAction),
);
expect(
fakeTextInputConfiguration.autocorrect,
equals(fakeTextInputConfiguration2.autocorrect),
);
expect(
fakeTextInputConfiguration.enableSuggestions,
equals(fakeTextInputConfiguration2.enableSuggestions),
);
expect(
fakeTextInputConfiguration.obscureText,
equals(fakeTextInputConfiguration2.obscureText),
);
expect(fakeTextInputConfiguration.readOnly, equals(fakeTextInputConfiguration2.readOnly));
expect(
fakeTextInputConfiguration.smartDashesType,
equals(fakeTextInputConfiguration2.smartDashesType),
);
expect(
fakeTextInputConfiguration.smartQuotesType,
equals(fakeTextInputConfiguration2.smartQuotesType),
);
expect(
fakeTextInputConfiguration.enableInteractiveSelection,
equals(fakeTextInputConfiguration2.enableInteractiveSelection),
);
expect(
fakeTextInputConfiguration.actionLabel,
equals(fakeTextInputConfiguration2.actionLabel),
);
expect(
fakeTextInputConfiguration.keyboardAppearance,
equals(fakeTextInputConfiguration2.keyboardAppearance),
);
expect(
fakeTextInputConfiguration.textCapitalization,
equals(fakeTextInputConfiguration2.textCapitalization),
);
expect(
fakeTextInputConfiguration.autofillConfiguration,
equals(fakeTextInputConfiguration2.autofillConfiguration),
);
expect(
fakeTextInputConfiguration.enableIMEPersonalizedLearning,
equals(fakeTextInputConfiguration2.enableIMEPersonalizedLearning),
);
expect(
fakeTextInputConfiguration.allowedMimeTypes,
equals(fakeTextInputConfiguration2.allowedMimeTypes),
);
expect(
fakeTextInputConfiguration.enableDeltaModel,
equals(fakeTextInputConfiguration2.enableDeltaModel),
);
});
test('copyWith method works correctly', () {
fakeTextInputConfiguration2 = fakeTextInputConfiguration.copyWith();
expect(fakeTextInputConfiguration, equals(fakeTextInputConfiguration2));
expect(fakeTextInputConfiguration.viewId, equals(fakeTextInputConfiguration2.viewId));
expect(fakeTextInputConfiguration.inputType, equals(fakeTextInputConfiguration2.inputType));
expect(
fakeTextInputConfiguration.inputAction,
equals(fakeTextInputConfiguration2.inputAction),
);
expect(
fakeTextInputConfiguration.autocorrect,
equals(fakeTextInputConfiguration2.autocorrect),
);
expect(
fakeTextInputConfiguration.enableSuggestions,
equals(fakeTextInputConfiguration2.enableSuggestions),
);
expect(
fakeTextInputConfiguration.obscureText,
equals(fakeTextInputConfiguration2.obscureText),
);
expect(fakeTextInputConfiguration.readOnly, equals(fakeTextInputConfiguration2.readOnly));
expect(
fakeTextInputConfiguration.smartDashesType,
equals(fakeTextInputConfiguration2.smartDashesType),
);
expect(
fakeTextInputConfiguration.smartQuotesType,
equals(fakeTextInputConfiguration2.smartQuotesType),
);
expect(
fakeTextInputConfiguration.enableInteractiveSelection,
equals(fakeTextInputConfiguration2.enableInteractiveSelection),
);
expect(
fakeTextInputConfiguration.actionLabel,
equals(fakeTextInputConfiguration2.actionLabel),
);
expect(
fakeTextInputConfiguration.keyboardAppearance,
equals(fakeTextInputConfiguration2.keyboardAppearance),
);
expect(
fakeTextInputConfiguration.textCapitalization,
equals(fakeTextInputConfiguration2.textCapitalization),
);
expect(
fakeTextInputConfiguration.autofillConfiguration,
equals(fakeTextInputConfiguration2.autofillConfiguration),
);
expect(
fakeTextInputConfiguration.enableIMEPersonalizedLearning,
equals(fakeTextInputConfiguration2.enableIMEPersonalizedLearning),
);
expect(
fakeTextInputConfiguration.allowedMimeTypes,
equals(fakeTextInputConfiguration2.allowedMimeTypes),
);
expect(
fakeTextInputConfiguration.enableDeltaModel,
equals(fakeTextInputConfiguration2.enableDeltaModel),
);
});
test('hashCode works correctly', () {
expect(fakeTextInputConfiguration.hashCode, equals(fakeTextInputConfiguration2.hashCode));
expect(
fakeTextInputConfiguration.viewId.hashCode,
equals(fakeTextInputConfiguration2.viewId.hashCode),
);
expect(
fakeTextInputConfiguration.inputType.hashCode,
equals(fakeTextInputConfiguration2.inputType.hashCode),
);
expect(
fakeTextInputConfiguration.inputAction.hashCode,
equals(fakeTextInputConfiguration2.inputAction.hashCode),
);
expect(
fakeTextInputConfiguration.autocorrect.hashCode,
equals(fakeTextInputConfiguration2.autocorrect.hashCode),
);
expect(
fakeTextInputConfiguration.enableSuggestions.hashCode,
equals(fakeTextInputConfiguration2.enableSuggestions.hashCode),
);
expect(
fakeTextInputConfiguration.obscureText.hashCode,
equals(fakeTextInputConfiguration2.obscureText.hashCode),
);
expect(
fakeTextInputConfiguration.readOnly.hashCode,
equals(fakeTextInputConfiguration2.readOnly.hashCode),
);
expect(
fakeTextInputConfiguration.smartDashesType.hashCode,
equals(fakeTextInputConfiguration2.smartDashesType.hashCode),
);
expect(
fakeTextInputConfiguration.smartQuotesType.hashCode,
equals(fakeTextInputConfiguration2.smartQuotesType.hashCode),
);
expect(
fakeTextInputConfiguration.enableInteractiveSelection.hashCode,
equals(fakeTextInputConfiguration2.enableInteractiveSelection.hashCode),
);
expect(
fakeTextInputConfiguration.actionLabel.hashCode,
equals(fakeTextInputConfiguration2.actionLabel.hashCode),
);
expect(
fakeTextInputConfiguration.keyboardAppearance.hashCode,
equals(fakeTextInputConfiguration2.keyboardAppearance.hashCode),
);
expect(
fakeTextInputConfiguration.textCapitalization.hashCode,
equals(fakeTextInputConfiguration2.textCapitalization.hashCode),
);
expect(
fakeTextInputConfiguration.autofillConfiguration.hashCode,
equals(fakeTextInputConfiguration2.autofillConfiguration.hashCode),
);
expect(
fakeTextInputConfiguration.enableIMEPersonalizedLearning.hashCode,
equals(fakeTextInputConfiguration2.enableIMEPersonalizedLearning.hashCode),
);
expect(
Object.hashAll(fakeTextInputConfiguration.allowedMimeTypes),
equals(Object.hashAll(fakeTextInputConfiguration2.allowedMimeTypes)),
);
expect(
fakeTextInputConfiguration.enableDeltaModel.hashCode,
equals(fakeTextInputConfiguration2.enableDeltaModel.hashCode),
);
});
test('sets expected defaults', () {
const TextInputConfiguration configuration = TextInputConfiguration();
expect(configuration.inputType, TextInputType.text);