FU

 view release on metacpan or  search on metacpan

t/validate.t  view on Meta::CPAN

use v5.36;
use Test::More;
use Storable 'dclone';
use experimental 'builtin';
use builtin qw/true false blessed/;

use FU::Validate;


my %validations = (
    hex => { regex => qr/^[0-9a-f]*$/i },
    prefix => sub { my $p = shift; { func => sub { $_[0] =~ /^$p/ } } },
    mybool => { default => 0, func => sub { $_[0] = $_[0]?1:0; 1 } },
    setundef => { func => sub { $_[0] = undef; 1 } },
    defaultsub1 => { default => sub { 2 } },
    defaultsub2 => { default => sub { defined $_[0] } },
    onerrorsub => { onerror => sub { ref $_[1] } },
    collapsews => { trim => 0, func => sub { $_[0] =~ s/\s+/ /g; 1 } },
    neverfails => { onerror => 'err' },
    doublefunc => [ func => sub { $_[0] == 0 }, func => sub { $_[0] = 2; 1; } ],
    revnum => { type => 'array', sort => sub($x,$y) { $y <=> $x } },
    uniquelength => { elems => { type => 'array' }, unique => sub { scalar @{$_[0]} } },
    person => {
        type => 'hash',
        unknown => 'pass',
        keys => {
            name => {},
            age => { missing => 'ignore' },
            sex => { missing => 'reject', default => 1 }
        }
    },
);


sub t($schema, $input, $output) {
    my $line = (caller)[2];

    my $schema_copy = dclone([$schema])->[0];
    my $input_copy = dclone([$input])->[0];

    #diag explain FU::Validate->compile($schema, \%validations) if $line == 95;
    my $res = FU::Validate->compile($schema, \%validations)->validate($input);
    is_deeply $schema, $schema_copy, "schema modification $line";
    is_deeply $input,  $input_copy,  "input modification $line";
    is_deeply $res, $output, "data ok $line";
}

sub f($schema, $input, $error, @msg) {
    my $line = (caller)[2];

    my $schema_copy = dclone([$schema])->[0];
    my $input_copy = dclone([$input])->[0];

    #diag explain FU::Validate->compile($schema, \%validations) if $line == 176;
    ok !eval { FU::Validate->compile($schema, \%validations)->validate($input); 1 }, "eval $line";
    is_deeply $schema, $schema_copy, "schema modification $line";
    is_deeply $input,  $input_copy,  "input modification $line";
    delete $@->{longmess};
    is_deeply { $@->%* }, $error, "err $line";
    is_deeply [$@->errors], \@msg, "errmsg $line";
}


# default
t {}, 0, 0;
f {}, '', { validation => 'required' }, 'required value missing';
f {}, undef, { validation => 'required' }, 'required value missing';
t { default => undef }, undef, undef;
t { default => undef }, '', undef;
f { default => \'required' }, '', { validation => 'required' }, 'required value missing';
t { defaultsub1 => 1 }, undef, 2;
t { defaultsub2 => 1 }, undef, '';
t { defaultsub2 => 1 }, '', 1;
t { onerrorsub => 1 }, undef, 'FU::Validate::err';

# trim
t {}, " Va\rl id \n ", 'Val id';
t { trim => 0 }, " Va\rl id \n ", " Va\rl id \n ";
f {}, '  ', { validation => 'required' }, 'required value missing';
t { trim => 0 }, '  ', '  ';

# allow_control
f {}, "\b", { validation => 'allow_control' }, 'invalid control character';
t { allow_control => 1 }, "\b", "\b";

# accept_array
t { default => undef, accept_array => 'first' }, [], undef;
t { default => undef, accept_array => 'first' }, [' x '], 'x';
t { accept_array => 'first' }, [1,2,3], 1;
t { accept_array => 'last' }, [1,2,3], 3;
f { accept_array => 'first' }, ['  ', 1], { validation => 'required' }, 'required value missing';
f { accept_array => 'first' }, [], { validation => 'required' }, 'required value missing';

# arrays
f {}, [], { validation => 'type', expected => 'scalar', got => 'array' }, "invalid type, expected 'scalar' but got 'array'";
f { type => 'array' }, 1, { validation => 'type', expected => 'array', got => 'scalar' }, "invalid type, expected 'array' but got 'scalar'";
t { type => 'array' }, [], [];
t { type => 'array' }, [undef,1,2,{}], [undef,1,2,{}];
t { type => 'array', accept_scalar => 1 }, 1, [1];
f { type => 'array', elems => {} }, [undef], { validation => 'elems', errors => [{ index => 0, validation => 'required' }] }, "[0]: required value missing";
t { type => 'array', elems => {} }, [' a '], ['a'];
t { type => 'array', sort => 'str' }, [qw/20 100 3/], [qw/100 20 3/];
t { type => 'array', sort => 'num' }, [qw/20 100 3/], [qw/3 20 100/];
t { revnum => 1 },                    [qw/20 100 3/], [qw/100 20 3/];
t { type => 'array', sort => 'num', unique => 1 }, [qw/3 2 1/], [qw/1 2 3/];
f { type => 'array', sort => 'num', unique => 1 }, [qw/3 2 3/], { validation => 'unique', index_a => 1, value_a => 3, index_b => 2, value_b => 3 }, q{[2] value '"3"' duplicated};
t { type => 'array', unique => 1 }, [qw/3 1 2/], [qw/3 1 2/];
f { type => 'array', unique => 1 }, [qw/3 1 3/], { validation => 'unique', index_a => 0, value_a => 3, index_b => 2, value_b => 3, key => 3 }, q{[2] value '"3"' duplicated};
t { uniquelength => 1 }, [[],[1],[1,2]], [[],[1],[1,2]];



( run in 2.471 seconds using v1.01-cache-2.11-cpan-5c0b1e786e0 )