Skip to content

Commit 3ed143e

Browse files
committed
model: Fetch and store custom emojis.
* Fetch custom emojis from server which can be used be the user using typeahead. * Model tests amended. * New fixture and test added for custom emojis. Minor note: The emojis are being sorted twice here, once when unicode emojis are stored in the file using the script ( which happens occasionally when it is manually updated ) and again after custom emojis are fetched ( which happens during every load ). The first sorting seems pointless, at first glance, but it improves sorting time since sorted() uses Timsort that can perform better if subsequences of the data are already sorted.
1 parent 5a78f8d commit 3ed143e

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

tests/conftest.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,15 @@ def streams_fixture():
177177
return deepcopy(streams)
178178

179179

180+
@pytest.fixture
181+
def custom_emojis():
182+
return OrderedDict([
183+
('urwid', {'code': '100', 'type': 'realm_emoji'}),
184+
('dancing', {'code': '3', 'type': 'realm_emoji'}),
185+
('snape', {'code': '20', 'type': 'realm_emoji'}),
186+
])
187+
188+
180189
@pytest.fixture
181190
def unicode_emojis():
182191
return OrderedDict([

tests/model/test_model.py

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
from collections import OrderedDict
23
from copy import deepcopy
34
from typing import Any
45

@@ -23,7 +24,7 @@ def mock_external_classes(self, mocker: Any) -> None:
2324

2425
@pytest.fixture
2526
def model(self, mocker, initial_data, user_profile,
26-
unicode_emojis):
27+
unicode_emojis, custom_emojis):
2728
mocker.patch('zulipterminal.model.Model.get_messages',
2829
return_value='')
2930
self.client.register.return_value = initial_data
@@ -39,11 +40,13 @@ def model(self, mocker, initial_data, user_profile,
3940
self.client.get_profile.return_value = user_profile
4041
mocker.patch('zulipterminal.model.emoji_data',
4142
EMOJI_DATA=unicode_emojis)
43+
mocker.patch('zulipterminal.model.Model.fetch_custom_emojis',
44+
return_value=custom_emojis)
4245
model = Model(self.controller)
4346
return model
4447

4548
def test_init(self, model, initial_data, user_profile,
46-
unicode_emojis):
49+
unicode_emojis, custom_emojis):
4750
assert hasattr(model, 'controller')
4851
assert hasattr(model, 'client')
4952
assert model.narrow == []
@@ -73,7 +76,11 @@ def test_init(self, model, initial_data, user_profile,
7376
assert model.unpinned_streams == []
7477
self.classify_unread_counts.assert_called_once_with(model)
7578
assert model.unread_counts == []
76-
assert model.emoji_data == unicode_emojis
79+
assert unicode_emojis.items() <= model.emoji_data.items()
80+
assert custom_emojis.items() <= model.emoji_data.items()
81+
print(model.emoji_data)
82+
assert model.emoji_data == OrderedDict(sorted(
83+
model.emoji_data.items(), key=lambda e: e[0]))
7784

7885
def test_init_InvalidAPIKey_response(self, mocker, initial_data):
7986
# Both network calls indicate the same response
@@ -1530,3 +1537,47 @@ def test_is_muted_topic(self, topic, is_muted, stream_dict, model):
15301537
]
15311538
assert model.is_muted_topic(stream_id=topic[0],
15321539
topic=topic[1]) == is_muted
1540+
1541+
@pytest.mark.parametrize('response', [
1542+
{
1543+
'emoji': {
1544+
'100': {
1545+
'author_id': 5,
1546+
'deactivated': False,
1547+
'id': '100',
1548+
'name': 'urwid',
1549+
'source_url': '/user_avatars/1/emoji/images/1.png'
1550+
},
1551+
'20': {
1552+
'author_id': 10,
1553+
'deactivated': False,
1554+
'id': '20',
1555+
'name': 'snape',
1556+
'source_url': '/user_avatars/2/emoji/images/2.png'
1557+
},
1558+
'3': {
1559+
'author_id': 5,
1560+
'deactivated': False,
1561+
'id': '3',
1562+
'name': 'dancing',
1563+
'source_url': '/user_avatars/3/emoji/images/3.png'
1564+
},
1565+
'81': {
1566+
'author_id': 5,
1567+
'deactivated': True,
1568+
'id': '81',
1569+
'name': 'green_tick',
1570+
'source_url': '/user_avatars/4/emoji/images/4.png'
1571+
},
1572+
},
1573+
'msg': '',
1574+
'result': 'success'
1575+
}
1576+
])
1577+
def test_fetch_custom_emojis(self, mocker, model, custom_emojis,
1578+
response):
1579+
self.client.get_realm_emoji.return_value = response
1580+
1581+
fetched_custom_emojis = model.fetch_custom_emojis()
1582+
1583+
assert fetched_custom_emojis == custom_emojis

zulipterminal/model.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,11 @@ def __init__(self, controller: Any) -> None:
126126
self.unread_counts = classify_unread_counts(self)
127127

128128
self.fetch_all_topics(workers=5)
129-
self.emoji_data = emoji_data.EMOJI_DATA
129+
130+
custom_emojis = self.fetch_custom_emojis()
131+
all_emojis = (list(emoji_data.EMOJI_DATA.items())
132+
+ list(custom_emojis.items()))
133+
self.emoji_data = OrderedDict(sorted(all_emojis, key=lambda e: e[0]))
130134

131135
self.new_user_input = True
132136
self._start_presence_updates()
@@ -337,6 +341,15 @@ def update_stream_message(self, topic: str, msg_id: int,
337341
response = self.client.update_message(request)
338342
return response['result'] == 'success'
339343

344+
def fetch_custom_emojis(self) -> Dict[str, Dict[str, str]]:
345+
response = self.client.get_realm_emoji()
346+
custom_emojis = {}
347+
for emoji_code, emoji in response['emoji'].items():
348+
if not emoji['deactivated']:
349+
custom_emojis[emoji['name']] = {'code': emoji_code,
350+
'type': 'realm_emoji'}
351+
return custom_emojis
352+
340353
def get_messages(self, *,
341354
num_after: int, num_before: int,
342355
anchor: Optional[int]) -> str:

0 commit comments

Comments
 (0)