The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl 
#
use warnings;
use strict;
use Prophet::Test tests => 69;
use File::Temp qw/tempfile/;

( my $_fh, $ENV{'PROPHET_APP_CONFIG'} ) =
  tempfile( UNLINK => !$ENV{PROPHET_DEBUG} );
close $_fh;    # or windows will cry :/
diag("Using config file $ENV{PROPHET_APP_CONFIG}");

use_ok('Prophet::CLI');

my $a = Prophet::CLI->new();
can_ok( $a,             'app_handle' );
can_ok( $a->app_handle, 'config' );
my $config = $a->config;
$config->load;

is_deeply( scalar $config->aliases, {}, 'initial alias is empty' );

# no news is good news
my @cmds = (
    {
        cmd     => ['show'],
        output  => qr/No aliases for the current repository/,
        comment => 'show empty aliases',
    },
    {
        cmd     => [ 'add', 'pull -a=pull --all' ],
        comment => 'add a new alias',

        # no output specified = no output expected
    },
    {
        cmd     => ['pull -a'],
        output  => qr/pull --all/,
        comment => 'new alias set correctly',
    },
    {
        # this alias is bad, please don't use it in real life
        cmd => [ 'set', 'pull -a=pull --local' ],
        comment =>
          q{changed alias 'pull -a' from 'pull --all' to 'pull --local'},
    },
    {
        cmd     => ['pull -a'],
        output  => qr/pull --local/,
        comment => 'alias changed correctly',
    },
    {
        cmd     => [ 'delete', 'pull -a' ],
        comment => q{deleted alias 'pull -a = pull --local'},
    },
    {
        cmd     => [ 'delete', 'pull -a' ],
        error   => qr/No occurrence of alias.pull -a found to unset/,
        comment => q{delete an alias that doesn't exist any more},
    },
    {
        cmd     => [ 'add', 'pull -a=pull --all' ],
        comment => 'add a new alias',
    },
    {
        cmd     => ['pull -a'],
        output  => qr/pull --all/,
        comment => 'alias is set correctly',
    },
    {
        cmd     => [ 'add', 'pull -l=pull --local' ],
        comment => 'add a new alias',
    },
    {
        cmd     => ['pull -l'],
        output  => qr/pull --local/,
        comment => 'alias is set correctly',
    },
    {
        cmd => ['show'],
        output =>
          qr/Active aliases for the current repository \(including user-wide and global\naliases if not overridden\):\n\npull -l = pull --local\npull -a = pull --all/,
        comment => 'show',
    },
    {
        cmd     => [ 'add', 'foo', 'bar', '=', 'bar', 'baz' ],
        comment => 'added alias foo bar',
    },
    {
        cmd     => ['foo bar'],
        output  => qr/bar baz/,
        comment => 'alias is set correctly',
    },
    {
        cmd     => [ 'foo', 'bar', '=bar', 'baz' ],
        comment => 'set alias foo bar again',
    },
    {
        cmd     => [ 'foo', 'bar=', 'bar', 'baz' ],
        comment => 'set alias with tail =',
    },
    {
        cmd     => ['foo bar'],
        output  => qr/bar baz/,
        comment => 'alias foo bar still the same',
    },
    {
        cmd     => [ 'delete', 'foo', 'bar' ],
        comment => 'deleted alias foo bar',
    },
    {
        cmd     => [ 'foo', 'bar' ],
        comment => 'deleted alias no longer exists',
    },
    {
        cmd => [ 'set', 'foo bar', '=', 'bar baz' ],
        comment => 'set alias again with different syntax',
    },

    # tests for alternate syntax
    {
        cmd     => [ 'foo bar', 'bar baz' ],
        comment => 'alias foo bar = bar baz didn\'t change',
    },
    {
        cmd     => [ 'foo', 'bar baz' ],
        comment => 'added alias foo',
    },
    {
        cmd     => ['foo'],
        output  => qr/bar baz/,
        comment => 'alias foo set correctly',
    },
    {
        cmd     => [ 'foo bar', 'bar' ],
        comment => 'changed alias foo bar',
    },
    {
        cmd     => [ 'pull --from http://www.example.com/', 'pfe' ],
        comment => 'added alias with weird characters',
    },
    {
        cmd     => ['pull --from http://www.example.com/'],
        output  => qr/pfe/,
        comment => 'alias with weird chars is correct',
    },

    # test cases for syntax error messages
    {
        cmd => ['add'],
        error =>
          qr/^usage: aliases.t aliases add "alias text" "cmd to translate to"$/,
        comment => 'add usage msg is correct',
    },
    {
        cmd     => ['delete'],
        error   => qr/^usage: aliases.t aliases delete "alias text"$/,
        comment => 'delete usage msg is correct',
    },

    # test warning when accidentally setting args
    {
        cmd => [ 'pt', '=', 'push', '--to', 'foo@example.com' ],
        output =>
          qr|W: You have args set that aren't used by this command! Quote your\nW: key/value if this was accidental.\nW: - offending args: to\nW: - running command with key 'alias.pt', value 'push'|,
        comment => 'warning when setting accidental arg',
    },
    {
        cmd     => [ 'delete', 'pt' ],
        comment => 'delete previous bad alias',
    },
);

for my $item (@cmds) {
    my $exp_output = defined $item->{output} ? $item->{output} : qr/^$/;
    my $exp_error  = defined $item->{error}  ? $item->{error}  : qr/^$/;

    my ( $got_output, $got_error ) =
      run_command( 'aliases', @{ $item->{cmd} } );

    like( $got_output, $exp_output, $item->{comment} . ' (STDOUT)' );
    like( $got_error,  $exp_error,  $item->{comment} . ' (STDERR)' );
}

# check aliases in config
my $aliases = Prophet::Config->new(
    app_handle => Prophet::CLI->new->app_handle,
    confname   => 'testrc'
)->aliases;

is_deeply(
    $aliases,
    {
        'pull -l'                             => 'pull --local',
        'pull -a'                             => 'pull --all',
        'foo bar'                             => 'bar',
        'foo'                                 => 'bar baz',
        'pull --from http://www.example.com/' => 'pfe',
    },
    'non empty aliases',
);

# check content in config
my $content = Prophet::Util->slurp( $ENV{PROPHET_APP_CONFIG} );
is( $content, <<EOF, 'content in config' );

[core]
	config-format-version = 0
[alias]
	pull -a = pull --all
	pull -l = pull --local
	foo = bar baz
	foo bar = bar
	pull --from http://www.example.com/ = pfe
EOF

my $template;
Prophet::Test::set_editor(
    sub {
        my $content = shift;

        $template = $content;

        $content =~
          s/^pull -l/something different/m;    # both an add and a delete
        $content =~ s/(?<=foo = )bar baz/sigh/m;    # just change a value

        return $content;
    }
);

my $output = run_command( 'aliases', 'edit' );
is( $output, <<'END_OUTPUT', 'aliases edit' );
Added alias 'something different' = 'pull --local'
Changed alias 'foo' from 'bar baz'to 'sigh'
Deleted alias 'pull -l'
END_OUTPUT

is( run_command( 'alias', 'foo' ), "sigh\n", 'Reloaded config after edit' );

# check with alias show
my $valid_settings_output = Prophet::Util->slurp('t/data/aliases.tmpl');

my $got_output = run_command( 'alias', 'show' );
is( $got_output, $valid_settings_output, 'changed alias output matches' );