#!perl

# t/metaresources-template.t #

#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#
#   Copyright © 2015 Van de Bugger
#
#   This file is part of perl-Dist-Zilla-Plugin-MetaResources-Template.
#
#   perl-Dist-Zilla-Plugin-MetaResources-Template is free software: you can redistribute it and/or
#   modify it under the terms of the GNU General Public License as published by the Free Software
#   Foundation, either version 3 of the License, or (at your option) any later version.
#
#   perl-Dist-Zilla-Plugin-MetaResources-Template is distributed in the hope that it will be
#   useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License along with
#   perl-Dist-Zilla-Plugin-MetaResources-Template. If not, see <http://www.gnu.org/licenses/>.
#
#   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

package MetaResourcesTemplateTester;

#   The test is written using `Moose`-based `Test::Routine`. It is not big deal, because we are
#   testing plugin for `Dist::Zilla`, and `Dist-Zilla` is also `Moose`-based.

use strict;
use warnings;
use autodie ':all';
use namespace::autoclean;

use File::Temp qw{ tempdir };
use Test::DZil;
use Test::Fatal;
use Test::More;
use Test::Routine;
use Test::Routine::Util;

# `AutoPrereqs` fails to detect these dependencies:
use IPC::System::Simple ();                     # Used by `autodie ':all'`.
use Software::License::GPL_3::or_later ();      # Used by generated `dust.ini`.

#   Just a function, not a method!
#   Check if elements of array match specified regular expressions.
sub like_deeply($$$) {
    my ( $actual, $expected, $name ) = @_;
    subtest $name => sub {
        plan tests => @$expected + 0;
        for my $n ( 0 .. @$expected - 1 ) {
            like( $actual->[ $n ], $expected->[ $n ], "element $n" );
        };
        done_testing();
    };
};

#   `MetaResources::Template` plugin options, in form acceptable by `Builder->from_config`.
has resources_in => (
    is          => 'ro',
    isa         => 'HashRef',
    required    => 1,
);

#   Expected resources, in form returned by `$tzil->distmeta->{ resources }`.
has resources_out => (
    is          => 'ro',
    isa         => 'HashRef',
    required    => 0,
);

#   Expected build result: either undef (default), if build must pass, or reqular expression to
#   match with exception, if build must fail.
has exception => (
    is          => 'ro',
    isa         => 'Maybe[RegexpRef]',
    required    => 0,
    default     => undef,
);

#   If build must fail: array of regular expressions to match with messages generated by the plugin,
#   without prefixes.
has messages => (
    is          => 'ro',
    isa         => 'ArrayRef[RegexpRef]',
    required    => 0,
);

#   Test `Dist::Zilla` instance.
has tzil => (
    is          => 'ro',
    isa         => 'Object',
    lazy        => 1,
    builder     => 'build_tzil',
    init_arg    => undef,
    handles     => [ 'build' ],
);

has prefix => (
    is          => 'ro',
    isa         => 'RegexpRef',
    init_arg    => undef,
    default     => sub { qr{\A\[MetaResources::Template\] } },
);

sub build_tzil {
    my ( $self ) = @_;
    return Builder->from_config(
        { dist_root => tempdir( CLEANUP => 1 ) },
        {
            add_files => {
                'source/lib/Dummy.pm' =>
                    "package Dummy;\n" .
                    "\n" .                  # Blank line for `PkgVersion`.
                    "# ABSTRACT: Dummy\n" .
                    "# VERSION\n" .
                    "1;\n",
                'source/dist.ini' => dist_ini(
                    {
                        name                => 'Dummy',
                        version             => '0.001',
                        author              => 'John Doe',
                        license             => 'GPL_3::or_later',
                        copyright_holder    => 'John Doe',
                        copyright_year      => '2007',
                    },
                    'GatherDir',
                    'Manifest',
                    'MetaYAML',
                    [ 'MetaResources::Template', $self->resources_in ],
                ),
            },
        },
    );
};

#   Return build log as single string.
sub build_log {
    my ( $self ) = @_;
    return
        join(
            "\n",
            map( $_->{ message }, @{ $self->tzil->chrome->logger->events } )
        );
};

sub events {
    my ( $self ) = @_;
    my $prefix = $self->prefix;
    my @events =
        map(
            $_->{ message },
            grep(
                $_->{ message } =~ $prefix,
                @{ $self->tzil->chrome->logger->events }
            )
        );
    $_->{ message } =~ s{$prefix}{} for @events;
    return \@events;
};

test 'test' => sub {
    my ( $self ) = @_;
    plan tests => 2;
    my $exception = exception { $self->build() };
    SKIP : {
        if ( $self->exception ) {
            like( $exception, $self->exception, 'build must fail' )
                or diag( "Build messages:\n" . $self->build_log )
                    #   If build unexpectedly fail, print out all the build messages to make failure
                    #   investigation easier.
                or skip 'build unexpectedly pass', 1;
            like_deeply( $self->events, $self->messages, 'build messages' );
        } else {
            is( $exception, undef, 'build must pass' )
                or diag( "Build messages:\n" . $self->build_log )
                    #   If build unexpectedly fail, print out all the build messages to make
                    #   failure investigation easier.
                and skip 'build unexpectedly fail', 1;
                    #   And skip the rest — they will fail anyway.
            my $resources = $self->tzil->distmeta->{ resources };
            is_deeply( $resources, $self->resources_out, 'check resources' );
        };
    };
};

# --------------------------------------------------------------------------------------------------

plan tests => 1;

my $license = Software::License::GPL_3::or_later->new( { holder => 'John Doe', year => '2007' } );

run_me( 'Successful build', {
    resources_in => {
        #   Check various types of resources:
        'homepage'          => 'http://example.org/{{ $dist->name }}',              # String.
        'license'           => [ '{{ $dist->license->url }}' ],                     # Array.
        'bugtracker.web'    => 'https://example.org/{{ $dist->name }}/bugs',        # Hash.
        'bugtracker.mailto' => 'mailto:bugs+{{ $dist->name }}@example.org',
        'x_plugin'          => '{{ $plugin->plugin_name }}',
    },
    resources_out => {
        homepage   => 'http://example.org/Dummy',
        bugtracker => {
            web    => 'https://example.org/Dummy/bugs',
            mailto => 'mailto:bugs+Dummy@example.org',
        },
        license    => [
            $license->url,
        ],
        x_plugin   => 'MetaResources::Template',
    },
} );

done_testing();

exit( 0 );

# end of file #
