Changeset View
Changeset View
Standalone View
Standalone View
swh/web/tests/api/test_apidoc.py
# Copyright (C) 2015-2019 The Software Heritage developers | # Copyright (C) 2015-2019 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU Affero General Public License version 3, or any later version | # License: GNU Affero General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
import textwrap | import textwrap | ||||
import pytest | import pytest | ||||
from rest_framework.response import Response | from rest_framework.response import Response | ||||
from swh.storage.exc import StorageAPIError, StorageDBError | from swh.storage.exc import StorageAPIError, StorageDBError | ||||
from swh.web.api.apidoc import _parse_httpdomain_doc, api_doc | from swh.web.api.apidoc import _parse_httpdomain_doc, api_doc | ||||
from swh.web.api.apiurls import api_route | from swh.web.api.apiurls import api_route | ||||
from swh.web.common.exc import BadInputExc, ForbiddenExc, NotFoundExc | from swh.web.common.exc import BadInputExc, ForbiddenExc, NotFoundExc | ||||
from swh.web.common.utils import prettify_html, reverse | from swh.web.common.utils import prettify_html, reverse | ||||
from swh.web.tests.django_asserts import assert_template_used | from swh.web.tests.utils import check_api_get_responses, check_html_get_response | ||||
_httpdomain_doc = """ | _httpdomain_doc = """ | ||||
.. http:get:: /api/1/revision/(sha1_git)/ | .. http:get:: /api/1/revision/(sha1_git)/ | ||||
Get information about a revision in the archive. | Get information about a revision in the archive. | ||||
Revisions are identified by **sha1** checksums, compatible with Git commit | Revisions are identified by **sha1** checksums, compatible with Git commit | ||||
identifiers. | identifiers. | ||||
See :func:`swh.model.identifiers.revision_identifier` in our data model | See :func:`swh.model.identifiers.revision_identifier` in our data model | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | def apidoc_route(request, myarg, myotherarg, akw=0): | ||||
""" | """ | ||||
Sample doc | Sample doc | ||||
""" | """ | ||||
return {"result": int(myarg) + int(myotherarg) + akw} | return {"result": int(myarg) + int(myotherarg) + akw} | ||||
def test_apidoc_route_doc(client): | def test_apidoc_route_doc(client): | ||||
url = reverse("api-1-some-doc-route-doc") | url = reverse("api-1-some-doc-route-doc") | ||||
rv = client.get(url, HTTP_ACCEPT="text/html") | check_html_get_response( | ||||
client, url, status_code=200, template_used="api/apidoc.html" | |||||
assert rv.status_code == 200, rv.content | ) | ||||
assert_template_used(rv, "api/apidoc.html") | |||||
def test_apidoc_route_fn(api_client): | def test_apidoc_route_fn(api_client): | ||||
url = reverse("api-1-some-doc-route", url_args={"myarg": 1, "myotherarg": 1}) | url = reverse("api-1-some-doc-route", url_args={"myarg": 1, "myotherarg": 1}) | ||||
rv = api_client.get(url) | check_api_get_responses(api_client, url, status_code=200) | ||||
assert rv.status_code == 200, rv.data | |||||
@api_route(r"/test/error/(?P<exc_name>.+)/", "api-1-test-error") | @api_route(r"/test/error/(?P<exc_name>.+)/", "api-1-test-error") | ||||
@api_doc("/test/error/") | @api_doc("/test/error/") | ||||
def apidoc_test_error_route(request, exc_name): | def apidoc_test_error_route(request, exc_name): | ||||
""" | """ | ||||
Sample doc | Sample doc | ||||
""" | """ | ||||
for e in _exception_http_code.keys(): | for e in _exception_http_code.keys(): | ||||
if e.__name__ == exc_name: | if e.__name__ == exc_name: | ||||
raise e("Error") | raise e("Error") | ||||
def test_apidoc_error(api_client): | def test_apidoc_error(api_client): | ||||
for exc, code in _exception_http_code.items(): | for exc, code in _exception_http_code.items(): | ||||
url = reverse("api-1-test-error", url_args={"exc_name": exc.__name__}) | url = reverse("api-1-test-error", url_args={"exc_name": exc.__name__}) | ||||
rv = api_client.get(url) | check_api_get_responses(api_client, url, status_code=code) | ||||
assert rv.status_code == code, rv.data | |||||
@api_route( | @api_route( | ||||
r"/some/full/(?P<myarg>[0-9]+)/(?P<myotherarg>[0-9]+)/", | r"/some/full/(?P<myarg>[0-9]+)/(?P<myotherarg>[0-9]+)/", | ||||
"api-1-some-complete-doc-route", | "api-1-some-complete-doc-route", | ||||
) | ) | ||||
@api_doc("/some/complete/doc/route/") | @api_doc("/some/complete/doc/route/") | ||||
def apidoc_full_stack(request, myarg, myotherarg, akw=0): | def apidoc_full_stack(request, myarg, myotherarg, akw=0): | ||||
""" | """ | ||||
Sample doc | Sample doc | ||||
""" | """ | ||||
return {"result": int(myarg) + int(myotherarg) + akw} | return {"result": int(myarg) + int(myotherarg) + akw} | ||||
def test_apidoc_full_stack_doc(client): | def test_apidoc_full_stack_doc(client): | ||||
url = reverse("api-1-some-complete-doc-route-doc") | url = reverse("api-1-some-complete-doc-route-doc") | ||||
rv = client.get(url, HTTP_ACCEPT="text/html") | check_html_get_response( | ||||
assert rv.status_code == 200, rv.content | client, url, status_code=200, template_used="api/apidoc.html" | ||||
assert_template_used(rv, "api/apidoc.html") | ) | ||||
def test_apidoc_full_stack_fn(api_client): | def test_apidoc_full_stack_fn(api_client): | ||||
url = reverse( | url = reverse( | ||||
"api-1-some-complete-doc-route", url_args={"myarg": 1, "myotherarg": 1} | "api-1-some-complete-doc-route", url_args={"myarg": 1, "myotherarg": 1} | ||||
) | ) | ||||
rv = api_client.get(url) | check_api_get_responses(api_client, url, status_code=200) | ||||
assert rv.status_code == 200, rv.data | |||||
@api_route(r"/test/post/only/", "api-1-test-post-only", methods=["POST"]) | @api_route(r"/test/post/only/", "api-1-test-post-only", methods=["POST"]) | ||||
@api_doc("/test/post/only/") | @api_doc("/test/post/only/") | ||||
def apidoc_test_post_only(request, exc_name): | def apidoc_test_post_only(request, exc_name): | ||||
""" | """ | ||||
Sample doc | Sample doc | ||||
""" | """ | ||||
return {"result": "some data"} | return {"result": "some data"} | ||||
def test_apidoc_post_only(client): | def test_apidoc_post_only(client): | ||||
# a dedicated view accepting GET requests should have | # a dedicated view accepting GET requests should have | ||||
# been created to display the HTML documentation | # been created to display the HTML documentation | ||||
url = reverse("api-1-test-post-only-doc") | url = reverse("api-1-test-post-only-doc") | ||||
rv = client.get(url, HTTP_ACCEPT="text/html") | check_html_get_response( | ||||
assert rv.status_code == 200, rv.content | client, url, status_code=200, template_used="api/apidoc.html" | ||||
assert_template_used(rv, "api/apidoc.html") | ) | ||||
def test_api_doc_parse_httpdomain(): | def test_api_doc_parse_httpdomain(): | ||||
doc_data = { | doc_data = { | ||||
"description": "", | "description": "", | ||||
"urls": [], | "urls": [], | ||||
"args": [], | "args": [], | ||||
"params": [], | "params": [], | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | .. http:post:: /api/1/post/endpoint/ | ||||
* **known (bool)**: whether the object was found | * **known (bool)**: whether the object was found | ||||
""" | """ | ||||
pass | pass | ||||
def test_apidoc_input_output_doc(client): | def test_apidoc_input_output_doc(client): | ||||
url = reverse("api-1-post-endpoint-doc") | url = reverse("api-1-post-endpoint-doc") | ||||
rv = client.get(url, HTTP_ACCEPT="text/html") | rv = check_html_get_response( | ||||
assert rv.status_code == 200, rv.content | client, url, status_code=200, template_used="api/apidoc.html" | ||||
assert_template_used(rv, "api/apidoc.html") | ) | ||||
input_html_doc = textwrap.indent( | input_html_doc = textwrap.indent( | ||||
( | ( | ||||
'<dl class="row">\n' | '<dl class="row">\n' | ||||
' <dt class="col col-md-2 text-right">\n' | ' <dt class="col col-md-2 text-right">\n' | ||||
" array\n" | " array\n" | ||||
" </dt>\n" | " </dt>\n" | ||||
' <dd class="col col-md-9">\n' | ' <dd class="col col-md-9">\n' | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | .. http:get:: /api/1/post/endpoint/ | ||||
:http:get:`/api/1/directory/(sha1_git)/[(path)/]` | :http:get:`/api/1/directory/(sha1_git)/[(path)/]` | ||||
and `archive <https://archive.softwareheritage.org>`_. | and `archive <https://archive.softwareheritage.org>`_. | ||||
""" | """ | ||||
pass | pass | ||||
def test_apidoc_with_links(client): | def test_apidoc_with_links(client): | ||||
url = reverse("api-1-endpoint-links-in-doc") | url = reverse("api-1-endpoint-links-in-doc") | ||||
rv = client.get(url, HTTP_ACCEPT="text/html") | rv = check_html_get_response( | ||||
assert rv.status_code == 200, rv.content | client, url, status_code=200, template_used="api/apidoc.html" | ||||
assert_template_used(rv, "api/apidoc.html") | ) | ||||
html = prettify_html(rv.content) | html = prettify_html(rv.content) | ||||
first_link = textwrap.indent( | first_link = textwrap.indent( | ||||
( | ( | ||||
'<a class="reference external" href="/api/1/content/doc/">\n' | '<a class="reference external" href="/api/1/content/doc/">\n' | ||||
" /api/1/content/\n" | " /api/1/content/\n" | ||||
"</a>" | "</a>" | ||||
Show All 26 Lines |