Catalyst-Plugin-JSONRPC-Server

 view release on metacpan or  search on metacpan

t/dispatcher-errors.t  view on Meta::CPAN

use v5.36;
use Test::More;
use Test::Fatal;
use JSON::MaybeXS qw/decode_json/;
use Catalyst::Plugin::JSONRPC::Server::Dispatcher;
use Catalyst::Plugin::JSONRPC::Server::Error;

my $d = Catalyst::Plugin::JSONRPC::Server::Dispatcher->new;
$d->register( ok_method => sub ($p) { 'fine' } );
$d->register( boom      => sub ($p) { die "kaboom at secret place\n" } );
$d->register( bad_param => sub ($p) {
    Catalyst::Plugin::JSONRPC::Server::Error->throw(
        code => -32602, message => 'Invalid params' );
} );
$d->register( obj => sub ($p) { bless {}, 'Foo::Unserializable' } );

# -32700 parse error (id is null)
is_deeply( $d->dispatch('this is not json'),
    { jsonrpc => '2.0', error => { code => -32700, message => 'Parse error' }, id => undef },
    'parse error' );

# -32600 not a JSON object
is_deeply( $d->dispatch('"a bare string"'),
    { jsonrpc => '2.0', error => { code => -32600, message => 'Invalid Request' }, id => undef },
    'non-object request is invalid' );

# -32600 wrong jsonrpc version (keeps the id)
is_deeply( $d->dispatch('{"jsonrpc":"1.0","method":"ok_method","id":9}'),
    { jsonrpc => '2.0', error => { code => -32600, message => 'Invalid Request' }, id => 9 },
    'bad jsonrpc version is invalid' );

# -32600 bad params type
is_deeply( $d->dispatch('{"jsonrpc":"2.0","method":"ok_method","params":"x","id":9}'),
    { jsonrpc => '2.0', error => { code => -32600, message => 'Invalid Request' }, id => 9 },
    'scalar params is invalid' );

# -32601 method not found
is_deeply( $d->dispatch('{"jsonrpc":"2.0","method":"nope","id":3}'),
    { jsonrpc => '2.0', error => { code => -32601, message => 'Method not found' }, id => 3 },
    'method not found' );

# handler dies plainly -> -32603, original message NOT leaked
is_deeply( $d->dispatch('{"jsonrpc":"2.0","method":"boom","id":4}'),
    { jsonrpc => '2.0', error => { code => -32603, message => 'Internal error' }, id => 4 },
    'plain die maps to internal error without leaking text' );

# handler throws a structured Error -> its code/message
is_deeply( $d->dispatch('{"jsonrpc":"2.0","method":"bad_param","id":5}'),
    { jsonrpc => '2.0', error => { code => -32602, message => 'Invalid params' }, id => 5 },
    'structured Error maps to its code' );

# --- I2: a structurally-invalid request that happens to lack an id is NOT a
# notification; it must still yield -32600 with id:null (JSON-RPC 2.0 examples).
is_deeply( $d->dispatch('{"foo":"boo"}'),
    { jsonrpc => '2.0', error => { code => -32600, message => 'Invalid Request' }, id => undef },
    'invalid id-less request returns -32600/id:null (not silently dropped)' );
is_deeply( $d->dispatch('[{"foo":"boo"}]'),
    [ { jsonrpc => '2.0', error => { code => -32600, message => 'Invalid Request' }, id => undef } ],
    'invalid id-less batch element yields an error element (not dropped)' );

# --- S1: a structured (array/object) id is invalid; reject with id:null.
is_deeply( $d->dispatch('{"jsonrpc":"2.0","method":"ok_method","id":[1,2]}'),
    { jsonrpc => '2.0', error => { code => -32600, message => 'Invalid Request' }, id => undef },



( run in 2.428 seconds using v1.01-cache-2.11-cpan-54e63673c56 )