Skip to content

Commit 451729b

Browse files
committed
streams: Handle adding/removing stream events.
1 parent 0305037 commit 451729b

File tree

2 files changed

+287
-2
lines changed

2 files changed

+287
-2
lines changed

tests/model/test_model.py

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,48 @@ def model(self, mocker, initial_data, user_profile,
4646
model = Model(self.controller)
4747
return model
4848

49+
@pytest.fixture
50+
def initial_pinned_streams(self):
51+
return [{
52+
'name': 'test1',
53+
'id': 101,
54+
'color': '#9af',
55+
'invite_only': False,
56+
'description': 'lets test',
57+
'in_home_view': False
58+
}]
59+
60+
@pytest.fixture
61+
def initial_unpinned_streams(self):
62+
return [{
63+
'name': 'test2',
64+
'id': 100,
65+
'color': '#9af',
66+
'invite_only': False,
67+
'description': 'lets test'
68+
}]
69+
70+
@pytest.fixture
71+
def initial_stream_dict(self):
72+
return {
73+
101: {
74+
'name': 'test1',
75+
'id': 101,
76+
'color': '#9af',
77+
'invite_only': False,
78+
'description': 'lets test',
79+
'in_home_view': False
80+
},
81+
100: {
82+
'name': 'test2',
83+
'id': 100,
84+
'color': '#9af',
85+
'invite_only': False,
86+
'description': 'lets test',
87+
'in_home_view': False
88+
}
89+
}
90+
4991
def test_init(self, model, initial_data, user_profile,
5092
unicode_emojis, custom_emojis, stream_dict):
5193
assert hasattr(model, 'controller')
@@ -2089,6 +2131,213 @@ def test_fetch_custom_emojis(self, mocker, model, custom_emojis,
20892131

20902132
assert fetched_custom_emojis == custom_emojis
20912133

2134+
@pytest.mark.parametrize(['event', 'expected_pinned_streams',
2135+
'expected_unpinned_streams'], [
2136+
(
2137+
{
2138+
'op': 'add',
2139+
'type': 'subscription',
2140+
'subscriptions': [
2141+
{
2142+
'name': 'all',
2143+
'stream_id': 1,
2144+
'description': '',
2145+
'color': '#95a5fd',
2146+
'pin_to_top': False,
2147+
'invite_only': False,
2148+
'in_home_view': True
2149+
}
2150+
]
2151+
},
2152+
[{
2153+
'name': 'test1',
2154+
'id': 101,
2155+
'color': '#9af',
2156+
'invite_only': False,
2157+
'description': 'lets test',
2158+
'in_home_view': False
2159+
}],
2160+
[{
2161+
'name': 'all',
2162+
'id': 1,
2163+
'color': '#9af',
2164+
'invite_only': False,
2165+
'description': ''
2166+
},
2167+
{
2168+
'name': 'test2',
2169+
'id': 100,
2170+
'color': '#9af',
2171+
'invite_only': False,
2172+
'description': 'lets test'
2173+
}]
2174+
),
2175+
(
2176+
{
2177+
'op': 'add',
2178+
'type': 'subscription',
2179+
'subscriptions': [
2180+
{
2181+
'name': 'design',
2182+
'stream_id': 2,
2183+
'description': '',
2184+
'color': '#95a5fd',
2185+
'pin_to_top': True,
2186+
'invite_only': False,
2187+
'in_home_view': True
2188+
}
2189+
]
2190+
},
2191+
[{
2192+
'name': 'design',
2193+
'id': 2,
2194+
'color': '#9af',
2195+
'invite_only': False,
2196+
'description': ''
2197+
},
2198+
{
2199+
'name': 'test1',
2200+
'id': 101,
2201+
'color': '#9af',
2202+
'invite_only': False,
2203+
'description': 'lets test',
2204+
'in_home_view': False,
2205+
'invite_only': False
2206+
}],
2207+
[{
2208+
'name': 'test2',
2209+
'id': 100,
2210+
'color': '#9af',
2211+
'invite_only': False,
2212+
'description': 'lets test'
2213+
}]
2214+
),
2215+
(
2216+
{
2217+
'op': 'add',
2218+
'type': 'subscription',
2219+
'subscriptions': [
2220+
{
2221+
'name': 'all',
2222+
'stream_id': 3,
2223+
'description': '',
2224+
'color': '#95a5fd',
2225+
'pin_to_top': True,
2226+
'invite_only': False,
2227+
'in_home_view': False
2228+
}
2229+
]
2230+
},
2231+
[{
2232+
'name': 'all',
2233+
'id': 3,
2234+
'color': '#9af',
2235+
'invite_only': False,
2236+
'description': ''
2237+
},
2238+
{
2239+
'name': 'test1',
2240+
'id': 101,
2241+
'color': '#9af',
2242+
'invite_only': False,
2243+
'description': 'lets test',
2244+
'in_home_view': False
2245+
}],
2246+
[{
2247+
'name': 'test2',
2248+
'id': 100,
2249+
'color': '#9af',
2250+
'invite_only': False,
2251+
'description': 'lets test'
2252+
}]
2253+
)], ids=[
2254+
'add_1',
2255+
'add_and_pin_2',
2256+
'add_and_mute_3'
2257+
]
2258+
)
2259+
def test__handle_subscription_event_add_stream(
2260+
self, model, mocker,
2261+
event,
2262+
expected_pinned_streams,
2263+
expected_unpinned_streams,
2264+
initial_pinned_streams,
2265+
initial_unpinned_streams
2266+
):
2267+
2268+
model.pinned_streams = deepcopy(initial_pinned_streams)
2269+
model.unpinned_streams = deepcopy(initial_unpinned_streams)
2270+
model._handle_subscription_event(event)
2271+
2272+
assert model.pinned_streams == expected_pinned_streams
2273+
assert model.unpinned_streams == expected_unpinned_streams
2274+
2275+
(model.controller.view.left_panel.update_stream_view
2276+
.assert_called_once_with())
2277+
model.controller.update_screen.assert_called_once_with()
2278+
2279+
@pytest.mark.parametrize(['event', 'expected_pinned_streams',
2280+
'expected_unpinned_streams'], [
2281+
(
2282+
{
2283+
'op': 'remove',
2284+
'type': 'subscription',
2285+
'subscriptions': [{
2286+
'name': 'test1',
2287+
'stream_id': 101
2288+
}]
2289+
},
2290+
[],
2291+
[{
2292+
'name': 'test2',
2293+
'id': 100,
2294+
'color': '#9af',
2295+
'invite_only': False,
2296+
'description': 'lets test'
2297+
}]
2298+
),
2299+
(
2300+
{
2301+
'op': 'remove',
2302+
'type': 'subscription',
2303+
'subscriptions': [{
2304+
'name': 'test2',
2305+
'stream_id': 100
2306+
}]
2307+
},
2308+
[{
2309+
'name': 'test1',
2310+
'id': 101,
2311+
'color': '#9af',
2312+
'invite_only': False,
2313+
'description': 'lets test',
2314+
'in_home_view': False
2315+
}],
2316+
[]
2317+
)], ids=[
2318+
'remove_2',
2319+
'remove_4'
2320+
]
2321+
)
2322+
def test__handle_subscription_event_remove_stream(
2323+
self, model, mocker,
2324+
event,
2325+
expected_pinned_streams,
2326+
expected_unpinned_streams,
2327+
initial_pinned_streams,
2328+
initial_unpinned_streams,
2329+
initial_stream_dict
2330+
):
2331+
model.pinned_streams = deepcopy(initial_pinned_streams)
2332+
model.unpinned_streams = deepcopy(initial_unpinned_streams)
2333+
model.stream_dict = initial_stream_dict
2334+
model._handle_subscription_event(event)
2335+
assert model.pinned_streams == expected_pinned_streams
2336+
assert model.unpinned_streams == expected_unpinned_streams
2337+
update_left_panel = model.controller.view.left_panel.update_stream_view
2338+
update_left_panel.assert_called_once_with()
2339+
model.controller.update_screen.assert_called_once_with()
2340+
20922341
# Use LoopEnder with raising_event to cause the event loop to end without
20932342
# processing the event
20942343
class LoopEnder(Exception):

zulipterminal/model.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,13 +826,41 @@ def _get_stream_by_id(self, streams: List[StreamData], stream_id: int
826826
return stream
827827
raise RuntimeError("Invalid stream id.")
828828

829+
def _unsubscribe_to_streams(self,
830+
stream_info_list: List[Subscription]) -> None:
831+
is_pinned_stream_removed = False
832+
is_unpinned_stream_removed = False
833+
for stream_info in stream_info_list:
834+
stream_id = stream_info['stream_id']
835+
if self.is_stream_in_list(stream_id, self.pinned_streams):
836+
stream = self._get_stream_by_id(self.pinned_streams,
837+
stream_id)
838+
self.pinned_streams.remove(stream)
839+
is_pinned_stream_removed = True
840+
else:
841+
stream = self._get_stream_by_id(self.unpinned_streams,
842+
stream_id)
843+
self.unpinned_streams.remove(stream)
844+
is_unpinned_stream_removed = True
845+
if stream_id in self.muted_streams:
846+
self.muted_streams.remove(stream_id)
847+
848+
if is_pinned_stream_removed:
849+
sort_streams(self.pinned_streams)
850+
if is_unpinned_stream_removed:
851+
sort_streams(self.unpinned_streams)
852+
829853
def _handle_subscription_event(self, event: Event) -> None:
830854
"""
831855
Handle changes in subscription (eg. muting/unmuting,
832856
pinning/unpinning streams)
833857
"""
834858
assert event['type'] == "subscription"
835859

860+
def _update_sidebar() -> None:
861+
self.controller.view.left_panel.update_stream_view()
862+
self.controller.update_screen()
863+
836864
if event['op'] == 'update':
837865
if hasattr(self.controller, 'view'):
838866
if event.get('property', None) == 'in_home_view':
@@ -875,8 +903,16 @@ def _handle_subscription_event(self, event: Event) -> None:
875903
self.unpinned_streams.append(stream)
876904
sort_streams(self.unpinned_streams)
877905
sort_streams(self.pinned_streams)
878-
self.controller.view.left_panel.update_stream_view()
879-
self.controller.update_screen()
906+
_update_sidebar()
907+
908+
elif event['op'] == 'add':
909+
self._subscribe_to_streams(event['subscriptions'])
910+
_update_sidebar()
911+
912+
elif event['op'] == 'remove':
913+
self._unsubscribe_to_streams(event['subscriptions'])
914+
_update_sidebar()
915+
880916
elif event['op'] in ('peer_add', 'peer_remove'):
881917
# NOTE: ZFL 35 commit was not atomic with API change
882918
# (ZFL >=35 can use new plural style)

0 commit comments

Comments
 (0)