kqc*_*cef 8 flutter flutter-test
我正在尝试为TextField我使用的地方编写一个测试IconButton作为 TextField 的,suffixIcon以便在按下时,它将切换 TextField 的obscureText属性。小部件本身按预期工作,但我很难接近测试。
代码示例:
密码字段.dart
import 'package:flutter/material.dart';
import 'package:app/util/app_theme.dart';
import 'package:app/widgets/inputs/text_validator.dart';
class PasswordField extends StatefulWidget {
final bool showValidator;
final ValueChanged<String> onChanged;
final String errorText;
PasswordField({
this.errorText,
@required this.onChanged,
this.showValidator = true,
});
@override
_PasswordFieldState createState() => _PasswordFieldState();
}
class _PasswordFieldState extends State<PasswordField> {
String _password;
bool _shouldHidePassword = true;
void _onChangedPassword(String password) {
setState(() {
_password = password;
});
widget.onChanged(password);
}
void _togglePasswordVisibility() {
setState(() {
_shouldHidePassword = !_shouldHidePassword;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextField(
onChanged: _onChangedPassword,
decoration: _buildInputDecoration(),
obscureText: _shouldHidePassword,
),
],
);
}
InputDecoration _buildInputDecoration() {
return InputDecoration(
suffixIcon: IconButton(
icon: Icon(
_shouldHidePassword ? CustomIcons.eye_show : CustomIcons.eye_hide),
onPressed: _togglePasswordVisibility,
),
labelText: 'Password',
);
}
}
Run Code Online (Sandbox Code Playgroud)
password_field_test.dart
testWidgets('should show an eye that obscures/unobscures the typed values', (WidgetTester tester) async {
// buildWidget just wraps target in a MediaQuery/Directionality/Material
Widget field = buildWidget(PasswordField(onChanged: (_) {}));
String testPW = 'passwordtotest';
await tester.pumpWidget(field);
expect(find.byType(TextField), findsOneWidget);
await tester.enterText(find.byType(TextField), testPW);
await tester.pump();
// These are what I've tried so far
expect(find.text('•' * testPW.length), findsOneWidget)
expect(find.byElementType(TextSpan))
await tester.tap(find.byType(IconButton));
await tester.pump();
expect(find.text(testPW), findsOneWidget);
});
});
Run Code Online (Sandbox Code Playgroud)
到目前为止,我已经尝试遵循 Flutter 小部件测试文档,但我无法通过 find.text('demopassword');
我也尝试将查找器用于底层 EditableText 和 TextSpan,但未成功,但即使我能够找到它们,我也不知道如何定位文本值。我怎样才能做到这一点?
小智 0
在上面的小部件中,虽然我们明显显示“*”或纯文本,但文本的存储始终是纯文本。因此,当试图通过测试来检查它时,它永远无法找到隐藏的密码。理想情况下,在测试模糊性时,我们应该只检查它们的标志状态(obscureText)。
尝试对您的测试进行以下修改 -
testWidgets('should show an eye that obscures/unobscures the typed values',
(WidgetTester tester) async {
// buildWidget just wraps target in a MediaQuery/Directionality/Material
Widget field = buildWidget(PasswordField(onChanged: (_) {}));
String testPW = 'passwordtotest';
await tester.pumpWidget(field);
expect(find.byType(TextField), findsOneWidget);
await tester.enterText(find.byType(TextField), testPW);
await tester.pump();
expect(
(tester.firstWidget(find.byType(TextField)) as TextField).obscureText,
true);
await tester.tap(find.byType(IconButton));
await tester.pump();
expect(
(tester.firstWidget(find.byType(TextField)) as TextField).obscureText,
false);
});Run Code Online (Sandbox Code Playgroud)
此外,作为工程建议,您实际上可以尝试使用 ValueListenableBuilder,而不是在代码中使用 setState()。它很简单,可以避免不必要的状态管理麻烦并防止性能影响。更多参考: https: //api.flutter.dev/flutter/widgets/ValueListenableBuilder-class.html
使用 ValueListenableBuilder,您的构建方法代码看起来有点像这样 -
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ValueListenableBuilder<bool>(
valueListenable: shouldHidePassword,
builder: (context, bool value, child) {
return TextField(
onChanged: _onChangedPassword,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(shouldHidePassword.value
? Icons.remove_red_eye_outlined
: Icons.remove_red_eye),
onPressed: () =>
shouldHidePassword.value = !shouldHidePassword.value,
),
labelText: 'Password',
),
obscureText: value,
);
},
),
],
);
}Run Code Online (Sandbox Code Playgroud)
更干净、更容易维护;而您以后可以避免一堆性能问题!
| 归档时间: |
|
| 查看次数: |
782 次 |
| 最近记录: |