App-makefilepl2cpanfile

 view release on metacpan or  search on metacpan

t/basics.t  view on Meta::CPAN

use Path::Tiny;

BEGIN { use_ok('App::makefilepl2cpanfile') }

my $dir = tempdir(CLEANUP => 1);
chdir $dir;

path('Makefile.PL')->spew_utf8(<<'END_MF');
WriteMakefile(
	MIN_PERL_VERSION => '5.010',
	PREREQ_PM => { 'Try::Tiny' => 0 },
);
END_MF

my $out = App::makefilepl2cpanfile::generate(makefile => 'Makefile.PL');

like $out, qr/requires 'Try::Tiny'/,   'runtime dep is present';
like $out, qr/'perl', '5.010'/,        'MIN_PERL_VERSION is emitted';
like $out, qr/^# Generated from/m,     'header comment is present';

# A versioned dependency must include the version constraint.
path('Makefile.PL')->spew_utf8(<<'END_MF');
WriteMakefile(
	PREREQ_PM => { 'Foo::Bar' => '1.23' },
);
END_MF

t/function.t  view on Meta::CPAN

# Private helpers are called via their fully-qualified names.  No strict-refs
# trick is needed because these are compile-time-known symbol names.
# The leading underscore is a convention; Sub::Private is not enforced.

Readonly my $PKG => 'App::makefilepl2cpanfile';

# Shared fixture: a realistic Makefile.PL string exercising the common cases.
Readonly my $MF_SIMPLE => <<'END_MF';
WriteMakefile(
	PREREQ_PM => {
		'Try::Tiny' => 0,
		'Moo'       => '2.000',   # object system
	},
	TEST_REQUIRES => {
		'Test::More' => 0,
	},
	MIN_PERL_VERSION => '5.010',
);
END_MF

# A minimal deps hashref used to drive _emit without going through parse_prereqs.

t/function.t  view on Meta::CPAN

