feat(form): add metadata tag to bypass validation #29

This commit is contained in:
Hugo Pointcheval 2022-11-15 18:48:02 -05:00
parent cecbc94a95
commit 6eb40de72c
Signed by: hugo
GPG Key ID: A9E8E9615379254F
3 changed files with 161 additions and 5 deletions

View File

@ -23,7 +23,21 @@ class OnlyRequiredInputValidator extends FormValidator {
@override
FormStatus validate(WyattForm form) {
// TODO(hpcl): use metadata to check if input is required or not.
if (isPure(form)) {
return FormStatus.pure;
}
final inputsToTest =
form.inputs.where((input) => input.metadata.isRequired);
if (inputsToTest.every((input) => input.validator.pure)) {
return FormStatus.pure;
}
if (inputsToTest.any((input) => input.validator.valid == false)) {
return FormStatus.invalid;
}
return FormStatus.valid;
}
}

View File

@ -18,38 +18,44 @@
import 'package:equatable/equatable.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
class FormInputMetadata<Extra> extends Equatable
implements Entity {
class FormInputMetadata<Extra> extends Equatable implements Entity {
final bool export;
final bool isRequired;
final String? name;
final Extra? extra;
const FormInputMetadata({
this.export = true,
this.isRequired = true,
this.name,
this.extra,
});
FormInputMetadata<Extra> copyWith({
bool? export,
bool? isRequired,
String? name,
Extra? extra,
}) =>
FormInputMetadata<Extra>(
export: export ?? this.export,
isRequired: isRequired ?? this.isRequired,
name: name ?? this.name,
extra: extra ?? this.extra,
);
FormInputMetadata<Extra> clone() => copyWith(
export: export,
isRequired: isRequired,
name: name,
extra: extra,
);
@override
bool? get stringify => true;
List<Object?> get props => [export, isRequired, name, extra];
@override
List<Object?> get props => [export, name, extra];
String toString() =>
'FormInputMetada(name: $name, export: $export, isRequired: $isRequired, '
'${(extra != null) ? "extra(${extra.runtimeType}): $extra" : ""})';
}

View File

@ -0,0 +1,136 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter_test/flutter_test.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
void main() {
group('FormValidator', () {
WyattForm form = WyattFormImpl(
const [],
name: 'signInForm',
);
group('EveryInputValidator', () {
setUp(() {
// Reset form
form = WyattFormImpl(
[
FormInput(
'email',
const Email.pure(),
),
FormInput(
'password',
const Password.pure(),
),
FormInput(
'phone',
const Phone.pure(),
metadata: const FormInputMetadata<void>(isRequired: false),
),
],
name: 'signInForm',
);
});
test('returns `pure` on untouched form', () {
expect(form.validate(), FormStatus.pure);
});
test('returns `invalid` when 1 input is invalid', () {
form.updateValidator('email', const Email.dirty('incorrect'));
expect(form.validate(), FormStatus.invalid);
});
test('returns `invalid` when 1 no required input is invalid ', () {
form.updateValidator('phone', const Phone.dirty('incorrect'));
expect(form.validate(), FormStatus.invalid);
});
test('returns `valid` when all inputs are valid', () {
form
..updateValidator('email', const Email.dirty('test@test.fr'))
..updateValidator('password', const Password.dirty('password1234'))
..updateValidator('phone', const Phone.dirty('0000000000'));
expect(form.validate(), FormStatus.valid);
});
});
group('OnlyRequiredInputValidator', () {
setUp(() {
// Reset form
form = WyattFormImpl(
[
FormInput(
'email',
const Email.pure(),
),
FormInput(
'password',
const Password.pure(),
),
FormInput(
'phone',
const Phone.pure(),
metadata: const FormInputMetadata<void>(isRequired: false),
),
],
name: 'signInForm',
validationStrategy: const OnlyRequiredInputValidator(),
);
});
test('returns `pure` on untouched form', () {
expect(form.validate(), FormStatus.pure);
});
test('returns `invalid` when 1 input is invalid', () {
form.updateValidator('email', const Email.dirty('incorrect'));
expect(form.validate(), FormStatus.invalid);
});
test(
'returns `pure` when no required input '
'are invalid but other untouched', () {
form.updateValidator('phone', const Phone.dirty('incorrect'));
expect(form.validate(), FormStatus.pure);
});
test(
'returns `valid` when required inputs '
'are valid but not the not required', () {
form
..updateValidator('email', const Email.dirty('test@test.fr'))
..updateValidator('password', const Password.dirty('password1234'))
..updateValidator('phone', const Phone.dirty('incorrect'));
expect(form.validate(), FormStatus.valid);
});
test('returns `valid` when all required inputs are valid', () {
form
..updateValidator('email', const Email.dirty('test@test.fr'))
..updateValidator('password', const Password.dirty('password1234'));
expect(form.validate(), FormStatus.valid);
});
test('returns `valid` when all inputs are valid', () {
form
..updateValidator('email', const Email.dirty('test@test.fr'))
..updateValidator('password', const Password.dirty('password1234'))
..updateValidator('phone', const Phone.dirty('0000000000'));
expect(form.validate(), FormStatus.valid);
});
});
});
}