"Fossies" - the Fresh Open Source Software Archive

Member "buildbot-2.5.1/buildbot/test/unit/test_www_hooks_bitbucketserver.py" (24 Nov 2019, 28755 Bytes) of package /linux/misc/buildbot-2.5.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "test_www_hooks_bitbucketserver.py": 2.3.1_vs_2.4.0.

    1 # This file is part of Buildbot.  Buildbot is free software: you can
    2 # redistribute it and/or modify it under the terms of the GNU General Public
    3 # License as published by the Free Software Foundation, version 2.
    4 #
    5 # This program is distributed in the hope that it will be useful, but WITHOUT
    6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    7 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    8 # details.
    9 #
   10 # You should have received a copy of the GNU General Public License along with
   11 # this program; if not, write to the Free Software Foundation, Inc., 51
   12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   13 #
   14 # Copyright Buildbot Team Members
   15 # Copyright Mamba Team
   16 
   17 from io import BytesIO
   18 
   19 from twisted.internet import defer
   20 from twisted.trial import unittest
   21 
   22 from buildbot.test.fake.web import FakeRequest
   23 from buildbot.test.fake.web import fakeMasterForHooks
   24 from buildbot.test.util.misc import TestReactorMixin
   25 from buildbot.util import unicode2bytes
   26 from buildbot.www import change_hook
   27 from buildbot.www.hooks.bitbucketserver import _HEADER_EVENT
   28 
   29 _CT_JSON = b'application/json'
   30 
   31 pushJsonPayload = """
   32 {
   33     "actor": {
   34         "username": "John",
   35         "displayName": "John Smith"
   36     },
   37     "repository": {
   38         "scmId": "git",
   39         "project": {
   40             "key": "CI",
   41             "name": "Continuous Integration"
   42         },
   43         "slug": "py-repo",
   44         "links": {
   45             "self": [
   46                 {
   47                     "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
   48                 }
   49             ]
   50         },
   51         "public": false,
   52         "ownerName": "CI",
   53         "owner": {
   54             "username": "CI",
   55             "displayName": "CI"
   56         },
   57         "fullName": "CI/py-repo"
   58     },
   59     "push": {
   60         "changes": [
   61             {
   62                 "created": false,
   63                 "closed": false,
   64                 "new": {
   65                     "type": "branch",
   66                     "name": "branch_1496411680",
   67                     "target": {
   68                         "type": "commit",
   69                         "hash": "793d4754230023d85532f9a38dba3290f959beb4"
   70                     }
   71                 },
   72                 "old": {
   73                     "type": "branch",
   74                     "name": "branch_1496411680",
   75                     "target": {
   76                         "type": "commit",
   77                         "hash": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba"
   78                     }
   79                 }
   80             }
   81         ]
   82     }
   83 }
   84 """
   85 
   86 pullRequestCreatedJsonPayload = """
   87 {
   88     "actor": {
   89         "username": "John",
   90         "displayName": "John Smith"
   91     },
   92     "pullrequest": {
   93         "id": "21",
   94         "title": "dot 1496311906",
   95         "link": "http://localhost:7990/projects/CI/repos/py-repo/pull-requests/21",
   96         "authorLogin": "John Smith",
   97         "fromRef": {
   98             "repository": {
   99                 "scmId": "git",
  100                 "project": {
  101                     "key": "CI",
  102                     "name": "Continuous Integration"
  103                 },
  104                 "slug": "py-repo",
  105                 "links": {
  106                     "self": [
  107                         {
  108                             "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  109                         }
  110                     ]
  111                 },
  112                 "public": false,
  113                 "ownerName": "CI",
  114                 "owner": {
  115                     "username": "CI",
  116                     "displayName": "CI"
  117                 },
  118                 "fullName": "CI/py-repo"
  119             },
  120             "commit": {
  121                 "message": null,
  122                 "date": null,
  123                 "hash": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba",
  124                 "authorTimestamp": 0
  125             },
  126             "branch": {
  127                 "rawNode": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba",
  128                 "name": "branch_1496411680"
  129             }
  130         },
  131         "toRef": {
  132             "repository": {
  133                 "scmId": "git",
  134                 "project": {
  135                     "key": "CI",
  136                     "name": "Continuous Integration"
  137                 },
  138                 "slug": "py-repo",
  139                 "links": {
  140                     "self": [
  141                         {
  142                             "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  143                         }
  144                     ]
  145                 },
  146                 "public": false,
  147                 "ownerName": "CI",
  148                 "owner": {
  149                     "username": "CI",
  150                     "displayName": "CI"
  151                 },
  152                 "fullName": "CI/py-repo"
  153             },
  154             "commit": {
  155                 "message": null,
  156                 "date": null,
  157                 "hash": "7aebbb0089c40fce138a6d0b36d2281ea34f37f5",
  158                 "authorTimestamp": 0
  159             },
  160             "branch": {
  161                 "rawNode": "7aebbb0089c40fce138a6d0b36d2281ea34f37f5",
  162                 "name": "master"
  163             }
  164         }
  165     },
  166     "repository": {
  167         "scmId": "git",
  168         "project": {
  169             "key": "CI",
  170             "name": "Continuous Integration"
  171         },
  172         "slug": "py-repo",
  173         "links": {
  174             "self": [
  175                 {
  176                     "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  177                 }
  178             ]
  179         },
  180         "public": false,
  181         "ownerName": "CI",
  182         "owner": {
  183             "username": "CI",
  184             "displayName": "CI"
  185         },
  186         "fullName": "CI/py-repo"
  187     }
  188 }
  189 """
  190 
  191 pullRequestUpdatedJsonPayload = """
  192 {
  193     "actor": {
  194         "username": "John",
  195         "displayName": "John Smith"
  196     },
  197     "pullrequest": {
  198         "id": "21",
  199         "title": "dot 1496311906",
  200         "link": "http://localhost:7990/projects/CI/repos/py-repo/pull-requests/21",
  201         "authorLogin": "Buildbot",
  202         "fromRef": {
  203             "repository": {
  204                 "scmId": "git",
  205                 "project": {
  206                     "key": "CI",
  207                     "name": "Continuous Integration"
  208                 },
  209                 "slug": "py-repo",
  210                 "links": {
  211                     "self": [
  212                         {
  213                             "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  214                         }
  215                     ]
  216                 },
  217                 "public": false,
  218                 "ownerName": "CI",
  219                 "owner": {
  220                     "username": "CI",
  221                     "displayName": "CI"
  222                 },
  223                 "fullName": "CI/py-repo"
  224             },
  225             "commit": {
  226                 "message": null,
  227                 "date": null,
  228                 "hash": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba",
  229                 "authorTimestamp": 0
  230             },
  231             "branch": {
  232                 "rawNode": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba",
  233                 "name": "branch_1496411680"
  234             }
  235         },
  236         "toRef": {
  237             "repository": {
  238                 "scmId": "git",
  239                 "project": {
  240                     "key": "CI",
  241                     "name": "Continuous Integration"
  242                 },
  243                 "slug": "py-repo",
  244                 "links": {
  245                     "self": [
  246                         {
  247                             "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  248                         }
  249                     ]
  250                 },
  251                 "public": false,
  252                 "ownerName": "CI",
  253                 "owner": {
  254                     "username": "CI",
  255                     "displayName": "CI"
  256                 },
  257                 "fullName": "CI/py-repo"
  258             },
  259             "commit": {
  260                 "message": null,
  261                 "date": null,
  262                 "hash": "7aebbb0089c40fce138a6d0b36d2281ea34f37f5",
  263                 "authorTimestamp": 0
  264             },
  265             "branch": {
  266                 "rawNode": "7aebbb0089c40fce138a6d0b36d2281ea34f37f5",
  267                 "name": "master"
  268             }
  269         }
  270     },
  271     "repository": {
  272         "scmId": "git",
  273         "project": {
  274             "key": "CI",
  275             "name": "Continuous Integration"
  276         },
  277         "slug": "py-repo",
  278         "links": {
  279             "self": [
  280                 {
  281                     "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  282                 }
  283             ]
  284         },
  285         "public": false,
  286         "ownerName": "CI",
  287         "owner": {
  288             "username": "CI",
  289             "displayName": "CI"
  290         },
  291         "fullName": "CI/py-repo"
  292     }
  293 }
  294 """
  295 
  296 pullRequestRejectedJsonPayload = """
  297 {
  298     "actor": {
  299         "username": "John",
  300         "displayName": "John Smith"
  301     },
  302     "pullrequest": {
  303         "id": "21",
  304         "title": "dot 1496311906",
  305         "link": "http://localhost:7990/projects/CI/repos/py-repo/pull-requests/21",
  306         "authorLogin": "Buildbot",
  307         "fromRef": {
  308             "repository": {
  309                 "scmId": "git",
  310                 "project": {
  311                     "key": "CI",
  312                     "name": "Continuous Integration"
  313                 },
  314                 "slug": "py-repo",
  315                 "links": {
  316                     "self": [
  317                         {
  318                             "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  319                         }
  320                     ]
  321                 },
  322                 "public": false,
  323                 "ownerName": "CI",
  324                 "owner": {
  325                     "username": "CI",
  326                     "displayName": "CI"
  327                 },
  328                 "fullName": "CI/py-repo"
  329             },
  330             "commit": {
  331                 "message": null,
  332                 "date": null,
  333                 "hash": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba",
  334                 "authorTimestamp": 0
  335             },
  336             "branch": {
  337                 "rawNode": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba",
  338                 "name": "branch_1496411680"
  339             }
  340         },
  341         "toRef": {
  342             "repository": {
  343                 "scmId": "git",
  344                 "project": {
  345                     "key": "CI",
  346                     "name": "Continuous Integration"
  347                 },
  348                 "slug": "py-repo",
  349                 "links": {
  350                     "self": [
  351                         {
  352                             "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  353                         }
  354                     ]
  355                 },
  356                 "public": false,
  357                 "ownerName": "CI",
  358                 "owner": {
  359                     "username": "CI",
  360                     "displayName": "CI"
  361                 },
  362                 "fullName": "CI/py-repo"
  363             },
  364             "commit": {
  365                 "message": null,
  366                 "date": null,
  367                 "hash": "7aebbb0089c40fce138a6d0b36d2281ea34f37f5",
  368                 "authorTimestamp": 0
  369             },
  370             "branch": {
  371                 "rawNode": "7aebbb0089c40fce138a6d0b36d2281ea34f37f5",
  372                 "name": "master"
  373             }
  374         }
  375     },
  376     "repository": {
  377         "scmId": "git",
  378         "project": {
  379             "key": "CI",
  380             "name": "Continuous Integration"
  381         },
  382         "slug": "py-repo",
  383         "links": {
  384             "self": [
  385                 {
  386                     "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  387                 }
  388             ]
  389         },
  390         "public": false,
  391         "ownerName": "CI",
  392         "owner": {
  393             "username": "CI",
  394             "displayName": "CI"
  395         },
  396         "fullName": "CI/py-repo"
  397     }
  398 }
  399 """
  400 
  401 pullRequestFulfilledJsonPayload = """
  402 {
  403     "actor": {
  404         "username": "John",
  405         "displayName": "John Smith"
  406     },
  407     "pullrequest": {
  408         "id": "21",
  409         "title": "Branch 1496411680",
  410         "link": "http://localhost:7990/projects/CI/repos/py-repo/pull-requests/21",
  411         "authorLogin": "Buildbot",
  412         "fromRef": {
  413             "repository": {
  414                 "scmId": "git",
  415                 "project": {
  416                     "key": "CI",
  417                     "name": "Continuous Integration"
  418                 },
  419                 "slug": "py-repo",
  420                 "links": {
  421                     "self": [
  422                         {
  423                             "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  424                         }
  425                     ]
  426                 },
  427                 "public": false,
  428                 "ownerName": "CI",
  429                 "owner": {
  430                     "username": "CI",
  431                     "displayName": "CI"
  432                 },
  433                 "fullName": "CI/py-repo"
  434             },
  435             "commit": {
  436                 "message": null,
  437                 "date": null,
  438                 "hash": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba",
  439                 "authorTimestamp": 0
  440             },
  441             "branch": {
  442                 "rawNode": "a87e21f7433d8c16ac7be7413483fbb76c72a8ba",
  443                 "name": "branch_1496411680"
  444             }
  445         },
  446         "toRef": {
  447             "repository": {
  448                 "scmId": "git",
  449                 "project": {
  450                     "key": "CI",
  451                     "name": "Continuous Integration"
  452                 },
  453                 "slug": "py-repo",
  454                 "links": {
  455                     "self": [
  456                         {
  457                             "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  458                         }
  459                     ]
  460                 },
  461                 "public": false,
  462                 "ownerName": "CI",
  463                 "owner": {
  464                     "username": "CI",
  465                     "displayName": "CI"
  466                 },
  467                 "fullName": "CI/py-repo"
  468             },
  469             "commit": {
  470                 "message": null,
  471                 "date": null,
  472                 "hash": "7aebbb0089c40fce138a6d0b36d2281ea34f37f5",
  473                 "authorTimestamp": 0
  474             },
  475             "branch": {
  476                 "rawNode": "7aebbb0089c40fce138a6d0b36d2281ea34f37f5",
  477                 "name": "master"
  478             }
  479         }
  480     },
  481     "repository": {
  482         "scmId": "git",
  483         "project": {
  484             "key": "CI",
  485             "name": "Continuous Integration"
  486         },
  487         "slug": "py-repo",
  488         "links": {
  489             "self": [
  490                 {
  491                     "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  492                 }
  493             ]
  494         },
  495         "public": false,
  496         "ownerName": "CI",
  497         "owner": {
  498             "username": "CI",
  499             "displayName": "CI"
  500         },
  501         "fullName": "CI/py-repo"
  502     }
  503 }
  504 """
  505 
  506 deleteTagJsonPayload = """
  507 {
  508     "actor": {
  509         "username": "John",
  510         "displayName": "John Smith"
  511     },
  512     "repository": {
  513         "scmId": "git",
  514         "project": {
  515             "key": "CI",
  516             "name": "Continuous Integration"
  517         },
  518         "slug": "py-repo",
  519         "links": {
  520             "self": [
  521                 {
  522                     "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  523                 }
  524             ]
  525         },
  526         "ownerName": "BUIL",
  527         "public": false,
  528         "owner": {
  529             "username": "CI",
  530             "displayName": "CI"
  531         },
  532         "fullName": "CI/py-repo"
  533     },
  534     "push": {
  535         "changes": [
  536             {
  537                 "created": false,
  538                 "closed": true,
  539                 "old": {
  540                     "type": "tag",
  541                     "name": "1.0.0",
  542                     "target": {
  543                         "type": "commit",
  544                         "hash": "793d4754230023d85532f9a38dba3290f959beb4"
  545                     }
  546                 },
  547                 "new": null
  548             }
  549         ]
  550     }
  551 }
  552 """
  553 
  554 deleteBranchJsonPayload = """
  555 {
  556     "actor": {
  557         "username": "John",
  558         "displayName": "John Smith"
  559     },
  560     "repository": {
  561         "scmId": "git",
  562         "project": {
  563             "key": "CI",
  564             "name": "Continuous Integration"
  565         },
  566         "slug": "py-repo",
  567         "links": {
  568             "self": [
  569                 {
  570                     "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  571                 }
  572             ]
  573         },
  574         "ownerName": "CI",
  575         "public": false,
  576         "owner": {
  577             "username": "CI",
  578             "displayName": "CI"
  579         },
  580         "fullName": "CI/py-repo"
  581     },
  582     "push": {
  583         "changes": [
  584             {
  585                 "created": false,
  586                 "closed": true,
  587                 "old": {
  588                     "type": "branch",
  589                     "name": "branch_1496758965",
  590                     "target": {
  591                         "type": "commit",
  592                         "hash": "793d4754230023d85532f9a38dba3290f959beb4"
  593                     }
  594                 },
  595                 "new": null
  596             }
  597         ]
  598     }
  599 }
  600 """
  601 
  602 newTagJsonPayload = """
  603 {
  604     "actor": {
  605         "username": "John",
  606         "displayName": "John Smith"
  607     },
  608     "repository": {
  609         "scmId": "git",
  610         "project": {
  611             "key": "CI",
  612             "name": "Continuous Integration"
  613         },
  614         "slug": "py-repo",
  615         "links": {
  616             "self": [
  617                 {
  618                     "href": "http://localhost:7990/projects/CI/repos/py-repo/browse"
  619                 }
  620             ]
  621         },
  622         "public": false,
  623         "ownerName": "CI",
  624         "owner": {
  625             "username": "CI",
  626             "displayName": "CI"
  627         },
  628         "fullName": "CI/py-repo"
  629     },
  630     "push": {
  631         "changes": [
  632             {
  633                 "created": true,
  634                 "closed": false,
  635                 "old": null,
  636                 "new": {
  637                     "type": "tag",
  638                     "name": "1.0.0",
  639                     "target": {
  640                         "type": "commit",
  641                         "hash": "793d4754230023d85532f9a38dba3290f959beb4"
  642                     }
  643                 }
  644             }
  645         ]
  646     }
  647 }
  648 """
  649 
  650 
  651 def _prepare_request(payload, headers=None, change_dict=None):
  652     headers = headers or {}
  653     request = FakeRequest(change_dict)
  654     request.uri = b"/change_hook/bitbucketserver"
  655     request.method = b"POST"
  656     if isinstance(payload, str):
  657         payload = unicode2bytes(payload)
  658     request.content = BytesIO(payload)
  659     request.received_headers[b'Content-Type'] = _CT_JSON
  660     request.received_headers.update(headers)
  661     return request
  662 
  663 
  664 class TestChangeHookConfiguredWithGitChange(unittest.TestCase,
  665                                             TestReactorMixin):
  666 
  667     def setUp(self):
  668         self.setUpTestReactor()
  669         self.change_hook = change_hook.ChangeHookResource(
  670             dialects={'bitbucketserver': {}}, master=fakeMasterForHooks(self))
  671 
  672     def _checkPush(self, change):
  673         self.assertEqual(
  674             change['repository'],
  675             'http://localhost:7990/projects/CI/repos/py-repo/')
  676         self.assertEqual(change['author'], 'John Smith <John>')
  677         self.assertEqual(change['project'], 'Continuous Integration')
  678         self.assertEqual(change['revision'],
  679                          '793d4754230023d85532f9a38dba3290f959beb4')
  680         self.assertEqual(
  681             change['comments'], 'Bitbucket Server commit '
  682                                 '793d4754230023d85532f9a38dba3290f959beb4')
  683         self.assertEqual(
  684             change['revlink'],
  685             'http://localhost:7990/projects/CI/repos/py-repo/commits/'
  686             '793d4754230023d85532f9a38dba3290f959beb4')
  687 
  688     @defer.inlineCallbacks
  689     def testHookWithChangeOnRefsChangedEvent(self):
  690 
  691         request = _prepare_request(
  692             pushJsonPayload, headers={_HEADER_EVENT: 'repo:refs_changed'})
  693 
  694         yield request.test_render(self.change_hook)
  695 
  696         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  697         change = self.change_hook.master.data.updates.changesAdded[0]
  698         self._checkPush(change)
  699         self.assertEqual(change['branch'], 'refs/heads/branch_1496411680')
  700         self.assertEqual(change['category'], 'push')
  701 
  702     @defer.inlineCallbacks
  703     def testHookWithChangeOnPushEvent(self):
  704 
  705         request = _prepare_request(
  706             pushJsonPayload, headers={_HEADER_EVENT: 'repo:push'})
  707 
  708         yield request.test_render(self.change_hook)
  709 
  710         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  711         change = self.change_hook.master.data.updates.changesAdded[0]
  712         self._checkPush(change)
  713         self.assertEqual(change['branch'], 'refs/heads/branch_1496411680')
  714         self.assertEqual(change['category'], 'push')
  715 
  716     @defer.inlineCallbacks
  717     def testHookWithNonDictOption(self):
  718         self.change_hook.dialects = {'bitbucketserver': True}
  719         yield self.testHookWithChangeOnPushEvent()
  720 
  721     def _checkPullRequest(self, change):
  722         self.assertEqual(
  723             change['repository'],
  724             'http://localhost:7990/projects/CI/repos/py-repo/')
  725         self.assertEqual(change['author'], 'John Smith <John>')
  726         self.assertEqual(change['project'], 'Continuous Integration')
  727         self.assertEqual(change['comments'],
  728                          'Bitbucket Server Pull Request #21')
  729         self.assertEqual(change['revlink'],
  730                          'http://localhost:7990/projects/'
  731                          'CI/repos/py-repo/pull-requests/21')
  732         self.assertEqual(change['revision'],
  733                          'a87e21f7433d8c16ac7be7413483fbb76c72a8ba')
  734         pr_url = change['properties'].get('pullrequesturl')
  735         self.assertNotEqual(pr_url, None)
  736         self.assertEqual(
  737             pr_url,
  738             "http://localhost:7990/projects/CI/repos/py-repo/pull-requests/21")
  739 
  740     @defer.inlineCallbacks
  741     def testHookWithChangeOnPullRequestCreated(self):
  742         request = _prepare_request(
  743             pullRequestCreatedJsonPayload,
  744             headers={_HEADER_EVENT: 'pullrequest:created'})
  745 
  746         yield request.test_render(self.change_hook)
  747 
  748         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  749         change = self.change_hook.master.data.updates.changesAdded[0]
  750         self._checkPullRequest(change)
  751         self.assertEqual(change['branch'], 'refs/pull-requests/21/merge')
  752         self.assertEqual(change['category'], 'pull-created')
  753 
  754     @defer.inlineCallbacks
  755     def testHookWithChangeOnPullRequestUpdated(self):
  756         request = _prepare_request(
  757             pullRequestUpdatedJsonPayload,
  758             headers={_HEADER_EVENT: 'pullrequest:updated'})
  759 
  760         yield request.test_render(self.change_hook)
  761 
  762         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  763         change = self.change_hook.master.data.updates.changesAdded[0]
  764         self._checkPullRequest(change)
  765         self.assertEqual(change['branch'], 'refs/pull-requests/21/merge')
  766         self.assertEqual(change['category'], 'pull-updated')
  767 
  768     @defer.inlineCallbacks
  769     def testHookWithChangeOnPullRequestRejected(self):
  770         request = _prepare_request(
  771             pullRequestRejectedJsonPayload,
  772             headers={_HEADER_EVENT: 'pullrequest:rejected'})
  773 
  774         yield request.test_render(self.change_hook)
  775 
  776         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  777         change = self.change_hook.master.data.updates.changesAdded[0]
  778         self._checkPullRequest(change)
  779         self.assertEqual(change['branch'], 'refs/heads/branch_1496411680')
  780         self.assertEqual(change['category'], 'pull-rejected')
  781 
  782     @defer.inlineCallbacks
  783     def testHookWithChangeOnPullRequestFulfilled(self):
  784         request = _prepare_request(
  785             pullRequestFulfilledJsonPayload,
  786             headers={_HEADER_EVENT: 'pullrequest:fulfilled'})
  787 
  788         yield request.test_render(self.change_hook)
  789 
  790         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  791         change = self.change_hook.master.data.updates.changesAdded[0]
  792         self._checkPullRequest(change)
  793         self.assertEqual(change['branch'], 'refs/heads/master')
  794         self.assertEqual(change['category'], 'pull-fulfilled')
  795 
  796     @defer.inlineCallbacks
  797     def _checkCodebase(self, event_type, expected_codebase):
  798         payloads = {
  799             'repo:refs_changed': pushJsonPayload,
  800             'pullrequest:updated': pullRequestUpdatedJsonPayload}
  801         request = _prepare_request(
  802             payloads[event_type], headers={_HEADER_EVENT: event_type})
  803         yield request.test_render(self.change_hook)
  804         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  805         change = self.change_hook.master.data.updates.changesAdded[0]
  806         self.assertEqual(change['codebase'], expected_codebase)
  807 
  808     @defer.inlineCallbacks
  809     def testHookWithCodebaseValueOnPushEvent(self):
  810         self.change_hook.dialects = {
  811             'bitbucketserver': {'codebase': 'super-codebase'}}
  812         yield self._checkCodebase('repo:refs_changed', 'super-codebase')
  813 
  814     @defer.inlineCallbacks
  815     def testHookWithCodebaseFunctionOnPushEvent(self):
  816         self.change_hook.dialects = {
  817             'bitbucketserver': {
  818                 'codebase':
  819                     lambda payload: payload['repository']['project']['key']}}
  820         yield self._checkCodebase('repo:refs_changed', 'CI')
  821 
  822     @defer.inlineCallbacks
  823     def testHookWithCodebaseValueOnPullEvent(self):
  824         self.change_hook.dialects = {
  825             'bitbucketserver': {'codebase': 'super-codebase'}}
  826         yield self._checkCodebase('pullrequest:updated', 'super-codebase')
  827 
  828     @defer.inlineCallbacks
  829     def testHookWithCodebaseFunctionOnPullEvent(self):
  830         self.change_hook.dialects = {
  831             'bitbucketserver': {
  832                 'codebase':
  833                     lambda payload: payload['repository']['project']['key']}}
  834         yield self._checkCodebase('pullrequest:updated', 'CI')
  835 
  836     @defer.inlineCallbacks
  837     def testHookWithUnhandledEvent(self):
  838         request = _prepare_request(
  839             pushJsonPayload, headers={_HEADER_EVENT: 'invented:event'})
  840         yield request.test_render(self.change_hook)
  841         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 0)
  842         self.assertEqual(request.written, b"Unknown event: invented_event")
  843 
  844     @defer.inlineCallbacks
  845     def testHookWithChangeOnCreateTag(self):
  846         request = _prepare_request(
  847             newTagJsonPayload, headers={_HEADER_EVENT: 'repo:refs_changed'})
  848         yield request.test_render(self.change_hook)
  849         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  850         change = self.change_hook.master.data.updates.changesAdded[0]
  851         self._checkPush(change)
  852         self.assertEqual(change['branch'], 'refs/tags/1.0.0')
  853         self.assertEqual(change['category'], 'push')
  854 
  855     @defer.inlineCallbacks
  856     def testHookWithChangeOnDeleteTag(self):
  857         request = _prepare_request(
  858             deleteTagJsonPayload, headers={_HEADER_EVENT: 'repo:refs_changed'})
  859         yield request.test_render(self.change_hook)
  860         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  861         change = self.change_hook.master.data.updates.changesAdded[0]
  862         self._checkPush(change)
  863         self.assertEqual(change['branch'], 'refs/tags/1.0.0')
  864         self.assertEqual(change['category'], 'ref-deleted')
  865 
  866     @defer.inlineCallbacks
  867     def testHookWithChangeOnDeleteBranch(self):
  868         request = _prepare_request(
  869             deleteBranchJsonPayload,
  870             headers={_HEADER_EVENT: 'repo:refs_changed'})
  871         yield request.test_render(self.change_hook)
  872         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 1)
  873         change = self.change_hook.master.data.updates.changesAdded[0]
  874         self._checkPush(change)
  875         self.assertEqual(change['branch'], 'refs/heads/branch_1496758965')
  876         self.assertEqual(change['category'], 'ref-deleted')
  877 
  878     @defer.inlineCallbacks
  879     def testHookWithInvalidContentType(self):
  880         request = _prepare_request(
  881             pushJsonPayload, headers={_HEADER_EVENT: b'repo:refs_changed'})
  882         request.received_headers[b'Content-Type'] = b'invalid/content'
  883         yield request.test_render(self.change_hook)
  884         self.assertEqual(len(self.change_hook.master.data.updates.changesAdded), 0)
  885         self.assertEqual(request.written,
  886                          b"Unknown content type: invalid/content")