From 9d120d94bcf93fc7317af9b54dcc4c8841d8b5e6 Mon Sep 17 00:00:00 2001 From: Dhruv Bhanushali Date: Wed, 1 Sep 2021 15:21:47 +0530 Subject: [PATCH 1/3] Use `HyperlinkedIdentityField` to automatically generate related URLs --- .../api/serializers/audio_serializers.py | 33 ++++++++----------- .../api/serializers/image_serializers.py | 15 ++++----- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/openverse-api/catalog/api/serializers/audio_serializers.py b/openverse-api/catalog/api/serializers/audio_serializers.py index 453d4ed47..ee96f49ab 100644 --- a/openverse-api/catalog/api/serializers/audio_serializers.py +++ b/openverse-api/catalog/api/serializers/audio_serializers.py @@ -1,4 +1,3 @@ -from django.urls import reverse from rest_framework import serializers from catalog.api.controllers.search_controller import get_sources @@ -96,12 +95,6 @@ class AudioSerializer(MediaSerializer): used to generate Swagger documentation. """ - thumbnail = serializers.SerializerMethodField( - help_text="A direct link to the miniature artwork." - ) - waveform = serializers.SerializerMethodField( - help_text='A direct link to the waveform peaks.' - ) audio_set = serializers.PrimaryKeyRelatedField( required=False, help_text='Reference to set of which this track is a part.', @@ -135,6 +128,18 @@ class AudioSerializer(MediaSerializer): ) # Hyperlinks + thumbnail = serializers.HyperlinkedIdentityField( + read_only=True, + view_name='audio-thumb', + lookup_field='identifier', + help_text="A direct link to the miniature artwork." + ) + waveform = serializers.HyperlinkedIdentityField( + read_only=True, + view_name='audio-waveform', + lookup_field='identifier', + help_text='A direct link to the waveform peaks.' + ) detail_url = serializers.HyperlinkedIdentityField( read_only=True, view_name='audio-detail', @@ -142,24 +147,12 @@ class AudioSerializer(MediaSerializer): help_text="A direct link to the detail view of this audio file." ) related_url = serializers.HyperlinkedIdentityField( + read_only=True, view_name='audio-related', lookup_field='identifier', - read_only=True, help_text="A link to an endpoint that provides similar audio files." ) - def get_thumbnail(self, obj): - request = self.context['request'] - host = request.get_host() - path = reverse('audio-thumb', kwargs={'identifier': obj.identifier}) - return f'https://{host}{path}' - - def get_waveform(self, obj): - request = self.context['request'] - host = request.get_host() - path = reverse('audio-waveform', kwargs={'identifier': obj.identifier}) - return f'https://{host}{path}' - class AudioSearchSerializer(MediaSearchSerializer): """ diff --git a/openverse-api/catalog/api/serializers/image_serializers.py b/openverse-api/catalog/api/serializers/image_serializers.py index e618c269b..f18927c0a 100644 --- a/openverse-api/catalog/api/serializers/image_serializers.py +++ b/openverse-api/catalog/api/serializers/image_serializers.py @@ -97,9 +97,6 @@ class ImageSerializer(MediaSerializer): used to generate Swagger documentation. """ - thumbnail = serializers.SerializerMethodField( - help_text="A direct link to the miniature image." - ) height = serializers.IntegerField( required=False, help_text="The height of the image in pixels. Not always available." @@ -110,6 +107,12 @@ class ImageSerializer(MediaSerializer): ) # Hyperlinks + thumbnail = serializers.HyperlinkedIdentityField( + read_only=True, + view_name='image-thumb', + lookup_field='identifier', + help_text="A direct link to the miniature image." + ) detail_url = serializers.HyperlinkedIdentityField( read_only=True, view_name='image-detail', @@ -123,12 +126,6 @@ class ImageSerializer(MediaSerializer): help_text="A link to an endpoint that provides similar images." ) - def get_thumbnail(self, obj): - request = self.context['request'] - host = request.get_host() - path = reverse('image-thumb', kwargs={'identifier': obj.identifier}) - return f'https://{host}{path}' - class ImageSearchSerializer(MediaSearchSerializer): """ From 4862f95141e8e1f923f335a31bf4b0ca2ba07c79 Mon Sep 17 00:00:00 2001 From: Dhruv Bhanushali Date: Wed, 1 Sep 2021 16:34:03 +0530 Subject: [PATCH 2/3] Fix nomenclature in example requests and responses --- openverse-api/catalog/api/docs/audio_docs.py | 28 +-- openverse-api/catalog/api/docs/image_docs.py | 40 ++-- .../catalog/api/examples/__init__.py | 36 ++-- .../catalog/api/examples/audio_requests.py | 58 +++--- .../catalog/api/examples/audio_responses.py | 139 +++++++++----- .../catalog/api/examples/image_requests.py | 64 ++++--- .../catalog/api/examples/image_responses.py | 178 ++++++++++-------- 7 files changed, 319 insertions(+), 224 deletions(-) diff --git a/openverse-api/catalog/api/docs/audio_docs.py b/openverse-api/catalog/api/docs/audio_docs.py index 785004007..580293cbd 100644 --- a/openverse-api/catalog/api/docs/audio_docs.py +++ b/openverse-api/catalog/api/docs/audio_docs.py @@ -9,19 +9,19 @@ MediaComplain, ) from catalog.api.examples import ( - audio_search_curl, + audio_search_list_curl, audio_search_200_example, audio_search_400_example, - recommendations_audio_read_curl, - recommendations_audio_read_200_example, - recommendations_audio_read_404_example, + audio_stats_curl, + audio_stats_200_example, audio_detail_curl, audio_detail_200_example, audio_detail_404_example, - audio_stats_curl, - audio_stats_200_example, - report_audio_curl, - audio_report_create_201_example, + audio_related_curl, + audio_related_200_example, + audio_related_404_example, + audio_complain_curl, + audio_complain_201_example, ) from catalog.api.serializers.audio_serializers import ( AudioSearchRequestSerializer, @@ -62,7 +62,7 @@ class AudioSearch(MediaSearch): code_examples = [ { 'lang': 'Bash', - 'source': audio_search_curl, + 'source': audio_search_list_curl, }, ] @@ -155,12 +155,12 @@ class AudioRelated(MediaRelated): responses = { "200": openapi.Response( description="OK", - examples=recommendations_audio_read_200_example, + examples=audio_related_200_example, schema=AudioSerializer ), "404": openapi.Response( description="Not Found", - examples=recommendations_audio_read_404_example, + examples=audio_related_404_example, schema=NotFoundErrorSerializer ) } @@ -168,7 +168,7 @@ class AudioRelated(MediaRelated): code_examples = [ { 'lang': 'Bash', - 'source': recommendations_audio_read_curl, + 'source': audio_related_curl, }, ] @@ -193,7 +193,7 @@ class AudioComplain(MediaComplain): responses = { "201": openapi.Response( description="OK", - examples=audio_report_create_201_example, + examples=audio_complain_201_example, schema=AudioReportSerializer ) } @@ -201,7 +201,7 @@ class AudioComplain(MediaComplain): code_examples = [ { 'lang': 'Bash', - 'source': report_audio_curl, + 'source': audio_complain_curl, } ] diff --git a/openverse-api/catalog/api/docs/image_docs.py b/openverse-api/catalog/api/docs/image_docs.py index 2c2570dd2..58ade5fca 100644 --- a/openverse-api/catalog/api/docs/image_docs.py +++ b/openverse-api/catalog/api/docs/image_docs.py @@ -10,22 +10,22 @@ MediaComplain, ) from catalog.api.examples import ( - image_search_curl, + image_search_list_curl, image_search_200_example, image_search_400_example, - recommendations_images_read_curl, - recommendations_images_read_200_example, - recommendations_images_read_404_example, + image_stats_curl, + image_stats_200_example, image_detail_curl, image_detail_200_example, image_detail_404_example, - image_stats_curl, - image_stats_200_example, - report_image_curl, - images_report_create_201_example, - oembed_list_curl, - oembed_list_200_example, - oembed_list_404_example, + image_related_curl, + image_related_200_example, + image_related_404_example, + image_complain_curl, + image_complain_201_example, + image_oembed_curl, + image_oembed_200_example, + image_oembed_404_example, ) from catalog.api.serializers.error_serializers import ( InputErrorSerializer, @@ -68,7 +68,7 @@ class ImageSearch(MediaSearch): code_examples = [ { 'lang': 'Bash', - 'source': image_search_curl, + 'source': image_search_list_curl, }, ] @@ -161,12 +161,12 @@ class ImageRelated(MediaRelated): responses = { "200": openapi.Response( description="OK", - examples=recommendations_images_read_200_example, + examples=image_related_200_example, schema=ImageSerializer ), "404": openapi.Response( description="Not Found", - examples=recommendations_images_read_404_example, + examples=image_related_404_example, schema=NotFoundErrorSerializer ) } @@ -174,7 +174,7 @@ class ImageRelated(MediaRelated): code_examples = [ { 'lang': 'Bash', - 'source': recommendations_images_read_curl + 'source': image_related_curl } ] @@ -199,7 +199,7 @@ class ImageComplain(MediaComplain): responses = { "201": openapi.Response( description="OK", - examples=images_report_create_201_example, + examples=image_complain_201_example, schema=ImageReportSerializer ) } @@ -207,7 +207,7 @@ class ImageComplain(MediaComplain): code_examples = [ { 'lang': 'Bash', - 'source': report_image_curl, + 'source': image_complain_curl, } ] @@ -234,12 +234,12 @@ class ImageOembed: responses = { "200": openapi.Response( description="OK", - examples=oembed_list_200_example, + examples=image_oembed_200_example, schema=OembedSerializer ), "404": openapi.Response( description="Not Found", - examples=oembed_list_404_example, + examples=image_oembed_404_example, schema=NotFoundErrorSerializer ) } @@ -247,7 +247,7 @@ class ImageOembed: code_examples = [ { 'lang': 'Bash', - 'source': oembed_list_curl, + 'source': image_oembed_curl, }, ] diff --git a/openverse-api/catalog/api/examples/__init__.py b/openverse-api/catalog/api/examples/__init__.py index e2117ee5d..550027607 100644 --- a/openverse-api/catalog/api/examples/__init__.py +++ b/openverse-api/catalog/api/examples/__init__.py @@ -1,37 +1,39 @@ from catalog.api.examples.audio_requests import ( + audio_search_list_curl, audio_search_curl, - recommendations_audio_read_curl, - audio_detail_curl, audio_stats_curl, - report_audio_curl, + audio_detail_curl, + audio_related_curl, + audio_complain_curl, ) from catalog.api.examples.audio_responses import ( audio_search_200_example, audio_search_400_example, + audio_stats_200_example, audio_detail_200_example, audio_detail_404_example, - recommendations_audio_read_200_example, - recommendations_audio_read_404_example, - audio_report_create_201_example, - audio_stats_200_example, + audio_related_200_example, + audio_related_404_example, + audio_complain_201_example, ) from catalog.api.examples.image_requests import ( + image_search_list_curl, image_search_curl, - recommendations_images_read_curl, - image_detail_curl, image_stats_curl, - report_image_curl, - oembed_list_curl, + image_detail_curl, + image_related_curl, + image_complain_curl, + image_oembed_curl, ) from catalog.api.examples.image_responses import ( image_search_200_example, image_search_400_example, + image_stats_200_example, image_detail_200_example, image_detail_404_example, - recommendations_images_read_200_example, - recommendations_images_read_404_example, - oembed_list_200_example, - oembed_list_404_example, - images_report_create_201_example, - image_stats_200_example, + image_related_200_example, + image_related_404_example, + image_complain_201_example, + image_oembed_200_example, + image_oembed_404_example, ) diff --git a/openverse-api/catalog/api/examples/audio_requests.py b/openverse-api/catalog/api/examples/audio_requests.py index 9074556e3..fc2e7ab5a 100644 --- a/openverse-api/catalog/api/examples/audio_requests.py +++ b/openverse-api/catalog/api/examples/audio_requests.py @@ -1,3 +1,11 @@ +import os + +token = os.getenv('AUDIO_REQ_TOKEN', 'DLBYIcfnKfolaXKcmMC8RIDCavc2hW') +origin = os.getenv('AUDIO_REQ_ORIGIN', 'https://api.openverse.engineering') + +auth = f'-H "Authorization: Bearer {token}"' if token else '' +identifier = '440a0240-8b20-49e2-a4e6-6fee550fcc41' + syntax_examples = { "using single query parameter": 'test', @@ -20,29 +28,37 @@ 'theatre~1', } -audio_search_curl = '\n\n'.join([ - (f'# Example {index}: Search for audio {purpose}\n' - 'curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" ' - f'https://api.openverse.engineering/v1/audio?q={syntax}') - for (index, (purpose, syntax)) in enumerate(syntax_examples.items()) -]) +audio_search_list_curl = '\n'.join(f""" +# Example {index}: Search for audio {purpose} +curl {auth} "{origin}/v1/audio/?q={syntax}" +""" for (index, (purpose, syntax)) in enumerate(syntax_examples.items())) -recommendations_audio_read_curl = """ -# Get related audio files for audio ID 7c829a03-fb24-4b57-9b03-65f43ed19395 -curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" http://api.openverse.engineering/v1/recommendations/audio/7c829a03-fb24-4b57-9b03-65f43ed19395 -""" # noqa +audio_search_curl = f""" +# Search for music titled "Friend" by Rob Costlow +curl {auth} "{origin}/v1/audio/?title=Friend&creator=Rob%20Costlow" +""" -audio_detail_curl = """ -# Get the details of audio ID 7c829a03-fb24-4b57-9b03-65f43ed19395 -curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" http://api.openverse.engineering/v1/audio/7c829a03-fb24-4b57-9b03-65f43ed19395 -""" # noqa - -audio_stats_curl = """ +audio_stats_curl = f""" # Get the statistics for audio sources -curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" http://api.openverse.engineering/v1/audio/stats -""" # noqa +curl {auth} "{origin}/v1/audio/stats/" +""" + +audio_detail_curl = f""" +# Get the details of audio ID {identifier} +curl {auth} "{origin}/v1/audio/{identifier}/" +""" + +audio_related_curl = f""" +# Get related audio files for audio ID {identifier} +curl {auth} "{origin}/v1/audio/{identifier}/related/" +""" -report_audio_curl = """ -# Report an issue about audio ID 7c829a03-fb24-4b57-9b03-65f43ed19395 -curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" -d '{"reason": "mature", "description": "This audio contains sensitive content"}' https://api.openverse.engineering/v1/audio/7c829a03-fb24-4b57-9b03-65f43ed19395/report +audio_complain_curl = f""" +# Report an issue about audio ID {identifier} +curl \\ + -X POST \\ + -H "Content-Type: application/json" \\ + {auth} \\ + -d '{{"reason": "mature", "description": "This audio contains sensitive content"}}' \\ + "{origin}/v1/audio/{identifier}/report/" """ # noqa diff --git a/openverse-api/catalog/api/examples/audio_responses.py b/openverse-api/catalog/api/examples/audio_responses.py index 1bb686ad4..2d7a96965 100644 --- a/openverse-api/catalog/api/examples/audio_responses.py +++ b/openverse-api/catalog/api/examples/audio_responses.py @@ -1,28 +1,68 @@ +import os + +origin = os.getenv('AUDIO_REQ_ORIGIN', 'https://api.openverse.engineering') + +identifier = '440a0240-8b20-49e2-a4e6-6fee550fcc41' + +base_audio = { + "id": identifier, + "title": "Friend", + "foreign_landing_url": "https://www.jamendo.com/track/5786", + "creator": "Rob Costlow", + "creator_url": "https://www.jamendo.com/artist/125/rob.costlow", + "url": "https://mp3d.jamendo.com/download/track/5786/mp32", + "license": "by-nc-nd", + "license_version": "3.0", + "license_url": "https://creativecommons.org/licenses/by-nc-nd/3.0/", + "provider": "jamendo", + "source": "jamendo", + "tags": [ + { + "name": "instrumental" + }, + { + "name": "neutral" + }, + { + "name": "speed_medium" + }, + { + "name": "piano" + }, + { + "name": "strings" + }, + { + "name": "love" + }, + { + "name": "upbeat" + }, + { + "name": "neutral" + } + ], + "genres": [ + "newage" + ], + "thumbnail": f"{origin}/v1/audio/{identifier}/thumb/", + "waveform": f"{origin}/v1/audio/{identifier}/waveform/", + "detail_url": f"{origin}/v1/audio/{identifier}/", + "related_url": f"{origin}/v1/audio/{identifier}/related/" +} + audio_search_200_example = { "application/json": { - "result_count": 77, - "page_count": 77, - "page_size": 1, + "result_count": 1, + "page_count": 0, + "page_size": 20, + "page": 1, "results": [ - { - "title": "File:Mozart - Eine kleine Nachtmusik - 1. Allegro.ogg", # noqa - "id": "36537842-b067-4ca0-ad67-e00ff2e06b2e", - "creator": "Wolfgang Amadeus Mozart", - "creator_url": "https://en.wikipedia.org/wiki/Wolfgang_Amadeus_Mozart", # noqa - "url": "https://upload.wikimedia.org/wikipedia/commons/2/24/Mozart_-_Eine_kleine_Nachtmusik_-_1._Allegro.ogg", # noqa - "provider": "wikimedia", - "source": "wikimedia", - "license": "by-sa", - "license_version": "2.0", - "license_url": "https://creativecommons.org/licenses/by-sa/2.0/", # noqa - "foreign_landing_url": "https://commons.wikimedia.org/w/index.php?curid=3536953", # noqa - "detail_url": "http://api.openverse.engineering/v1/audio/36537842-b067-4ca0-ad67-e00ff2e06b2e", # noqa - "related_url": "http://api.openverse.engineering/v1/recommendations/audio/36537842-b067-4ca0-ad67-e00ff2e06b2e", # noqa + base_audio | { "fields_matched": [ - "description", "title" ] - } + }, ] }, } @@ -37,7 +77,36 @@ } } -recommendations_audio_read_200_example = { +audio_stats_200_example = { + "application/json": [ + { + "source_name": "jamendo", + "display_name": "Jamendo", + "source_url": "https://www.jamendo.com", + "logo_url": None, + "media_count": 5153, + } + ] +} + +audio_detail_200_example = { + "application/json": base_audio | { + "attribution": "\"Friend\" by Rob Costlow is licensed under CC-BY-NC-ND 3.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-nd/3.0/.", # noqa + "audio_set": None, + "duration": 240000, + "bit_rate": None, + "sample_rate": None, + "alt_files": None + }, +} + +audio_detail_404_example = { + "application/json": { + "detail": "Not found." + } +} + +audio_related_200_example = { "application/json": { "result_count": 10000, "page_count": 0, @@ -73,40 +142,16 @@ } } -recommendations_audio_read_404_example = { +audio_related_404_example = { "application/json": { "detail": "An internal server error occurred." } } -audio_detail_200_example = { +audio_complain_201_example = { "application/json": { - # TODO - } -} - -audio_detail_404_example = { - "application/json": { - "detail": "Not found." - } -} - -audio_report_create_201_example = { - "application/json": { - "id": 10, - "identifier": "7c829a03-fb24-4b57-9b03-65f43ed19395", + "identifier": identifier, "reason": "mature", "description": "This audio contains sensitive content" } } - -audio_stats_200_example = { - "application/json": [ - { - "source_name": "jamendo", - "audio_count": 123456789, - "display_name": "Jamendo", - "source_url": "https://www.jamendo.com" - } - ] -} diff --git a/openverse-api/catalog/api/examples/image_requests.py b/openverse-api/catalog/api/examples/image_requests.py index 906a82475..e0535b886 100644 --- a/openverse-api/catalog/api/examples/image_requests.py +++ b/openverse-api/catalog/api/examples/image_requests.py @@ -1,3 +1,11 @@ +import os + +token = os.getenv('AUDIO_REQ_TOKEN', 'DLBYIcfnKfolaXKcmMC8RIDCavc2hW') +origin = os.getenv('AUDIO_REQ_ORIGIN', 'https://api.openverse.engineering') + +auth = f'-H "Authorization: Bearer {token}"' if token else '' +identifier = '29cb352c-60c1-41d8-bfa1-7d6f7d955f63' + syntax_examples = { "using single query parameter": 'test', @@ -20,34 +28,42 @@ 'theatre~1', } -image_search_curl = '\n\n'.join([ - (f'# Example {index}: Search for images {purpose}\n' - 'curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" ' - f'https://api.openverse.engineering/v1/images?q={syntax}') - for (index, (purpose, syntax)) in enumerate(syntax_examples.items()) -]) +image_search_list_curl = '\n'.join(f""" +# Example {index}: Search for images {purpose} +curl {auth} "{origin}/v1/images?q={syntax}" +""" for (index, (purpose, syntax)) in enumerate(syntax_examples.items())) -recommendations_images_read_curl = """ -# Get related images for image ID 7c829a03-fb24-4b57-9b03-65f43ed19395 -curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" http://api.openverse.engineering/v1/recommendations/images/7c829a03-fb24-4b57-9b03-65f43ed19395 -""" # noqa +image_search_curl = f""" +# Search for images titled "Bust" by Talbot +curl {auth} "{origin}/v1/images/?title=Bust&creator=Talbot" +""" -image_detail_curl = """ -# Get the details of image ID 7c829a03-fb24-4b57-9b03-65f43ed19395 -curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" http://api.openverse.engineering/v1/images/7c829a03-fb24-4b57-9b03-65f43ed19395 -""" # noqa - -image_stats_curl = """ +image_stats_curl = f""" # Get the statistics for image sources -curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" http://api.openverse.engineering/v1/images/stats -""" # noqa +curl {auth} "{origin}/v1/images/stats/" +""" + +image_detail_curl = f""" +# Get the details of image ID {identifier} +curl {auth} "{origin}/v1/images/{identifier}/" +""" + +image_related_curl = f""" +# Get related images for image ID {identifier} +curl {auth} "{origin}/v1/images/{identifier}/related/" +""" -report_image_curl = """ -# Report an issue about image ID 7c829a03-fb24-4b57-9b03-65f43ed19395 -curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" -d '{"reason": "mature", "description": "This image contains sensitive content"}' https://api.openverse.engineering/v1/images/7c829a03-fb24-4b57-9b03-65f43ed19395/report +image_complain_curl = f""" +# Report an issue about image ID {identifier} +curl \\ + -X POST \\ + -H "Content-Type: application/json" \\ + {auth} \\ + -d '{{"reason": "mature", "description": "This image contains sensitive content"}}' \\ + "{origin}/v1/images/{identifier}/report/" """ # noqa -oembed_list_curl = """ -# Retrieve embedded content from image URL (https://wordpress.org/openverse/photos/7c829a03-fb24-4b57-9b03-65f43ed19395) -curl -H "Authorization: Bearer DLBYIcfnKfolaXKcmMC8RIDCavc2hW" https://api.openverse.engineering/v1/oembed/?url=https://wordpress.org/openverse/photos/7c829a03-fb24-4b57-9b03-65f43ed19395 +image_oembed_curl = f""" +# Retrieve embedded content from image URL (https://wordpress.org/openverse/photos/{identifier}) +curl {auth} "{origin}/v1/images/oembed/?url=https://wordpress.org/openverse/photos/{identifier}" """ # noqa diff --git a/openverse-api/catalog/api/examples/image_responses.py b/openverse-api/catalog/api/examples/image_responses.py index ce4edcc19..1f3040aa6 100644 --- a/openverse-api/catalog/api/examples/image_responses.py +++ b/openverse-api/catalog/api/examples/image_responses.py @@ -1,28 +1,36 @@ +import os + +origin = os.getenv('AUDIO_REQ_ORIGIN', 'https://api.openverse.engineering') + +identifier = '29cb352c-60c1-41d8-bfa1-7d6f7d955f63' + +base_image = { + "id": identifier, + "title": "Bust of Patroclus (photograph; calotype; salt print)", + "foreign_landing_url": "https://collection.sciencemuseumgroup.org.uk/objects/co8554747/bust-of-patroclus-photograph-calotype-salt-print", # noqa + "creator": "William Henry Fox Talbot", + "url": "https://coimages.sciencemuseumgroup.org.uk/images/439/67/large_1937_1281_0001__0001_.jpg", # noqa + "license": "by-nc-nd", + "license_version": "4.0", + "license_url": "https://creativecommons.org/licenses/by-nc-nd/4.0/", + "provider": "sciencemuseum", + "source": "sciencemuseum", + "thumbnail": f"{origin}/v1/images/{identifier}/thumb/", + "detail_url": f"{origin}/v1/images/{identifier}/", + "related_url": f"{origin}/v1/images/{identifier}/related/" +} + image_search_200_example = { "application/json": { - "result_count": 77, - "page_count": 77, - "page_size": 1, + "result_count": 1, + "page_count": 0, + "page_size": 20, + "page": 1, "results": [ - { - "title": "File:Well test separator.svg", - "id": "36537842-b067-4ca0-ad67-e00ff2e06b2d", - "creator": "en:User:Oil&GasIndustry", - "creator_url": "https://en.wikipedia.org/wiki/User:Oil%26GasIndustry", # noqa - "url": "https://upload.wikimedia.org/wikipedia/commons/3/3a/Well_test_separator.svg", # noqa - "thumbnail": "https://api.openverse.engineering/v1/thumbs/36537842-b067-4ca0-ad67-e00ff2e06b2d", # noqa - "provider": "wikimedia", - "source": "wikimedia", - "license": "by", - "license_version": "3.0", - "license_url": "https://creativecommons.org/licenses/by/3.0", - "foreign_landing_url": "https://commons.wikimedia.org/w/index.php?curid=26229990", # noqa - "detail_url": "http://api.openverse.engineering/v1/images/36537842-b067-4ca0-ad67-e00ff2e06b2d", # noqa - "related_url": "http://api.openverse.engineering/v1/recommendations/images/36537842-b067-4ca0-ad67-e00ff2e06b2d", # noqa + base_image | { "fields_matched": [ - "description", "title" - ] + ], } ] }, @@ -38,7 +46,63 @@ } } -recommendations_images_read_200_example = { +image_stats_200_example = { + "application/json": [ + { + "source_name": "flickr", + "display_name": "Flickr", + "source_url": "https://www.flickr.com", + "logo_url": None, + "media_count": 1000 + }, + { + "source_name": "rawpixel", + "display_name": "rawpixel", + "source_url": "https://www.rawpixel.com", + "logo_url": None, + "media_count": 1000 + }, + { + "source_name": "sciencemuseum", + "display_name": "Science Museum", + "source_url": "https://www.sciencemuseum.org.uk", + "logo_url": None, + "media_count": 1000 + }, + { + "source_name": "stocksnap", + "display_name": "StockSnap", + "source_url": "https://stocksnap.io", + "logo_url": None, + "media_count": 1000 + }, + { + "source_name": "wikimedia", + "display_name": "Wikimedia", + "source_url": "https://commons.wikimedia.org", + "logo_url": None, + "media_count": 1000 + } + ] +} + +image_detail_200_example = { + "application/json": base_image | { + "attribution": "\"Bust of Patroclus (photograph; calotype; salt print)\" by William Henry Fox Talbot is licensed under CC-BY-NC-ND 4.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-nd/4.0/.", # noqa + "height": 1536, + "width": 1276, + "tags": None, + "creator_url": None, + } +} + +image_detail_404_example = { + "application/json": { + "detail": "Not found." + } +} + +image_related_200_example = { "application/json": { "result_count": 10000, "page_count": 0, @@ -71,83 +135,35 @@ } } -recommendations_images_read_404_example = { +image_related_404_example = { "application/json": { "detail": "An internal server error occurred." } } -image_detail_200_example = { - "application/json": { - "title": "exam test", - "id": "7c829a03-fb24-4b57-9b03-65f43ed19395", - "creator": "Sean MacEntee", - "creator_url": "https://www.flickr.com/photos/18090920@N07", - "tags": [ - { - "name": "exam" - }, - { - "name": "test" - } - ], - "url": "https://live.staticflickr.com/5122/5264886972_3234d62748.jpg", - "thumbnail": "https://api.openverse.engineering/v1/thumbs/7c829a03-fb24-4b57-9b03-65f43ed19395", # noqa - "provider": "flickr", - "source": "flickr", - "license": "by", - "license_version": "2.0", - "license_url": "https://creativecommons.org/licenses/by/2.0/", - "foreign_landing_url": "https://www.flickr.com/photos/18090920@N07/5264886972", # noqa - "detail_url": "http://api.openverse.engineering/v1/images/7c829a03-fb24-4b57-9b03-65f43ed19395", # noqa - "related_url": "http://api.openverse.engineering/v1/recommendations/images/7c829a03-fb24-4b57-9b03-65f43ed19395", # noqa - "height": 167, - "width": 500, - "attribution": "\"exam test\" by Sean MacEntee is licensed under CC-BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/" # noqa - } -} - -image_detail_404_example = { - "application/json": { - "detail": "Not found." - } -} - -oembed_list_200_example = { +image_oembed_200_example = { "application/json": { - "version": 1, + "version": '1.0', "type": "photo", - "width": 500, - "height": 167, - "title": "exam test", - "author_name": "Sean MacEntee", - "author_url": "https://www.flickr.com/photos/18090920@N07", - "license_url": "https://creativecommons.org/licenses/by/2.0/" + "width": 1276, + "height": 1536, + "title": "Bust of Patroclus (photograph; calotype; salt print)", + "author_name": "William Henry Fox Talbot", + "author_url": None, + "license_url": "https://creativecommons.org/licenses/by-nc-nd/4.0/", } } -oembed_list_404_example = { +image_oembed_404_example = { "application/json": { "detail": "An internal server error occurred." } } -images_report_create_201_example = { +image_complain_201_example = { "application/json": { - "id": 10, - "identifier": "7c829a03-fb24-4b57-9b03-65f43ed19395", + "identifier": identifier, "reason": "mature", "description": "This image contains sensitive content" } } - -image_stats_200_example = { - "application/json": [ - { - "source_name": "flickr", - "image_count": 465809213, - "display_name": "Flickr", - "source_url": "https://www.flickr.com", - } - ] -} From a0012435bd6b04b31426246b2fb277646b226fa3 Mon Sep 17 00:00:00 2001 From: Dhruv Bhanushali Date: Wed, 1 Sep 2021 16:34:27 +0530 Subject: [PATCH 3/3] Define request response mappings and use them to run tests on the endpoints --- .../catalog/api/examples/__init__.py | 14 +++++++ openverse-api/test/examples_test.py | 39 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 openverse-api/test/examples_test.py diff --git a/openverse-api/catalog/api/examples/__init__.py b/openverse-api/catalog/api/examples/__init__.py index 550027607..9d6f55bf5 100644 --- a/openverse-api/catalog/api/examples/__init__.py +++ b/openverse-api/catalog/api/examples/__init__.py @@ -37,3 +37,17 @@ image_oembed_200_example, image_oembed_404_example, ) + +audio_mappings = { + audio_search_curl: audio_search_200_example, + audio_stats_curl: audio_stats_200_example, + audio_detail_curl: audio_detail_200_example, + audio_complain_curl: audio_complain_201_example, +} +image_mappings = { + image_search_curl: image_search_200_example, + image_stats_curl: image_stats_200_example, + image_detail_curl: image_detail_200_example, + image_complain_curl: image_complain_201_example, + image_oembed_curl: image_oembed_200_example, +} diff --git a/openverse-api/test/examples_test.py b/openverse-api/test/examples_test.py new file mode 100644 index 000000000..2c64937f5 --- /dev/null +++ b/openverse-api/test/examples_test.py @@ -0,0 +1,39 @@ +import json +import os +import subprocess + +import pytest + +from test.constants import API_URL + +os.environ['AUDIO_REQ_TOKEN'] = '' +os.environ['AUDIO_REQ_ORIGIN'] = API_URL +os.environ['AUDIO_REQ_IDX'] = '440a0240-8b20-49e2-a4e6-6fee550fcc41' + +from catalog.api.examples import ( # noqa | Set env vars before import + audio_mappings, + image_mappings, +) + + +def execute_request(request): + proc = subprocess.run(request, check=True, capture_output=True, shell=True) + return json.loads(proc.stdout) + + +@pytest.mark.parametrize( + 'in_val, out_val', + list(audio_mappings.items()) +) +def test_audio_success_examples(in_val, out_val): + res = execute_request(in_val) + assert res == out_val['application/json'] + + +@pytest.mark.parametrize( + 'in_val, out_val', + list(image_mappings.items()) +) +def test_image_success_examples(in_val, out_val): + res = execute_request(in_val) + assert res == out_val['application/json']