The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# Test Ext.Direct API declaration handling

use strict;
use warnings;
no  warnings 'uninitialized';

use Test::More tests => 105;

BEGIN { use_ok 'RPC::ExtDirect::Client::API' };

my $source_js = <<'END_JS';
Ext.app.REMOTING_API = {
    "actions":{
        "Bar":[
                { "len":5, "name":"bar_bar" },
                { "formHandler":true, "len":0, "name":"bar_baz" },
                { "len":4, "name":"bar_foo" }
              ],
        "Foo":[
                { "len":2, "name":"foo_bar" },
                { "name":"foo_baz", "params":["foo","bar","baz"] },
                { "len":1, "name":"foo_foo" },
                { "len":0, "name":"foo_zero" }
              ],
        "Qux":[
                { "len":5, "name":"bar_bar" },
                { "formHandler":true, "len":0, "name":"bar_baz" },
                { "len":4, "name":"bar_foo" },
                { "len":2, "name":"foo_bar" },
                { "name":"foo_baz", "params":["foo","bar","baz"] },
                { "len":1, "name":"foo_foo" }
              ]
    },
    "type":"remoting",
    "url":"/extdirectrouter"
};
END_JS

my $aclass = 'RPC::ExtDirect::Client::API';

my $api = $aclass->new($source_js);

ok     $api,          'Got object';
isa_ok $api, $aclass, 'Right object, too,';

is $api->type, 'remoting',         'Type';
is $api->url,  '/extdirectrouter', 'URL';

my @tests = (
    { name    => 'Bar',
      methods => [
        { name => 'bar_bar', len => 5, is_named => '', is_ordered => 1,
          is_formhandler => '', formHandler => undef, params => undef, },
        { name => 'bar_baz', len => 0, is_named => '', is_ordered => '',
          is_formhandler => 1, formHandler => 1, params => undef, },
        { name => 'bar_foo', len => 4, is_named => '', is_ordered => 1,
          is_formhandler => '', formHandler => undef, params => undef, },
      ],
    },
    { name    => 'Foo',
      methods => [
        { name => 'foo_bar', len => 2, is_named => '', is_ordered => 1,
          is_formhandler => '', formHandler => undef, params => undef, },
        { name => 'foo_baz', len => 0, is_named => 1, is_ordered => '',
          is_formhandler => '', formHandler => undef,
          params => [ 'foo', 'bar', 'baz' ],
        },
        { name => 'foo_foo', len => 1, is_named => '', is_ordered => 1,
          is_formhandler => '', formHandler => undef, params => undef, },
        { name => 'foo_zero', len => 0, is_named => '', is_ordered => '',
          is_formhandler => '', formHandler => undef, params => undef, },
      ],
    },
    { name    => 'Qux',
      methods => [
        { name => 'bar_bar', len => 5, is_named => '', is_ordered => 1,
          is_formhandler => '', formHandler => undef, params => undef, },
        { name => 'bar_baz', len => 0, is_named => '', is_ordered => '',
          is_formhandler => 1, formHandler => 1, params => undef, },
        { name => 'bar_foo', len => 4, is_named => '', is_ordered => 1,
          is_formhandler => '', formHandler => undef, params => undef, },
        { name => 'foo_bar', len => 2, is_named => '', is_ordered => 1,
          is_formhandler => '', formHandler => undef, params => undef, },
        { name => 'foo_baz', len => 0, is_named => 1, is_ordered => '',
          is_formhandler => '', formHandler => undef,
          params => [ 'foo', 'bar', 'baz' ],
        },
        { name => 'foo_foo', len => 1, is_named => '', is_ordered => 1,
          is_formhandler => '', formHandler => undef, params => undef, },
      ],
    },
);

# Test all actions at once

my @actions = sort { $a->name cmp $b->name } $api->actions;

for my $action ( @actions ) {
    my $test = shift @tests;

    my $aname = $action->name;
    
    is $aname, $test->{name}, "Action $aname name";

    my @methods = @{ $test->{methods} };

    for my $method ( @methods ) {
        my $mname = $method->{name};

        while ( my ( $meth, $exp ) = each %$method ) {
            if ( $meth eq 'params' ) {
                is_deeply $action->method($mname)->$meth, $exp,
                          "Action $aname method $mname: $meth";
            }
            else {
                is $action->method($mname)->$meth, $exp,
                   "Action $aname method $mname: $meth";
            };
        };
    };
};

# Test returning a sliced set of actions

@actions = sort { $a->name cmp $b->name } $api->actions('Qux', 'Foo');

is scalar @actions,   2,     'Number of sliced actions';
is $actions[0]->name, 'Foo', 'First sliced action name';
is $actions[1]->name, 'Qux', 'Second sliced action name';

# Test returning a single action in scalar context

my $action = $api->actions('Bar');

my $act_class = 'RPC::ExtDirect::Client::API::Action';

ok     $action,                   'Got single action object';
isa_ok $action,       $act_class, 'Right single action object class, too,';
is     $action->name, 'Bar',      'Single action name';