|
| 1 | +# This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | +# License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 | +# file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 4 | +""" |
| 5 | +Data factories for writing integration tests. |
| 6 | +""" |
| 7 | +from copy import deepcopy |
| 8 | + |
| 9 | +from landoapi.utils import extract_rawdiff_id_from_uri |
| 10 | +from tests.canned_responses.phabricator.repos import CANNED_REPO_MOZCENTRAL |
| 11 | +from tests.canned_responses.phabricator.revisions import CANNED_EMPTY_RESULT, \ |
| 12 | + CANNED_REVISION_1, CANNED_REVISION_1_DIFF, CANNED_REVISION_1_RAW_DIFF |
| 13 | +from tests.canned_responses.phabricator.users import CANNED_USER_1 |
| 14 | +from tests.utils import phab_url, first_result_in_response, phid_for_response, \ |
| 15 | + form_matcher |
| 16 | + |
| 17 | + |
| 18 | +class PhabResponseFactory: |
| 19 | + """Mock Phabricator service responses with generated data.""" |
| 20 | + |
| 21 | + def __init__(self, requestmocker): |
| 22 | + """ |
| 23 | + Args: |
| 24 | + requestmocker: A requests_mock.mock() object. |
| 25 | + """ |
| 26 | + self.mock = requestmocker |
| 27 | + self.mock_responses = {} |
| 28 | + self.install_404_responses() |
| 29 | + |
| 30 | + def install_404_responses(self): |
| 31 | + """Install catch-all 404 response handlers for API queries.""" |
| 32 | + query_urls = ['differential.query', 'phid.query', 'user.query'] |
| 33 | + for query_url in query_urls: |
| 34 | + self.mock.get( |
| 35 | + phab_url(query_url), status_code=404, json=CANNED_EMPTY_RESULT |
| 36 | + ) |
| 37 | + |
| 38 | + def user(self): |
| 39 | + """Return a Phabricator User.""" |
| 40 | + user = deepcopy(CANNED_USER_1) |
| 41 | + self.mock.get(phab_url('user.query'), status_code=200, json=user) |
| 42 | + return user |
| 43 | + |
| 44 | + def revision(self, **kwargs): |
| 45 | + """Return a Phabricator Revision.""" |
| 46 | + result_json = deepcopy(CANNED_REVISION_1) |
| 47 | + revision = first_result_in_response(result_json) |
| 48 | + |
| 49 | + if 'id' in kwargs: |
| 50 | + # Convert 'D000' form to just '000'. |
| 51 | + str_id = kwargs['id'] |
| 52 | + num_id = str_id[1:] |
| 53 | + revision['id'] = num_id |
| 54 | + revision['phid'] = "PHID-DREV-%s" % num_id |
| 55 | + |
| 56 | + if 'depends_on' in kwargs: |
| 57 | + parent_revision_response_data = kwargs['depends_on'] |
| 58 | + if parent_revision_response_data: |
| 59 | + # This Revisions depends on another Revision. |
| 60 | + new_value = [phid_for_response(parent_revision_response_data)] |
| 61 | + else: |
| 62 | + # The user passed in None or an empty list, saying "this |
| 63 | + # revision has no parent revisions." |
| 64 | + new_value = [] |
| 65 | + revision['auxiliary']['phabricator:depends-on'] = new_value |
| 66 | + |
| 67 | + # Revisions have at least one Diff. |
| 68 | + diff = self.diff() |
| 69 | + diffID = extract_rawdiff_id_from_uri( |
| 70 | + first_result_in_response(diff)['uri'] |
| 71 | + ) |
| 72 | + rawdiff = self.rawdiff(diffID=str(diffID)) |
| 73 | + revision['activeDiffPHID'] = phid_for_response(diff) |
| 74 | + |
| 75 | + # Revisions may have a Repo. |
| 76 | + repo = self.repo() |
| 77 | + revision['repositoryPHID'] = phid_for_response(repo) |
| 78 | + |
| 79 | + def match_revision(request): |
| 80 | + # Revisions can be looked up by PHID or ID. |
| 81 | + found_phid = form_matcher('phids[]', revision['phid'])(request) |
| 82 | + found_id = form_matcher('ids[]', revision['id'])(request) |
| 83 | + return found_phid or found_id |
| 84 | + |
| 85 | + self.mock.get( |
| 86 | + phab_url('differential.query'), |
| 87 | + status_code=200, |
| 88 | + json=result_json, |
| 89 | + additional_matcher=match_revision |
| 90 | + ) |
| 91 | + |
| 92 | + # Revisions can also be looked up by phid.query. |
| 93 | + self.phid(result_json) |
| 94 | + |
| 95 | + return result_json |
| 96 | + |
| 97 | + def diff(self): |
| 98 | + """Return a Revision Diff.""" |
| 99 | + diff = deepcopy(CANNED_REVISION_1_DIFF) |
| 100 | + self.phid(diff) |
| 101 | + return diff |
| 102 | + |
| 103 | + def rawdiff(self, diffID='12345'): |
| 104 | + """Return raw diff text for a Revision Diff.""" |
| 105 | + rawdiff = deepcopy(CANNED_REVISION_1_RAW_DIFF) |
| 106 | + self.mock.get( |
| 107 | + phab_url('differential.getrawdiff'), |
| 108 | + status_code=200, |
| 109 | + json=rawdiff, |
| 110 | + additional_matcher=form_matcher('diffID', diffID) |
| 111 | + ) |
| 112 | + return rawdiff |
| 113 | + |
| 114 | + def repo(self): |
| 115 | + """Return a Phabricator Repo.""" |
| 116 | + repo = deepcopy(CANNED_REPO_MOZCENTRAL) |
| 117 | + self.phid(repo) |
| 118 | + return repo |
| 119 | + |
| 120 | + def phid(self, response_data): |
| 121 | + """Add a phid.query matcher for the given Phabricator response object. |
| 122 | + """ |
| 123 | + phid = phid_for_response(response_data) |
| 124 | + self.mock.get( |
| 125 | + phab_url('phid.query'), |
| 126 | + status_code=200, |
| 127 | + additional_matcher=form_matcher('phids[]', phid), |
| 128 | + json=response_data |
| 129 | + ) |
0 commit comments