Cavil-CLI
view release on metacpan or search on metacpan
t/scenario_whoami.t view on Meta::CPAN
use Mojo::JSON qw(decode_json);
use Mojolicious::Lite;
app->log->level('error');
# A mock whoami that answers only with a valid Bearer token, so the test also proves the header is sent.
my @auth;
get '/api/v1/whoami' => sub ($c) {
push @auth, $c->req->headers->authorization;
return $c->render(json => {error => 'Unauthorized'}, status => 403)
unless ($c->req->headers->authorization // '') eq 'Bearer test-token';
$c->render(json => {id => 23, user => 'tester', roles => ['admin', 'classifier'], write_access => \0});
};
my $test = CavilCliTest->new(app);
subtest 'whoami reports the identity, roles and round-trip time' => sub {
my $result = $test->run_command('whoami');
is $result->{exit}, 0, 'a working login exits cleanly';
like $result->{stdout}, qr/Authenticated as tester \(id 23\)/, 'names the user and id';
like $result->{stdout}, qr/roles: admin, classifier/, 'lists the roles';
like $result->{stdout}, qr/write access: no/, 'shows write access';
like $result->{stdout}, qr/round-trip: \d+ ms/, 'and the round-trip time';
is $auth[0], 'Bearer test-token', 'the Bearer token was sent';
};
subtest 'whoami json is machine readable for CI' => sub {
my $result = $test->run_command('whoami', '--format', 'json');
my $data = decode_json($result->{stdout});
is $data->{user}, 'tester', 'user present';
is $data->{write_access}, 0, 'write access present';
ok exists $data->{round_trip_ms}, 'round-trip time is included';
};
subtest 'a bad token fails clearly and non-zero' => sub {
# Point at the mock but with a token it rejects. Credentials only ever come from the environment or the saved
# config, so a bad one is supplied the same way a user would supply a good one.
my $result = $test->run_with_env({CAVIL_URL => $test->url, CAVIL_API_KEY => 'wrong'}, 'whoami');
isnt $result->{exit}, 0, 'a rejected login is non-zero';
like $result->{stderr}, qr/Not authenticated/, 'says authentication failed';
like $result->{stderr}, qr/CAVIL_API_KEY/, 'and points at what to check';
};
subtest 'a server and its token can only be given together' => sub {
# Mixing sources is how a token saved for one instance gets sent to another, so half a pair is refused
# outright rather than quietly completed from somewhere else.
for my $half ({CAVIL_URL => $test->url}, {CAVIL_API_KEY => 'test-token'}) {
my $result = $test->run_with_env($half, 'whoami');
is $result->{exit}, 2, 'one half of the pair is a usage error';
like $result->{stderr}, qr/from the same source/, 'and says why';
}
# --url would aim the saved token at a different server, so it is only accepted when saving settings.
my $aimed = $test->run_bare(['whoami', '--url', $test->url]);
is $aimed->{exit}, 2, '--url is refused outside the config command';
like $aimed->{stderr}, qr/only applies to 'cavil-cli config'/, 'pointing at the command that does take it';
};
subtest 'config saves credentials and later commands use them without any flags' => sub {
# --url is fine on the command line; the token is read from stdin (never a flag), here by piping it in.
my $save = $test->run_bare(['config', '--url', $test->url], "test-token\n");
is $save->{exit}, 0, 'saving succeeds';
like $save->{stdout}, qr/Saved configuration/, 'it confirms the save';
unlike $save->{stdout}, qr/test-token/, 'and never echoes the token';
# --show reveals the URL but masks the token.
my $show = $test->run_bare(['config', '--show']);
like $show->{stdout}, qr{url:\s+\Q@{[$test->url]}\E}, 'show lists the url';
like $show->{stdout}, qr/token:\s+\*+ \(set\)/, 'show masks the token';
unlike $show->{stdout}, qr/test-token/, 'the real token is never printed';
# whoami with no flags and nothing in the environment now works, from the saved config alone.
my $who = $test->run_bare(['whoami']);
is $who->{exit}, 0, 'the saved credentials authenticate';
like $who->{stdout}, qr/Authenticated as tester/, 'and identify the user';
};
done_testing;
( run in 1.083 second using v1.01-cache-2.11-cpan-007c89162af )