README.md

Bureaucrat
==========

Bureaucrat is a library that lets you generate API documentation of your Phoenix
app from tests.


Installation
------------

First, add Bureaucrat to your `mix.exs` dependencies:

```elixir
defp deps do
  [{:bureaucrat, "~> 0.1.4"}]
end
```

Then, update your dependencies:

```
$ mix deps.get
```

Next, in your `test/test_helper.exs` you should start Bureaucrat and configure
ExUnit to use its formatter. You would probably like to keep the default
`ExUnit.CLIFormatter` as well.

```elixir
Bureaucrat.start
ExUnit.start(formatters: [ExUnit.CLIFormatter, Bureaucrat.Formatter])
```

And finally, import Bureaucrat helpers in `test/support/conn_case.ex`:

```elixir
defmodule Spell.ConnCase do
  using do
    quote do
      import Bureaucrat.Helpers
    end
  end
end
```

To generate Phoenix channel documentation, import the helpers in `test/support/channel_case.ex` alike.

Usage
-----

Bureaucrat collects data from connection structs used in tests.
If you want a connection to be documented, pass it to the `doc/1` function:

```elixir
test "GET /api/v1/products" do
  conn = conn()
      |> get("/api/v1/products")
      |> doc
  assert conn.status == 200
end
```

Additional options can be passed to the backend formatter:

```elixir
test "GET /api/v1/products" do
  conn = conn()
      |> get("/api/v1/products")
      |> doc(description: "List all products", operation_id: "list_products")
  assert conn.status == 200
end

```

Then, to generate the documentation file(s) run `DOC=1 mix test`.
The default output file is `web/controllers/README.md`.

### Custom intro sections

To add a custom intro section, for each output file, bureaucrat will look for an __intro markdown file__ in the output directory,
named like the output file with a `_intro` or `_INTRO` suffix (before `.md`, if present), e.g.

  * `web/controllers/README` -> `web/controllers/README_INTRO`
  * `web/controllers/readme.md` -> `web/controllers/readme_intro.md`

Currently only supported by the (default) `Bureaucrat.MarkdownWriter`.

Documenting Phoenix Channels
----------------------------

Bureaucrat can also generate documentation for messages, replies and broadcasts in [Phoenix Channels](http://www.phoenixframework.org/docs/channels).

Results of `assert_push`, `assert_broadcast` and the underlying `assert_receive` (if used for messages or broadcasts) can be passed to the `doc` function.

To document usage of [Phoenix.ChannelTest](https://hexdocs.pm/phoenix/Phoenix.ChannelTest.html) helpers `push`, `broadcast_from` and `broadcast_from!`, Bureaucrat includes documenting alternatives, prefixed with `doc_`:
  * `doc_push`
  * `doc_broadcast_from`
  * `doc_broadcast_from!`

```elixir
test "message:new broadcasts are pushed to the client", %{socket: socket} do
  doc_broadcast_from! socket, "message:new", %{body: "Hello there!", timestamp: 1483971926566, user: "marla"}
  assert_push("message:new", %{body: "Hello there!", timestamp: 1483971926566, user: "marla"})
  |> doc
end
```

Channels docs output is currently only supported by the `Bureaucrat.MarkdownWriter` and only to the `default_path` (see [Configuration](#configuration) below).

Swagger & Slate Integration
---------------------------

Bureaucrat comes with the `Bureaucrat.SwaggerSlateMarkdownWriter` backend that will merge test examples with a swagger spec to produce markdown files that can be processed with the [slate](https://github.com/lord/slate) static generator.

To configure swagger integration, first write a swagger file by hand or generate one using [phoenix_swagger](https://github.com/xerions/phoenix_swagger). In the example below, the swagger file exists in the project at `priv/static/swagger.json`.

Clone the slate project into a directory in your project:

```
git clone --shallow https://github.com/lord/slate doc
```

Configure Bureaucrat `writer`, `default_path` and `swagger`:

```elixir
Bureaucrat.start(
  env_var: "DOC",
  writer: Bureaucrat.SwaggerSlateMarkdownWriter,
  default_path: "doc/source/index.html.md",
  swagger: "priv/static/swagger.json" |> File.read!() |> Poison.decode!())
```

Within each test, link the test example to a swagger operation by passing an `operation_id` to the `doc` helper:

```elixir
test "creates and renders resource when data is valid", %{conn: conn} do
  conn =
    conn
    |> post(user_path(conn, :create), user: @valid_attrs)
    |> doc(operation_id: "create_user")

  assert json_response(conn, 201)["data"]["id"]
  assert Repo.get_by(User, @valid_attrs)
end
```

Now generate documentation with `DOC=1 mix test`.

Use slate to convert the markdown to HTML:

```
cd doc
bundle install
bundle exec middleman build
```

To serve the documentation directly from your application, copy the slate build output to your `priv/static` directory:

```
mkdir priv/static/doc
cp -R doc/build/* priv/static/doc
```

Whitelist the `doc` directory for static assets in the `Plug.Static` configuration:

```elixir
plug Plug.Static,
  at: "/", from: :swagger_demo, gzip: false,
  only: ~w(css doc fonts images js favicon.ico robots.txt)
```

Run your application with `mix phoenix.server` and visit `http://localhost:4000/doc/index.html` to see your documentation.

For a full example see the `examples/swagger_demo` project.

Configuration
-------------

The configuration options can be passed to `Bureaucrat.start`:

```elixir
Bureaucrat.start(
 writer: Bureaucrat.MarkdownWriter,
 default_path: "web/controllers/README.md",
 paths: [],
 titles: [],
 env_var: "DOC"
)
```

The available options are:

* `:writer`: The module used to generate docs from the list of captured
connections.
* `:default_path`: The path where the docs are written by default.
* `:paths`: Allows you to specify different doc paths for some of your modules.
For example `[{YourApp.Api.V1, "web/controllers/api/v1/README.md"}]` will
cause the docs for controllers under `YourApp.Api.V1` namespace to
be written to `web/controllers/api/v1/README.md`.
* `:titles`: Allows you to specify explicit titles for some of your modules.
For example `[{YourApp.Api.V1.UserController, "API /v1/users"}]` will
change the title (Table of Contents entry and heading) for this controller.
* `:env_var`: The environment variable used as a flag to trigger doc generation.