App-Test-Generator

 view release on metacpan or  search on metacpan

t/SchemaExtractor.t  view on Meta::CPAN

	ok(exists $fields->{port},          'field with default detected');
	is($fields->{port}{_default}, 3306, 'default value extracted');
	ok($fields->{port}{optional},       'field with default is optional');

	# Field with :isa type constraint -- type set to object
	$fields = $fn->("field \$logger :param :isa(Log::Any);\n");
	ok(exists $fields->{logger},             'field with isa detected');
	is($fields->{logger}{isa},   'Log::Any', 'isa type extracted');
	is($fields->{logger}{type},  'object',   'type set to object for isa');

	done_testing();
};

# ==================================================================
# _parse_signature_parameter
# --------------------------------------------------
# Tests for the individual signature parameter parser
# ==================================================================
subtest '_parse_signature_parameter' => sub {
	my $e  = _extractor();
	my $fn = sub { $e->_parse_signature_parameter(@_) };

	# Plain scalar parameter at position 0
	my $info = $fn->('$name', 0);
	is($info->{name},     'name', 'plain param name extracted');
	is($info->{position}, 0,      'position set correctly');
	is($info->{optional}, 0,      'plain param is required');

	# Parameter with a numeric default value makes it optional
	$info = $fn->('$port = 3306', 1);
	is($info->{name},     'port', 'default param name extracted');
	is($info->{optional}, 1,      'param with default is optional');
	is($info->{_default}, 3306,   'default value extracted');
	is($info->{position}, 1,      'position set correctly');

	# Parameter with :Int type constraint maps to 'integer'
	$info = $fn->('$count :Int', 0);
	is($info->{name},     'count',   'typed param name extracted');
	is($info->{type},     'integer', ':Int maps to integer type');
	is($info->{optional}, 0,         'typed param without default is required');

	# Parameter with :Num constraint and default
	$info = $fn->('$ratio :Num = 1.0', 0);
	is($info->{type},     'number', ':Num maps to number type');
	is($info->{optional}, 1,        'typed param with default is optional');

	# Slurpy array parameter
	$info = $fn->('@args', 2);
	is($info->{name},   'args',  'slurpy array name extracted');
	is($info->{type},   'array', 'slurpy array has array type');
	ok($info->{slurpy},           'slurpy flag set for @param');
	ok($info->{optional},         'slurpy array is optional');

	# Slurpy hash parameter
	$info = $fn->('%opts', 2);
	is($info->{name},   'opts', 'slurpy hash name extracted');
	is($info->{type},   'hash', 'slurpy hash has hash type');
	ok($info->{slurpy},          'slurpy flag set for %param');

	# Non-matching pattern returns undef without dying
	is($fn->('not_a_param', 0), undef, 'non-matching pattern returns undef');

	done_testing();
};

# ==================================================================
# _infer_type_from_expression
# --------------------------------------------------
# Tests for the return expression type inferrer.
# This function checks booleans (^[01]$) BEFORE integers
# so single 0 and 1 are correctly classified as boolean.
# ==================================================================
subtest '_infer_type_from_expression' => sub {
	my $e  = _extractor();
	my $fn = sub { $e->_infer_type_from_expression(@_) };

	# Undef returns scalar as the safe default
	is($fn->(undef)->{type}, 'scalar', 'undef expr returns scalar type');

	# Array-like expressions
	is($fn->('@array')->{type},    'array',    '@array is array');
	is($fn->('qw(a b c)')->{type}, 'array',    'qw() is array');
	is($fn->('\@ref')->{type},     'arrayref', '\@ref is arrayref');
	is($fn->('[1,2,3]')->{type},   'arrayref', '[...] is arrayref');

	# Hash-like expressions
	is($fn->('\%hash')->{type}, 'hashref', '\%hash is hashref');
	is($fn->('{}')->{type},     'hashref', '{} is hashref');

	# Numeric scalar literals
	is($fn->('42')->{type},   'integer', 'integer literal');
	is($fn->('-1')->{type},   'integer', 'negative integer');
	is($fn->('3.14')->{type}, 'number',  'float literal');

	# String literal
	is($fn->("'hello'")->{type}, 'string', 'single-quoted string');

	# Single-digit 0 and 1 are boolean -- the boolean check /^[01]$/
	# appears before the integer check in the function after the bug fix
	is($fn->('1')->{type}, 'boolean', '1 is boolean in expression context');
	is($fn->('0')->{type}, 'boolean', '0 is boolean in expression context');

	# scalar() function returns integer with min 0
	my $res = $fn->('scalar(@arr)');
	is($res->{type}, 'integer', 'scalar() returns integer');
	is($res->{min},  0,         'scalar() has min 0');

	# Comma-separated values indicate an array
	is($fn->('$a, $b')->{type}, 'array', 'comma-separated is array');

	# length() returns integer with min 0
	$res = $fn->('length($s)');
	is($res->{type}, 'integer', 'length() returns integer');
	is($res->{min},  0,         'length() has min 0');

	done_testing();
};

# ==================================================================
# _calculate_input_confidence
# --------------------------------------------------



( run in 0.529 second using v1.01-cache-2.11-cpan-9581c071862 )