# Strategy: test comment capture, blank/comment line skipping, first-
# occurrence-wins across a single call and across multiple calls, return
# value, and in-place mutation semantics.
# -----------------------------------------------------------------------
subtest '_extract_pairs — block parser' => sub {

	# Basic: one module with version zero, one with an explicit version.
	{
		my %deps;
		App::makefilepl2cpanfile::_extract_pairs(
			"    'Try::Tiny' => 0,\n    'Moo' => '2.000',\n",
			\%deps, 'runtime', 'requires',
		);

		ok  exists $deps{runtime}{requires}{'Try::Tiny'}, 'Try::Tiny extracted';
		is  $deps{runtime}{requires}{'Try::Tiny'}{version}, 0, 'version 0 stored';
		is  $deps{runtime}{requires}{'Try::Tiny'}{comment}, undef, 'no comment stored as undef';

		ok  exists $deps{runtime}{requires}{'Moo'}, 'Moo extracted';
		is  $deps{runtime}{requires}{'Moo'}{version}, '2.000', 'explicit version stored';
	}

	# Inline comment must be captured before the comment text is stripped.
	{
		my %deps;
		App::makefilepl2cpanfile::_extract_pairs(
			"    'Foo::Bar' => 0,   # used in bin/ scripts\n",

t/function.t  view on Meta::CPAN

subtest 'generate — integration: parse, merge, format' => sub {

	# Redirect config loading to an empty home so default develop tools are
	# injected whenever with_develop => 1 is in effect.  The guard is held for
	# the entire subtest; it restores File::HomeDir when the sub returns.
	my $empty_home = tempdir( CLEANUP => 1 );
	my $g = mock_scoped 'File::HomeDir::my_home' => sub { $empty_home };

	my $dir = tempdir( CLEANUP => 1 );
	my $mf  = path($dir)->child('Makefile.PL');
	$mf->spew_utf8("WriteMakefile(PREREQ_PM => { 'Try::Tiny' => 0 });\n");

	# ---- Guard: croak on missing file ----
	throws_ok {
		App::makefilepl2cpanfile::generate( makefile => "$dir/nonexistent.pl" )
	}
		qr/Cannot read/,
		'croaks with "Cannot read" for missing makefile';

	# ---- Guard: croak when path is a directory, not a file ----
	throws_ok {
		App::makefilepl2cpanfile::generate( makefile => $dir )
	}
		qr/Cannot read/,
		'croaks when path is a directory';

	# ---- Minimal valid Makefile.PL ----
	{
		my $out;
		lives_ok { $out = App::makefilepl2cpanfile::generate( makefile => "$mf", with_develop => 0 ) }
			'lives with a valid minimal Makefile.PL';
		like $out, qr/requires 'Try::Tiny'/, 'module appears in output';
		like $out, qr/\n$/, 'output ends with a newline';
	}

	# ---- Flat-hash calling style ----
	{
		my $r = App::makefilepl2cpanfile::generate( makefile => "$mf", with_develop => 0 );
		like $r, qr/requires 'Try::Tiny'/, 'flat hash calling style works';
	}

	# ---- Hashref calling style ----
	{
		my $r = App::makefilepl2cpanfile::generate(
			{ makefile => "$mf", with_develop => 0 }
		);
		like $r, qr/requires 'Try::Tiny'/, 'hashref calling style works';
	}

	# ---- with_develop defaults to 1 when the argument is omitted ----
	{
		my $r = App::makefilepl2cpanfile::generate( makefile => "$mf" );
		like $r, qr/Perl::Critic/, 'with_develop defaults to 1 — develop block present';
	}

	# ---- with_develop => 0 suppresses the develop block entirely ----
	{

t/integration.t  view on Meta::CPAN

# -----------------------------------------------------------------------
# Fixture constants — shared across all subtests.
# -----------------------------------------------------------------------

# Makefile.PL with only PREREQ_PM entries; no version constraints, no comments.
Readonly my $MF_SIMPLE => <<'END';
use ExtUtils::MakeMaker;
WriteMakefile(
	PREREQ_PM => {
		'Moo'     => 0,
		'Try::Tiny' => 0,
	},
);
END

# Makefile.PL with all four simple key types.
Readonly my $MF_ALL_PHASES => <<'END';
use ExtUtils::MakeMaker;
WriteMakefile(
	CONFIGURE_REQUIRES => { 'ExtUtils::MakeMaker' => '6.64' },
	BUILD_REQUIRES     => { 'Module::Build' => '0.42' },

t/integration.t  view on Meta::CPAN

#
# Strategy: call generate() with two different Makefile.PLs (A and B),
# then call generate() for A again.  The first and third outputs must be
# identical, and A must differ from B.  This confirms no shared mutable
# state exists between calls.
# -----------------------------------------------------------------------

subtest 'statelessness: independent generate() calls do not interfere' => sub {
	my $g = empty_home();

	my $mf_a = make_mf($MF_SIMPLE);       # Moo + Try::Tiny
	my $mf_b = make_mf($MF_ALL_PHASES);   # completely different modules

	my $out_a1 = App::makefilepl2cpanfile::generate(
		makefile => "$mf_a", with_develop => 0
	);
	my $out_b = App::makefilepl2cpanfile::generate(
		makefile => "$mf_b", with_develop => 0
	);
	my $out_a2 = App::makefilepl2cpanfile::generate(
		makefile => "$mf_a", with_develop => 0

t/parse_prereqs.t  view on Meta::CPAN

use App::makefilepl2cpanfile;

# -----------------------------------------------------------------------
# Basic extraction — simple PREREQ_PM / TEST_REQUIRES / etc. form
# -----------------------------------------------------------------------

my $content = <<'END_MF';
WriteMakefile(
	PREREQ_PM => {
		'Moo'       => '2.000',
		'Try::Tiny' => 0,
	},
	TEST_REQUIRES => {
		'Test::More' => 0,
	},
	CONFIGURE_REQUIRES => {
		'ExtUtils::MakeMaker' => '6.64',
	},
	BUILD_REQUIRES => {
		'Module::Build' => '0.42',
	},

t/parse_prereqs.t  view on Meta::CPAN

END_MF

my $deps = App::makefilepl2cpanfile::parse_prereqs($content);

isa_ok $deps, 'HASH', 'parse_prereqs returns a hashref';

# The simple keys all map to the 'requires' relationship.
ok exists $deps->{runtime}{requires}{'Moo'},       'Moo is in runtime/requires';
is $deps->{runtime}{requires}{'Moo'}{version}, '2.000', 'Moo carries its version';

ok exists $deps->{runtime}{requires}{'Try::Tiny'}, 'Try::Tiny is in runtime/requires';
is $deps->{runtime}{requires}{'Try::Tiny'}{version}, 0, 'Try::Tiny version is 0';

ok exists $deps->{test}{requires}{'Test::More'},   'Test::More in test/requires';

ok exists $deps->{configure}{requires}{'ExtUtils::MakeMaker'}, 'EMM in configure/requires';
is $deps->{configure}{requires}{'ExtUtils::MakeMaker'}{version}, '6.64',
    'ExtUtils::MakeMaker version correct';

ok exists $deps->{build}{requires}{'Module::Build'}, 'Module::Build in build/requires';
is $deps->{build}{requires}{'Module::Build'}{version}, '0.42',
    'Module::Build version correct';

t/unit.t  view on Meta::CPAN

# Write a Makefile.PL into a tempdir and return its path object.
sub make_mf {
	my ($content) = @_;
	my $dir = tempdir( CLEANUP => 1 );
	my $mf  = path($dir)->child('Makefile.PL');
	$mf->spew_utf8($content);
	return $mf;
}

Readonly my $MF_SIMPLE =>
	"WriteMakefile(PREREQ_PM => { 'Try::Tiny' => 0 });\n";

Readonly my $MF_VERSIONED =>
	"WriteMakefile(PREREQ_PM => { 'Moo' => '2.000' });\n";

# -----------------------------------------------------------------------
# generate() — error / message paths
# -----------------------------------------------------------------------

subtest 'generate() — croak on unreadable makefile' => sub {
	my $g = empty_home();

t/unit.t  view on Meta::CPAN

	my $dir = tempdir( CLEANUP => 1 );
	path($dir)->child('Makefile.PL')->spew_utf8($MF_SIMPLE);

	my $orig = Path::Tiny->cwd;
	chdir $dir;

	my $out;
	lives_ok {
		$out = App::makefilepl2cpanfile::generate( with_develop => 0 )
	} 'generate() reads Makefile.PL from cwd when no makefile arg given';
	like $out, qr/Try::Tiny/, 'content from default Makefile.PL appears in output';

	chdir "$orig";
	covered('generate.arg.default_makefile');
};

subtest 'generate() — default argument: existing is empty string' => sub {
	my $g = empty_home();

	# When 'existing' is omitted, no pre-existing develop entries should be
	# merged (there are none to merge from an empty string).

t/unit.t  view on Meta::CPAN

	my $out;
	lives_ok {
		$out = App::makefilepl2cpanfile::generate(
			makefile     => "$mf",
			with_develop => 0,
		)
	} 'generate() with no existing arg lives';

	# The output must contain the parsed module but no phantom develop entries
	# from a non-existent pre-existing cpanfile.
	like   $out, qr/Try::Tiny/, 'parsed module present';
	unlike $out, qr/on 'develop' => sub/, 'no develop block from empty existing';
	covered('generate.arg.default_existing_empty');
};

subtest 'generate() — default argument: with_develop is 1 (true)' => sub {
	my $g = empty_home();    # no config file -> uses DEFAULT_DEVELOP

	my $mf  = make_mf($MF_SIMPLE);
	my $out = App::makefilepl2cpanfile::generate( makefile => "$mf" );

t/unit.t  view on Meta::CPAN

};

# -----------------------------------------------------------------------
# generate() — calling style variants
# -----------------------------------------------------------------------

subtest 'generate() — flat hash calling style' => sub {
	my $g = empty_home();
	my $mf  = make_mf($MF_SIMPLE);
	my $out = App::makefilepl2cpanfile::generate( makefile => "$mf", with_develop => 0 );
	like $out, qr/Try::Tiny/, 'flat hash calling style works';
	covered('generate.calling.flat_hash');
};

subtest 'generate() — hashref calling style' => sub {
	my $g = empty_home();
	my $mf  = make_mf($MF_SIMPLE);
	my $out = App::makefilepl2cpanfile::generate(
		{ makefile => "$mf", with_develop => 0 }
	);
	like $out, qr/Try::Tiny/, 'single hashref calling style works';
	covered('generate.calling.hashref');
};

# -----------------------------------------------------------------------
# generate() — with_develop behaviour
# -----------------------------------------------------------------------

subtest 'generate() — develop block injected when with_develop => 1' => sub {
	# Use an empty home so default tools (Perl::Critic etc.) are injected.
	my $g = empty_home();



( run in 0.803 second using v1.01-cache-2.11-cpan-5fbc6bb55f2 )