### ----------------------------------------------------
### -- Bailador
### -- Licenses: MIT
### -- Authors: Tadeusz “tadzik” Sośnierz, Anthony Parsons, Carl Masak, Gabor Szabo, GlitchMr, Moritz Lenz, Panu Ervamaa, Paul Cochrane, Solomon Foster, Sterling Hanenkamp, Tobias Leich, ugexe, vendethiel, Martin Barth (ufobat), Emeric Fischer, Julien Simonet (jsimonet)
### -- File: xt/20-cli.t
### ----------------------------------------------------
use v6.c;
use lib 'xt/lib';

use File::Temp;
use Helpers;
use Test;

use Bailador::CLI;

plan 10;

my $dir = tempdir();
#diag $dir;

my $git_dir = $*CWD;
chdir($dir);
diag $*CWD;
diag "PERL6LIB=" ~ (%*ENV<PERL6LIB> // '');
# diag $*EXECUTABLE;
# $*EXECUTABLE   -> /home/travis/.rakudobrew/bin/../moar-nom/install/bin/perl6
# want to append -> /home/travis/.rakudobrew/moar-nom/install/share/perl6/site/bin';
#                ->$*EXECUTABLE.parent.parent.child('share/perl6/site/bin')
#diag "PATH=" ~  %*ENV<PATH>;

subtest {
    plan 2;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), :out, :err);
    is $p.err.get, 'Usage:' or diag "Rest of STDERR:\n" ~ $p.err.slurp;
    is $p.out.get, Nil;
    #diag $p.out.slurp: :close;
}, 'Show Usage when no parameter is supplied.';

subtest {
    plan 1;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'new', :out, :err);
    is $p.err.get, 'Usage:' or diag "Rest of STDERR:\n" ~ $p.err.slurp;
    #diag $p.out.slurp: :close;
}, 'Show Usage when <name> is not supplied.';



subtest {
    plan 10;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'new', 'App-Name', :out, :err);
    my $out = $p.out.slurp: :close;
    like $out, rx:s{Generating App\-Name};
    like $out, rx{App\-Name\/bin\/app.pl6};
    like $out, rx{App\-Name\/t\/app.t};
    like $out, rx{App\-Name\/views\/index.html};
    my $err = $p.err.slurp: :close;
    is $err, '' or diag "Rest of STDERR:\n" ~ $p.err.slurp; # TODO Why is this the empty string and above it is Nil?
    my @main_dir = dir();
    is-deeply @main_dir.map(*.Str), ('App-Name',);

    my @app_dir = dir('App-Name');
    is-deeply @app_dir.map(*.Str).sort, ('App-Name/bin', 'App-Name/t', 'App-Name/views');

    my @views_dir = dir('App-Name/views');
    is-deeply @views_dir.map(*.Str), ('App-Name/views/index.html',);

    my @bin_dir = dir('App-Name/bin/');
    is-deeply @bin_dir.map(*.Str), ('App-Name/bin/app.pl6',);

    my @t_dir = dir('App-Name/t');
    is-deeply @t_dir.map(*.Str), ('App-Name/t/app.t',);
}, 'Create application';

subtest {
    plan 2;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'new', 'App-Name', :out, :err);
    my $out = $p.out.slurp: :close;
    is $out, q{Generating App-Name
App-Name already exists. Exiting.
};
    my $err = $p.err.slurp: :close;
    is $err, ''; # TODO Why is this the empty string and above it is Nil?
}, 'Will not overwrite existing directory';

subtest {
    plan 10;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'new', 'Foo-Bar', :out, :err);
    my $out = $p.out.slurp: :close;
    like $out, rx:s{Generating Foo\-Bar};
    like $out, rx{Foo\-Bar\/bin\/app.pl6};
    like $out, rx{Foo\-Bar\/t\/app.t};
    like $out, rx{Foo\-Bar\/views\/index.html};
    my $err = $p.err.slurp: :close;
    is $err, ''; # TODO Why is this the empty string and above it is Nil?
    my @main_dir = dir();
    is-deeply @main_dir.map(*.Str).sort, ('App-Name', 'Foo-Bar',);

    my @app_dir = dir('Foo-Bar');
    is-deeply @app_dir.map(*.Str).sort, ('Foo-Bar/bin', 'Foo-Bar/t', 'Foo-Bar/views');

    my @views_dir = dir('Foo-Bar/views');
    is-deeply @views_dir.map(*.Str), ('Foo-Bar/views/index.html',);

    my @bin_dir = dir('Foo-Bar/bin/');
    is-deeply @bin_dir.map(*.Str), ('Foo-Bar/bin/app.pl6',);

    my @t_dir = dir('Foo-Bar/t');
    is-deeply @t_dir.map(*.Str), ('Foo-Bar/t/app.t',);
}, 'Create application parameters in the other order';



