docs: Attempt to clarify the REST API writing docs.

This commit is contained in:
Tim Abbott
2018-06-04 15:58:11 -07:00
parent 371cacde35
commit ce4f00bd84

View File

@@ -3,17 +3,26 @@
This document briefly explains how to document This document briefly explains how to document
[Zulip's REST API endpoints](https://zulipchat.com/api/rest). [Zulip's REST API endpoints](https://zulipchat.com/api/rest).
Our API documentation files live under `templates/zerver/api/*`. To begin, Our API documentation files live under `templates/zerver/api/*`. To
we recommend copying over an existing doc file (`render-message.md` is a good begin, we recommend using an existing doc file (`render-message.md` is
example) and using it as a template. Make sure you link to your new Markdown a good example) as a template. Make sure you link to your new Markdown
file in `templates/zerver/help/rest-endpoints.md`, so that it can be displayed file in `templates/zerver/help/rest-endpoints.md` , so that it appears
in the sidebar on the `/api` page. in the index in the left sidebar on the `/api` page.
If you look at the documentation for existing endpoints (see a live example The markdown framework is the same one used by the
[here](https://zulipchat.com/api/render-message)), you'll notice that the [user docs](../subsystems/user-docs.html), which supports macros and
documentation is roughly divided into three sections: **Usage examples**, various other features, though we don't use them heavily here.
**Arguments**, and **Response**. The rest of this guide describes how to write
each of these sections. If you look at the documentation for existing endpoints (see a live
example [here](https://zulipchat.com/api/render-message)), you'll
notice that a typical endpoint's documentation is roughly divided into
three sections: **Usage examples**, **Arguments**, and
**Response**. The rest of this guide describes how to write each of
these sections.
There's also a small section at the top, where you'll want to explain
what the endpoint does in clear English, and any important notes on
how to use it correctly or what it's good or bad for.
## Usage examples ## Usage examples
@@ -22,37 +31,43 @@ For JavaScript and `curl` we simply recommend copying and pasting the examples
directly into the Markdown file. JavaScript examples should conform to the directly into the Markdown file. JavaScript examples should conform to the
coding style and structure of [Zulip's existing JavaScript examples][1]. coding style and structure of [Zulip's existing JavaScript examples][1].
However, since Zulip's Python bindings are used most frequently, the process However, since Zulip's Python bindings are used most frequently, the process
of adding Python examples for an endpoint is a bit more involved. of adding Python examples for an endpoint have a more involved process
that includes automated tests for your documentation(!).
[1]: https://github.com/zulip/zulip-js/tree/master/examples [1]: https://github.com/zulip/zulip-js/tree/master/examples
We recommend skimming `zerver/lib/api_test_helpers.py` before proceeding with the We recommend skimming `zerver/lib/api_test_helpers.py` before proceeding with the
steps below. steps below.
1. Add a function for the endpoint you'd like to document to 1. Start adding a function for the endpoint you'd like to document to
`zerver/lib/api_test_helpers.py`. `render_message` is a good example to `zerver/lib/api_test_helpers.py`. `render_message` is a good
follow. example to follow. There are generally two key pieces to your
test: (1) doing an API query and (2) verifying its result is
1. Add the function to the `TEST_FUNCTIONS` dict. as expected using `test_against_fixture`.
1. Make the desired API call inside the function. If our Python bindings don't 1. Make the desired API call inside the function. If our Python bindings don't
have a dedicated method for a specific API call, you may either use have a dedicated method for a specific API call, you may either use
`client.call_endpoint` or add a dedicated function to the `client.call_endpoint` or add a dedicated function to the
[zulip PyPI package](https://github.com/zulip/python-zulip-api/tree/master/zulip). [zulip PyPI package](https://github.com/zulip/python-zulip-api/tree/master/zulip).
Ultimately, the goal is for every endpoint to be documented the
latter way, but it's nice to be able to write your docs before you
have to finish writing dedicated functions.
1. Capture the fixture returned by the API call and add it to 1. Add the function to the `TEST_FUNCTIONS` dict and one of the
`templates/zerver/api/fixtures.json`, where the key is the name of the Markdown `test_*` functions at the end of `zerver/lib/api_test_helpers.py`;
file documenting the endpoint (without the `.md` extension), and the value is these will ensure your function will be called when running `test-api`.
the fixture JSON object. Make sure that the JSON is formatted properly before
you add it to `fixtures.json` (see [Formatting JSON](#formatting-json) for more
info).
1. In `zerver/lib/api_test_helpers.py`, use `test_against_fixture` to test the 1. Capture the JSON response returned by the API call (the test
result of the API call against the fixture captured in the previous step. This "fixture"). The easiest way to do this is add an appropriate print
should be done inside the function you added in step 1. Make sure you update the statement, and then run `tools/test-api` (see
`test_*` functions at the end of `zerver/lib/api_test_helpers.py` apppropriately. [Formatting JSON](#formatting-json) for how to get in it the right
JSON format). Add the fixture to
`templates/zerver/api/fixtures.json`, where the key is the name of
the Markdown file documenting the endpoint (without the `.md`
extension), and the value is the fixture JSON object.
1. Run `./tools/test-api` to make sure the tests pass. 1. Run `./tools/test-api` to make sure your new test function is being
run and the tests pass.
1. Now, inside the function, isolate the lines of code that call the API and could 1. Now, inside the function, isolate the lines of code that call the API and could
be displayed as a code example. Wrap the relevant lines in be displayed as a code example. Wrap the relevant lines in
@@ -71,10 +86,11 @@ steps below.
`KEY_IN_TEST_FUNCTIONS` is the key in the `TEST_FUNCTIONS` dict (added in step 2) `KEY_IN_TEST_FUNCTIONS` is the key in the `TEST_FUNCTIONS` dict (added in step 2)
that points to your test function. that points to your test function.
This Markdown-based framework allows us to extract code examples from within tests, This Markdown-based framework allows us to extract code examples from
which makes sure that code examples never get out of date or fail, and if they do, within tests, which makes sure that code examples never get out of
`./tools/test-api` complains very loudly. To learn more about how this Markdown date, since if they do, `./tools/test-api` will fail in our continuous
extension works, see `zerver/lib/bugdown/api_code_examples.py`. integration. To learn more about how this Markdown extension works,
see `zerver/lib/bugdown/api_code_examples.py`.
## Documenting arguments ## Documenting arguments
@@ -102,6 +118,9 @@ The best way to find out what arguments an API endpoint takes is to
find the corresponding URL pattern in `zprojects/urls.py` and examining find the corresponding URL pattern in `zprojects/urls.py` and examining
the backend function that the URL pattern points to. the backend function that the URL pattern points to.
Be careful here! There's no currently automated testing verifying
that the arguments match the code.
## Displaying example payloads/responses ## Displaying example payloads/responses
If you've already followed the steps in the [Usage examples](#usage-examples) If you've already followed the steps in the [Usage examples](#usage-examples)