App-karr
view release on metacpan or search on metacpan
t/51-json-output.t view on Meta::CPAN
$@;
};
return ( $err, $out );
}
subtest 'Task->to_json_hash: frontmatter plus body only when body is set' => sub {
my $with = App::karr::Task->new( id => 1, title => 'Alpha', body => 'hello' );
my $h = $with->to_json_hash;
is( $h->{id}, 1, 'id carried through from frontmatter' );
is( $h->{title}, 'Alpha', 'title carried through from frontmatter' );
is( $h->{body}, 'hello', 'body key present when body is non-empty' );
my $without = App::karr::Task->new( id => 2, title => 'Beta' );
my $h2 = $without->to_json_hash;
is( $h2->{id}, 2, 'frontmatter still built when body is empty' );
ok( !exists $h2->{body}, 'body key absent when body is empty' );
};
subtest 'move --json: single id is a bare object, batch is an array' => sub {
my $store = _fresh_store();
_save( $store, id => 1, title => 'Alpha', status => 'todo' );
my $cmd = App::karr::Cmd::Move->new( store => $store, json => 1 );
my ( $err, $out ) = _run_execute( $cmd, '1', 'done' );
is( $err, '', 'move 1 done --json does not die' ) or diag $err;
my $data = eval { decode_json($out) };
is( ref $data, 'HASH', 'single move --json emits a bare JSON object' ) or diag $out;
is( $data->{id}, 1, 'object carries the moved id' );
is( $data->{old_status}, 'todo', 'old_status reported' );
is( $data->{new_status}, 'done', 'new_status reported' );
my $store2 = _fresh_store();
_save( $store2, id => 1, title => 'Alpha', status => 'todo' );
_save( $store2, id => 2, title => 'Beta', status => 'todo' );
my $cmd2 = App::karr::Cmd::Move->new( store => $store2, json => 1 );
my ( $err2, $out2 ) = _run_execute( $cmd2, '1,2', 'done' );
is( $err2, '', 'move 1,2 done --json does not die' ) or diag $err2;
my $arr = eval { decode_json($out2) };
is( ref $arr, 'ARRAY', 'batch move --json emits a JSON array' ) or diag $out2;
is( scalar @$arr, 2, 'one array entry per moved task' );
is( $arr->[0]{id}, 1, 'first entry is task 1' );
is( $arr->[1]{id}, 2, 'second entry is task 2' );
};
subtest 'move without --json: print_json_results is a no-op (guard)' => sub {
my $store = _fresh_store();
_save( $store, id => 1, title => 'Alpha', status => 'todo' );
my $cmd = App::karr::Cmd::Move->new( store => $store );
my ( $err, $out ) = _run_execute( $cmd, '1', 'done' );
is( $err, '', 'move without --json does not die' );
like( $out, qr/Moved task 1/, 'human-readable line printed' );
# A removed guard would leak the results object/array into plain output; the
# human line itself carries no braces, so any brace means JSON leaked through.
unlike( $out, qr/[{}]/, 'no JSON emitted when --json is absent' );
my $decoded = eval { decode_json($out) };
ok( !defined $decoded, 'plain output is not JSON-decodable' );
};
subtest 'edit --json: single id is a bare object with id and title' => sub {
my $store = _fresh_store();
_save( $store, id => 1, title => 'Old title', status => 'todo' );
my $cmd = App::karr::Cmd::Edit->new(
store => $store,
json => 1,
title => 'New title',
);
my ( $err, $out ) = _run_execute( $cmd, '1' );
is( $err, '', 'edit 1 --json does not die' ) or diag $err;
my $data = eval { decode_json($out) };
is( ref $data, 'HASH', 'single edit --json emits a bare JSON object' ) or diag $out;
is( $data->{id}, 1, 'object carries the edited id' );
is( $data->{title}, 'New title', 'edited title reflected in the payload' );
};
subtest 'show --json: explicit id renders frontmatter + body via to_json_hash' => sub {
my $store = _fresh_store();
_save( $store, id => 1, title => 'Alpha', status => 'todo', body => 'Alpha body' );
my $cmd = App::karr::Cmd::Show->new( store => $store, json => 1 );
my ( $err, $out ) = _run_execute( $cmd, '1' );
is( $err, '', 'show 1 --json does not die' ) or diag $err;
my $data = eval { decode_json($out) };
is( ref $data, 'HASH', 'explicit id --json stays a bare object' ) or diag $out;
is( $data->{id}, 1, 'id present' );
is( $data->{title}, 'Alpha', 'title present' );
is( $data->{status}, 'todo', 'status present' );
is( $data->{body}, 'Alpha body', 'body included when present' );
};
subtest 'pick --json: picked task payload built via to_json_hash' => sub {
my $store = _fresh_store();
_save( $store, id => 1, title => 'Alpha', status => 'todo', priority => 'high', body => 'Alpha body' );
my $cmd = App::karr::Cmd::Pick->new(
store => $store,
claim => 'agent-test',
json => 1,
);
my ( $err, $out ) = _run_execute($cmd);
is( $err, '', 'pick --json does not die' ) or diag $err;
my $data = eval { decode_json($out) };
is( ref $data, 'HASH', 'pick --json emits a bare JSON object' ) or diag $out;
is( $data->{id}, 1, 'picked id present' );
is( $data->{claimed_by}, 'agent-test', 'claim reflected in payload' );
is( $data->{body}, 'Alpha body', 'body included' );
};
subtest 'handoff --json: review payload built via to_json_hash' => sub {
my $store = _fresh_store();
_save( $store, id => 1, title => 'Alpha', status => 'in-progress', body => 'Alpha body' );
my $cmd = App::karr::Cmd::Handoff->new(
( run in 0.567 second using v1.01-cache-2.11-cpan-9581c071862 )