### ----------------------------------------------------
### -- Collection-Plugin-Development
### -- Licenses: Artistic-2.0
### -- Authors: Richard Hainsworth, aka finanalyst
### -- File: xt/20-prepare-plugin.rakutest
### ----------------------------------------------------
use v6.d;
use Test;
use Test::Deeply::Relaxed;

use Test::Run :runs_ok;
use File::Directory::Tree;
use RakuConfig;
use Collection::PreparePlugins;

plan 19;

constant DIR = 'xt/prepare-test';
if DIR.IO ~~ :e & :d {
    rmtree DIR
}
constant TO = DIR ~ '/to';
constant FROM = DIR ~ '/from';
constant PLUG = FROM ~ '/plugins/html/plug';
mktree TO ~ '/plugins/html';
mktree PLUG ~ '/t';
mktree PLUG ~ '/extra';

for <one two three> {
    (PLUG ~ "/$_").IO.spurt: "This is file $_";
    (PLUG ~ "/t/$_").IO.spurt: "This is file t/$_";
    (PLUG ~ "/extra/$_").IO.spurt: "This is file extra/$_";
}

lives-ok { copy-plugin(:node(PLUG.IO), :to(TO ~ '/plugins/html/plug_v1_auth_collection')) }, 'copy-plugin lives';
ok (TO ~ '/plugins/html/plug_v1_auth_collection').IO ~~ :e & :d , 'plug dir made';
ok (TO ~ '/plugins/html/plug_v1_auth_collection/one').IO ~~ :e & :f, 'root file transfered';
ok (TO ~ '/plugins/html/plug_v1_auth_collection/extra/one').IO ~~ :e & :f, 'sub-dir file transfered';
empty-directory TO; # plug has no config
#make configs
(PLUG ~ "/config.raku").IO.spurt(q:to/CONF/);
    %(
        :compilation<a-callable.raku>,
        :version<2.1.1>,
        :auth<collection>,
    )
    CONF
my @args = 'raku', '-I.', 'bin/prepare-plugins', '-test', '-repo=' ~ TO, '-origin=' ~ FROM;
runs_ok(
    :@args,
    :exitcode(0),
    :out(/'From' .+ 'to release' .+ 'Transferring' /),
    'map-to-repo lives'
);
ok PLUG.IO.dir.map({ .basename }) (==) (TO ~ '/plugins/html/plug_v2_auth_collection').IO.dir.map({ .basename }), 'same files in to & from';

(PLUG ~ "/config.raku").IO.spurt(q:to/CONF/);
    %(
        :compilation<a-callable.raku>,
        :version<2.1.2>,
        :auth<collection>,
    )
    CONF
(PLUG ~ "/new-file.raku").IO.spurt(q:to/NEWF/);
    say "Another file";
    NEWF
runs_ok(
    :@args,
    :exitcode(0),
    :out(/'Release exists.' .+ 'Different versions'/),
    'map-to-repo copies when the version is different'
);
ok (TO ~ '/plugins/html/plug_v2_auth_collection/new-file.raku').IO ~~ :e & :f, 'new file transferred';

runs_ok(
    :@args,
    :exitcode(0),
    :out(/'Release exists.' .+ 'Same version' .+ 'No change'/),
    'map-to-repo does not copy when the version is the same and no new files'
);

(PLUG ~ "/new-file.raku").IO.spurt(q:to/NEWF/);
    say "this is new content";
    NEWF
runs_ok(
    :@args,
    :exitcode(0),
    :out(/
        'Release exists.'
        .+ 'Same version'
        .+ 'Changes'
        .+ 'new-file' .+ 'was modified'
    /),
    'map-to-repo warns when the version is the same, but working has new content'
);

#test manifest.rakuon
empty-directory TO;
runs_ok(
    :@args,
    :exitcode(0),
    :out(/'From' .+ 'to release' .+ 'Transferring' /),
    'prepare runs on empty TO'
);
my %manifest;
lives-ok { %manifest = EVALFILE TO ~ '/manifest.rakuon' }, 'gets manifest';
is-deeply-relaxed
    %manifest,
    %( :plugins( %( :html( %( :plug_v2_auth_collection( %( :version<2.1.2>, ) ), ) ), ) ), ),
    'manifest is as expected';
(PLUG ~ "/config.raku").IO.spurt(q:to/CONF/);
    %(
        :compilation<a-callable.raku>,
        :version<2.2.2>,
        :auth<collection>,
    )
    CONF
runs_ok(
    :@args,
    :exitcode(0),
    :out(/'Release exists.' .+ 'Different versions'/),
    'prepare runs when new version'
);
%manifest = EVALFILE TO ~ '/manifest.rakuon';
is-deeply-relaxed
    %manifest,
    %( :plugins( %(
        :html( %(
            :plug_v2_auth_collection(%(
                :version<2.2.2>,
                ) )
            ) ),
        ) ),
    ),
    'manifest updated';

(PLUG ~ "/config.raku").IO.spurt(q:to/CONF/);
    %(
        :compilation<a-callable.raku>,
        :version<3.3.4>,
        :auth<collection>,
    )
    CONF
runs_ok(
    :@args,
    :exitcode(0),
    :out(/'From' .+ 'to release' .+ 'Transferring' /),
    'moves new version'
);
%manifest = EVALFILE TO ~ '/manifest.rakuon';
is-deeply-relaxed
    %manifest,
    %(
    :plugins( %(
        :html( %(
                :plug_v2_auth_collection(%(
                    :version<2.2.2>,
                ) ),
                :plug_v3_auth_collection(%(
                    :version<3.3.4>,
                ) ),
            ) )
        ) )
    ),
    'manifest has new plugin';

# test rebuild
@args.pop;
@args.append: '-rebuild';
runs_ok(
    :@args,
    :exitcode(0),
    :out(/'Rebuilt ｢' .+ '/manifest.rakuon｣' /),
    'moves new version'
);
my %new-manifest = EVALFILE TO ~ '/manifest.rakuon';
is-deeply-relaxed
    %manifest,
    %new-manifest,
    'rebuild manifest the same as before';

done-testing;


