#! /usr/bin/env perl
# ABSTRACT: Upload your TAP results to TestRail after they've finished
# PODNAME: testrail-report


use strict;
use warnings;

use Getopt::Long;
use Term::ANSIColor qw(colorstrip);
use Test::Rail::Parser;
use IO::Interactive::Tiny ();

print "testrail-report\n----------------------\n";

sub help {
    print "testrail-report - report raw TAP results to a TestRail install

USAGE:
  testrail-report [OPTIONS] tapfile
  prove -v sometest.t > results.tap && testrail-report [OPTIONS] \\
  results.tap

  prove -v sometest.t | testrail-report [OPTIONS]

  prove -PTestRail='http://some.testlink.install/','someUser',\\
  'somePassword' sometest.t

PARAMETERS:
  [MANDATORY PARAMETERS]
  --project [someproject] : associate results (if any) with the
                            provided project name.

  --run [somerun] : associates results (if any) with the provided run
                    name.

  IF none of these options are provided, you will be asked to type
  these in as needed, supposing you are not redirecting input
  (such as piping into this command).

  [CONFIG OVERRIDES]
  In your \$HOME, put a file called .testrailrc with key=value
  syntax separated by newlines.  Valid Keys are: apiurl,user,password

  [CONFIG OPTIONS] - These override the config, if present.
                     If neither are used, you will be prompted.

  --apiurl   [url] : full URL to get to TestRail index document
  --password [key] : Your TestRail Password.
  --user    [name] : Your TestRail User Name.

  [BEHAVIOR]
  --case-ok      : Whether to consider each OK to correspond to
                   a test in TestRail

  --step-results [name] : 'System Name' of a 'step_results' type field
                    to set for your tests.

  These options are mutually exclusive.  If neither is set, the
  overall result of the test will be used as the pass/fail for the test.

PROVE PLUGIN:

  passing -PTestRail=apiurl,user,pass,project,run to prove will
  automatically upload your test results while the test is running if
  real-time results are desired.

  See App::Prove::Plugin::TestRail for more information.

REQUIREMENTS:
  Your TestRail install must have 3 custom statuses with the internal
  names 'skip', 'todo_pass', and 'todo_fail', to represent those
  states which TAP can have.

";
    exit 0;
}

sub userInput {
 $| = 1;
 my $rt = <STDIN>;
 chomp $rt;
 return $rt;
}

sub parseConfig {
    my $results = {};
    my $arr =[];

    open(my $fh, '<', $ENV{"HOME"} . '/.testrailrc') or return (undef,undef,undef);#couldn't open!
    while (<$fh>) {
        chomp;
        @$arr = split(/=/,$_);
        if (scalar(@$arr) != 2) {
            warn("Could not parse $_ in tlreport config\n");
            next;
        }
        $results->{lc($arr->[0])} = $arr->[1];
    }
    close($fh);
    return ($results->{'apiurl'},$results->{'password'},$results->{'user'});
}

#Main loop------------

my ($help,$apiurl,$user,$password,$project,$run,$case_per_ok,$step_results);

#parse switches
GetOptions(
    'run=s'          => \$run,
    'apiurl=s'       => \$apiurl,
    'password=s'     => \$password,
    'user=s'         => \$user,
    'project=s'      => \$project,
    'case-ok'        => \$case_per_ok,
    'step-results=s' => \$step_results,
    'help'           => \$help
);

if ($help) { help(); }

#Parse config file if we are missing api url/key or user
if (-e $ENV{"HOME"} . '/.testrailrc' && (!$apiurl || !$password || !$user) ) {
    ($apiurl,$password,$user) = parseConfig();
}

#If argument is passed use it instead of stdin
my $file = $ARGV[0];
die "No Such File $file" if ($file && !-e $file);
my ($fh,$fcontents);
if ($file) {
    open($fh,'<',$file);
    while (<$fh>) {
        $_ = colorstrip($_); #strip prove brain damage
        s/^\s*//g; #Fix more brain damage
        $fcontents .= $_;
    }
    close($fh);
} else {
    #Just read STDIN, print help if no file was passed
    if (IO::Interactive::Tiny::is_interactive()) { print "ERROR: no file passed, and no data piped in! See --help for usage." }
    if ( !$run || !$apiurl || !$password || !$user || !$project ) { print "ERROR: Interactive mode not allowed when piping input.  See --help for options.\n"; exit 0;};
    while (<>) {
        $_ = colorstrip($_); #strip prove brain damage
        s/^\s*//g; #Fix prove brain damage
        $fcontents .= $_;
    }
    help() if !$fcontents; #Nothing passed to stdin!
}

