use
Zapp::Util
qw( get_path_from_data get_path_from_schema )
;
my
$t
= Test::Zapp->new(
'Zapp'
);
my
$temp
= tempdir();
my
$uploads_dir
=
$temp
->child(
'public'
)->make_path;
$t
->app->home(
$temp
);
my
$file_value
=
$uploads_dir
->child(
'file.txt'
)->spurt(
'File content'
)->to_rel(
$uploads_dir
);
my
%plan_data
= (
label
=>
'Test Plan'
,
inputs
=> [
{
name
=>
'boolean'
,
type
=>
'boolean'
,
config
=> encode_json( 1 ),
},
{
name
=>
'selectbox'
,
type
=>
'selectbox'
,
config
=> encode_json(
{
options
=> [
{
label
=>
'Scruffy'
,
value
=>
'Scruffy'
},
{
label
=>
'Katrina'
,
value
=>
'Katrina'
},
{
label
=>
'Xanthor'
,
value
=>
'Xanthor'
},
],
selected_index
=> 0,
},
),
},
{
name
=>
'file'
,
type
=>
'file'
,
config
=>
undef
,
},
{
name
=>
'integer'
,
type
=>
'integer'
,
config
=> encode_json( 56 ),
},
{
name
=>
'number'
,
type
=>
'number'
,
config
=> encode_json( 1.234 ),
},
{
name
=>
'string'
,
type
=>
'string'
,
config
=> encode_json(
'string'
),
},
],
);
subtest
'plan input'
=>
sub
{
subtest
'plan edit form'
=>
sub
{
my
$plan
=
$t
->app->create_plan({
%plan_data
});
$t
->get_ok(
'/plan/'
.
$plan
->{plan_id} .
'/edit'
)->status_is( 200 );
subtest
'input 0 - boolean'
=>
sub
{
$t
->element_exists(
'form [name="input[0].config"]'
)
->attr_is(
'form [name="input[0].config"]'
,
type
=>
'text'
)
->attr_is(
'form [name="input[0].config"]'
,
value
=> 1 )
->attr_is(
'form [name="input[0].type"]'
,
value
=>
'boolean'
)
->attr_is(
'form [name="input[0].name"]'
,
value
=>
'boolean'
)
};
subtest
'input 1 - selectbox'
=>
sub
{
$t
->element_exists(
'form [name="input[1].config.options[0].label"]'
)
->attr_is(
'form [name="input[1].type"]'
,
value
=>
'selectbox'
)
->attr_is(
'form [name="input[1].name"]'
,
value
=>
'selectbox'
)
};
subtest
'input 2 - file'
=>
sub
{
$t
->element_exists(
'form [name="input[2].type"]'
)
->attr_is(
'form [name="input[2].type"]'
,
value
=>
'file'
)
->attr_is(
'form [name="input[2].name"]'
,
value
=>
'file'
)
};
subtest
'input 3 - number'
=>
sub
{
$t
->element_exists(
'form [name="input[3].config"]'
)
->attr_is(
'form [name="input[3].config"]'
,
type
=>
'text'
)
->attr_is(
'form [name="input[3].config"]'
,
value
=>
'56'
)
->attr_is(
'form [name="input[3].type"]'
,
value
=>
'integer'
)
->attr_is(
'form [name="input[3].name"]'
,
value
=>
'integer'
)
};
subtest
'input 4 - number'
=>
sub
{
$t
->element_exists(
'form [name="input[4].config"]'
)
->attr_is(
'form [name="input[4].config"]'
,
type
=>
'text'
)
->attr_is(
'form [name="input[4].config"]'
,
value
=>
'1.234'
)
->attr_is(
'form [name="input[4].type"]'
,
value
=>
'number'
)
->attr_is(
'form [name="input[4].name"]'
,
value
=>
'number'
)
};
subtest
'input 5 - string'
=>
sub
{
$t
->element_exists(
'form [name="input[5].config"]'
)
->attr_is(
'form [name="input[5].config"]'
,
type
=>
'text'
)
->attr_is(
'form [name="input[5].config"]'
,
value
=>
'string'
)
->attr_is(
'form [name="input[5].type"]'
,
value
=>
'string'
)
->attr_is(
'form [name="input[5].name"]'
,
value
=>
'string'
)
};
};
subtest
'save plan'
=>
sub
{
my
$plan
=
$t
->app->create_plan({
%plan_data
});
$t
->post_ok(
'/plan/'
.
$plan
->{plan_id} .
'/edit'
,
form
=> {
%plan_data
{
qw( label )
},
'input[0].name'
=>
'boolean'
,
'input[0].type'
=>
'boolean'
,
'input[0].config'
=> 0,
'input[1].name'
=>
'selectbox'
,
'input[1].type'
=>
'selectbox'
,
'input[1].config.options[0].label'
=>
'Scruffy'
,
'input[1].config.options[0].value'
=>
'Scruffy'
,
'input[1].config.options[1].label'
=>
'Katrina'
,
'input[1].config.options[1].value'
=>
'Katrina'
,
'input[1].config.options[2].label'
=>
'Xanthor'
,
'input[1].config.options[2].value'
=>
'Xanthor'
,
'input[1].config.selected_index'
=> 1,
'input[2].name'
=>
'file'
,
'input[2].type'
=>
'file'
,
'input[3].name'
=>
'integer'
,
'input[3].type'
=>
'integer'
,
'input[3].config'
=> 67,
'input[4].name'
=>
'number'
,
'input[4].type'
=>
'number'
,
'input[4].config'
=> 2.345,
'input[5].name'
=>
'string'
,
'input[5].type'
=>
'string'
,
'input[5].config'
=>
'new string'
,
} )->status_is( 302 );
my
@inputs
=
$t
->app->yancy->list(
zapp_plan_inputs
=> {
plan_id
=>
$plan
->{plan_id} }, {
order_by
=>
'rank'
} );
subtest
'input 0 - boolean'
=>
sub
{
is decode_json(
$inputs
[0]{config} ), 0;
};
subtest
'input 1 - selectbox'
=>
sub
{
is_deeply decode_json(
$inputs
[1]{config} ),
{
options
=> [
{
label
=>
'Scruffy'
,
value
=>
'Scruffy'
},
{
label
=>
'Katrina'
,
value
=>
'Katrina'
},
{
label
=>
'Xanthor'
,
value
=>
'Xanthor'
},
],
selected_index
=> 1,
},
'config is correct'
;
};
subtest
'input 2 - file'
=>
sub
{
is_deeply decode_json(
$inputs
[2]{config} ), {},
'no config'
;
};
subtest
'input 3 - integer'
=>
sub
{
is decode_json(
$inputs
[3]{config} ), 67;
};
subtest
'input 4 - number'
=>
sub
{
is decode_json(
$inputs
[4]{config} ), 2.345;
};
subtest
'input 5 - string'
=>
sub
{
is decode_json(
$inputs
[5]{config} ),
'new string'
;
};
};
subtest
'run form'
=>
sub
{
my
$plan
=
$t
->app->create_plan({
%plan_data
});
$t
->get_ok(
'/plan/'
.
$plan
->{plan_id} .
'/run'
)->status_is( 200 );
subtest
'input 0 - boolean'
=>
sub
{
$t
->element_exists(
'form [name="input[0].value"]'
)
->attr_is(
'form [name="input[0].value"]'
,
type
=>
'text'
)
->attr_is(
'form [name="input[0].value"]'
,
value
=> 1 )
->attr_is(
'form [name="input[0].type"]'
,
value
=>
'boolean'
)
->attr_is(
'form [name="input[0].name"]'
,
value
=>
'boolean'
)
};
subtest
'input 1 - selectbox'
=>
sub
{
$t
->element_exists(
'form [name="input[1].value"]'
)
->element_exists(
'form select[name="input[1].value"]'
,
'tag is <select>'
)
->attr_is(
'form [name="input[1].value"] [selected]'
,
value
=>
'Scruffy'
)
->attr_is(
'form [name="input[1].type"]'
,
value
=>
'selectbox'
)
->attr_is(
'form [name="input[1].name"]'
,
value
=>
'selectbox'
)
};
subtest
'input 2 - file'
=>
sub
{
$t
->element_exists(
'form [name="input[2].value"]'
)
->attr_is(
'form [name="input[2].value"]'
,
type
=>
'file'
)
->attr_is(
'form [name="input[2].type"]'
,
value
=>
'file'
)
->attr_is(
'form [name="input[2].name"]'
,
value
=>
'file'
)
};
subtest
'input 3 - number'
=>
sub
{
$t
->element_exists(
'form [name="input[3].value"]'
)
->attr_is(
'form [name="input[3].value"]'
,
type
=>
'text'
)
->attr_is(
'form [name="input[3].value"]'
,
value
=>
'56'
)
->attr_is(
'form [name="input[3].type"]'
,
value
=>
'integer'
)
->attr_is(
'form [name="input[3].name"]'
,
value
=>
'integer'
)
};
subtest
'input 4 - number'
=>
sub
{
$t
->element_exists(
'form [name="input[4].value"]'
)
->attr_is(
'form [name="input[4].value"]'
,
type
=>
'text'
)
->attr_is(
'form [name="input[4].value"]'
,
value
=>
'1.234'
)
->attr_is(
'form [name="input[4].type"]'
,
value
=>
'number'
)
->attr_is(
'form [name="input[4].name"]'
,
value
=>
'number'
)
};
subtest
'input 5 - string'
=>
sub
{
$t
->element_exists(
'form [name="input[5].value"]'
)
->attr_is(
'form [name="input[5].value"]'
,
type
=>
'text'
)
->attr_is(
'form [name="input[5].value"]'
,
value
=>
'string'
)
->attr_is(
'form [name="input[5].type"]'
,
value
=>
'string'
)
->attr_is(
'form [name="input[5].name"]'
,
value
=>
'string'
)
};
};
subtest
'save run'
=>
sub
{
my
$plan
=
$t
->app->create_plan({
%plan_data
});
$t
->post_ok(
'/run'
,
form
=> {
plan_id
=>
$plan
->{plan_id},
'input[0].name'
=>
'boolean'
,
'input[0].type'
=>
'boolean'
,
'input[0].value'
=> 1,
'input[1].name'
=>
'selectbox'
,
'input[1].type'
=>
'selectbox'
,
'input[1].config'
=> encode_json({
options
=> [
{
label
=>
'Scruffy'
,
value
=>
'Scruffy'
,
},
{
label
=>
'Katrina'
,
value
=>
'Katrina'
,
},
{
label
=>
'Xanthor'
,
value
=>
'Xanthor'
,
},
],
selected_index
=> 0,
}),
'input[1].value'
=>
'Xanthor'
,
'input[2].name'
=>
'file'
,
'input[2].type'
=>
'file'
,
'input[2].value'
=> {
content
=>
'Run File'
,
filename
=>
'file.txt'
,
},
'input[3].name'
=>
'integer'
,
'input[3].type'
=>
'integer'
,
'input[3].value'
=> 89,
'input[4].name'
=>
'number'
,
'input[4].type'
=>
'number'
,
'input[4].value'
=> 3.456,
'input[5].name'
=>
'string'
,
'input[5].type'
=>
'string'
,
'input[5].value'
=>
'run string'
,
} )->status_is( 302 );
my
(
$run_id
) =
$t
->tx->res->headers->location =~ m{/run/(\d+)};
my
$run
=
$t
->app->yancy->get(
zapp_runs
=>
$run_id
);
my
$input
= decode_json(
$run
->{input} );
subtest
'input 0 - boolean'
=>
sub
{
is
$input
->[0]{value}, 1;
};
subtest
'input 1 - selectbox'
=>
sub
{
is
$input
->[1]{value},
'Xanthor'
;
};
subtest
'input 2 - file'
=>
sub
{
like
$input
->[2]{value},
qr{Pw/Qd/XOBNWd9H5Zc5lIXvadI_0pk/file\.txt}
;
my
$file
=
$t
->app->home->child(
'public'
,
$input
->[2]{value} );
ok -e
$file
,
'file exists'
;
is
$file
->slurp,
'Run File'
,
'file content correct'
;
};
subtest
'input 3 - integer'
=>
sub
{
is
$input
->[3]{value}, 89;
};
subtest
'input 4 - number'
=>
sub
{
is
$input
->[4]{value}, 3.456;
};
subtest
'input 5 - string'
=>
sub
{
is
$input
->[5]{value},
'run string'
;
};
};
};
subtest
'task input'
=>
sub
{
my
$file
=
$uploads_dir
->child(
'zapp'
)->spurt(
'File content'
);
my
$plan
=
$t
->app->create_plan({
label
=>
'Task Input Plan'
,
tasks
=> [
{
label
=>
'string: input'
,
name
=>
'string_input'
,
class
=>
'Zapp::Task::Script'
,
input
=> encode_json({
vars
=> [
{
name
=>
'string'
,
value
=>
'=string'
},
],
script
=>
'echo -n $string'
,
}),
},
{
label
=>
'integer: input'
,
name
=>
'integer_input'
,
class
=>
'Zapp::Task::Script'
,
input
=> encode_json({
vars
=> [
{
name
=>
'int'
,
value
=>
'=integer'
},
],
script
=>
'echo -n $int'
,
}),
},
{
label
=>
'number: input'
,
name
=>
'number_input'
,
class
=>
'Zapp::Task::Script'
,
input
=> encode_json({
vars
=> [
{
name
=>
'num'
,
value
=>
'=number'
},
],
script
=>
'echo -n $num'
,
}),
},
{
label
=>
'boolean: input'
,
name
=>
'boolean_input'
,
class
=>
'Zapp::Task::Script'
,
input
=> encode_json({
vars
=> [
{
name
=>
'bool'
,
value
=>
'=boolean'
},
],
script
=>
'echo -n $bool'
,
}),
},
{
label
=>
'file: input'
,
name
=>
'file_input'
,
class
=>
'Zapp::Task::Script'
,
input
=> encode_json({
vars
=> [
{
name
=>
'file'
,
value
=>
'=file'
},
],
script
=>
'cat $file'
,
}),
},
{
label
=>
'selectbox: input'
,
name
=>
'selectbox_input'
,
class
=>
'Zapp::Task::Script'
,
input
=> encode_json({
vars
=> [
{
name
=>
'val'
,
value
=>
'=selectbox'
},
],
script
=>
'echo -n $val'
,
}),
},
],
inputs
=> [
{
name
=>
'string'
,
type
=>
'string'
,
value
=>
'String input'
,
},
{
name
=>
'integer'
,
type
=>
'integer'
,
value
=> 1234,
},
{
name
=>
'number'
,
type
=>
'number'
,
value
=> 5.678,
},
{
name
=>
'boolean'
,
type
=>
'boolean'
,
value
=> 1,
},
{
name
=>
'file'
,
type
=>
'file'
,
value
=>
$file
->to_rel(
$uploads_dir
).
""
,
},
{
name
=>
'selectbox'
,
type
=>
'selectbox'
,
value
=>
'Scruffy'
,
config
=> encode_json({
options
=> [
{
label
=>
'Scruffy'
,
value
=>
'Scruffy'
},
{
label
=>
'Katrina'
,
value
=>
'Katrina'
},
{
label
=>
'Xanthor'
,
value
=>
'Xanthor'
},
],
selected_index
=> 0,
}),
},
],
});
my
$input
= {
string
=>
'String input'
,
integer
=> 1234,
number
=> 5.678,
boolean
=> 1,
file
=>
$file
->to_rel(
$uploads_dir
),
selectbox
=>
'Scruffy'
,
};
my
$run
=
$t
->app->enqueue_plan(
$plan
->{plan_id},
$input
);
$t
->run_queue;
subtest
'string: input'
=>
sub
{
my
$job
=
$t
->app->minion->job(
$run
->{tasks}[0]{job_id} );
my
$result
=
$job
->info->{result};
is
$result
->{output},
$input
->{string},
'string input correct'
;
};
subtest
'integer: input'
=>
sub
{
my
$job
=
$t
->app->minion->job(
$run
->{tasks}[1]{job_id} );
my
$result
=
$job
->info->{result};
is
$result
->{output},
$input
->{integer},
'integer input correct'
;
};
subtest
'number: input'
=>
sub
{
my
$job
=
$t
->app->minion->job(
$run
->{tasks}[2]{job_id} );
my
$result
=
$job
->info->{result};
is
$result
->{output},
$input
->{number},
'number input correct'
;
};
subtest
'boolean: input'
=>
sub
{
my
$job
=
$t
->app->minion->job(
$run
->{tasks}[3]{job_id} );
my
$result
=
$job
->info->{result};
is
$result
->{output},
$input
->{boolean},
'boolean input correct'
;
};
subtest
'file: input'
=>
sub
{
my
$job
=
$t
->app->minion->job(
$run
->{tasks}[4]{job_id} );
my
$result
=
$job
->info->{result};
my
$path
=
$t
->app->home->child(
'public'
,
$input
->{file} );
is
$result
->{output},
$path
->slurp,
'file input correct'
;
};
subtest
'selectbox: input'
=>
sub
{
my
$job
=
$t
->app->minion->job(
$run
->{tasks}[5]{job_id} );
my
$result
=
$job
->info->{result};
is
$result
->{output},
$input
->{selectbox},
'selectbox input correct'
;
};
};
done_testing;