App-Test-Generator
view release on metacpan or search on metacpan
t/default_value_extraction.t view on Meta::CPAN
'Cleans boolean true (1)'
);
is(
$extractor->_clean_default_value('0'),
0,
'Cleans boolean false (0)'
);
is(
$extractor->_clean_default_value('true'),
1,
'Cleans boolean true string'
);
is(
$extractor->_clean_default_value('false'),
0,
'Cleans boolean false string'
);
# Test data structures
is_deeply(
$extractor->_clean_default_value('[]'),
[],
'Cleans empty arrayref'
);
is_deeply(
$extractor->_clean_default_value('{}'),
{},
'Cleans empty hashref'
);
# Test special values
is(
$extractor->_clean_default_value('undef'),
undef,
'Cleans undef'
);
is(
$extractor->_clean_default_value('__PACKAGE__'),
'__PACKAGE__',
'Preserves __PACKAGE__ constant'
);
# Test with extra whitespace
is(
$extractor->_clean_default_value(" 'test' "),
'test',
'Cleans string with whitespace'
);
is(
$extractor->_clean_default_value(' 42 '),
42,
'Cleans integer with whitespace'
);
# Test escaped strings
is(
$extractor->_clean_default_value('"line1\\nline2"'),
"line1\nline2",
'Handles escaped newlines'
);
is(
$extractor->_clean_default_value("'it\\'s working'"),
"it's working",
'Handles escaped quotes'
);
done_testing();
};
# POD default value extraction
subtest 'POD Default Value Extraction' => sub {
my $module = <<'END_MODULE';
package Test::PODDefaults;
use strict;
use warnings;
=head2 process_data
Process data with various parameters.
=over 4
=item * $name - string, the name to process. Default: 'anonymous'
=item * $count - integer, number of items. Default: 10
=item * $enabled - boolean, whether enabled. Default: true
=item * $mode - string, processing mode. Optional, default: 'auto'
=back
Defaults to: 1 on success
=cut
sub process_data {
my ($self, $name, $count, $enabled, $mode) = @_;
$name ||= 'anonymous';
$count //= 10;
$enabled //= 1;
$mode = 'auto' unless defined $mode;
return 1;
}
=head2 another_method
Another method with different POD patterns.
Parameters:
$host - string, hostname. Defaults to: 'localhost'
$port - integer, port number. Default: 8080
$timeout - number, timeout in seconds. Optional, default: 30.0
=cut
sub another_method {
my ($self, $host, $port, $timeout) = @_;
$host ||= 'localhost';
$port //= 8080;
$timeout = 30.0 unless defined $timeout;
t/default_value_extraction.t view on Meta::CPAN
'boolean',
'Type inferred from boolean default'
);
is(
$configure_input->{timeout}{_default},
30.0,
'Schema includes timeout default'
);
is(
$configure_input->{timeout}{type},
'number',
'Type inferred from float default'
);
# Test process method with data structures
my $process_schema = $schemas->{process};
my $process_input = $process_schema->{input};
is_deeply(
$process_input->{items}{_default},
[],
'Schema includes empty arrayref default'
);
is(
$process_input->{items}{type},
'arrayref',
'Type inferred from arrayref default'
);
is_deeply(
$process_input->{options}{_default},
{},
'Schema includes empty hashref default'
);
is(
$process_input->{options}{type},
'hashref',
'Type inferred from hashref default'
);
done_testing();
};
# Edge cases and tricky patterns
subtest 'Edge Cases and Tricky Patterns' => sub {
my $module = <<'END_MODULE';
package Test::EdgeCases;
use strict;
use warnings;
sub edge_cases {
my ($self, $param1, $param2, $param3, $param4, $param5) = @_;
# Edge case 1: Default with quotes inside quotes
$param1 = $param1 || "it's complicated";
# Edge case 2: Default with escaped characters
$param2 //= "line1\\nline2\\ttab";
# Edge case 3: Default as expression in parentheses
$param3 = defined $param3 ? $param3 : (10 + 20);
# Edge case 4: Default with trailing comment
$param4 = $param4 || 'default'; # this is a comment
# Edge case 5: Default with q// operator
$param5 = $param5 || q{default value};
return 1;
}
sub no_defaults {
my ($self, $required) = @_;
# No default - should be required
die 'Required!' unless defined $required;
return 1;
}
END_MODULE
my $extractor = create_extractor($module);
# Test edge case method
my $doc = PPI::Document->new($extractor->{input_file});
$extractor->{_document} = $doc;
my $methods = $extractor->_find_methods($doc);
my $edge_cases = (grep { $_->{name} eq 'edge_cases' } @$methods)[0];
# Analyze parameters
my $body = $edge_cases->{body};
my $code_params = $extractor->_analyze_code($edge_cases->{body});
# Check specific edge cases
is(
$code_params->{param1}{_default},
"it's complicated",
'Handles quotes inside string default'
);
is(
$code_params->{param2}{_default},
"line1\\nline2\\ttab",
'Preserves escaped characters in default'
);
is(
$code_params->{param2}{_default},
"line1\\nline2\\ttab",
'Preserves escaped characters in default'
);
# Note: param3 returns expression "(10 + 20)" which we can't evaluate
ok(
$code_params->{param3}{_default},
'Extracts expression default (even if unevaluatable)'
);
is(
$code_params->{param4}{_default},
'default',
'Ignores trailing comments in default extraction'
);
is(
$code_params->{param5}{_default},
'default value',
'Extracts default from q{} operator'
);
# Test required parameter (no defaults)
my $no_defaults = (grep { $_->{name} eq 'no_defaults' } @$methods)[0];
my $no_defaults_params = $extractor->_analyze_code($no_defaults->{body});
is(
$no_defaults_params->{required}{optional},
0,
'Parameter without default is marked as required'
);
ok(
!exists $no_defaults_params->{required}{_default},
'Required parameter has no default value'
);
done_testing();
};
# Real-world example
subtest 'Real-World Example' => sub {
my $module = <<'END_MODULE';
package Test::RealWorld;
use strict;
use warnings;
=head2 connect_to_database
Connect to a database with sensible defaults.
Parameters:
$host - Database hostname. Default: 'localhost'
$port - Database port. Default: 3306
$user - Username. Optional, default: 'app_user'
$password - Password. Optional, default: undef (no password)
$database - Database name. Required.
$ssl - Use SSL connection. Default: false
$timeout - Connection timeout in seconds. Default: 10
Returns: Database connection object
( run in 0.519 second using v1.01-cache-2.11-cpan-df04353d9ac )