You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
11 KiB

  1. package github
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "net/http/httptest"
  9. "strings"
  10. "testing"
  11. "github.com/matrix-org/go-neb/database"
  12. "github.com/matrix-org/go-neb/testutils"
  13. "github.com/matrix-org/go-neb/types"
  14. "maunium.net/go/mautrix"
  15. mevt "maunium.net/go/mautrix/event"
  16. )
  17. var roomID = "!testroom:id"
  18. func TestGithubWebhook(t *testing.T) {
  19. database.SetServiceDB(&database.NopStorage{})
  20. // Intercept message sending to Matrix and mock responses
  21. msgs := []mevt.MessageEventContent{}
  22. matrixTrans := struct{ testutils.MockTransport }{}
  23. matrixTrans.RT = func(req *http.Request) (*http.Response, error) {
  24. if !strings.Contains(req.URL.String(), "/send/m.room.message") {
  25. return nil, fmt.Errorf("Unhandled URL: %s", req.URL.String())
  26. }
  27. var msg mevt.MessageEventContent
  28. if err := json.NewDecoder(req.Body).Decode(&msg); err != nil {
  29. return nil, fmt.Errorf("Failed to decode request JSON: %s", err)
  30. }
  31. msgs = append(msgs, msg)
  32. return &http.Response{
  33. StatusCode: 200,
  34. Body: ioutil.NopCloser(bytes.NewBufferString(`{"event_id":"$yup:event"}`)),
  35. }, nil
  36. }
  37. matrixCli, _ := mautrix.NewClient("https://hyrule", "@ghwebhook:hyrule", "its_a_secret")
  38. matrixCli.Client = &http.Client{Transport: matrixTrans}
  39. // create the service
  40. ghwh := makeService(t)
  41. if ghwh == nil {
  42. t.Fatal("TestGithubWebhook Failed to create service")
  43. }
  44. // inject the webhook event request
  45. req, err := http.NewRequest(
  46. "POST", "https://neb.endpoint/gh-webhook-service", bytes.NewBufferString(`
  47. {
  48. "action": "closed",
  49. "issue": {
  50. "url": "https://api.github.com/repos/DummyAccount/reponame/issues/15",
  51. "repository_url": "https://api.github.com/repos/DummyAccount/reponame",
  52. "labels_url": "https://api.github.com/repos/DummyAccount/reponame/issues/15/labels{/name}",
  53. "comments_url": "https://api.github.com/repos/DummyAccount/reponame/issues/15/comments",
  54. "events_url": "https://api.github.com/repos/DummyAccount/reponame/issues/15/events",
  55. "html_url": "https://github.com/DummyAccount/reponame/issues/15",
  56. "id": 159196956,
  57. "number": 15,
  58. "title": "aaaaaa",
  59. "user": {
  60. "login": "DummyAccount",
  61. "id": 7190048,
  62. "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3",
  63. "gravatar_id": "",
  64. "url": "https://api.github.com/users/DummyAccount",
  65. "html_url": "https://github.com/DummyAccount",
  66. "followers_url": "https://api.github.com/users/DummyAccount/followers",
  67. "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}",
  68. "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}",
  69. "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}",
  70. "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions",
  71. "organizations_url": "https://api.github.com/users/DummyAccount/orgs",
  72. "repos_url": "https://api.github.com/users/DummyAccount/repos",
  73. "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}",
  74. "received_events_url": "https://api.github.com/users/DummyAccount/received_events",
  75. "type": "User",
  76. "site_admin": false
  77. },
  78. "labels": [
  79. ],
  80. "state": "closed",
  81. "locked": false,
  82. "assignee": null,
  83. "milestone": null,
  84. "comments": 1,
  85. "created_at": "2016-06-08T15:40:44Z",
  86. "updated_at": "2016-06-08T15:41:36Z",
  87. "closed_at": "2016-06-08T15:41:36Z",
  88. "body": ""
  89. },
  90. "repository": {
  91. "id": 21138172,
  92. "name": "reponame",
  93. "full_name": "DummyAccount/reponame",
  94. "owner": {
  95. "login": "DummyAccount",
  96. "id": 7190048,
  97. "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3",
  98. "gravatar_id": "",
  99. "url": "https://api.github.com/users/DummyAccount",
  100. "html_url": "https://github.com/DummyAccount",
  101. "followers_url": "https://api.github.com/users/DummyAccount/followers",
  102. "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}",
  103. "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}",
  104. "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}",
  105. "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions",
  106. "organizations_url": "https://api.github.com/users/DummyAccount/orgs",
  107. "repos_url": "https://api.github.com/users/DummyAccount/repos",
  108. "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}",
  109. "received_events_url": "https://api.github.com/users/DummyAccount/received_events",
  110. "type": "User",
  111. "site_admin": false
  112. },
  113. "private": false,
  114. "html_url": "https://github.com/DummyAccount/reponame",
  115. "description": "Android Development Device Monitor",
  116. "fork": false,
  117. "url": "https://api.github.com/repos/DummyAccount/reponame",
  118. "forks_url": "https://api.github.com/repos/DummyAccount/reponame/forks",
  119. "keys_url": "https://api.github.com/repos/DummyAccount/reponame/keys{/key_id}",
  120. "collaborators_url": "https://api.github.com/repos/DummyAccount/reponame/collaborators{/collaborator}",
  121. "teams_url": "https://api.github.com/repos/DummyAccount/reponame/teams",
  122. "hooks_url": "https://api.github.com/repos/DummyAccount/reponame/hooks",
  123. "issue_events_url": "https://api.github.com/repos/DummyAccount/reponame/issues/events{/number}",
  124. "events_url": "https://api.github.com/repos/DummyAccount/reponame/events",
  125. "assignees_url": "https://api.github.com/repos/DummyAccount/reponame/assignees{/user}",
  126. "branches_url": "https://api.github.com/repos/DummyAccount/reponame/branches{/branch}",
  127. "tags_url": "https://api.github.com/repos/DummyAccount/reponame/tags",
  128. "blobs_url": "https://api.github.com/repos/DummyAccount/reponame/git/blobs{/sha}",
  129. "git_tags_url": "https://api.github.com/repos/DummyAccount/reponame/git/tags{/sha}",
  130. "git_refs_url": "https://api.github.com/repos/DummyAccount/reponame/git/refs{/sha}",
  131. "trees_url": "https://api.github.com/repos/DummyAccount/reponame/git/trees{/sha}",
  132. "statuses_url": "https://api.github.com/repos/DummyAccount/reponame/statuses/{sha}",
  133. "languages_url": "https://api.github.com/repos/DummyAccount/reponame/languages",
  134. "stargazers_url": "https://api.github.com/repos/DummyAccount/reponame/stargazers",
  135. "contributors_url": "https://api.github.com/repos/DummyAccount/reponame/contributors",
  136. "subscribers_url": "https://api.github.com/repos/DummyAccount/reponame/subscribers",
  137. "subscription_url": "https://api.github.com/repos/DummyAccount/reponame/subscription",
  138. "commits_url": "https://api.github.com/repos/DummyAccount/reponame/commits{/sha}",
  139. "git_commits_url": "https://api.github.com/repos/DummyAccount/reponame/git/commits{/sha}",
  140. "comments_url": "https://api.github.com/repos/DummyAccount/reponame/comments{/number}",
  141. "issue_comment_url": "https://api.github.com/repos/DummyAccount/reponame/issues/comments{/number}",
  142. "contents_url": "https://api.github.com/repos/DummyAccount/reponame/contents/{+path}",
  143. "compare_url": "https://api.github.com/repos/DummyAccount/reponame/compare/{base}...{head}",
  144. "merges_url": "https://api.github.com/repos/DummyAccount/reponame/merges",
  145. "archive_url": "https://api.github.com/repos/DummyAccount/reponame/{archive_format}{/ref}",
  146. "downloads_url": "https://api.github.com/repos/DummyAccount/reponame/downloads",
  147. "issues_url": "https://api.github.com/repos/DummyAccount/reponame/issues{/number}",
  148. "pulls_url": "https://api.github.com/repos/DummyAccount/reponame/pulls{/number}",
  149. "milestones_url": "https://api.github.com/repos/DummyAccount/reponame/milestones{/number}",
  150. "notifications_url": "https://api.github.com/repos/DummyAccount/reponame/notifications{?since,all,participating}",
  151. "labels_url": "https://api.github.com/repos/DummyAccount/reponame/labels{/name}",
  152. "releases_url": "https://api.github.com/repos/DummyAccount/reponame/releases{/id}",
  153. "deployments_url": "https://api.github.com/repos/DummyAccount/reponame/deployments",
  154. "created_at": "2014-06-23T18:51:33Z",
  155. "updated_at": "2015-07-22T07:42:19Z",
  156. "pushed_at": "2015-07-22T07:42:19Z",
  157. "git_url": "git://github.com/DummyAccount/reponame.git",
  158. "ssh_url": "git@github.com:DummyAccount/reponame.git",
  159. "clone_url": "https://github.com/DummyAccount/reponame.git",
  160. "svn_url": "https://github.com/DummyAccount/reponame",
  161. "homepage": null,
  162. "size": 725,
  163. "stargazers_count": 0,
  164. "watchers_count": 0,
  165. "language": "Java",
  166. "has_issues": true,
  167. "has_downloads": true,
  168. "has_wiki": true,
  169. "has_pages": false,
  170. "forks_count": 1,
  171. "mirror_url": null,
  172. "open_issues_count": 0,
  173. "forks": 1,
  174. "open_issues": 0,
  175. "watchers": 0,
  176. "default_branch": "master"
  177. },
  178. "sender": {
  179. "login": "DummyAccount",
  180. "id": 7190048,
  181. "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3",
  182. "gravatar_id": "",
  183. "url": "https://api.github.com/users/DummyAccount",
  184. "html_url": "https://github.com/DummyAccount",
  185. "followers_url": "https://api.github.com/users/DummyAccount/followers",
  186. "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}",
  187. "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}",
  188. "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}",
  189. "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions",
  190. "organizations_url": "https://api.github.com/users/DummyAccount/orgs",
  191. "repos_url": "https://api.github.com/users/DummyAccount/repos",
  192. "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}",
  193. "received_events_url": "https://api.github.com/users/DummyAccount/received_events",
  194. "type": "User",
  195. "site_admin": false
  196. }
  197. }
  198. `),
  199. )
  200. if err != nil {
  201. t.Fatalf("TestGithubWebhook Failed to create webhook request: %s", err)
  202. }
  203. req.Header.Set("X-GitHub-Event", "issues")
  204. req.Header.Set("Content-Type", "application/json")
  205. mockWriter := httptest.NewRecorder()
  206. ghwh.OnReceiveWebhook(mockWriter, req, matrixCli)
  207. // check response
  208. if mockWriter.Code != 200 {
  209. t.Fatalf("TestGithubWebhook Expected response 200 OK, got %d", mockWriter.Code)
  210. }
  211. if len(msgs) != 1 {
  212. t.Fatalf("TestGithubWebhook Expected sent 1 msg, sent %d", len(msgs))
  213. }
  214. }
  215. func makeService(t *testing.T) *WebhookService {
  216. srv, err := types.CreateService("id", WebhookServiceType, "@ghwebhook:hyrule", []byte(
  217. `{
  218. "ClientUserID": "@alice:hyrule",
  219. "RealmID": "ghrealm",
  220. "Rooms":{
  221. "`+roomID+`": {
  222. "Repos": {
  223. "DummyAccount/reponame": {
  224. "Events": ["issues"]
  225. }
  226. }
  227. }
  228. }
  229. }`,
  230. ))
  231. if err != nil {
  232. t.Error("Failed to create GH webhook service: ", err)
  233. return nil
  234. }
  235. return srv.(*WebhookService)
  236. }