#!/usr/local/cpanel/3rdparty/bin/perl -w

# cpanel - t/medium/Cpanel-Plugins-RestApiClient.t Copyright 2023 cPanel, L.L.C.
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

package t::medium::Cpanel::Plugins::RestApiClient;

use cPstrict;
use Test::Cpanel::Policy;

use Test2::V0;
use Test2::Tools::Explain;
use Test2::Tools::Compare;
use Test2::Plugin::NoWarnings;
use Test2::Tools::Exception;
use Test::MockModule;

use base qw(Test::Class);

use Cpanel::Plugins::RestApiClient ();

my ( $status, $success, $retries, $content, $headers );
my @mocks;
push( @mocks, Test::MockModule->new('Cpanel::HTTP::Client') );
$mocks[-1]->redefine( 'new'                  => sub { return bless {}, shift } );
$mocks[-1]->redefine( 'return_on_http_error' => sub { return shift; } );
$mocks[-1]->redefine(
    'request' => sub {
        my ( $self, $method, $path, $data ) = @_;
        $retries++;
        $headers = $data->{headers};
        return bless(
            {
                content => $content,
                status  => $status,
                success => $success,
            },
            "Cpanel::HTTP::Client::Response"
        );
    }
);

push( @mocks, Test::MockModule->new('Cpanel::Plugins::RestApiClient') );
$mocks[-1]->redefine( '_throw_error' => sub { die "An error was thrown." } );

__PACKAGE__->new()->runtests() if !caller;

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

sub test_new : Tests(1) {

    my $obj = Cpanel::Plugins::RestApiClient->new();
    isa_ok( $obj, 'Cpanel::Plugins::RestApiClient' );

    return;
}

sub test_run : Tests(9) {

    my $obj = Cpanel::Plugins::RestApiClient->new();
    ok( dies { $obj->run() }, "Dies when the required attributes are not set." );

    $obj->base_url('https://foobar/v1');
    $obj->endpoint('users');

    $status  = 200;
    $success = 1;
    ok( lives { $obj->run() }, "Lives when attribues are set, status is 200, and success is true." );

    $retries = 0;
    $status  = 599;
    $success = 0;
    eval { $obj->run() };
    is( $retries, $obj->retry, "On network failure retry the request up to the value of retry." );

    $retries = 0;
    $status  = 505;
    $success = 0;
    eval { $obj->run() };
    is( $retries, 1, "Do not retry on an error that is not network related." );

    $status  = 200;
    $success = 1;
    $content = '{"abcd":"efgh","foo":"bar"}';
    is( $obj->run(),                { abcd => 'efgh', foo => 'bar' }, "Got the expected content from a successful request." );
    is( $headers->{'Content-Type'}, 'application/json',               "The default Content-Type header is included." );

    $content = undef;
    is( $obj->run(), 1, "A true value is returned when the request is successful but returns no content." );

    $obj->auth_token('1234');
    $headers = undef;
    eval { $obj->run() };
    is( $headers->{'Authorization'}, 'Bearer 1234',      "The Authorization Bearer header is set when auth_token is defined." );
    is( $headers->{'Content-Type'},  'application/json', "The default Content-Type header is included also." );

    return;
}

1;
