Skip to content

Commit 7e94ba0

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 python's sorted() function uses Timsort that can perform better if subsequences of the data are already sorted.
1 parent 7b641e4 commit 7e94ba0

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 typing import Any
34

45
import pytest
@@ -22,7 +23,7 @@ def mock_external_classes(self, mocker: Any) -> None:
2223

2324
@pytest.fixture
2425
def model(self, mocker, initial_data, user_profile,
25-
unicode_emojis):
26+
unicode_emojis, custom_emojis):
2627
mocker.patch('zulipterminal.model.Model.get_messages',
2728
return_value='')
2829
self.client.register.return_value = initial_data
@@ -38,11 +39,13 @@ def model(self, mocker, initial_data, user_profile,
3839
self.client.get_profile.return_value = user_profile
3940
mocker.patch('zulipterminal.model.emoji_data',
4041
EMOJI_DATA=unicode_emojis)
42+
mocker.patch('zulipterminal.model.Model.fetch_custom_emojis',
43+
return_value=custom_emojis)
4144
model = Model(self.controller)
4245
return model
4346

4447
def test_init(self, model, initial_data, user_profile,
45-
unicode_emojis):
48+
unicode_emojis, custom_emojis):
4649
assert hasattr(model, 'controller')
4750
assert hasattr(model, 'client')
4851
assert model.msg_view is None
@@ -74,7 +77,11 @@ def test_init(self, model, initial_data, user_profile,
7477
assert model.unpinned_streams == []
7578
self.classify_unread_counts.assert_called_once_with(model)
7679
assert model.unread_counts == []
77-
assert model.emoji_data == unicode_emojis
80+
assert unicode_emojis.items() <= model.emoji_data.items()
81+
assert custom_emojis.items() <= model.emoji_data.items()
82+
print(model.emoji_data)
83+
assert model.emoji_data == OrderedDict(sorted(
84+
model.emoji_data.items(), key=lambda e: e[0]))
7885

7986
def test_init_InvalidAPIKey_response(self, mocker, initial_data):
8087
# Both network calls indicate the same response
@@ -1452,3 +1459,47 @@ def test_is_muted_topic(self, topic, is_muted, stream_dict, model):
14521459
]
14531460
assert model.is_muted_topic(stream_id=topic[0],
14541461
topic=topic[1]) == is_muted
1462+
1463+
@pytest.mark.parametrize('response', [
1464+
{
1465+
'emoji': {
1466+
'100': {
1467+
'author_id': 5,
1468+
'deactivated': False,
1469+
'id': '100',
1470+
'name': 'urwid',
1471+
'source_url': '/user_avatars/1/emoji/images/1.png'
1472+
},
1473+
'20': {
1474+
'author_id': 10,
1475+
'deactivated': False,
1476+
'id': '20',
1477+
'name': 'snape',
1478+
'source_url': '/user_avatars/2/emoji/images/2.png'
1479+
},
1480+
'3': {
1481+
'author_id': 5,
1482+
'deactivated': False,
1483+
'id': '3',
1484+
'name': 'dancing',
1485+
'source_url': '/user_avatars/3/emoji/images/3.png'
1486+
},
1487+
'81': {
1488+
'author_id': 5,
1489+
'deactivated': True,
1490+
'id': '81',
1491+
'name': 'green_tick',
1492+
'source_url': '/user_avatars/4/emoji/images/4.png'
1493+
},
1494+
},
1495+
'msg': '',
1496+
'result': 'success'
1497+
}
1498+
])
1499+
def test_fetch_custom_emojis(self, mocker, model, custom_emojis,
1500+
response):
1501+
self.client.get_realm_emoji.return_value = response
1502+
1503+
fetched_custom_emojis = model.fetch_custom_emojis()
1504+
1505+
assert fetched_custom_emojis == custom_emojis

zulipterminal/model.py

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

123123
self.fetch_all_topics(workers=5)
124-
self.emoji_data = emoji_data.EMOJI_DATA
124+
125+
custom_emojis = self.fetch_custom_emojis()
126+
all_emojis = (list(emoji_data.EMOJI_DATA.items())
127+
+ list(custom_emojis.items()))
128+
self.emoji_data = OrderedDict(sorted(all_emojis, key=lambda e: e[0]))
125129

126130
self.new_user_input = True
127131
self._start_presence_updates()
@@ -332,6 +336,15 @@ def update_stream_message(self, topic: str, msg_id: int,
332336
response = self.client.update_message(request)
333337
return response['result'] == 'success'
334338

339+
def fetch_custom_emojis(self) -> Dict[str, Dict[str, str]]:
340+
response = self.client.get_realm_emoji()
341+
custom_emojis = {}
342+
for emoji_code, emoji in response['emoji'].items():
343+
if not emoji['deactivated']:
344+
custom_emojis[emoji['name']] = {'code': emoji_code,
345+
'type': 'realm_emoji'}
346+
return custom_emojis
347+
335348
def get_messages(self, *,
336349
num_after: int, num_before: int,
337350
anchor: Optional[int]) -> str:

0 commit comments

Comments
 (0)