Skip to content

Commit 827ef2c

Browse files
committed
widget: Add process_poll_widget function.
Added process_poll_widget function to process submessages containing a poll widget. Returns the question of the poll along with options and their voters in a dict.
1 parent d88adae commit 827ef2c

File tree

2 files changed

+363
-1
lines changed

2 files changed

+363
-1
lines changed

tests/widget/test_widget.py

Lines changed: 321 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
import pytest
44
from pytest import param as case
55

6-
from zulipterminal.widget import Submessage, find_widget_type, process_todo_widget
6+
from zulipterminal.widget import (
7+
Submessage,
8+
find_widget_type,
9+
process_poll_widget,
10+
process_todo_widget,
11+
)
712

813

914
@pytest.mark.parametrize(
@@ -343,3 +348,318 @@ def test_process_todo_widget(
343348

344349
assert title == expected_title
345350
assert tasks == expected_tasks
351+
352+
353+
@pytest.mark.parametrize(
354+
"submessage, expected_poll_question, expected_options",
355+
[
356+
case(
357+
[
358+
{
359+
"id": 12082,
360+
"message_id": 1957499,
361+
"sender_id": 27294,
362+
"msg_type": "widget",
363+
"content": (
364+
'{"widget_type": "poll", "extra_data": {'
365+
'"question": "Do polls work on ZT?", "options": ["Yes", "No"]}}'
366+
),
367+
},
368+
{
369+
"id": 12083,
370+
"message_id": 1957499,
371+
"sender_id": 27294,
372+
"msg_type": "widget",
373+
"content": '{"type":"vote","key":"canned,0","vote":1}',
374+
},
375+
{
376+
"id": 12084,
377+
"message_id": 1957499,
378+
"sender_id": 27294,
379+
"msg_type": "widget",
380+
"content": '{"type":"vote","key":"canned,0","vote":-1}',
381+
},
382+
{
383+
"id": 12085,
384+
"message_id": 1957499,
385+
"sender_id": 27294,
386+
"msg_type": "widget",
387+
"content": '{"type":"vote","key":"canned,1","vote":1}',
388+
},
389+
{
390+
"id": 12086,
391+
"message_id": 1957499,
392+
"sender_id": 27294,
393+
"msg_type": "widget",
394+
"content": '{"type":"vote","key":"canned,0","vote":1}',
395+
},
396+
{
397+
"id": 12087,
398+
"message_id": 1957499,
399+
"sender_id": 27294,
400+
"msg_type": "widget",
401+
"content": '{"type":"vote","key":"canned,1","vote":-1}',
402+
},
403+
],
404+
"Do polls work on ZT?",
405+
{
406+
"canned,0": {"option": "Yes", "votes": [27294]},
407+
"canned,1": {"option": "No", "votes": []},
408+
},
409+
id="poll_widget_with_votes",
410+
),
411+
case(
412+
[
413+
{
414+
"id": 12089,
415+
"message_id": 1957662,
416+
"sender_id": 27294,
417+
"msg_type": "widget",
418+
"content": (
419+
'{"widget_type": "poll", "extra_data": {"question": "Is '
420+
'this a poll with options added later?", '
421+
'"options": ["Yes", "No"]}}'
422+
),
423+
},
424+
{
425+
"id": 12090,
426+
"message_id": 1957662,
427+
"sender_id": 27294,
428+
"msg_type": "widget",
429+
"content": '{"type":"new_option","idx":1,"option":"Maybe"}',
430+
},
431+
{
432+
"id": 12091,
433+
"message_id": 1957662,
434+
"sender_id": 27294,
435+
"msg_type": "widget",
436+
"content": '{"type":"vote","key":"canned,1","vote":1}',
437+
},
438+
{
439+
"id": 12092,
440+
"message_id": 1957662,
441+
"sender_id": 27294,
442+
"msg_type": "widget",
443+
"content": '{"type":"vote","key":"canned,1","vote":-1}',
444+
},
445+
{
446+
"id": 12093,
447+
"message_id": 1957662,
448+
"sender_id": 27294,
449+
"msg_type": "widget",
450+
"content": '{"type":"vote","key":"27294,1","vote":1}',
451+
},
452+
{
453+
"id": 12094,
454+
"message_id": 1957662,
455+
"sender_id": 27294,
456+
"msg_type": "widget",
457+
"content": '{"type":"vote","key":"canned,0","vote":1}',
458+
},
459+
],
460+
"Is this a poll with options added later?",
461+
{
462+
"canned,0": {"option": "Yes", "votes": [27294]},
463+
"canned,1": {"option": "No", "votes": []},
464+
"27294,1": {"option": "Maybe", "votes": [27294]},
465+
},
466+
id="poll_widget_with_new_option_and_votes",
467+
),
468+
case(
469+
[
470+
{
471+
"id": 12095,
472+
"message_id": 1957682,
473+
"sender_id": 27294,
474+
"msg_type": "widget",
475+
"content": (
476+
'{"widget_type": "poll", "extra_data": {"question": '
477+
'"Let\'s change this question later?", "options": ["Yes"]}}'
478+
),
479+
},
480+
{
481+
"id": 12096,
482+
"message_id": 1957682,
483+
"sender_id": 27294,
484+
"msg_type": "widget",
485+
"content": '{"type":"vote","key":"canned,0","vote":1}',
486+
},
487+
{
488+
"id": 12097,
489+
"message_id": 1957682,
490+
"sender_id": 27294,
491+
"msg_type": "widget",
492+
"content": '{"type":"new_option","idx":1,"option":"No"}',
493+
},
494+
{
495+
"id": 12098,
496+
"message_id": 1957682,
497+
"sender_id": 27294,
498+
"msg_type": "widget",
499+
"content": '{"type":"vote","key":"canned,0","vote":-1}',
500+
},
501+
{
502+
"id": 12099,
503+
"message_id": 1957682,
504+
"sender_id": 27294,
505+
"msg_type": "widget",
506+
"content": '{"type":"question",'
507+
'"question":"Has this question stayed the same?"}',
508+
},
509+
{
510+
"id": 12100,
511+
"message_id": 1957682,
512+
"sender_id": 27294,
513+
"msg_type": "widget",
514+
"content": '{"type":"vote","key":"27294,1","vote":1}',
515+
},
516+
],
517+
"Has this question stayed the same?",
518+
{
519+
"canned,0": {"option": "Yes", "votes": []},
520+
"27294,1": {"option": "No", "votes": [27294]},
521+
},
522+
id="poll_widget_with_new_question_and_votes",
523+
),
524+
case(
525+
[
526+
{
527+
"id": 12101,
528+
"message_id": 1957693,
529+
"sender_id": 27294,
530+
"msg_type": "widget",
531+
"content": (
532+
'{"widget_type": "poll", "extra_data": {"question": "",'
533+
' "options": ["Yes", "No"]}}'
534+
),
535+
}
536+
],
537+
"",
538+
{
539+
"canned,0": {"option": "Yes", "votes": []},
540+
"canned,1": {"option": "No", "votes": []},
541+
},
542+
id="poll_widget_with_empty_question",
543+
),
544+
case(
545+
[
546+
{
547+
"id": 12102,
548+
"message_id": 1957700,
549+
"sender_id": 27294,
550+
"msg_type": "widget",
551+
"content": (
552+
'{"widget_type": "poll", "extra_data": {'
553+
'"question": "Does this poll have options?", "options": []}}'
554+
),
555+
}
556+
],
557+
"Does this poll have options?",
558+
{},
559+
id="poll_widget_with_empty_options",
560+
),
561+
case(
562+
[
563+
{
564+
"id": 12112,
565+
"message_id": 1957722,
566+
"sender_id": 27294,
567+
"msg_type": "widget",
568+
"content": (
569+
'{"widget_type": "poll", "extra_data": {"question": "",'
570+
' "options": []}}'
571+
),
572+
}
573+
],
574+
"",
575+
{},
576+
id="poll_widget_with_empty_question_and_options",
577+
),
578+
case(
579+
[
580+
{
581+
"id": 12103,
582+
"message_id": 1957719,
583+
"sender_id": 27294,
584+
"msg_type": "widget",
585+
"content": (
586+
'{"widget_type": "poll", "extra_data": {"question": "Does'
587+
' this poll have multiple voters?", "options": ["Yes", "No"]}}'
588+
),
589+
},
590+
{
591+
"id": 12104,
592+
"message_id": 1957719,
593+
"sender_id": 27294,
594+
"msg_type": "widget",
595+
"content": '{"type":"vote","key":"canned,0","vote":1}',
596+
},
597+
{
598+
"id": 12105,
599+
"message_id": 1957719,
600+
"sender_id": 27294,
601+
"msg_type": "widget",
602+
"content": '{"type":"vote","key":"canned,1","vote":1}',
603+
},
604+
{
605+
"id": 12106,
606+
"message_id": 1957719,
607+
"sender_id": 27294,
608+
"msg_type": "widget",
609+
"content": '{"type":"vote","key":"canned,0","vote":-1}',
610+
},
611+
{
612+
"id": 12107,
613+
"message_id": 1957719,
614+
"sender_id": 32159,
615+
"msg_type": "widget",
616+
"content": '{"type":"new_option","idx":1,"option":"Maybe"}',
617+
},
618+
{
619+
"id": 12108,
620+
"message_id": 1957719,
621+
"sender_id": 32159,
622+
"msg_type": "widget",
623+
"content": '{"type":"vote","key":"32159,1","vote":1}',
624+
},
625+
{
626+
"id": 12109,
627+
"message_id": 1957719,
628+
"sender_id": 32159,
629+
"msg_type": "widget",
630+
"content": '{"type":"vote","key":"canned,0","vote":1}',
631+
},
632+
{
633+
"id": 12110,
634+
"message_id": 1957719,
635+
"sender_id": 27294,
636+
"msg_type": "widget",
637+
"content": '{"type":"vote","key":"canned,1","vote":-1}',
638+
},
639+
{
640+
"id": 12111,
641+
"message_id": 1957719,
642+
"sender_id": 27294,
643+
"msg_type": "widget",
644+
"content": '{"type":"vote","key":"canned,0","vote":1}',
645+
},
646+
],
647+
"Does this poll have multiple voters?",
648+
{
649+
"canned,0": {"option": "Yes", "votes": [32159, 27294]},
650+
"canned,1": {"option": "No", "votes": []},
651+
"32159,1": {"option": "Maybe", "votes": [32159]},
652+
},
653+
id="poll_widget_with_multiple_voters",
654+
),
655+
],
656+
)
657+
def test_process_poll_widget(
658+
submessage: List[Submessage],
659+
expected_poll_question: str,
660+
expected_options: Dict[str, Dict[str, Union[str, List[str]]]],
661+
) -> None:
662+
poll_question, options = process_poll_widget(submessage)
663+
664+
assert poll_question == expected_poll_question
665+
assert options == expected_options

zulipterminal/widget.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,45 @@ def process_todo_widget(
7474
title = widget["title"]
7575

7676
return title, tasks
77+
78+
79+
def process_poll_widget(
80+
poll_content: List[Submessage],
81+
) -> Tuple[str, Dict[str, Dict[str, Union[str, List[str]]]]]:
82+
poll_question = ""
83+
options = {}
84+
85+
for entry in poll_content:
86+
content = entry["content"]
87+
sender_id = entry["sender_id"]
88+
msg_type = entry["msg_type"]
89+
90+
if msg_type == "widget" and isinstance(content, str):
91+
widget = json.loads(content)
92+
93+
if widget.get("widget_type") == "poll":
94+
poll_question = widget["extra_data"]["question"]
95+
for i, option in enumerate(widget["extra_data"]["options"]):
96+
option_id = f"canned,{i}"
97+
options[option_id] = {"option": option, "votes": []}
98+
99+
elif widget.get("type") == "question":
100+
poll_question = widget["question"]
101+
102+
elif widget.get("type") == "vote":
103+
option_id = widget["key"]
104+
vote_type = widget["vote"]
105+
106+
if option_id in options:
107+
if vote_type == 1 and sender_id not in options[option_id]["votes"]:
108+
options[option_id]["votes"].append(sender_id)
109+
elif vote_type == -1 and sender_id in options[option_id]["votes"]:
110+
options[option_id]["votes"].remove(sender_id)
111+
112+
elif widget.get("type") == "new_option":
113+
idx = widget["idx"]
114+
new_option = widget["option"]
115+
option_id = f"{sender_id},{idx}"
116+
options[option_id] = {"option": new_option, "votes": []}
117+
118+
return poll_question, options

0 commit comments

Comments
 (0)