#Interrogate user if they didn't provide info
if (!$apiurl) {
    print "Type the API endpoint url for your testLink install below:\n";
    $apiurl = userInput();
}

if (!$user) {
    print "Type your testLink user name below:\n";
    $user = userInput();
}

if (!$password) {
    print "Type the password for your testLink user below:\n";
    $password = userInput();
}

if (!$apiurl || !$password || !$user) {
    print "ERROR: api url, username and password cannot be blank.\n";
    exit 1;
}

#Interrogate user if they didn't provide info
if (!$project) {
    print "Type the name of the project you are testing under:\n";
    $project = userInput();
}

# Interrogate user if options were not passed
if (!$run) {
    print "Type the name of the existing run you would like to run against:\n";
    $run = userInput();
}

my $tap = Test::Rail::Parser->new({
    'tap'                 => $fcontents,
    'apiurl'              => $apiurl,
    'user'                => $user,
    'pass'                => $password,
    'run'                 => $run,
    'project'             => $project,
    'case_per_ok'         => $case_per_ok,
    'step_results'        => $step_results,
    'merge'               => 1
});
$tap->run();

print "Done.\n";

#all done
0;

__END__

=pod

=encoding UTF-8

=head1 NAME

testrail-report - Upload your TAP results to TestRail after they've finished

=head1 VERSION

version 0.012

=head1 SYNOPSIS

  testrail-report [OPTIONS] tapfile
  prove -v sometest.t > results.tap && testrail-report [OPTIONS] results.tap

  prove -v sometest.t | testrail-report [OPTIONS]

  prove -PTestRail='http://some.testlink.install/,someUser,somePassword,someProject,someRun,0,step_results' sometest.t

=head1 DESCRIPTION

testrail-report - report raw TAP results to a TestRail install

USAGE:
=head2 PARAMETERS:

=head3 MANDATORY PARAMETERS

    --project [someproject] : associate results (if any) with theprovided project name.

    --run [somerun] : associates results (if any) with the provided run name.

IF none of these options are provided, you will be asked to type
these in as needed, supposing you are not redirecting input
(such as piping into this command).

=head3 CONFIG OVERRIDES

In your \$HOME, put a file called .testrailrc with key=value
syntax separated by newlines.  Valid Keys are: apiurl,user,password

=head3 CONFIG OPTIONS

These override the config, if present.  If neither are used, you will be prompted.

    --apiurl   [url] : full URL to get to TestRail index document

    --password [key] : Your TestRail Password.

    --user    [name] : Your TestRail User Name.

=head3 BEHAVIOR

    --case-ok      : Whether to consider each OK to correspond to a test in TestRail

    --step-results [name] : 'System Name' of a 'step_results' type field to set for your tests.

These options are mutually exclusive.  If neither is set, the
overall result of the test will be used as the pass/fail for the test.

=head2 PROVE PLUGIN:

passing -PTestRail=apiurl,user,pass,project,run to prove will
automatically upload your test results while the test is running if
real-time results are desired.

See L<App::Prove::Plugin::TestRail> for more information.

=head2 REQUIREMENTS:

Your TestRail install must have 3 custom statuses with the internal
names 'skip', 'todo_pass', and 'todo_fail', to represent those
states which TAP can have.

=head1 SEE ALSO

L<TestRail::API>

L<App::Prove::Plugin::TestRail>

L<TAP::Parser>

=head1 SPECIAL THANKS

Thanks to cPanel Inc, for graciously funding the creation of this module.

=head1 AUTHOR

George S. Baugh <teodesian@cpan.org>

=head1 SOURCE

The development version is on github at L<http://github.com/teodesian/TestRail-Perl>
and may be cloned from L<git://github.com/teodesian/TestRail-Perl.git>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by George S. Baugh.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
