237 lines
8.3 KiB
Dart
237 lines
8.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:sxchnge_theme/sxchnge_theme.dart';
|
|
|
|
import 'package:sxchnge_app/kyc/birth.dart';
|
|
|
|
import 'package:sxchnge_app/generated/i18n/app_localizations.dart';
|
|
|
|
void main() {
|
|
final day = find.byKey(const ValueKey('birth-day'));
|
|
final year = find.byKey(const ValueKey('birth-year'));
|
|
final month = find.byType(DropdownButtonFormField<int>);
|
|
|
|
Future<void> mount(
|
|
WidgetTester t,
|
|
ValueNotifier<String> value, {
|
|
Locale locale = const Locale('en'),
|
|
bool enabled = true,
|
|
}) async {
|
|
await t.pumpWidget(
|
|
MaterialApp(
|
|
theme: SxchngeTheme.light(),
|
|
locale: locale,
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: Scaffold(
|
|
body: SingleChildScrollView(
|
|
padding: const EdgeInsets.all(24),
|
|
child: ValueListenableBuilder<String>(
|
|
valueListenable: value,
|
|
builder: (_, date, _) => BirthField(
|
|
value: date,
|
|
enabled: enabled,
|
|
onChanged: (date) => value.value = date,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await t.pumpAndSettle();
|
|
}
|
|
|
|
Future<void> select(WidgetTester t, String name) async {
|
|
await t.ensureVisible(month);
|
|
await t.tap(month);
|
|
await t.pumpAndSettle();
|
|
await t.tap(find.text(name).last);
|
|
await t.pumpAndSettle();
|
|
}
|
|
|
|
testWidgets('enters and corrects a birthday without ISO syntax', (t) async {
|
|
final value = ValueNotifier('');
|
|
addTearDown(value.dispose);
|
|
await mount(t, value);
|
|
expect(find.text('Date of birth'), findsOneWidget);
|
|
await t.enterText(day, '23');
|
|
await select(t, 'April');
|
|
expect(value.value, '');
|
|
await t.enterText(year, '1990');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '1990-04-23');
|
|
await t.enterText(day, '9');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '1990-04-09');
|
|
await t.enterText(year, '19');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '');
|
|
// A provider rebuild must retain the other components of an incomplete date.
|
|
expect(t.widget<TextFormField>(day).controller!.text, '9');
|
|
expect(find.text('April'), findsOneWidget);
|
|
await t.enterText(year, '1985');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '1985-04-09');
|
|
});
|
|
|
|
testWidgets('leap dates, impossible days and future dates recover inline', (
|
|
t,
|
|
) async {
|
|
final value = ValueNotifier('2000-02-29');
|
|
addTearDown(value.dispose);
|
|
await mount(t, value);
|
|
expect(find.text('February'), findsOneWidget);
|
|
await t.enterText(year, '2001');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '');
|
|
expect(find.text('Enter a valid date of birth.'), findsOneWidget);
|
|
expect(t.widget<TextFormField>(day).controller!.text, '29');
|
|
await t.enterText(year, '2004');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '2004-02-29');
|
|
expect(find.text('Enter a valid date of birth.'), findsNothing);
|
|
await t.enterText(day, '31');
|
|
await select(t, 'April');
|
|
expect(value.value, '');
|
|
expect(find.text('Enter a valid date of birth.'), findsOneWidget);
|
|
await t.enterText(day, '30');
|
|
await t.enterText(year, '${DateTime.now().year + 1}');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '');
|
|
expect(find.text('Date of birth cannot be in the future.'), findsOneWidget);
|
|
await t.enterText(year, '1990');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '1990-04-30');
|
|
await t.enterText(day, '0');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '');
|
|
expect(find.text('Enter a valid date of birth.'), findsOneWidget);
|
|
await t.enterText(day, '1');
|
|
await t.enterText(year, '0000');
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '');
|
|
expect(find.text('Enter a valid date of birth.'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets(
|
|
'prefill, external replacement, locale change and clear synchronize',
|
|
(t) async {
|
|
final value = ValueNotifier('1990-04-23');
|
|
addTearDown(value.dispose);
|
|
await mount(t, value);
|
|
expect(t.widget<TextFormField>(year).controller!.text, '1990');
|
|
value.value = '1985-12-09';
|
|
await t.pumpAndSettle();
|
|
expect(t.widget<TextFormField>(day).controller!.text, '09');
|
|
expect(t.widget<TextFormField>(year).controller!.text, '1985');
|
|
expect(find.text('December'), findsOneWidget);
|
|
await mount(t, value, locale: const Locale('ru'));
|
|
expect(find.text('Дата рождения'), findsOneWidget);
|
|
expect(find.text('декабрь'), findsOneWidget);
|
|
expect(value.value, '1985-12-09');
|
|
await select(t, 'апрель');
|
|
expect(value.value, '1985-04-09');
|
|
value.value = '';
|
|
await t.pumpAndSettle();
|
|
expect(t.widget<TextFormField>(day).controller!.text, '');
|
|
expect(t.widget<TextFormField>(year).controller!.text, '');
|
|
expect(find.text('апрель'), findsNothing);
|
|
},
|
|
);
|
|
|
|
testWidgets('digits and length limits keep each component usable', (t) async {
|
|
final value = ValueNotifier('1990-04-23');
|
|
addTearDown(value.dispose);
|
|
await mount(t, value);
|
|
await t.enterText(day, '');
|
|
await t.enterText(day, 'a123');
|
|
await t.enterText(year, '');
|
|
await t.enterText(year, 'b19856');
|
|
await t.pumpAndSettle();
|
|
expect(t.widget<TextFormField>(day).controller!.text, '12');
|
|
expect(t.widget<TextFormField>(year).controller!.text, '1985');
|
|
expect(value.value, '1985-04-12');
|
|
});
|
|
|
|
testWidgets('busy state disables every birthday control', (t) async {
|
|
final value = ValueNotifier('1990-04-23');
|
|
addTearDown(value.dispose);
|
|
await mount(t, value, enabled: false);
|
|
expect(t.widget<TextFormField>(day).enabled, isFalse);
|
|
expect(t.widget<TextFormField>(year).enabled, isFalse);
|
|
expect(t.widget<DropdownButtonFormField<int>>(month).onChanged, isNull);
|
|
expect(value.value, '1990-04-23');
|
|
});
|
|
|
|
testWidgets('keyboard can traverse, choose month, cancel and edit year', (
|
|
t,
|
|
) async {
|
|
final value = ValueNotifier('1990-04-23');
|
|
addTearDown(value.dispose);
|
|
await mount(t, value);
|
|
await t.sendKeyEvent(LogicalKeyboardKey.tab);
|
|
await t.pump();
|
|
expect(
|
|
t
|
|
.widget<EditableText>(
|
|
find.descendant(of: day, matching: find.byType(EditableText)),
|
|
)
|
|
.focusNode
|
|
.hasFocus,
|
|
isTrue,
|
|
);
|
|
await t.sendKeyEvent(LogicalKeyboardKey.tab);
|
|
await t.sendKeyEvent(LogicalKeyboardKey.enter);
|
|
await t.pumpAndSettle();
|
|
await t.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
|
await t.sendKeyEvent(LogicalKeyboardKey.enter);
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '1990-05-23');
|
|
await t.sendKeyEvent(LogicalKeyboardKey.enter);
|
|
await t.pumpAndSettle();
|
|
await t.sendKeyEvent(LogicalKeyboardKey.escape);
|
|
await t.pumpAndSettle();
|
|
expect(value.value, '1990-05-23');
|
|
await t.sendKeyEvent(LogicalKeyboardKey.tab);
|
|
await t.pump();
|
|
expect(
|
|
t
|
|
.widget<EditableText>(
|
|
find.descendant(of: year, matching: find.byType(EditableText)),
|
|
)
|
|
.focusNode
|
|
.hasFocus,
|
|
isTrue,
|
|
);
|
|
});
|
|
|
|
testWidgets(
|
|
'Russian controls and errors fit 320px with large text and labeled targets',
|
|
(t) async {
|
|
t.view.physicalSize = const Size(320, 900);
|
|
t.view.devicePixelRatio = 1;
|
|
t.platformDispatcher.textScaleFactorTestValue = 1.6;
|
|
addTearDown(t.view.resetPhysicalSize);
|
|
addTearDown(t.view.resetDevicePixelRatio);
|
|
addTearDown(t.platformDispatcher.clearTextScaleFactorTestValue);
|
|
final semantics = t.ensureSemantics();
|
|
final value = ValueNotifier('1990-09-23');
|
|
addTearDown(value.dispose);
|
|
await mount(t, value, locale: const Locale('ru'));
|
|
expect(find.text('сентябрь'), findsOneWidget);
|
|
expect(t, meetsGuideline(labeledTapTargetGuideline));
|
|
expect(t, meetsGuideline(androidTapTargetGuideline));
|
|
await t.enterText(day, '31');
|
|
await t.pumpAndSettle();
|
|
expect(find.text('Укажите корректную дату рождения.'), findsOneWidget);
|
|
await select(t, 'март');
|
|
expect(value.value, '1990-03-31');
|
|
expect(t.takeException(), isNull);
|
|
semantics.dispose();
|
|
},
|
|
);
|
|
}
|