use Mojo::Base -strict;
use Test::Mojo;
use Test::More;

use Mojolicious::Lite;
my $auth = app->routes->under('/api')->to(
  cb => sub {
    my $c    = shift;
    my $spec = $c->openapi->spec;

    # skip authentication
    return 1 if $spec->{'x-no-auth'};

    # really bad authentication
    return 1 if $c->param('unsafe_token');

    # not authenticated
    $c->render(openapi => {errors => [{message => 'not logged in'}]}, status => 401);
    return;
  }
);

get
  '/login' => sub { shift->render(openapi => {id => 123}, status => 200) },
  'login';

get
  '/protected' => sub { shift->render(openapi => {protected => 'secret'}, status => 200) },
  'protected';

plugin OpenAPI => {route => $auth, url => 'data://main/api.json'};

my $t = Test::Mojo->new;

$t->get_ok('/api')->status_is(401)->json_is('/errors/0/message', 'not logged in');
$t->get_ok('/api?unsafe_token=1')->status_is(200)->json_is('/swagger', '2.0');
$t->get_ok('/api/login')->status_is(200)->json_is('/id', 123);
$t->get_ok('/api/protected')->status_is(401)->json_is('/errors/0/message', 'not logged in');
$t->get_ok('/api/protected?unsafe_token=1')->status_is(200)->json_is('/protected', 'secret');

done_testing;

__DATA__
@@ api.json
{
  "swagger": "2.0",
  "info": { "version": "0.8", "title": "Test protected api" },
  "basePath": "/api",
  "paths": {
    "/login": {
      "get": {
        "x-no-auth": true,
        "x-mojo-name": "login",
        "responses": {
          "200": { "description": "response", "schema": { "type": "object" } }
        }
      }
    },
    "/protected": {
      "get": {
        "x-mojo-name": "protected",
        "responses": {
          "200": { "description": "response", "schema": { "type": "object" } }
        }
      }
    }
  }
}
