The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

Build Status Coverage Status

NAME

Test::JsonAPI::Autodoc - Test JSON API response and auto generate API documents

SYNOPSIS

use HTTP::Request::Common;
use Test::More;
use Test::JsonAPI::Autodoc;

# JSON request
describe 'POST /foo' => sub {
    my $req = POST 'http://localhost:5000/foo';
    $req->header('Content-Type' => 'application/json');
    $req->content(q{
        {
            "id": 1,
            "message": "blah blah"
        }
    });
    my $res = http_ok($req, 200, "returns response"); # <= Check status whether 200, and generate documents.
                                                      #    And this test method returns the response as hash reference.
};

# Can also request application/x-www-form-urlencoded
describe 'POST /bar' => sub {
    my $req = POST 'http://localhost:3000/bar', [ id => 42, message => 'hello' ];
    http_ok($req, 200, "returns response");
}

# And you can use Plack::Test
use Plack::Test;
use Plack::Request;
my $app = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    if ($req->path eq '/') {
        return [ 200, [ 'Content-Type' => 'application/json' ], ['{ "message" : "success" }'] ];
    }
    return [ 404, [ 'Content-Type' => 'text/plain' ], [ "Not found" ] ];
};

my $test_app = Plack::Test->create($app);
describe 'POST /' => sub {
    my $req = POST '/';
    $req->header('Content-Type' => 'application/json');
    $req->content(q{
        {
            "id": 1,
            "message": "blah blah"
        }
    });
    plack_ok($test_app, $req, 200, "get message ok");
};

# Of course you can use `test_psgi`
test_psgi $app, sub {
    my $cb = shift;

    describe 'POST /not-exist' => sub {
        my $req = POST '/not-exist';
        $req->header('Content-Type' => 'application/json');
        $req->content(q{
            {
                "id": 1,
                "message": "blah blah"
            }
        });
        plack_ok($cb, $req, 404, "not found");
    };
};

DESCRIPTION

Test::JsonAPI::Autodoc tests JSON API response (only check status code). And it generates API documents according to the response automatically. Please refer to "USAGE" for details.

USAGE

A document will be generated if describe is used instead of Test::More::subtest. And call http_ok or plack_ok at inside of describe, then it tests API response and convert the response to markdown document.

Run test as follows.

$ TEST_JSONAPI_AUTODOC=1 prove t/test.t

If TEST_JSONAPI_AUTODOC doesn't have true value, documents will not generate.

The example of test.t is as follows.

use HTTP::Request::Common;
use Test::More;
use Test::JsonAPI::Autodoc;

# JSON request
describe 'POST /foo' => sub {
    my $req = POST 'http://localhost:5000/foo';
    $req->header('Content-Type' => 'application/json');
    $req->content(q{
        {
            "id": 1,
            "message": "blah blah"
        }
    });
    http_ok($req, 200, "get message ok");
};

The following markdown document are outputted after execution of a test. Document will output to $project_root/docs/test.md on default setting.

generated at: 2013-11-04 22:41:10

## POST /foo

get message ok

### Target Server

http://localhost:5000

### Parameters

__application/json__

- `id`: Number (e.g. 1)
- `message`: String (e.g. "blah blah")

### Request

POST /foo

### Response

- Status:       200
- Content-Type: application/json

```json
{
   "message" : "success"
}

```

Please also refer to example (https://github.com/moznion/Test-JsonAPI-Autodoc/tree/master/eg).

METHODS

REQUIREMENTS

Generated document will output to $project_root/docs/ on default setting. $project_root means the directory on which cpanfile discovered while going back to a root directory from a test script is put. Therefore, it is necessary to put cpanfile on a project root.

CONFIGURATION AND ENVIRONMENT

CUSTOM TEMPLATE

You can customize template of markdown documents.

Available variables are the followings.

Example

: if $generated_at {
generated at: <: $generated_at :>

: }
## <: $description :>

: for $results -> $result {
<: $result.note :>

: if $result.server {
### Target Server

<: $result.server :>
: if $result.is_plack_app {

(Plack application)
: }

:}
### Parameters

: if $result.request_parameters {
    : if $result.request_content_type {
__<: $result.request_content_type :>__

    : }
: for $result.request_parameters -> $parameter {
<: $parameter :>
: }
: }
: else {
Not required
: }

### Request

<: $result.method:> <: $result.path :>
: if $result.query {

    <: $result.query :>
: }

### Response

- Status:       <: $result.status :>
- Content-Type: <: $result.response_content_type :>

```json
<: $result.response_body :>
```
: }

Template needs to be written by Text::Xslate::Syntax::Kolon as looking.

FAQ

Does this module correspond to JSON-RPC?

Yes. It can use as https://github.com/moznion/Test-JsonAPI-Autodoc/tree/master/eg/json_rpc.t.

Can methods of Test::More (e.g. subtest()) be called in describe()?

Yes, of course!

INSPIRED

This module is inspired by “autodoc”, which is written by Ruby. That is very nice RSpec extension.

See also https://github.com/r7kamura/autodoc

CONTRIBUTORS

LICENSE

Copyright (C) moznion.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHOR

moznion moznion@gmail.com