# Ensure that the tests in the skeleton generated by "bailador new" passess.
subtest {
    plan 3;

    chdir 'App-Name';
    # temp %*ENV<PERL6LIB> = join(':', "$git_dir/lib", |get-path-from-repo());
    # diag %*ENV<PERL6LIB>;
    # my @includes = map { "-I=" ~ $_ } ("$git_dir/lib", |get-path-from-repo());
    my $prove6 = $*EXECUTABLE.parent.parent.child('share/perl6/site/bin/prove6');
    if $prove6.IO.e {
        # my $p = run($prove6, |@includes '-l', :out, :err);
        my $p = run($prove6, '-I', "$git_dir/lib", '-l', :out, :err);
        my $exitcode = $p.exitcode;
        is $exitcode, 0, 'program terminated successfully';
        # diag "exitcode: " ~ $exitcode;
        my $out = $p.out.slurp: :close;
        like $out, rx:s/Result\: PASS/;
        # diag $out;
        my $err = $p.err.slurp: :close;
        is $err, '';
    } else {
        skip 'prove6 is not available - you need to install Tap::Harness before Bailador installs it as a dependency', 3;
    }
    # diag $err;
    chdir '..';
}, 'test newly generated app with its test cases';

# Ensure that tha application generated by "bailador new" will work
subtest {
    plan 2;

    chdir 'App-Name';

    my $port = 5007;
    my @args = "--config=host:0.0.0.0,port:$port", "-w={$git_dir.IO.child('t').child('views')}", 'watch', 'bin/app.pl6';
    my @includes = repo-to-includes();
    my $server = Proc::Async.new($*EXECUTABLE, "-I$git_dir/lib", |@includes, $git_dir.IO.child('bin').child('bailador'), |@args);
    $server.stdout.tap; # : -> $s {say "out: ", $s};
    $server.stderr.tap; # : -> $s {say "err: ", $s};
    $server.start;

    # Wait for server to come online
    wait-port($port, times => 600);

    #diag $server;
    #diag $server.^methods;

    my $resp = req("GET / HTTP/1.0\r\nContent-length: 0\r\n\r\n", $port);
    #diag $resp;
    like $resp, rx:s/\<h1\>Bailador App\<\/h1\>/;
    like $resp, rx:s/Version 0\.0\.1/;

    $server.kill(SIGINT);
    chdir '..';
}, 'start app with bin/bailador watch';

# Ensure that tha application generated by "bailador new" will work even if the app.pl6 was moved to the root of the project
subtest {
    plan 2;

    chdir 'App-Name';

    copy "bin/app.pl6", "root.pl6";

    my $port = 5006;
    my @args = "--config=host:0.0.0.0,port:$port", "-w={$git_dir.IO.child('t').child('views')}", 'watch', 'root.pl6';
    my @includes = repo-to-includes();
    my $server = Proc::Async.new($*EXECUTABLE, "-I$git_dir/lib", |@includes, $git_dir.IO.child('bin').child('bailador'), |@args);
    $server.stdout.tap; # : -> $s {say "out: ", $s};
    $server.stderr.tap; # : -> $s {say "err: ", $s};
    $server.start;

    # Wait for server to come online
    wait-port($port, times => 600);

    #diag $server;
    #diag $server.^methods;

    my $resp = req("GET / HTTP/1.0\r\nContent-length: 0\r\n\r\n", $port);
    #diag $resp;
    like $resp, rx:s/\<h1\>Bailador App\<\/h1\>/;
    like $resp, rx:s/Version 0\.0\.1/;

    $server.kill(SIGINT);
    chdir '..';
}, 'test app with watch command without bin directory';

subtest {
    plan 1;
    my $port = 5005;
    my @args = "--config=host:0.0.0.0,port:$port", "-w={$git_dir.IO.child('t').child('views')}", 'watch',
               ~ $git_dir.IO.child('t').child('apps').child('app.pl6');
    my @includes = repo-to-includes();
    my $server = Proc::Async.new($*EXECUTABLE, "-I$git_dir/lib", |@includes, $git_dir.IO.child('bin').child('bailador'), |@args);
    $server.stdout.tap; #: -> $s {say "out: ", $s};
    $server.stderr.tap; #: -> $s {say "err: ", $s};
    $server.start;

    # Wait for server to come online
    wait-port($port, times => 600);

    my $expected = "host:0.0.0.0,port:$port";
    my $response = req("GET /config HTTP/1.0\r\nContent-length: 0\r\n\r\n", $port);
    # diag $response;
    like $response, rx/ $expected /;

    $server.kill(SIGINT);
}, '--config options are stored in BAILADOR env';

subtest {
    plan 1;
    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'routes', "$git_dir/examples/prefix/prefix.pl6", :out, :err);

    my $exitcode = $p.exitcode;
    is $exitcode, 0, 'program terminated successfully';

    my $out = $p.out.slurp: :close;
    my $err = $p.err.slurp: :close;

    # diag $out;
    # diag $err;
}, 'bin/bailador routes command'

# vim: expandtab
# vim: tabstop=4


