diff options
| author | 2018-08-16 22:44:24 +0200 | |
|---|---|---|
| committer | 2018-08-16 22:44:24 +0200 | |
| commit | a804d855e649a8148cd215bbbe3a47f9d7e9164a (patch) | |
| tree | 79cd0fdc83b2d9231d8f5f3030011ea3952febb9 /api | |
| parent | Make test user superuser. (diff) | |
Add support for `create` & `destroy`.
Diffstat (limited to '')
| -rw-r--r-- | api/tests/test_documentation_links.py | 89 | ||||
| -rw-r--r-- | api/viewsets.py | 55 | 
2 files changed, 133 insertions, 11 deletions
| diff --git a/api/tests/test_documentation_links.py b/api/tests/test_documentation_links.py index c3ffe5bb..e560a2fd 100644 --- a/api/tests/test_documentation_links.py +++ b/api/tests/test_documentation_links.py @@ -21,6 +21,19 @@ class UnauthedDocumentationLinkAPITests(APISubdomainTestCase):          self.assertEqual(response.status_code, 401) +    def test_create_returns_401(self): +        url = reverse('bot:documentationlink-list', host='api') +        response = self.client.post(url, data={'hi': 'there'}) + +        self.assertEqual(response.status_code, 401) + +    def test_delete_returns_401(self): +        url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') +        response = self.client.delete(url) + +        self.assertEqual(response.status_code, 401) + +  class EmptyDatabaseDocumentationLinkAPITests(APISubdomainTestCase):      def test_detail_lookup_returns_404(self):          url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') @@ -35,6 +48,12 @@ class EmptyDatabaseDocumentationLinkAPITests(APISubdomainTestCase):          self.assertEqual(response.status_code, 200)          self.assertEqual(response.json(), []) +    def test_delete_returns_404(self): +        url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') +        response = self.client.delete(url) + +        self.assertEqual(response.status_code, 404) +  class DetailLookupDocumentationLinkAPITests(APISubdomainTestCase):      @classmethod @@ -70,3 +89,73 @@ class DetailLookupDocumentationLinkAPITests(APISubdomainTestCase):          self.assertEqual(response.status_code, 200)          self.assertEqual(response.json(), [self.doc_json]) + +    def test_create_invalid_body_returns_400(self): +        url = reverse('bot:documentationlink-list', host='api') +        response = self.client.post(url, data={'i': 'am', 'totally': 'valid'}) + +        self.assertEqual(response.status_code, 400) + +    def test_create_invalid_url_returns_400(self): +        body = { +            'package': 'example', +            'base_url': 'https://example.com', +            'inventory_url': 'totally an url' +        } + +        url = reverse('bot:documentationlink-list', host='api') +        response = self.client.post(url, data=body) + +        self.assertEqual(response.status_code, 400) + + +class DocumentationLinkCreationTests(APISubdomainTestCase): +    def setUp(self): +        super().setUp() + +        self.body = { +            'package': 'example', +            'base_url': 'https://example.com', +            'inventory_url': 'https://docs.example.com' +        } + +        url = reverse('bot:documentationlink-list', host='api') +        response = self.client.post(url, data=self.body) + +        self.assertEqual(response.status_code, 201) + +    def test_package_in_full_list(self): +        url = reverse('bot:documentationlink-list', host='api') +        response = self.client.get(url) + +        self.assertEqual(response.status_code, 200) +        self.assertEqual(response.json(), [self.body]) + +    def test_detail_lookup_works_with_package(self): +        url = reverse('bot:documentationlink-detail', args=(self.body['package'],), host='api') +        response = self.client.get(url) + +        self.assertEqual(response.status_code, 200) +        self.assertEqual(response.json(), self.body) + + +class DocumentationLinkDeletionTests(APISubdomainTestCase): +    @classmethod +    def setUpTestData(cls): +        cls.doc_link = DocumentationLink.objects.create( +            package='example', +            base_url='https://example.com', +            inventory_url='https://docs.example.com' +        ) + +    def test_unknown_package_returns_404(self): +        url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') +        response = self.client.delete(url) + +        self.assertEqual(response.status_code, 404) + +    def test_delete_known_package_returns_204(self): +        url = reverse('bot:documentationlink-detail', args=(self.doc_link.package,), host='api') +        response = self.client.delete(url) + +        self.assertEqual(response.status_code, 204) diff --git a/api/viewsets.py b/api/viewsets.py index 48b2f226..39721847 100644 --- a/api/viewsets.py +++ b/api/viewsets.py @@ -1,4 +1,4 @@ -from rest_framework.mixins import ListModelMixin, RetrieveModelMixin +from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin  from rest_framework.response import Response  from rest_framework.viewsets import GenericViewSet, ViewSet @@ -6,14 +6,15 @@ from .models import DocumentationLink, SnakeName  from .serializers import DocumentationLinkSerializer, SnakeNameSerializer -class DocumentationLinkViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): +class DocumentationLinkViewSet(CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, GenericViewSet):      """ -    View providing documentation links used in the bot's `Doc` cog. +    View providing management of documentation links used in the bot's `Doc` cog.      ## Routes      ### GET /bot/documentation-links -    Return all documentation links in the database in the following format: +    Retrieve all currently stored entries from the database. +    #### Response format      >>> [      ...     {      ...         'package': 'flask', @@ -23,17 +24,43 @@ class DocumentationLinkViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSe      ...     # ...      ... ] +    #### Status codes +    - 200: returned on success +      ### GET /bot/documentation-links/<package:str>      Look up the documentation object for the given `package`. -    If an entry exists, return data in the following format: +    #### Response format      >>> {      ...     'package': 'flask',      ...     'base_url': 'https://flask.pocoo.org/docs/dev',      ...     'inventory_url': 'https://flask.pocoo.org/docs/objects.inv'      ... } -    Otherwise, if no entry for the given `package` exists, returns 404. +    #### Status codes +    - 200: returned on success +    - 404: if no entry for the given `package` exists + +    ### POST /bot/documentation-links +    Create a new documentation link object. + +    #### Body schema +    >>> { +    ...     'package': str, +    ...     'base_url': URL, +    ...     'inventory_url': URL +    ... } + +    #### Status codes +    - 201: returned on success +    - 400: if the request body has invalid fields, see the response for details + +    ### DELETE /bot/documentation-links/<package:str> +    Delete the entry for the given `package`. + +    #### Status codes +    - 204: returned on success +    - 404: if the given `package` could not be found      """      queryset = DocumentationLink.objects.all() @@ -47,23 +74,29 @@ class SnakeNameViewSet(ViewSet):      ## Routes      ### GET /bot/snake-names -    By default, return a single random snake name as JSON in the following format: +    By default, return a single random snake name along with its name and scientific name. +    If the `get_all` query parameter is given, for example using... +        $ curl api.pythondiscord.local:8000/bot/snake-names?get_all=yes +    ...then the API will return all snake names and scientific names in the database. +    #### Response format +    Without `get_all` query parameter:      >>> {      ...     'name': "Python",      ...     'scientific': "Langus greatus"      ... } -    If the `get_all` query parameter is given, for example using... -        $ curl api.pythondiscord.local:8000/bot/snake-names?get_all=yes -    ...then the API will return all snake names and scientific names in the database, -    for example: +    If the database is empty for whatever reason, this will return an empty dictionary. +    With `get_all` query parameter:      >>> [      ...     {'name': "Python 3", 'scientific': "Langus greatus"},      ...     {'name': "Python 2", 'scientific': "Langus decentus"}      ... ] +    #### Status codes +    - 200: returned on success +      ## Authentication      Requires a API token.      """ | 
