def mock_graphql_request(mocker, payload=None, error=None, body_match=None,
                         status_code=None, attempts=None):
    """Mock a sequence of graphql requests (retries) and their eventual response.

    Arguments:
        mocker: request_mocker fixture
        payload (nested dict/list): Response body to eventually return.
        error (nested dict/list): Error payload to return rather than `payload`.
        body_match (str = 'query'): A string to match in the request body that
            causes this mock to be used. This is important any time you're using
            more than one request mock at once. Otherwise, the last mock defined
            will determine what gets returned.
        status_code (int = 200): HTTP response status code to return on request
            attempts before the final one. The final attempt will always return
            200.
        attempts (int): Number of attempts to wait for before allowing the
            request to succeed or fail.
    """
    if error:
        body={'errors': error}
    else:
        body={'data': payload}
    if body_match is None:
        body_match='query'
    if status_code is None:
        status_code=200
    if attempts is None:
        attempts=1

    def match_body(request):
        return body_match in (request.text or '')

    res=[{'json': body, 'status_code': status_code}]
    if attempts > 1:
        for i in range(attempts - 1):
            if i == attempts - 2:
                status_code=200
            res.append({'json': body, 'status_code': status_code})
    return mocker.register_uri('POST', 'https://api.wandb.ai/graphql',
                               res, additional_matcher=match_body)