mirror of https://github.com/zulip/zulip.git
webhooks/beeminder: Mock time.time() to avoid race.
Rewritten in significant part by tabbott to actually be correct. One particularly nasty thing the original webhook integration did is do `current_time = time.time()` at the top of the `view.py` function -- that means that code ran at import time, not runtime.
This commit is contained in:
parent
713ca1e5f2
commit
7c830c5767
|
@ -1,40 +1,42 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import time
|
||||
|
||||
from typing import Text
|
||||
from unittest.mock import patch
|
||||
from typing import Text, Any
|
||||
from zerver.lib.test_classes import WebhookTestCase
|
||||
|
||||
class BeeminderHookTests(WebhookTestCase):
|
||||
STREAM_NAME = 'beeminder'
|
||||
URL_TEMPLATE = u"/api/v1/external/beeminder?api_key={api_key}&email=AARON@zulip.com"
|
||||
|
||||
def test_beeminder_derail(self) -> None:
|
||||
# Important: These checks need to be in the test to avoid a race.
|
||||
# TODO: We should mock time.time for these tests
|
||||
current_time = float(time.time())
|
||||
time_delta_in_hours = (float(1517759100) - current_time)/float(3600)
|
||||
|
||||
@patch('zerver.webhooks.beeminder.view.time.time')
|
||||
def test_beeminder_derail(self, time: Any) -> None:
|
||||
time.return_value = 1517739100 # 5.6 hours from fixture value
|
||||
expected_subject = u"beekeeper"
|
||||
expected_message = u"Hello **aaron**! I am the Beeminder bot! :octopus: \n You are going to derail \
|
||||
from goal **gainweight** in **{:0.1f} hours** \n You need **+2 in 7 days (60)** to avoid derailing \n * Pledge: **0$** :relieved:".format(time_delta_in_hours)
|
||||
expected_message = '\n'.join([
|
||||
'Hello **aaron**! I am the Beeminder bot! :octopus:',
|
||||
' You are going to derail from goal **gainweight** in **{:0.1f} hours**'.format(5.6),
|
||||
' You need **+2 in 7 days (60)** to avoid derailing',
|
||||
' * Pledge: **0$** :relieved:'
|
||||
])
|
||||
|
||||
self.send_and_test_stream_message('derail',
|
||||
expected_subject,
|
||||
expected_message,
|
||||
content_type="application/x-www-form-urlencoded")
|
||||
|
||||
def test_beeminder_derail_pm(self) -> None:
|
||||
# Important: These checks need to be in the test to avoid a race.
|
||||
# TODO: We should mock time.time for these tests
|
||||
current_time = float(time.time())
|
||||
time_delta_in_hours = (float(1517759100) - current_time)/float(3600)
|
||||
|
||||
@patch('zerver.webhooks.beeminder.view.time.time')
|
||||
def test_beeminder_derail_pm(self, time: Any) -> None:
|
||||
time.return_value = 1517739100 # 5.6 hours from fixture value
|
||||
self.url = self.build_webhook_url(
|
||||
email="AARON@zulip.com",
|
||||
username="aaron",
|
||||
user_ip="127.0.0.1"
|
||||
)
|
||||
expected_message = u"I am the Beeminder bot! :octopus: \n You are going to derail from \
|
||||
goal **gainweight** in **{:0.1f} hours** \n You need **+2 in 7 days (60)** to avoid derailing \n * Pledge: **5$**:worried:".format(time_delta_in_hours)
|
||||
expected_message = '\n'.join([
|
||||
'I am the Beeminder bot! :octopus:',
|
||||
' You are going to derail from goal **gainweight** in **{:0.1f} hours**'.format(5.6),
|
||||
' You need **+2 in 7 days (60)** to avoid derailing',
|
||||
' * Pledge: **5$**:worried:'
|
||||
])
|
||||
self.send_and_test_private_message('derail_pm',
|
||||
expected_message,
|
||||
content_type="application/json")
|
||||
|
|
|
@ -7,13 +7,17 @@ from zerver.lib.request import REQ, has_request_variables
|
|||
from zerver.lib.response import json_success
|
||||
from zerver.models import UserProfile, get_user_profile_by_email
|
||||
import time
|
||||
current_time = time.time()
|
||||
|
||||
def get_user_name(email: str) -> str:
|
||||
profile = get_user_profile_by_email(email)
|
||||
name = profile.short_name
|
||||
return name
|
||||
|
||||
def get_time(payload: Dict[str, Any]) -> Any:
|
||||
losedate = payload["goal"]["losedate"]
|
||||
time_remaining = (losedate - time.time())/3600
|
||||
return time_remaining
|
||||
|
||||
@api_key_only_webhook_view("beeminder")
|
||||
@has_request_variables
|
||||
def api_beeminder_webhook(request: HttpRequest, user_profile: UserProfile,
|
||||
|
@ -24,10 +28,9 @@ def api_beeminder_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
|
||||
secret = payload["goal"]["secret"]
|
||||
goal_name = payload["goal"]["slug"]
|
||||
losedate = payload["goal"]["losedate"]
|
||||
limsum = payload["goal"]["limsum"]
|
||||
pledge = payload["goal"]["pledge"]
|
||||
time_remain = (losedate - current_time)/3600 # time in hours
|
||||
time_remain = get_time(payload) # time in hours
|
||||
# To show user's probable reaction by looking at pledge amount
|
||||
if pledge > 0:
|
||||
expression = ':worried:'
|
||||
|
@ -36,10 +39,9 @@ def api_beeminder_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
|
||||
if not secret:
|
||||
# In this case notifications will be sent to stream
|
||||
|
||||
name = get_user_name(email)
|
||||
body = u"Hello **{}**! I am the Beeminder bot! :octopus: \n You are going to derail \
|
||||
from goal **{}** in **{:0.1f} hours** \n You need **{}** to avoid derailing \n * Pledge: **{}$** {}"
|
||||
body = u"Hello **{}**! I am the Beeminder bot! :octopus:\n You are going to derail \
|
||||
from goal **{}** in **{:0.1f} hours**\n You need **{}** to avoid derailing\n * Pledge: **{}$** {}"
|
||||
body = body.format(name, goal_name, time_remain, limsum, pledge, expression)
|
||||
check_send_stream_message(user_profile, request.client, stream, topic, body)
|
||||
return json_success()
|
||||
|
@ -47,8 +49,8 @@ def api_beeminder_webhook(request: HttpRequest, user_profile: UserProfile,
|
|||
else:
|
||||
# In this case PM will be sent to user
|
||||
p = get_user_profile_by_email(email)
|
||||
body = u"I am the Beeminder bot! :octopus: \n You are going to derail from \
|
||||
goal **{}** in **{:0.1f} hours** \n You need **{}** to avoid derailing \n * Pledge: **{}$**{}"
|
||||
body = u"I am the Beeminder bot! :octopus:\n You are going to derail from \
|
||||
goal **{}** in **{:0.1f} hours**\n You need **{}** to avoid derailing\n * Pledge: **{}$**{}"
|
||||
body = body.format(goal_name, time_remain, limsum, pledge, expression)
|
||||
check_send_private_message(user_profile, request.client, p, body)
|
||||
return json_success()
|
||||
|
|
Loading…
Reference in New Issue