test_photo_command.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. # location-guessing-game-telegram-bot - Telegram Bot Sending Random Wikimedia Commons Photos
  2. #
  3. # Copyright (C) 2021 Fabian Peter Hammerle <fabian@hammerle.me>
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. import collections
  18. import logging
  19. import unittest.mock
  20. import telegram.error
  21. # pylint: disable=import-private-name; tests
  22. from location_guessing_game_telegram_bot import _photo_command
  23. def test_send_photo(caplog, wikimap_photos):
  24. update_mock = unittest.mock.MagicMock()
  25. update_mock.effective_chat.send_photo.return_value.message_id = "photo message id"
  26. context_mock = unittest.mock.MagicMock()
  27. context_mock.bot_data = {"photos": wikimap_photos[:1]}
  28. context_mock.chat_data = {}
  29. http_response_mock = unittest.mock.MagicMock()
  30. with unittest.mock.patch(
  31. "urllib.request.urlopen", return_value=http_response_mock
  32. ) as urlopen_mock, caplog.at_level(logging.INFO):
  33. _photo_command(update=update_mock, context=context_mock)
  34. assert caplog.record_tuples == [
  35. (
  36. "location_guessing_game_telegram_bot",
  37. logging.INFO,
  38. "sending photo https://commons.wikimedia.org/wiki"
  39. "/File:H%C3%BCtteltalkopf_(Venedigergruppe)_from_Tristkopf.jpg",
  40. )
  41. ]
  42. update_mock.effective_chat.send_message.assert_called_once_with(
  43. text="Neues Photo wird ausgewählt und gesendet.", disable_notification=True
  44. )
  45. urlopen_mock.assert_called_once_with(
  46. "https://upload.wikimedia.org/wikipedia/commons/a/ab"
  47. "/H%C3%BCtteltalkopf_%28Venedigergruppe%29_from_Tristkopf.jpg"
  48. )
  49. update_mock.effective_chat.send_photo.assert_called_once_with(
  50. photo=http_response_mock.__enter__(), # pylint: disable=unnecessary-dunder-call
  51. caption="Wo wurde dieses Photo aufgenommen?",
  52. )
  53. assert context_mock.chat_data == {
  54. "last_photo": wikimap_photos[0],
  55. "last_photo_message_id": "photo message id",
  56. }
  57. def test_send_solution_and_next_photo(caplog, wikimap_photos):
  58. update_mock = unittest.mock.MagicMock()
  59. update_mock.effective_chat.send_photo.return_value.message_id = (
  60. "second photo message id"
  61. )
  62. update_mock.effective_chat.id = "chat id for send_location"
  63. context_mock = unittest.mock.MagicMock()
  64. context_mock.bot_data = {"photos": wikimap_photos[1:2]}
  65. context_mock.chat_data = {
  66. "last_photo": wikimap_photos[0],
  67. "last_photo_message_id": "first photo message id",
  68. }
  69. http_response_mock = unittest.mock.MagicMock()
  70. with unittest.mock.patch(
  71. "urllib.request.urlopen", return_value=http_response_mock
  72. ) as urlopen_mock, caplog.at_level(logging.INFO):
  73. _photo_command(update=update_mock, context=context_mock)
  74. assert update_mock.effective_chat.send_message.call_count == 2
  75. assert update_mock.effective_chat.send_message.call_args_list[
  76. 0
  77. ] == unittest.mock.call(
  78. text="Lösung: https://commons.wikimedia.org/wiki"
  79. "/File:H%C3%BCtteltalkopf_(Venedigergruppe)_from_Tristkopf.jpg",
  80. disable_web_page_preview=True,
  81. reply_to_message_id="first photo message id",
  82. )
  83. # update_mock.effective_chat.send_location.assert_called_once_with(
  84. context_mock.bot.send_location.assert_called_once_with(
  85. chat_id="chat id for send_location",
  86. # float comparison? :o
  87. latitude=47.288805,
  88. longitude=12.144116,
  89. disable_notification=True,
  90. )
  91. # next photo:
  92. urlopen_mock.assert_called_once_with(
  93. "https://upload.wikimedia.org/wikipedia/commons/6/65/Gro%C3%9Fvenediger3.JPG"
  94. )
  95. update_mock.effective_chat.send_photo.assert_called_once_with(
  96. photo=http_response_mock.__enter__(), # pylint: disable=unnecessary-dunder-call
  97. caption="Wo wurde dieses Photo aufgenommen?",
  98. )
  99. assert context_mock.chat_data == {
  100. "last_photo": wikimap_photos[1],
  101. "last_photo_message_id": "second photo message id",
  102. }
  103. def test__photo_command_file_size_exceeded(caplog, wikimap_photos):
  104. update_mock = unittest.mock.MagicMock()
  105. update_mock.effective_chat.send_photo.side_effect = [
  106. telegram.error.BadRequest(
  107. 'File "/var/lib/engine/tmpfs_numa0/image.jpeg" of size 42 bytes is too big for a photo'
  108. )
  109. ] * 4 + [
  110. collections.namedtuple("Photo", ["message_id"])(message_id="photo message id"),
  111. ]
  112. context_mock = unittest.mock.MagicMock()
  113. context_mock.bot_data = {"photos": wikimap_photos[:1]}
  114. context_mock.chat_data = {}
  115. http_response_mock = unittest.mock.MagicMock()
  116. with unittest.mock.patch(
  117. "urllib.request.urlopen", return_value=http_response_mock
  118. ) as urlopen_mock, caplog.at_level(logging.INFO):
  119. _photo_command(update=update_mock, context=context_mock)
  120. assert urlopen_mock.call_count == 4 + 1
  121. assert update_mock.effective_chat.send_photo.call_count == 4 + 1
  122. assert len(caplog.records) == 4 * 2 + 1
  123. assert caplog.record_tuples[0::2] == [
  124. (
  125. "location_guessing_game_telegram_bot",
  126. logging.INFO,
  127. "sending photo https://commons.wikimedia.org/wiki"
  128. "/File:H%C3%BCtteltalkopf_(Venedigergruppe)_from_Tristkopf.jpg",
  129. )
  130. ] * (4 + 1)
  131. assert caplog.record_tuples[1::2] == [
  132. (
  133. "location_guessing_game_telegram_bot",
  134. logging.WARNING,
  135. "file size limit exceeded?",
  136. )
  137. ] * (4)
  138. assert context_mock.chat_data == {
  139. "last_photo": wikimap_photos[0],
  140. "last_photo_message_id": "photo message id",
  141. }
  142. def test__photo_command_timeout(caplog, wikimap_photos):
  143. update_mock = unittest.mock.MagicMock()
  144. update_mock.effective_chat.send_photo.side_effect = [
  145. telegram.error.TimedOut
  146. ] * 3 + [
  147. collections.namedtuple("Photo", ["message_id"])(
  148. message_id="photo message id after timeout"
  149. ),
  150. ]
  151. context_mock = unittest.mock.MagicMock()
  152. context_mock.bot_data = {"photos": wikimap_photos[:1]}
  153. context_mock.chat_data = {}
  154. http_response_mock = unittest.mock.MagicMock()
  155. with unittest.mock.patch(
  156. "urllib.request.urlopen", return_value=http_response_mock
  157. ) as urlopen_mock, caplog.at_level(logging.INFO):
  158. _photo_command(update=update_mock, context=context_mock)
  159. assert urlopen_mock.call_count == 3 + 1
  160. assert update_mock.effective_chat.send_photo.call_count == 3 + 1
  161. assert len(caplog.records) == 3 * 2 + 1
  162. assert caplog.record_tuples[1::2] == [
  163. (
  164. "location_guessing_game_telegram_bot",
  165. logging.WARNING,
  166. "timeout",
  167. )
  168. ] * (3)
  169. assert context_mock.chat_data == {
  170. "last_photo": wikimap_photos[0],
  171. "last_photo_message_id": "photo message id after timeout",
  172. }