Test-JSON-RPC-Autodoc/lib/Test/JSON/RPC/Autodoc/Request.pm
package Test::JSON::RPC::Autodoc::Request;
use strict;
use warnings;
use parent qw/HTTP::Request/;
use Clone qw/clone/;
use JSON qw/to_json/;
use Test::Builder;
use Try::Tiny;
use Test::JSON::RPC::Autodoc::Response;
use Test::JSON::RPC::Autodoc::Validator;
use Plack::Test::MockHTTP;
sub new {
my ($class, %opt) = @_;
my $self = $class->SUPER::new();
$self->uri($opt{path} || '/');
$self->{method} = 'POST';
$self->{app} = $opt{app};
$self->{id} = $opt{id} || 1;
$self->{label} = $opt{label} || undef;
return $self;
}
sub json_rpc_method {
my ($self, $name) = @_;
return $self->{json_rpc_method} unless $name;
$self->{json_rpc_method} = $name;
return $name;
}
sub main_content {
my ($self, $content) = @_;
return $self->{main_content} unless $content;
$self->{main_content} = $content;
return $content;
}
sub params {
my ($self, %params) = @_;
$self->{rule} = clone \%params;
for my $p (%params) {
next unless ref $p eq 'HASH';
for my $key (keys %$p) {
if ( $key eq 'required' ) {
$p->{optional} = !$p->{required};
delete $p->{$key};
}
}
}
my $validator = Data::Validator->new(%params)->with('NoThrow');
$self->{validator} = $validator;
return $validator;
}
sub validator {
my $self = shift;
return $self->{validator} if $self->{validator};
return Data::Validator->new->with('NoThrow');
}
sub post_ok {
my ($self, $method, $params, $headers) = @_;
$params ||= {};
my $args = $self->validator->validate(%$params);
my $ok = 1;
$ok = 0 if $self->validator->has_errors;
$self->validator->clear_errors();
my $json = $self->_make_request($method, $params, $headers);
my $mock = Plack::Test::MockHTTP->new($self->{app});
my $res = $mock->request($self);
$ok = 0 if $res->code != 200;
my $Test = Test::Builder->new();
$Test->ok($ok);
$self->{response} = $res;
$self->{main_content} = $json;
$self->{json_rpc_method} = $method;
return $res;
}
sub post_only {
my ($self, $method, $params, $headers) = @_;
$self->_make_request($method, $params, $headers);
my $mock = Plack::Test::MockHTTP->new($self->{app});
my $res = $mock->request($self);
return $res;
}
sub post_not_ok {
my ($self, $method, $params, $headers) = @_;
$params ||= {};
my $args = $self->validator->validate(%$params);
my $ok = 1 if $self->validator->has_errors;
$self->validator->clear_errors();
$self->_make_request($method, $params, $headers);
my $mock = Plack::Test::MockHTTP->new($self->{app});
my $res = $mock->request($self);
$ok = 1 if $res->code == 200;
my $Test = Test::Builder->new();
$Test->ok($ok);
}
sub _make_request {
my ($self, $method, $params, $headers) = @_;
my $json = to_json(
{
jsonrpc => '2.0',
id => $self->{id},
method => $method,
params => $params,
}, { pretty => 1, utf8 => 1 }
);
$self->header('Content-Type' => 'application/json');
$self->header('Content-Length' => length $json);
if($headers && ref $headers eq 'ARRAY') {
for my $header (@$headers) {
$self->header(@$header);
}
}
$self->content($json);
return $json;
}
sub method { shift->{method} }
sub rule { shift->{rule} }
sub label { shift->{label} }
sub response {
my $self = shift;
return $self->{response} if $self->{response};
return;
}
1;