Skip to content

Commit 752010c

Browse files
committed
test(ChannelList): assert removed channels are evicted from activeChannels (#2599)
Regression test for #2599: removing the current user from a channel must evict it from client.activeChannels, otherwise recoverState() re-watches it on the next reconnect (recoverStateOnReconnect defaults to true) and the list resurrects it. The eviction itself lives in stream-chat core (GetStream/stream-chat-js#1788). This test is red until that fix ships in a stream-chat release and the dependency here is bumped to it; the bump + green run will accompany closing #2599.
1 parent d5d874b commit 752010c

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

src/components/ChannelList/__tests__/ChannelList.test.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,47 @@ describe('ChannelList', () => {
14691469
const results = await axe(container);
14701470
expect(results).toHaveNoViolations();
14711471
});
1472+
1473+
// Regression: #2599. Removing the current user from a channel must evict it
1474+
// from `client.activeChannels`. Otherwise the channel lingers there and, on
1475+
// reconnect, `recoverState()` re-watches it (`recoverStateOnReconnect` defaults
1476+
// to `true`, so `usePaginatedChannels` does not re-query and relies on core
1477+
// recovery) - channel events then resume and the list resurrects it. The
1478+
// eviction itself lives in stream-chat core (`StreamChat._handleClientEvent`);
1479+
// this test guards that the behaviour ChannelList depends on stays in place.
1480+
it('evicts the removed channel from client.activeChannels so reconnect cannot re-watch it (#2599)', async () => {
1481+
const { getByRole, getByTestId } = await render(
1482+
<Chat client={chatClient}>
1483+
<WithComponents
1484+
overrides={{
1485+
ChannelListItemUI: ChannelPreviewComponent,
1486+
ChannelListUI: ChannelListComponent,
1487+
}}
1488+
>
1489+
<ChannelList {...channelListProps} />
1490+
</WithComponents>
1491+
</Chat>,
1492+
);
1493+
await waitFor(() => {
1494+
expect(getByRole('list')).toBeInTheDocument();
1495+
});
1496+
1497+
const { cid } = testChannel3.channel;
1498+
const removedNode = getByTestId(testChannel3.channel.id);
1499+
// precondition: the loaded channel is tracked by the client
1500+
expect(chatClient.activeChannels[cid]).toBeDefined();
1501+
1502+
act(() =>
1503+
dispatchNotificationRemovedFromChannel(chatClient, testChannel3.channel),
1504+
);
1505+
1506+
await waitFor(() => {
1507+
expect(removedNode).not.toBeInTheDocument();
1508+
});
1509+
// the channel must no longer be tracked, otherwise `recoverState()` would
1510+
// re-watch it on the next reconnect and bring it back into the list
1511+
expect(chatClient.activeChannels[cid]).toBeUndefined();
1512+
});
14721513
});
14731514

14741515
describe('channel.updated', () => {

0 commit comments

Comments
 (0)