api/api_helpers.py (66 lines of code) (raw):
"""File holding some reusable methods used in the API addon submission tests"""
import hashlib
import json
import zipfile
import requests
def make_addon(manifest_data):
"""Dynamically create a simple extension with minimal manifest properties"""
with open('sample-addons/manifest.json', 'w') as f:
# the contents of the manifest will be defined in tests based on the scenario we want to verify
json.dump(manifest_data, f)
print(f'Manifest content: {manifest_data}')
# add the manifest to the addon zip we want to upload - this will always be the 'make-addon.zip' file
# if the zip files contains a manifest already, it will be overwritten by the new manifest
with zipfile.ZipFile('sample-addons/make-addon.zip', 'w') as zipf:
manifest = 'sample-addons/manifest.json'
destination = 'manifest.json'
zipf.write(manifest, destination)
def verify_addon_response_details(payload, response, request):
"""Method checking that the values set in the request payload are found
in the response returned by the API. It can be used both for verifying
new uploads and addon edits, based on the <request> argument."""
# save the request values (stored in a dictionary) in a list
addon_details = [value for value in payload.values()]
# capture the necessary response values from the JSON response and add them to a list
response_values = [
response['categories'],
response['slug'],
response['name'],
response['summary'],
response['description'],
response['developer_comments'],
response['homepage']['url'],
response['support_email'],
response['is_experimental'],
response['requires_payment'],
response['contributions_url']['url'].split('?')[0],
response['tags'],
]
# for new uploads, we need to check the version values as well
if request == 'create':
# remove the 'upload' value from the request details because it is not present in the JSON response
addon_details[-1].pop('upload')
# store the version request details, which are stored in a nested dict inside
# the 'addon details' dict, in a separate list
version_details = addon_details[-1].values()
# remove the dictionary from the 'addon details' initial list
# and replace it with the individual values stored in the 'version_details' list
addon_details.pop()
addon_details.extend([detail for detail in version_details])
# extend the response values to include the 'current_version' details
response_values.extend(
[
response['current_version']['license']['slug'],
response['current_version']['release_notes'],
response['current_version']['compatibility'],
]
)
print(f'List of request values: {addon_details}')
print(f'List of response values: {response_values}')
# compare the request details list with the response details list
return addon_details == response_values
def compare_source_files(file_a, file_b, request):
"""Method to compare the hashes of the uploaded and downloaded
addon source files to make sure they are matching; the comparison differs
between POST and PATCH requests, so the method is split in two checks"""
# this is the source file downloaded from AMO used in both request types
source_from_api = hashlib.sha256(file_b.content).digest()
if request == 'POST':
# in POST request we compare the local source uploaded with the source from the API
local_file = hashlib.sha256(open(file_a, 'rb').read()).digest()
assert (
local_file == source_from_api
), f'File contents did not match: local_file_hash = {local_file}, source_from_api_hash = {source_from_api}'
if request == 'PATCH':
# in PATCH requests, we are fetching the previous source file attached to the version
# and compare it to the new attached files to make sure they are different
previous_source_from_api = hashlib.sha256(file_a.content).digest()
assert previous_source_from_api != source_from_api, (
f'Source files were not updated successfully: previous_source_from_api_hash = {previous_source_from_api}, '
f'source_from_api_hash = {source_from_api}'
)
def get_addon_version_string(base_url, addon, auth):
"""Get the version string of an addon's latest version by using
the /addons/versions/ API endpoint"""
request = requests.get(
url=f'{base_url}/api/v5/addons/addon/{addon}/versions/?filter=all_with_unlisted',
headers={'Authorization': f'Session {auth}'},
)
assert (
request.status_code == 200
), f'Actual response was: status code: {request.status_code}, {request.text}'
version_string = request.json()['results'][0]['version']
return version_string