# Zulip's OpenAPI-based API documentation system is documented at # https://zulip.readthedocs.io/en/latest/documentation/api.html # # This file contains the top-level logic for testing the cURL examples # in Zulip's API documentation; the details are in # zerver.openapi.curl_param_value_generators. import html import json import os import re import shlex import subprocess import markdown from django.conf import settings from zulip import Client from zerver.models import get_realm from zerver.openapi import markdown_extension from zerver.openapi.curl_param_value_generators import ( AUTHENTICATION_LINE, assert_all_helper_functions_called, ) def test_generated_curl_examples_for_success(client: Client) -> None: default_authentication_line = f"{client.email}:{client.api_key}" # A limited Markdown engine that just processes the code example syntax. realm = get_realm("zulip") md_engine = markdown.Markdown( extensions=[markdown_extension.makeExtension(api_url=realm.uri + "/api")] ) # We run our curl tests in alphabetical order (except that we # delay the deactivate-user test to the very end), since we depend # on "add" tests coming before "remove" tests in some cases. We # should try to either avoid ordering dependencies or make them # very explicit. rest_endpoints_path = os.path.join( settings.DEPLOY_ROOT, "templates/zerver/help/include/rest-endpoints.md" ) rest_endpoints_raw = open(rest_endpoints_path, "r").read() ENDPOINT_REGEXP = re.compile(r"/api/\s*(.*?)\)") endpoint_list = sorted(set(re.findall(ENDPOINT_REGEXP, rest_endpoints_raw))) for endpoint in endpoint_list: article_name = endpoint + ".md" file_name = os.path.join(settings.DEPLOY_ROOT, "templates/zerver/api/", article_name) with open(file_name) as f: for line in f: # Set AUTHENTICATION_LINE to default_authentication_line. # Set this every iteration, because deactivate_own_user # will override this for its test. AUTHENTICATION_LINE[0] = default_authentication_line # A typical example from the Markdown source looks like this: # {generate_code_example(curl, ...} if not line.startswith("{generate_code_example(curl"): continue # To do an end-to-end test on the documentation examples # that will be actually shown to users, we use the # Markdown rendering pipeline to compute the user-facing # example, and then run that to test it. curl_command_html = md_engine.convert(line.strip()) unescaped_html = html.unescape(curl_command_html) curl_command_text = unescaped_html[len("
curl\n") : -len("