1
0

test_http.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. # Copyright 2018 New Vector
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from unittest.mock import Mock
  15. from twisted.internet.defer import Deferred
  16. import synapse.rest.admin
  17. from synapse.logging.context import make_deferred_yieldable
  18. from synapse.push import PusherConfigException
  19. from synapse.rest.client.v1 import login, room
  20. from synapse.rest.client.v2_alpha import receipts
  21. from tests.unittest import HomeserverTestCase, override_config
  22. class HTTPPusherTests(HomeserverTestCase):
  23. servlets = [
  24. synapse.rest.admin.register_servlets_for_client_rest_resource,
  25. room.register_servlets,
  26. login.register_servlets,
  27. receipts.register_servlets,
  28. ]
  29. user_id = True
  30. hijack_auth = False
  31. def default_config(self):
  32. config = super().default_config()
  33. config["start_pushers"] = True
  34. return config
  35. def make_homeserver(self, reactor, clock):
  36. self.push_attempts = []
  37. m = Mock()
  38. def post_json_get_json(url, body):
  39. d = Deferred()
  40. self.push_attempts.append((d, url, body))
  41. return make_deferred_yieldable(d)
  42. m.post_json_get_json = post_json_get_json
  43. hs = self.setup_test_homeserver(proxied_blacklisted_http_client=m)
  44. return hs
  45. def test_invalid_configuration(self):
  46. """Invalid push configurations should be rejected."""
  47. # Register the user who gets notified
  48. user_id = self.register_user("user", "pass")
  49. access_token = self.login("user", "pass")
  50. # Register the pusher
  51. user_tuple = self.get_success(
  52. self.hs.get_datastore().get_user_by_access_token(access_token)
  53. )
  54. token_id = user_tuple.token_id
  55. def test_data(data):
  56. self.get_failure(
  57. self.hs.get_pusherpool().add_pusher(
  58. user_id=user_id,
  59. access_token=token_id,
  60. kind="http",
  61. app_id="m.http",
  62. app_display_name="HTTP Push Notifications",
  63. device_display_name="pushy push",
  64. pushkey="a@example.com",
  65. lang=None,
  66. data=data,
  67. ),
  68. PusherConfigException,
  69. )
  70. # Data must be provided with a URL.
  71. test_data(None)
  72. test_data({})
  73. test_data({"url": 1})
  74. # A bare domain name isn't accepted.
  75. test_data({"url": "example.com"})
  76. # A URL without a path isn't accepted.
  77. test_data({"url": "http://example.com"})
  78. # A url with an incorrect path isn't accepted.
  79. test_data({"url": "http://example.com/foo"})
  80. def test_sends_http(self):
  81. """
  82. The HTTP pusher will send pushes for each message to a HTTP endpoint
  83. when configured to do so.
  84. """
  85. # Register the user who gets notified
  86. user_id = self.register_user("user", "pass")
  87. access_token = self.login("user", "pass")
  88. # Register the user who sends the message
  89. other_user_id = self.register_user("otheruser", "pass")
  90. other_access_token = self.login("otheruser", "pass")
  91. # Register the pusher
  92. user_tuple = self.get_success(
  93. self.hs.get_datastore().get_user_by_access_token(access_token)
  94. )
  95. token_id = user_tuple.token_id
  96. self.get_success(
  97. self.hs.get_pusherpool().add_pusher(
  98. user_id=user_id,
  99. access_token=token_id,
  100. kind="http",
  101. app_id="m.http",
  102. app_display_name="HTTP Push Notifications",
  103. device_display_name="pushy push",
  104. pushkey="a@example.com",
  105. lang=None,
  106. data={"url": "http://example.com/_matrix/push/v1/notify"},
  107. )
  108. )
  109. # Create a room
  110. room = self.helper.create_room_as(user_id, tok=access_token)
  111. # The other user joins
  112. self.helper.join(room=room, user=other_user_id, tok=other_access_token)
  113. # The other user sends some messages
  114. self.helper.send(room, body="Hi!", tok=other_access_token)
  115. self.helper.send(room, body="There!", tok=other_access_token)
  116. # Get the stream ordering before it gets sent
  117. pushers = self.get_success(
  118. self.hs.get_datastore().get_pushers_by({"user_name": user_id})
  119. )
  120. pushers = list(pushers)
  121. self.assertEqual(len(pushers), 1)
  122. last_stream_ordering = pushers[0].last_stream_ordering
  123. # Advance time a bit, so the pusher will register something has happened
  124. self.pump()
  125. # It hasn't succeeded yet, so the stream ordering shouldn't have moved
  126. pushers = self.get_success(
  127. self.hs.get_datastore().get_pushers_by({"user_name": user_id})
  128. )
  129. pushers = list(pushers)
  130. self.assertEqual(len(pushers), 1)
  131. self.assertEqual(last_stream_ordering, pushers[0].last_stream_ordering)
  132. # One push was attempted to be sent -- it'll be the first message
  133. self.assertEqual(len(self.push_attempts), 1)
  134. self.assertEqual(
  135. self.push_attempts[0][1], "http://example.com/_matrix/push/v1/notify"
  136. )
  137. self.assertEqual(
  138. self.push_attempts[0][2]["notification"]["content"]["body"], "Hi!"
  139. )
  140. # Make the push succeed
  141. self.push_attempts[0][0].callback({})
  142. self.pump()
  143. # The stream ordering has increased
  144. pushers = self.get_success(
  145. self.hs.get_datastore().get_pushers_by({"user_name": user_id})
  146. )
  147. pushers = list(pushers)
  148. self.assertEqual(len(pushers), 1)
  149. self.assertTrue(pushers[0].last_stream_ordering > last_stream_ordering)
  150. last_stream_ordering = pushers[0].last_stream_ordering
  151. # Now it'll try and send the second push message, which will be the second one
  152. self.assertEqual(len(self.push_attempts), 2)
  153. self.assertEqual(
  154. self.push_attempts[1][1], "http://example.com/_matrix/push/v1/notify"
  155. )
  156. self.assertEqual(
  157. self.push_attempts[1][2]["notification"]["content"]["body"], "There!"
  158. )
  159. # Make the second push succeed
  160. self.push_attempts[1][0].callback({})
  161. self.pump()
  162. # The stream ordering has increased, again
  163. pushers = self.get_success(
  164. self.hs.get_datastore().get_pushers_by({"user_name": user_id})
  165. )
  166. pushers = list(pushers)
  167. self.assertEqual(len(pushers), 1)
  168. self.assertTrue(pushers[0].last_stream_ordering > last_stream_ordering)
  169. def test_sends_high_priority_for_encrypted(self):
  170. """
  171. The HTTP pusher will send pushes at high priority if they correspond
  172. to an encrypted message.
  173. This will happen both in 1:1 rooms and larger rooms.
  174. """
  175. # Register the user who gets notified
  176. user_id = self.register_user("user", "pass")
  177. access_token = self.login("user", "pass")
  178. # Register the user who sends the message
  179. other_user_id = self.register_user("otheruser", "pass")
  180. other_access_token = self.login("otheruser", "pass")
  181. # Register a third user
  182. yet_another_user_id = self.register_user("yetanotheruser", "pass")
  183. yet_another_access_token = self.login("yetanotheruser", "pass")
  184. # Create a room
  185. room = self.helper.create_room_as(user_id, tok=access_token)
  186. # The other user joins
  187. self.helper.join(room=room, user=other_user_id, tok=other_access_token)
  188. # Register the pusher
  189. user_tuple = self.get_success(
  190. self.hs.get_datastore().get_user_by_access_token(access_token)
  191. )
  192. token_id = user_tuple.token_id
  193. self.get_success(
  194. self.hs.get_pusherpool().add_pusher(
  195. user_id=user_id,
  196. access_token=token_id,
  197. kind="http",
  198. app_id="m.http",
  199. app_display_name="HTTP Push Notifications",
  200. device_display_name="pushy push",
  201. pushkey="a@example.com",
  202. lang=None,
  203. data={"url": "http://example.com/_matrix/push/v1/notify"},
  204. )
  205. )
  206. # Send an encrypted event
  207. # I know there'd normally be set-up of an encrypted room first
  208. # but this will do for our purposes
  209. self.helper.send_event(
  210. room,
  211. "m.room.encrypted",
  212. content={
  213. "algorithm": "m.megolm.v1.aes-sha2",
  214. "sender_key": "6lImKbzK51MzWLwHh8tUM3UBBSBrLlgup/OOCGTvumM",
  215. "ciphertext": "AwgAErABoRxwpMipdgiwXgu46rHiWQ0DmRj0qUlPrMraBUDk"
  216. "leTnJRljpuc7IOhsYbLY3uo2WI0ab/ob41sV+3JEIhODJPqH"
  217. "TK7cEZaIL+/up9e+dT9VGF5kRTWinzjkeqO8FU5kfdRjm+3w"
  218. "0sy3o1OCpXXCfO+faPhbV/0HuK4ndx1G+myNfK1Nk/CxfMcT"
  219. "BT+zDS/Df/QePAHVbrr9uuGB7fW8ogW/ulnydgZPRluusFGv"
  220. "J3+cg9LoPpZPAmv5Me3ec7NtdlfN0oDZ0gk3TiNkkhsxDG9Y"
  221. "YcNzl78USI0q8+kOV26Bu5dOBpU4WOuojXZHJlP5lMgdzLLl"
  222. "EQ0",
  223. "session_id": "IigqfNWLL+ez/Is+Duwp2s4HuCZhFG9b9CZKTYHtQ4A",
  224. "device_id": "AHQDUSTAAA",
  225. },
  226. tok=other_access_token,
  227. )
  228. # Advance time a bit, so the pusher will register something has happened
  229. self.pump()
  230. # Make the push succeed
  231. self.push_attempts[0][0].callback({})
  232. self.pump()
  233. # Check our push made it with high priority
  234. self.assertEqual(len(self.push_attempts), 1)
  235. self.assertEqual(
  236. self.push_attempts[0][1], "http://example.com/_matrix/push/v1/notify"
  237. )
  238. self.assertEqual(self.push_attempts[0][2]["notification"]["prio"], "high")
  239. # Add yet another person — we want to make this room not a 1:1
  240. # (as encrypted messages in a 1:1 currently have tweaks applied
  241. # so it doesn't properly exercise the condition of all encrypted
  242. # messages need to be high).
  243. self.helper.join(
  244. room=room, user=yet_another_user_id, tok=yet_another_access_token
  245. )
  246. # Check no push notifications are sent regarding the membership changes
  247. # (that would confuse the test)
  248. self.pump()
  249. self.assertEqual(len(self.push_attempts), 1)
  250. # Send another encrypted event
  251. self.helper.send_event(
  252. room,
  253. "m.room.encrypted",
  254. content={
  255. "ciphertext": "AwgAEoABtEuic/2DF6oIpNH+q/PonzlhXOVho8dTv0tzFr5m"
  256. "9vTo50yabx3nxsRlP2WxSqa8I07YftP+EKWCWJvTkg6o7zXq"
  257. "6CK+GVvLQOVgK50SfvjHqJXN+z1VEqj+5mkZVN/cAgJzoxcH"
  258. "zFHkwDPJC8kQs47IHd8EO9KBUK4v6+NQ1uE/BIak4qAf9aS/"
  259. "kI+f0gjn9IY9K6LXlah82A/iRyrIrxkCkE/n0VfvLhaWFecC"
  260. "sAWTcMLoF6fh1Jpke95mljbmFSpsSd/eEQw",
  261. "device_id": "SRCFTWTHXO",
  262. "session_id": "eMA+bhGczuTz1C5cJR1YbmrnnC6Goni4lbvS5vJ1nG4",
  263. "algorithm": "m.megolm.v1.aes-sha2",
  264. "sender_key": "rC/XSIAiYrVGSuaHMop8/pTZbku4sQKBZwRwukgnN1c",
  265. },
  266. tok=other_access_token,
  267. )
  268. # Advance time a bit, so the pusher will register something has happened
  269. self.pump()
  270. self.assertEqual(len(self.push_attempts), 2)
  271. self.assertEqual(
  272. self.push_attempts[1][1], "http://example.com/_matrix/push/v1/notify"
  273. )
  274. self.assertEqual(self.push_attempts[1][2]["notification"]["prio"], "high")
  275. def test_sends_high_priority_for_one_to_one_only(self):
  276. """
  277. The HTTP pusher will send pushes at high priority if they correspond
  278. to a message in a one-to-one room.
  279. """
  280. # Register the user who gets notified
  281. user_id = self.register_user("user", "pass")
  282. access_token = self.login("user", "pass")
  283. # Register the user who sends the message
  284. other_user_id = self.register_user("otheruser", "pass")
  285. other_access_token = self.login("otheruser", "pass")
  286. # Register a third user
  287. yet_another_user_id = self.register_user("yetanotheruser", "pass")
  288. yet_another_access_token = self.login("yetanotheruser", "pass")
  289. # Create a room
  290. room = self.helper.create_room_as(user_id, tok=access_token)
  291. # The other user joins
  292. self.helper.join(room=room, user=other_user_id, tok=other_access_token)
  293. # Register the pusher
  294. user_tuple = self.get_success(
  295. self.hs.get_datastore().get_user_by_access_token(access_token)
  296. )
  297. token_id = user_tuple.token_id
  298. self.get_success(
  299. self.hs.get_pusherpool().add_pusher(
  300. user_id=user_id,
  301. access_token=token_id,
  302. kind="http",
  303. app_id="m.http",
  304. app_display_name="HTTP Push Notifications",
  305. device_display_name="pushy push",
  306. pushkey="a@example.com",
  307. lang=None,
  308. data={"url": "http://example.com/_matrix/push/v1/notify"},
  309. )
  310. )
  311. # Send a message
  312. self.helper.send(room, body="Hi!", tok=other_access_token)
  313. # Advance time a bit, so the pusher will register something has happened
  314. self.pump()
  315. # Make the push succeed
  316. self.push_attempts[0][0].callback({})
  317. self.pump()
  318. # Check our push made it with high priority — this is a one-to-one room
  319. self.assertEqual(len(self.push_attempts), 1)
  320. self.assertEqual(
  321. self.push_attempts[0][1], "http://example.com/_matrix/push/v1/notify"
  322. )
  323. self.assertEqual(self.push_attempts[0][2]["notification"]["prio"], "high")
  324. # Yet another user joins
  325. self.helper.join(
  326. room=room, user=yet_another_user_id, tok=yet_another_access_token
  327. )
  328. # Check no push notifications are sent regarding the membership changes
  329. # (that would confuse the test)
  330. self.pump()
  331. self.assertEqual(len(self.push_attempts), 1)
  332. # Send another event
  333. self.helper.send(room, body="Welcome!", tok=other_access_token)
  334. # Advance time a bit, so the pusher will register something has happened
  335. self.pump()
  336. self.assertEqual(len(self.push_attempts), 2)
  337. self.assertEqual(
  338. self.push_attempts[1][1], "http://example.com/_matrix/push/v1/notify"
  339. )
  340. # check that this is low-priority
  341. self.assertEqual(self.push_attempts[1][2]["notification"]["prio"], "low")
  342. def test_sends_high_priority_for_mention(self):
  343. """
  344. The HTTP pusher will send pushes at high priority if they correspond
  345. to a message containing the user's display name.
  346. """
  347. # Register the user who gets notified
  348. user_id = self.register_user("user", "pass")
  349. access_token = self.login("user", "pass")
  350. # Register the user who sends the message
  351. other_user_id = self.register_user("otheruser", "pass")
  352. other_access_token = self.login("otheruser", "pass")
  353. # Register a third user
  354. yet_another_user_id = self.register_user("yetanotheruser", "pass")
  355. yet_another_access_token = self.login("yetanotheruser", "pass")
  356. # Create a room
  357. room = self.helper.create_room_as(user_id, tok=access_token)
  358. # The other users join
  359. self.helper.join(room=room, user=other_user_id, tok=other_access_token)
  360. self.helper.join(
  361. room=room, user=yet_another_user_id, tok=yet_another_access_token
  362. )
  363. # Register the pusher
  364. user_tuple = self.get_success(
  365. self.hs.get_datastore().get_user_by_access_token(access_token)
  366. )
  367. token_id = user_tuple.token_id
  368. self.get_success(
  369. self.hs.get_pusherpool().add_pusher(
  370. user_id=user_id,
  371. access_token=token_id,
  372. kind="http",
  373. app_id="m.http",
  374. app_display_name="HTTP Push Notifications",
  375. device_display_name="pushy push",
  376. pushkey="a@example.com",
  377. lang=None,
  378. data={"url": "http://example.com/_matrix/push/v1/notify"},
  379. )
  380. )
  381. # Send a message
  382. self.helper.send(room, body="Oh, user, hello!", tok=other_access_token)
  383. # Advance time a bit, so the pusher will register something has happened
  384. self.pump()
  385. # Make the push succeed
  386. self.push_attempts[0][0].callback({})
  387. self.pump()
  388. # Check our push made it with high priority
  389. self.assertEqual(len(self.push_attempts), 1)
  390. self.assertEqual(
  391. self.push_attempts[0][1], "http://example.com/_matrix/push/v1/notify"
  392. )
  393. self.assertEqual(self.push_attempts[0][2]["notification"]["prio"], "high")
  394. # Send another event, this time with no mention
  395. self.helper.send(room, body="Are you there?", tok=other_access_token)
  396. # Advance time a bit, so the pusher will register something has happened
  397. self.pump()
  398. self.assertEqual(len(self.push_attempts), 2)
  399. self.assertEqual(
  400. self.push_attempts[1][1], "http://example.com/_matrix/push/v1/notify"
  401. )
  402. # check that this is low-priority
  403. self.assertEqual(self.push_attempts[1][2]["notification"]["prio"], "low")
  404. def test_sends_high_priority_for_atroom(self):
  405. """
  406. The HTTP pusher will send pushes at high priority if they correspond
  407. to a message that contains @room.
  408. """
  409. # Register the user who gets notified
  410. user_id = self.register_user("user", "pass")
  411. access_token = self.login("user", "pass")
  412. # Register the user who sends the message
  413. other_user_id = self.register_user("otheruser", "pass")
  414. other_access_token = self.login("otheruser", "pass")
  415. # Register a third user
  416. yet_another_user_id = self.register_user("yetanotheruser", "pass")
  417. yet_another_access_token = self.login("yetanotheruser", "pass")
  418. # Create a room (as other_user so the power levels are compatible with
  419. # other_user sending @room).
  420. room = self.helper.create_room_as(other_user_id, tok=other_access_token)
  421. # The other users join
  422. self.helper.join(room=room, user=user_id, tok=access_token)
  423. self.helper.join(
  424. room=room, user=yet_another_user_id, tok=yet_another_access_token
  425. )
  426. # Register the pusher
  427. user_tuple = self.get_success(
  428. self.hs.get_datastore().get_user_by_access_token(access_token)
  429. )
  430. token_id = user_tuple.token_id
  431. self.get_success(
  432. self.hs.get_pusherpool().add_pusher(
  433. user_id=user_id,
  434. access_token=token_id,
  435. kind="http",
  436. app_id="m.http",
  437. app_display_name="HTTP Push Notifications",
  438. device_display_name="pushy push",
  439. pushkey="a@example.com",
  440. lang=None,
  441. data={"url": "http://example.com/_matrix/push/v1/notify"},
  442. )
  443. )
  444. # Send a message
  445. self.helper.send(
  446. room,
  447. body="@room eeek! There's a spider on the table!",
  448. tok=other_access_token,
  449. )
  450. # Advance time a bit, so the pusher will register something has happened
  451. self.pump()
  452. # Make the push succeed
  453. self.push_attempts[0][0].callback({})
  454. self.pump()
  455. # Check our push made it with high priority
  456. self.assertEqual(len(self.push_attempts), 1)
  457. self.assertEqual(
  458. self.push_attempts[0][1], "http://example.com/_matrix/push/v1/notify"
  459. )
  460. self.assertEqual(self.push_attempts[0][2]["notification"]["prio"], "high")
  461. # Send another event, this time as someone without the power of @room
  462. self.helper.send(
  463. room, body="@room the spider is gone", tok=yet_another_access_token
  464. )
  465. # Advance time a bit, so the pusher will register something has happened
  466. self.pump()
  467. self.assertEqual(len(self.push_attempts), 2)
  468. self.assertEqual(
  469. self.push_attempts[1][1], "http://example.com/_matrix/push/v1/notify"
  470. )
  471. # check that this is low-priority
  472. self.assertEqual(self.push_attempts[1][2]["notification"]["prio"], "low")
  473. def test_push_unread_count_group_by_room(self):
  474. """
  475. The HTTP pusher will group unread count by number of unread rooms.
  476. """
  477. # Carry out common push count tests and setup
  478. self._test_push_unread_count()
  479. # Carry out our option-value specific test
  480. #
  481. # This push should still only contain an unread count of 1 (for 1 unread room)
  482. self.assertEqual(
  483. self.push_attempts[5][2]["notification"]["counts"]["unread"], 1
  484. )
  485. @override_config({"push": {"group_unread_count_by_room": False}})
  486. def test_push_unread_count_message_count(self):
  487. """
  488. The HTTP pusher will send the total unread message count.
  489. """
  490. # Carry out common push count tests and setup
  491. self._test_push_unread_count()
  492. # Carry out our option-value specific test
  493. #
  494. # We're counting every unread message, so there should now be 4 since the
  495. # last read receipt
  496. self.assertEqual(
  497. self.push_attempts[5][2]["notification"]["counts"]["unread"], 4
  498. )
  499. def _test_push_unread_count(self):
  500. """
  501. Tests that the correct unread count appears in sent push notifications
  502. Note that:
  503. * Sending messages will cause push notifications to go out to relevant users
  504. * Sending a read receipt will cause a "badge update" notification to go out to
  505. the user that sent the receipt
  506. """
  507. # Register the user who gets notified
  508. user_id = self.register_user("user", "pass")
  509. access_token = self.login("user", "pass")
  510. # Register the user who sends the message
  511. other_user_id = self.register_user("other_user", "pass")
  512. other_access_token = self.login("other_user", "pass")
  513. # Create a room (as other_user)
  514. room_id = self.helper.create_room_as(other_user_id, tok=other_access_token)
  515. # The user to get notified joins
  516. self.helper.join(room=room_id, user=user_id, tok=access_token)
  517. # Register the pusher
  518. user_tuple = self.get_success(
  519. self.hs.get_datastore().get_user_by_access_token(access_token)
  520. )
  521. token_id = user_tuple.token_id
  522. self.get_success(
  523. self.hs.get_pusherpool().add_pusher(
  524. user_id=user_id,
  525. access_token=token_id,
  526. kind="http",
  527. app_id="m.http",
  528. app_display_name="HTTP Push Notifications",
  529. device_display_name="pushy push",
  530. pushkey="a@example.com",
  531. lang=None,
  532. data={"url": "http://example.com/_matrix/push/v1/notify"},
  533. )
  534. )
  535. # Send a message
  536. response = self.helper.send(
  537. room_id, body="Hello there!", tok=other_access_token
  538. )
  539. # To get an unread count, the user who is getting notified has to have a read
  540. # position in the room. We'll set the read position to this event in a moment
  541. first_message_event_id = response["event_id"]
  542. # Advance time a bit (so the pusher will register something has happened) and
  543. # make the push succeed
  544. self.push_attempts[0][0].callback({})
  545. self.pump()
  546. # Check our push made it
  547. self.assertEqual(len(self.push_attempts), 1)
  548. self.assertEqual(
  549. self.push_attempts[0][1], "http://example.com/_matrix/push/v1/notify"
  550. )
  551. # Check that the unread count for the room is 0
  552. #
  553. # The unread count is zero as the user has no read receipt in the room yet
  554. self.assertEqual(
  555. self.push_attempts[0][2]["notification"]["counts"]["unread"], 0
  556. )
  557. # Now set the user's read receipt position to the first event
  558. #
  559. # This will actually trigger a new notification to be sent out so that
  560. # even if the user does not receive another message, their unread
  561. # count goes down
  562. channel = self.make_request(
  563. "POST",
  564. "/rooms/%s/receipt/m.read/%s" % (room_id, first_message_event_id),
  565. {},
  566. access_token=access_token,
  567. )
  568. self.assertEqual(channel.code, 200, channel.json_body)
  569. # Advance time and make the push succeed
  570. self.push_attempts[1][0].callback({})
  571. self.pump()
  572. # Unread count is still zero as we've read the only message in the room
  573. self.assertEqual(len(self.push_attempts), 2)
  574. self.assertEqual(
  575. self.push_attempts[1][2]["notification"]["counts"]["unread"], 0
  576. )
  577. # Send another message
  578. self.helper.send(
  579. room_id, body="How's the weather today?", tok=other_access_token
  580. )
  581. # Advance time and make the push succeed
  582. self.push_attempts[2][0].callback({})
  583. self.pump()
  584. # This push should contain an unread count of 1 as there's now been one
  585. # message since our last read receipt
  586. self.assertEqual(len(self.push_attempts), 3)
  587. self.assertEqual(
  588. self.push_attempts[2][2]["notification"]["counts"]["unread"], 1
  589. )
  590. # Since we're grouping by room, sending more messages shouldn't increase the
  591. # unread count, as they're all being sent in the same room
  592. self.helper.send(room_id, body="Hello?", tok=other_access_token)
  593. # Advance time and make the push succeed
  594. self.pump()
  595. self.push_attempts[3][0].callback({})
  596. self.helper.send(room_id, body="Hello??", tok=other_access_token)
  597. # Advance time and make the push succeed
  598. self.pump()
  599. self.push_attempts[4][0].callback({})
  600. self.helper.send(room_id, body="HELLO???", tok=other_access_token)
  601. # Advance time and make the push succeed
  602. self.pump()
  603. self.push_attempts[5][0].callback({})
  604. self.assertEqual(len(self.push_attempts), 6)