App-Sqitch
view release on metacpan or search on metacpan
use Test::More tests => 243;
#use Test::More 'no_plan';
use App::Sqitch;
use App::Sqitch::Target;
use Locale::TextDomain qw(App-Sqitch);
use Path::Class;
use Test::Exception;
use Test::Warn;
use Test::Dir;
use File::Temp 'tempdir';
use Test::File qw(file_not_exists_ok file_exists_ok);
use Test::File::Contents 0.05;
use File::Path qw(make_path remove_tree);
use Test::NoWarnings 0.083;
use lib 't/lib';
use MockOutput;
use TestConfig;
my $CLASS = 'App::Sqitch::Command::add';
my $config = TestConfig->new(
# Test _add().
my $test_add = sub {
my $engine = shift;
make_path 'test-add';
my $fn = $target->plan_file;
open my $fh, '>', $fn or die "Cannot open $fn: $!";
say $fh "%project=add\n\n";
close $fh or die "Error closing $fn: $!";
END { remove_tree 'test-add' };
my $out = file 'test-add', 'sqitch_change_test.sql';
file_not_exists_ok $out;
ok my $add = $CLASS->new(
sqitch => $sqitch,
template_directory => $tmpldir,
), 'Create add command';
ok $add->_add('sqitch_change_test', $out, $tmpl, 'sqlite', 'add'),
'Write out a script';
file_exists_ok $out;
file_contents_is $out, <<EOF, 'The template should have been evaluated';
-- Deploy add:sqitch_change_test to sqlite
$plan->_plan( $plan->load);
delete $plan->{$_} for qw(_changes _lines project uri);
};
my $deploy_file = file qw(test-add deploy widgets_table.sql);
my $revert_file = file qw(test-add revert widgets_table.sql);
my $verify_file = file qw(test-add verify widgets_table.sql);
my $plan = $add->default_target->plan;
is $plan->get('widgets_table'), undef, 'Should not have "widgets_table" in plan';
dir_not_exists_ok +File::Spec->catdir('test-add', $_) for qw(deploy revert verify);
ok $add->execute('widgets_table'), 'Add change "widgets_table"';
# Reload the plan.
$reload->($plan);
# Make sure the change was written to the plan file.
isa_ok my $change = $plan->get('widgets_table'), 'App::Sqitch::Plan::Change',
'Added change';
is $change->name, 'widgets_table', 'Change name should be set';
is_deeply [$change->requires], [], 'It should have no requires';
with_scripts => { verify => 0 },
template_directory => $tmpldir,
), 'Create another add with template_directory and no verify script';
$deploy_file = file qw(test-add deploy foo_table.sql);
$revert_file = file qw(test-add revert foo_table.sql);
$verify_file = file qw(test-add ferify foo_table.sql);
$deploy_file->touch;
file_exists_ok $deploy_file;
file_not_exists_ok $_ for ($revert_file, $verify_file);
is $plan->get('foo_table'), undef, 'Should not have "foo_table" in plan';
ok $add->execute, 'Add change "foo_table"';
file_exists_ok $_ for ($deploy_file, $revert_file);
file_not_exists_ok $verify_file;
$plan = $add->default_target->plan;
isa_ok $change = $plan->get('foo_table'), 'App::Sqitch::Plan::Change',
'"foo_table" change';
is_deeply \%request_params, {
for => __ 'add',
scripts => [$change->deploy_file, $change->revert_file],
}, 'It should have prompted for a note';
is $change->name, 'foo_table', 'Change name should be set to "foo_table"';
is_deeply [$change->requires], [dep 0, 'widgets_table'], 'It should have requires';
'Added change';
is $change->name, 'custom_script', 'Change name should be set';
is_deeply [$change->requires], [], 'It should have no requires';
is_deeply [$change->conflicts], [], 'It should have no conflicts';
is_deeply \%request_params, {
for => __ 'add',
scripts => [ map { $change->script_file($_) } qw(deploy revert whatev)]
}, 'It should have prompted for a note';
file_exists_ok $_ for ($deploy_file, $revert_file, $whatev_file);
file_not_exists_ok $verify_file;
file_contents_like $deploy_file, qr/^-- Deploy add:custom_script/,
'Deploy script should look right';
file_contents_like $revert_file, qr/^-- Revert add:custom_script/,
'Revert script should look right';
file_contents_like $whatev_file, qr/^-- Verify add:custom_script/,
'Whatev script should look right';
file_contents_unlike $whatev_file, qr/^BEGIN/,
'Whatev script should be based on the MySQL verify script';
is_deeply +MockOutput->get_info, [
[__x 'Created {file}', file => $deploy_file],
ok !$targets{pg}->plan->get('choc'), 'Should not have "choc" in the pg plan';
ok !$targets{mysql}->plan->get('choc'), 'Should not have "choc" in the mysql plan';
ok $targets{sqlite}->plan->get('choc'), 'Should have "choc" in the sqlite plan';
@scripts = map {
my $dir = dir $_;
$dir->mkpath;
map { $dir->file($_, 'choc.sql') } qw(deploy revert verify);
} qw(sqlite pg mysql);
file_exists_ok $_ for @scripts[0..2];
file_not_exists_ok $_ for @scripts[3..8];
is_deeply +MockOutput->get_info, [
(map { [__x 'Created {file}', file => $_] } @scripts[0..2]),
[
__x 'Added "{change}" to {file}',
change => 'choc',
file => $targets{sqlite}->plan_file,
],
], 'Info should have reported sqlite choc script creations and plan updates';
chdir File::Spec->updir;
use strict;
use warnings;
use utf8;
use Test::More tests => 301;
#use Test::More 'no_plan';
use App::Sqitch;
use Path::Class;
use Test::Exception;
use Test::Warn;
use Test::File qw(file_exists_ok file_not_exists_ok);
use Test::File::Contents;
use Locale::TextDomain qw(App-Sqitch);
use File::Path qw(remove_tree);
use Test::NoWarnings;
use lib 't/lib';
use MockOutput;
use TestConfig;
my $CLASS = 'App::Sqitch::Command::bundle';
is $dir_for->{$sub}, $dir->subdir('engine', $sub),
"Dest $sub dir should be _build/sql/engine/$sub";
}
##############################################################################
# Test _copy().
my $path = dir 'delete.me';
END { remove_tree $path->stringify if -e $path }
my $file = file qw(sql deploy roles.sql);
my $dest = file $path, qw(deploy roles.sql);
file_not_exists_ok $dest, "File $dest should not exist";
ok $bundle->_copy_if_modified($file, $dest), "Copy $file to $dest";
file_exists_ok $dest, "File $dest should now exist";
file_contents_identical $dest, $file;
is_deeply +MockOutput->get_debug, [
[' ', __x 'Created {file}', file => $dest->dir],
[' ', __x(
"Copying {source} -> {dest}",
source => $file,
dest => $dest
)],
), 'Copy fail error message should be correct';
}
##############################################################################
# Test bundle_config().
END {
my $to_remove = $dir->parent->stringify;
remove_tree $to_remove if -e $to_remove;
}
$dest = file $dir, qw(sqitch.conf);
file_not_exists_ok $dest;
ok $bundle->bundle_config, 'Bundle the config file';
file_exists_ok $dest;
file_contents_identical $dest, file('sqitch.conf');
is_deeply +MockOutput->get_info, [[__ 'Writing config']],
'Should have config notice';
##############################################################################
# Test bundle_plan().
$dest = file $bundle->dest_top_dir($bundle->default_target), qw(sqitch.plan);
file_not_exists_ok $dest;
ok $bundle->bundle_plan($bundle->default_target),
'Bundle the default target plan file';
file_exists_ok $dest;
file_contents_identical $dest, file(qw(engine sqitch.plan));
is_deeply +MockOutput->get_info, [[__ 'Writing plan']],
'Should have plan notice';
# Make sure that --from works.
isa_ok $bundle = App::Sqitch::Command->load({
sqitch => $sqitch,
my @scripts = (
$dir_for->{reworked_deploy}->file('users@alpha.sql'),
$dir_for->{reworked_revert}->file('users@alpha.sql'),
$dir_for->{deploy}->file('widgets.sql'),
$dir_for->{revert}->file('widgets.sql'),
$dir_for->{deploy}->file(qw(func add_user.sql)),
$dir_for->{revert}->file(qw(func add_user.sql)),
$dir_for->{deploy}->file('users.sql'),
$dir_for->{revert}->file('users.sql'),
);
file_not_exists_ok $_ for @scripts;
$config->update( 'core.extension' => 'sql');
isa_ok $bundle = App::Sqitch::Command->load({
sqitch => $sqitch,
command => 'bundle',
config => $config,
}), $CLASS, 'another bundle command';
ok $bundle->bundle_scripts($bundle->default_target),
'Bundle default target scripts';
file_exists_ok $_ for @scripts;
is_deeply +MockOutput->get_info, [
], 'Should have change notices';
# Make sure that --from works.
remove_tree $dir->parent->stringify;
isa_ok $bundle = App::Sqitch::Command::bundle->new(
sqitch => $sqitch,
dest_dir => $bundle->dest_dir,
from => 'widgets',
), $CLASS, 'bundle from "widgets"';
ok $bundle->bundle_scripts($bundle->default_target, 'widgets'), 'Bundle scripts';
file_not_exists_ok $_ for @scripts[0,1];
file_exists_ok $_ for @scripts[2,3];
is_deeply +MockOutput->get_info, [
[__ 'Writing scripts'],
[' + ', 'widgets'],
[' + ', 'func/add_user'],
[' + ', 'users'],
], 'Should have changes only from "widets" onward in notices';
# Make sure that --to works.
remove_tree $dir->parent->stringify;
isa_ok $bundle = App::Sqitch::Command::bundle->new(
sqitch => $sqitch,
dest_dir => $bundle->dest_dir,
to => 'users@alpha',
), $CLASS, 'bundle to "users"';
ok $bundle->bundle_scripts($bundle->default_target, undef, 'users@alpha'), 'Bundle scripts';
file_exists_ok $_ for @scripts[0,1];
file_not_exists_ok $_ for @scripts[2,3];
is_deeply +MockOutput->get_info, [
[__ 'Writing scripts'],
[' + ', 'users @alpha'],
], 'Should have only "users" in change notices';
# Should throw exceptions on unknonw changes.
for my $key (qw(from to)) {
my $bundle = $CLASS->new( sqitch => $sqitch, $key => 'nonexistent' );
throws_ok {
$bundle->bundle_scripts($bundle->default_target, 'nonexistent')
##############################################################################
# Test execute().
MockOutput->get_debug;
remove_tree $dir->parent->stringify;
@scripts = (
file($dir, 'sqitch.conf'),
file($bundle->dest_top_dir($bundle->default_target), 'sqitch.plan'),
@scripts,
);
file_not_exists_ok $_ for @scripts;
isa_ok $bundle = App::Sqitch::Command->load({
sqitch => $sqitch,
command => 'bundle',
config => $config,
}), $CLASS, 'another bundle command';
ok $bundle->execute, 'Execute!';
file_exists_ok $_ for @scripts;
is_deeply +MockOutput->get_info, [
[__x 'Bundling into {dir}', dir => $bundle->dest_dir ],
[__ 'Writing config'],
$multidir->file(qw(engine reworked deploy users@alpha.sql)),
$multidir->file(qw(engine reworked revert users@alpha.sql)),
$multidir->file(qw(engine deploy widgets.sql)),
$multidir->file(qw(engine revert widgets.sql)),
$multidir->file(qw(engine deploy func add_user.sql)),
$multidir->file(qw(engine revert func add_user.sql)),
$multidir->file(qw(engine deploy users.sql)),
$multidir->file(qw(engine revert users.sql)),
);
my $conf_file = $multidir->file('multiplan.conf'),;
file_not_exists_ok $_ for ($conf_file, @sql, @engine);
$config = TestConfig->from(local => 'multiplan.conf');
$sqitch = App::Sqitch->new(config => $config);
isa_ok $bundle = $CLASS->new(
sqitch => $sqitch,
config => $config,
all => 1,
from => '@ROOT',
dest_dir => dir '_build',
), $CLASS, 'all multiplan bundle command';
# Try without --all.
isa_ok $bundle = $CLASS->new(
sqitch => $sqitch,
config => $sqitch->config,
dest_dir => dir '_build',
), $CLASS, 'multiplan bundle command';
remove_tree $multidir->stringify;
ok $bundle->execute, qq{Execute with no arg};
file_exists_ok $_ for ($conf_file, @engine);
file_not_exists_ok $_ for @sql;
# Make sure it works with bundle.all set, as well.
$config->update('bundle.all' => 1);
remove_tree $multidir->stringify;
ok $bundle->execute, qq{Execute with bundle.all config};
file_exists_ok $_ for ($conf_file, @engine, @sql);
# Try limiting it in various ways.
for my $spec (
[
],
[
'plan file' => file(qw(sql sqitch.plan))->stringify,
{ include => \@sql, exclude => \@engine },
],
) {
my ($type, $arg, $files) = @{ $spec };
remove_tree $multidir->stringify;
ok $bundle->execute($arg), qq{Execute with $type arg "$arg"};
file_exists_ok $_ for ($conf_file, @{ $files->{include} });
file_not_exists_ok $_ for @{ $files->{exclude} };
}
# Make sure we handle --to and --from.
isa_ok $bundle = $CLASS->new(
sqitch => $sqitch,
config => $sqitch->config,
from => 'widgets',
to => 'widgets',
dest_dir => dir '_build',
), $CLASS, 'to/from bundle command';
remove_tree $multidir->stringify;
ok $bundle->execute('pg'), 'Execute to/from bundle!';
file_exists_ok $_ for ($conf_file, @engine[0,3,4]);
file_not_exists_ok $_ for (@engine[1,2,5..$#engine]);
file_contents_is $engine[0],
'%syntax-version=' . App::Sqitch::Plan::SYNTAX_VERSION . "\n"
. '%project=engine' . "\n"
. "\n"
. $plan->find('widgets')->as_string . "\n",
'Plan should have written only "widgets"';
# Make sure we handle to and from args.
isa_ok $bundle = $CLASS->new(
sqitch => $sqitch,
config => $sqitch->config,
dest_dir => dir '_build',
), $CLASS, 'another bundle command';
remove_tree $multidir->stringify;
ok $bundle->execute(qw(pg widgets @HEAD)), 'Execute bundle with to/from args!';
file_exists_ok $_ for ($conf_file, @engine[0,3..$#engine]);
file_not_exists_ok $_ for (@engine[1,2]);
file_contents_is $engine[0],
'%syntax-version=' . App::Sqitch::Plan::SYNTAX_VERSION . "\n"
. '%project=engine' . "\n"
. "\n"
. $plan->find('widgets')->as_string . "\n"
. $plan->find('func/add_user')->as_string . "\n"
. $plan->find('users@HEAD')->as_string . "\n",
'Plan should have written "widgets" and "func/add_user"';
# Should die on unknown argument.
t/command.t view on Meta::CPAN
like capture_stderr {
throws_ok { $cmd->usage('Invalid whozit') } qr/EXITED: 2/
}, qr/\Qsqitch <command> [options] [command-options] [args]/,
'usage should prefer sqitch-$command-usage';
##############################################################################
# Test _mkpath.
require MockOutput;
my $path = dir 'delete.me';
dir_not_exists_ok $path, "Path $path should not exist";
END { remove_tree $path->stringify if -e $path }
ok $cmd->_mkpath($path), "Create $path";
dir_exists_ok $path, "Path $path should now exist";
is_deeply +MockOutput->get_debug, [[' ', __x 'Created {file}', file => $path]],
'The mkdir info should have been output';
# Create it again.
ok $cmd->_mkpath($path), "Create $path again";
dir_exists_ok $path, "Path $path should still exist";
is_deeply +MockOutput->get_debug, [], 'Nothing should have been emitted';
t/engine_cmd.t view on Meta::CPAN
use strict;
use warnings;
use utf8;
use Test::More tests => 201;
# use Test::More 'no_plan';
use App::Sqitch;
use Locale::TextDomain qw(App-Sqitch);
use Test::Exception;
use Test::Warn;
use Test::Dir;
use Test::File qw(file_not_exists_ok file_exists_ok);
use Test::NoWarnings;
use File::Copy;
use Path::Class;
use List::Util qw(max);
use File::Temp 'tempdir';
use lib 't/lib';
use MockOutput;
use TestConfig;
my $CLASS = 'App::Sqitch::Command::engine';
t/engine_cmd.t view on Meta::CPAN
# Should die on existing key.
throws_ok { $cmd->add('pg') } 'App::Sqitch::X',
'Should get error for existing engine';
is $@->ident, 'engine', 'Existing engine error ident should be "engine"';
is $@->message, __x(
'Engine "{engine}" already exists',
engine => 'pg'
), 'Existing engine error message should be correct';
# Now add a new engine.
dir_not_exists_ok $_ for qw(deploy revert verify);
ok $cmd->add('vertica'), 'Add engine "vertica"';
dir_exists_ok $_ for qw(deploy revert verify);
$config->load;
is $config->get(key => 'engine.vertica.target'), 'db:vertica:',
'Engine "test" target should have been set';
for my $key (qw(
client
registry
top_dir
plan_file
t/engine_cmd.t view on Meta::CPAN
verify_dir => dir('ver'),
reworked_dir => dir('r'),
reworked_deploy_dir => dir('r/d'),
extension => 'ddl',
variables => { ay => 'first', Bee => 'second' },
);
isa_ok $cmd = $CLASS->new({
sqitch => $sqitch,
properties => { %props },
}), $CLASS, 'Engine with all properties';
file_not_exists_ok 'my.plan';
dir_not_exists_ok dir $_ for qw(top/deploy top/revert top/verify r/d r/revert r/verify);
ok $cmd->add('firebird'), 'Add engine "firebird"';
dir_exists_ok dir $_ for qw(top/deploy top/revert top/verify r/d r/revert r/verify);
file_exists_ok 'my.plan';
$config->load;
while (my ($k, $v) = each %props) {
if ($k ne 'variables') {
is $config->get(key => "engine.firebird.$k"), $v,
qq{Engine "firebird" should have $k set};
} else {
is_deeply $config->get_section(section => "engine.firebird.$k"), $v,
t/engine_cmd.t view on Meta::CPAN
is_deeply $config->get_section(section => "engine.firebird.$k"), $v,
qq{Engine "firebird" should have $k};
}
}
# Try changing the top directory.
isa_ok $cmd = $CLASS->new({
sqitch => $sqitch,
properties => { top_dir => dir 'pg' },
}), $CLASS, 'Engine with new top_dir property';
dir_not_exists_ok dir $_ for qw(pg pg/deploy pg/revert pg/verify);
ok $cmd->alter('pg'), 'Alter engine "pg"';
dir_exists_ok dir $_ for qw(pg pg/deploy pg/revert pg/verify);
$config->load;
is $config->get(key => 'engine.pg.top_dir'), 'pg',
'The pg top_dir should have been set';
# An attempt to alter a missing engine should show the target if in props.
throws_ok { $cmd->alter('oracle') } 'App::Sqitch::X',
'Should again get error for missing engine';
is $@->ident, 'engine', 'Missing engine error ident should still be "engine"';
use strict;
use warnings;
use 5.010;
use utf8;
use Test::More tests => 196;
# use Test::More 'no_plan';
use App::Sqitch;
use Locale::TextDomain qw(App-Sqitch);
use Path::Class;
use Test::Dir;
use Test::File qw(file_not_exists_ok file_exists_ok);
use Test::Exception;
use Test::Warn;
use Test::File::Contents;
use Test::NoWarnings;
use File::Path qw(remove_tree make_path);
use URI;
use lib 't/lib';
use MockOutput;
use TestConfig;
'Unknown directory names: {dirs}',
2,
dirs => 'cavort, foo',
), 'The invalid properties messsage should be correct';
isa_ok my $target = $init->config_target, 'App::Sqitch::Target', 'default target';
##############################################################################
# Test make_directories_for.
can_ok $init, 'make_directories_for';
dir_not_exists_ok $target->top_dir;
dir_not_exists_ok $_ for $init->directories_for($target);
my $top_dir_string = $target->top_dir->stringify;
END { remove_tree $top_dir_string if -e $top_dir_string }
ok $init->make_directories_for($target), 'Make the directories';
dir_exists_ok $_ for $init->directories_for($target);
my $sep = dir('')->stringify;
my $dirs = $init->properties;
is_deeply +MockOutput->get_info, [
END { remove_tree $write_dir }
chdir $write_dir;
END { chdir File::Spec->updir }
my $conf_file = $sqitch->config->local_file;
my $uri = URI->new('https://github.com/sqitchers/sqitch/');
ok $init = $CLASS->new(
sqitch => $sqitch,
), 'Another init object';
file_not_exists_ok $conf_file;
$target = $init->config_target;
# Write empty config.
ok $init->write_config, 'Write the config';
file_exists_ok $conf_file;
is_deeply $config->data_from($conf_file), {
}, 'The configuration file should have no variables';
is_deeply +MockOutput->get_info, [
[__x 'Created {file}', file => $conf_file]
], 'The creation should be sent to info';
is_deeply +MockOutput->get_info, [
], 'Nothing should have been sent to info';
USERCONF: {
# Delete the file and write with a user config loaded.
unlink $conf_file;
my $config = TestConfig->from( user => file +File::Spec->updir, 'user.conf' );
my $sqitch = App::Sqitch->new(config => $config);
ok my $init = $CLASS->new( sqitch => $sqitch, properties => { extension => 'foo' }),
'Make an init object with user config';
file_not_exists_ok $conf_file;
ok $init->write_config, 'Write the config with a user conf';
file_exists_ok $conf_file;
is_deeply $config->data_from($conf_file), {
'core.extension' => 'foo',
}, 'The configuration should just have core.top_dir';
is_deeply +MockOutput->get_info, [
[__x 'Created {file}', file => $conf_file]
], 'The creation should be sent to info again';
file_contents_like $conf_file, qr{\Q
# engine =
}
SYSTEMCONF: {
# Delete the file and write with a system config loaded.
unlink $conf_file;
my $config = TestConfig->from( system => file +File::Spec->updir, 'sqitch.conf' );
my $sqitch = App::Sqitch->new(config => $config);
ok my $init = $CLASS->new( sqitch => $sqitch, properties => { extension => 'foo' } ),
'Make an init object with system config';
ok $target = $init->config_target, 'Get target';
file_not_exists_ok $conf_file;
ok $init->write_config, 'Write the config with a system conf';
file_exists_ok $conf_file;
is_deeply $config->data_from($conf_file), {
'core.extension' => 'foo',
'core.engine' => 'pg',
}, 'The configuration should have local and system config' or diag $conf_file->slurp;
is_deeply +MockOutput->get_info, [
[__x 'Created {file}', file => $conf_file]
], 'The creation should be sent to info again';
# Now build it with other config.
USERCONF: {
# Delete the file and write with a user config loaded.
unlink $conf_file;
my $config = TestConfig->from( user => file +File::Spec->updir, 'user.conf' );
$config->update('core.engine' => 'sqlite');
my $sqitch = App::Sqitch->new(config => $config);
ok my $init = $CLASS->new( sqitch => $sqitch ),
'Make an init with sqlite and user config';
file_not_exists_ok $conf_file;
ok $init->write_config, 'Write the config with sqlite config';
is_deeply +MockOutput->get_info, [
[__x 'Created {file}', file => $conf_file]
], 'The creation should be sent to info once more';
is_deeply $config->data_from($conf_file), {
'core.engine' => 'sqlite',
}, 'New config should have been written with sqlite values';
file_contents_like $conf_file, qr{^\t\Q# client = /opt/local/bin/sqlite3\E\n}m,
}m, 'Engine section should be present but commented-out' or diag $conf_file->slurp;
USERCONF: {
# Delete the file and write with a user config loaded.
unlink $conf_file;
my $config = TestConfig->from( user => file +File::Spec->updir, 'user.conf' );
$config->update('core.engine' => 'pg');
my $sqitch = App::Sqitch->new(config => $config);
ok my $init = $CLASS->new( sqitch => $sqitch ),
'Make an init with pg and user config';
file_not_exists_ok $conf_file;
ok $init->write_config, 'Write the config with pg config';
is_deeply +MockOutput->get_info, [
[__x 'Created {file}', file => $conf_file]
], 'The pg config creation should be sent to info';
is_deeply $config->data_from($conf_file), {
'core.engine' => 'pg',
}, 'The configuration should have been written with pg options' or diag $conf_file->slurp;
file_contents_like $conf_file, qr/^\t# registry = meta\n/m,
file_contents_like $conf_file,
qr{^\t# target = db:pg://postgres\@localhost/thingies\n}m,
'Configured target should be in a comment';
}
##############################################################################
# Test write_plan().
can_ok $init, 'write_plan';
$target = $init->config_target;
$plan_file = $target->plan_file;
file_not_exists_ok $plan_file, 'Plan file should not yet exist';
ok $init->write_plan( project => 'nada' ), 'Write the plan file';
is_deeply +MockOutput->get_info, [
[__x 'Created {file}', file => $plan_file]
], 'The plan creation should be sent to info';
file_exists_ok $plan_file, 'Plan file should now exist';
file_contents_is $plan_file,
'%syntax-version=' . App::Sqitch::Plan::SYNTAX_VERSION() . "\n" .
'%project=nada' . "\n\n",
'The contents should be correct';
[qw(you)], 'Search with offset 2, limit 1, direction "desc" should work';
is_deeply $get_all_names->( $plan->search_changes( limit => 3, direction => 'desc' ) ),
[qw(hey-there this/rocks you)], 'Search with limit 3, direction "desc" should work';
##############################################################################
# Test writing the plan.
can_ok $plan, 'write_to';
my $to = file 'plan.out';
END { unlink $to }
file_not_exists_ok $to;
ok $plan->write_to($to), 'Write out the file';
file_exists_ok $to;
my $v = App::Sqitch->VERSION;
file_contents_is $to,
'%syntax-version=' . App::Sqitch::Plan::SYNTAX_VERSION . "\n"
. $file->slurp(iomode => '<:utf8_strict'),
'The contents should look right';
# Make sure it will start from a certain point.
ok $plan->write_to($to, 'this/rocks'), 'Write out the file from "this/rocks"';
use warnings;
use utf8;
use Test::More tests => 256;
# use Test::More 'no_plan';
use App::Sqitch;
use Locale::TextDomain qw(App-Sqitch);
use Test::Exception;
use Test::Warn;
use App::Sqitch::Command::add;
use Path::Class;
use Test::File qw(file_not_exists_ok file_exists_ok);
use Test::File::Contents qw(file_contents_identical file_contents_is files_eq);
use File::Path qw(make_path remove_tree);
use Test::NoWarnings;
use lib 't/lib';
use MockOutput;
use TestConfig;
my $CLASS = 'App::Sqitch::Command::rework';
my $test_dir = dir 'test-rework';
# Use the same plan.
my $mock_plan = Test::MockModule->new(ref $target);
$mock_plan->mock(plan => $plan);
ok my $add = App::Sqitch::Command::add->new(
sqitch => $sqitch,
change_name => 'foo',
template_directory => Path::Class::dir(qw(etc templates))
), 'Create another add with template_directory';
file_not_exists_ok($_) for ($deploy_file, $revert_file, $verify_file);
ok $add->execute, 'Execute with the --change option';
file_exists_ok($_) for ($deploy_file, $revert_file, $verify_file);
ok my $foo = $plan->get('foo'), 'Get the "foo" change';
throws_ok { $rework->execute('foo') } 'App::Sqitch::X',
'Should get an example for duplicate change';
is $@->ident, 'plan', 'Duplicate change error ident should be "plan"';
is $@->message, __x(
qq{Cannot rework "{change}" without an intervening tag.\n}
. 'Use "sqitch tag" to create a tag and try again',
), 'Fail message should say a tag is needed';
# Tag it, and *then* it should work.
ok $plan->tag( name => '@alpha' ), 'Tag it';
my $deploy_file2 = file qw(test-rework deploy foo@alpha.sql);
my $revert_file2 = file qw(test-rework revert foo@alpha.sql);
my $verify_file2 = file qw(test-rework verify foo@alpha.sql);
MockOutput->get_info;
file_not_exists_ok($_) for ($deploy_file2, $revert_file2, $verify_file2);
ok $rework->execute('foo'), 'Rework "foo"';
# The files should have been copied.
file_exists_ok($_) for ($deploy_file, $revert_file, $verify_file);
file_exists_ok($_) for ($deploy_file2, $revert_file2, $verify_file2);
file_contents_identical($deploy_file2, $deploy_file);
file_contents_identical($verify_file2, $verify_file);
file_contents_identical($revert_file, $deploy_file);
file_contents_is($revert_file2, <<'EOF', 'New revert should revert');
-- Revert empty:foo from sqlite
##############################################################################
# Let's do that again. This time with more dependencies and fewer files.
$deploy_file = file qw(test-rework deploy bar.sql);
$revert_file = file qw(test-rework revert bar.sql);
$verify_file = file qw(test-rework verify bar.sql);
ok $add = App::Sqitch::Command::add->new(
sqitch => $sqitch,
template_directory => Path::Class::dir(qw(etc templates)),
with_scripts => { revert => 0, verify => 0 },
), 'Create another add with template_directory';
file_not_exists_ok($_) for ($deploy_file, $revert_file, $verify_file);
$add->execute('bar');
file_exists_ok($deploy_file);
file_not_exists_ok($_) for ($revert_file, $verify_file);
ok $plan->tag( name => '@beta' ), 'Tag it with @beta';
my $deploy_file3 = file qw(test-rework deploy bar@beta.sql);
my $revert_file3 = file qw(test-rework revert bar@beta.sql);
my $verify_file3 = file qw(test-rework verify bar@beta.sql);
MockOutput->get_info;
isa_ok $rework = App::Sqitch::Command::rework->new(
sqitch => $sqitch,
command => 'rework',
config => $config,
requires => ['foo'],
note => [qw(hi there)],
conflicts => ['dr_evil'],
), $CLASS, 'rework command with requirements and conflicts';
# Check the files.
file_not_exists_ok($_) for ($deploy_file3, $revert_file3, $verify_file3);
ok $rework->execute('bar'), 'Rework "bar"';
file_exists_ok($deploy_file);
file_not_exists_ok($_) for ($revert_file, $verify_file);
file_exists_ok($deploy_file3);
file_not_exists_ok($_) for ($revert_file3, $verify_file3);
# The note should have been required.
is_deeply \%request_params, {
for => __ 'rework',
scripts => [$deploy_file],
}, 'It should have prompted for a note';
# The plan file should have been updated.
ok $plan->load, 'Reload the plan file again';
ok @steps = $plan->changes, 'Get the steps';
), 'Create another add with open_editor';
ok $plan->tag( name => '@gamma' ), 'Tag it';
my $rework_file = file qw(test-rework deploy bar.sql);
my $deploy_file = file qw(test-rework deploy bar@gamma.sql);
my $revert_file = file qw(test-rework revert bar@gamma.sql);
my $verify_file = file qw(test-rework verify bar@gamma.sql);
MockOutput->get_info;
file_not_exists_ok($_) for ($deploy_file, $revert_file, $verify_file);
ok $rework->execute('bar'), 'Rework "bar"';
# The files should have been copied.
file_exists_ok($_) for ($rework_file, $deploy_file);
file_not_exists_ok($_) for ($revert_file, $verify_file);
is $shell_cmd, join(' ', $sqitch->editor, $rework_file),
'It should have prompted to edit sql files';
is_deeply +MockOutput->get_info, [
[__x(
'Added "{change}" to {file}.',
change => 'bar [bar@gamma]',
file => $target->plan_file,
)],
my $dir = dir $type;
$dir->mkpath;
my $script = $dir->file('gadgets.sql');
$script->spew("-- $dir gadgets");
push @change => $script;
push @reworked => dir('_reworked', $type)->file('gadgets@foo.sql');
}
# We should have the change scripts but not yet reworked.
file_exists_ok $_ for @change;
file_not_exists_ok '_reworked';
file_not_exists_ok $_ for @reworked;
my $config = TestConfig->from(local => $conf);
my $sqitch = App::Sqitch->new(config => $config);
ok $rework = $CLASS->new(
sqitch => $sqitch,
note => ['Testing reworked_dir'],
template_directory => dir->parent->subdir(qw(etc templates))
), 'Create another rework with custom reworked_dir config';
# Let's do this thing!
t/target_cmd.t view on Meta::CPAN
use strict;
use warnings;
use utf8;
use Test::More tests => 243;
#use Test::More 'no_plan';
use App::Sqitch;
use Locale::TextDomain qw(App-Sqitch);
use Test::Exception;
use Test::Warn;
use Test::Dir;
use Test::File qw(file_not_exists_ok file_exists_ok);
use Test::NoWarnings;
use File::Copy;
use Path::Class;
use List::Util qw(max);
use File::Temp 'tempdir';
use lib 't/lib';
use MockOutput;
use TestConfig;
my $CLASS = 'App::Sqitch::Command::target';
t/target_cmd.t view on Meta::CPAN
# Should die on existing key.
throws_ok { $cmd->add('dev', 'db:pg:') } 'App::Sqitch::X',
'Should get error for existing target';
is $@->ident, 'target', 'Existing target error ident should be "target"';
is $@->message, __x(
'Target "{target}" already exists',
target => 'dev'
), 'Existing target error message should be correct';
# Now add a new target.
dir_not_exists_ok $_ for qw(deploy revert verify);
ok $cmd->add('test', 'db:pg:test'), 'Add target "test"';
dir_exists_ok $_ for qw(deploy revert verify);
$config->load;
is $config->get(key => 'target.test.uri'), 'db:pg:test',
'Target "test" URI should have been set';
for my $key (qw(
client
registry
top_dir
plan_file
t/target_cmd.t view on Meta::CPAN
verify_dir => dir('ver'),
reworked_dir => dir('r'),
reworked_deploy_dir => dir('r/d'),
extension => 'ddl',
variables => { ay => 'first', Bee => 'second' },
);
isa_ok $cmd = $CLASS->new({
sqitch => $sqitch,
properties => { %props },
}), $CLASS, 'Target with all properties';
file_not_exists_ok 'my.plan';
dir_not_exists_ok dir $_ for qw(top/deploy top/revert top/verify r/d r/revert r/verify);
ok $cmd->add('withall', 'db:pg:withall'), 'Add target "withall"';
dir_exists_ok dir $_ for qw(top/deploy top/revert top/verify r/d r/revert r/verify);
file_exists_ok 'my.plan';
$config->load;
is $config->get(key => "target.withall.uri"), 'db:pg:withall',
qq{Target "withall" should have uri set};
while (my ($k, $v) = each %props) {
if ($k ne 'variables') {
is $config->get(key => "target.withall.$k"), $v,
qq{Target "withall" should have $k set};
t/target_cmd.t view on Meta::CPAN
is_deeply $config->get_section(section => "target.withall.$k"), $v,
qq{Target "withall" should have merged $k set};
}
}
# Try changing the top directory.
isa_ok $cmd = $CLASS->new({
sqitch => $sqitch,
properties => { top_dir => dir 'big' },
}), $CLASS, 'Target with new top_dir property';
dir_not_exists_ok dir $_ for qw(big big/deploy big/revert big/verify);
ok $cmd->alter('withall'), 'Alter target "withall"';
dir_exists_ok dir $_ for qw(big big/deploy big/revert big/verify);
$config->load;
is $config->get(key => 'target.withall.top_dir'), 'big',
'The withall top_dir should have been set';
##############################################################################
# Test rename.
MISSINGARGS: {
# Test handling of no names.
( run in 0.699 second using v1.01-cache-2.11-cpan-cc502c75498 )