// 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('FormInputValidator', () {
    group('Boolean', () {
      test('is pure at the beginning', () {
        const validator = Boolean.pure();
        expect(validator.pure, true);
      });

      test('contains `false` at the beginning', () {
        const validator = Boolean.pure();
        expect(validator.pure, true);
        expect(validator.value, false);
      });

      test('contains `true` when intialized with', () {
        const validator = Boolean.pure(defaultValue: true);
        expect(validator.pure, true);
        expect(validator.value, true);
      });

      test('returns ValidationStandardError.invalid on null', () {
        const validator = Boolean.dirty();
        expect(validator.error, ValidationStandardError.invalid);
      });

      test('is invalid and contains `null` when update with `null`', () {
        const validator = Boolean.dirty();
        expect(validator.invalid, true);
        expect(validator.value, null);
      });

      test('is valid and contains `true` when update with `true`', () {
        const validator = Boolean.dirty(value: true);
        expect(validator.valid, true);
        expect(validator.value, true);
      });

      test('is valid and contains `false` when update with `false`', () {
        const validator = Boolean.dirty(value: false);
        expect(validator.valid, true);
        expect(validator.value, false);
      });

      test('== to another boolean validator with the same attributes', () {
        const validator1 = Boolean.dirty(value: false);
        const validator2 = Boolean.dirty(value: false);
        expect(validator1 == validator2, isTrue);
      });

      test('!= to another boolean validator with different attributes', () {
        const validator1 = Boolean.dirty(value: false);
        const validator2 = Boolean.dirty(value: true);
        expect(validator1 == validator2, isFalse);
      });
    });

    group('ConfirmedPassword', () {
      test('is pure at the beginning', () {
        const validator = ConfirmedPassword.pure();
        expect(validator.pure, true);
      });

      test('contains `null` at the beginning', () {
        const validator = ConfirmedPassword.pure();
        expect(validator.pure, true);
        expect(validator.value, null);
      });

      test('contains `pwd` when intialized with', () {
        const validator = ConfirmedPassword.pure(defaultValue: 'pwd');
        expect(validator.pure, true);
        expect(validator.value, 'pwd');
      });

      test('returns ValidationStandardError.invalid on null', () {
        const validator = ConfirmedPassword.dirty(password: 'pwd');
        expect(validator.error, ValidationStandardError.invalid);
      });

      test('returns ValidationStandardError.notEqual on different values', () {
        const validator =
            ConfirmedPassword.dirty(password: 'pwd', value: 'incorrect');
        expect(validator.error, ValidationStandardError.notEqual);
      });

      test('is invalid and contains `null` when update with `null`', () {
        const validator = ConfirmedPassword.dirty(password: 'pwd');
        expect(validator.invalid, true);
        expect(validator.value, null);
      });

      test('is invalid and contains `incorrect` when update with `incorrect`',
          () {
        const validator =
            ConfirmedPassword.dirty(password: 'pwd', value: 'incorrect');
        expect(validator.invalid, true);
        expect(validator.value, 'incorrect');
      });

      test('is valid and contains `pwd` when update with `pwd`', () {
        const validator =
            ConfirmedPassword.dirty(password: 'pwd', value: 'pwd');
        expect(validator.valid, true);
        expect(validator.value, 'pwd');
      });

      test(
          '== to another confirmed password validator with the same attributes',
          () {
        const validator1 =
            ConfirmedPassword.dirty(password: 'pwd', value: 'pwd');
        const validator2 =
            ConfirmedPassword.dirty(password: 'pwd', value: 'pwd');
        expect(validator1 == validator2, isTrue);
      });

      test(
          '!= to another confirmed password validator '
          'with different attributes', () {
        const validator1 =
            ConfirmedPassword.dirty(password: 'pwd', value: 'pwd1');
        const validator2 =
            ConfirmedPassword.dirty(password: 'pwd', value: 'pwd2');
        expect(validator1 == validator2, isFalse);
      });

      test('!= to another confirmed password validator with different password',
          () {
        const validator1 =
            ConfirmedPassword.dirty(password: 'pwd1', value: 'pwd');
        const validator2 =
            ConfirmedPassword.dirty(password: 'pwd2', value: 'pwd');
        expect(validator1 == validator2, isFalse);
      });
    });
  });

  // TODO(hpcl): add tests for all validators...
}
