Skip to content

Commit f964523

Browse files
committed
refactor(tests): annotate high-traffic component tests
Type annotations for 21 component test files. No behavior changes — only type imports, describe-scope `let` declarations, context-value casts via the established `as unknown as ContextValue` pattern, and narrow casts at SDK-type access points. - Channel/__tests__/{Channel,ownCapabilities,useMessageListPagination, isAttachmentEqualHandler}.test.tsx - ChannelList/__tests__/{ChannelList,ChannelListView}.test.tsx - ChannelPreview/__tests__/ChannelPreviewView.test.tsx - Chat/__tests__/Chat.test.tsx - Message/MessageItemView/__tests__/{Message,MessageAuthor, MessageContent,MessageItemView,MessagePinnedHeader,MessageReplies, MessageStatus,MessageTextContainer,ReactionListBottom, ReactionListTop}.test.tsx - MessageList/__tests__/{MessageList,ScrollToBottomButton}.test.tsx - Thread/__tests__/Thread.test.tsx Conventions applied: - `let client: StreamChat; let channel: Channel;` at describe scope. - `{...} as unknown as ChannelContextValue` (or `ChatContextValue`, `MessagesContextValue`, etc.) for partial context mocks — matches `components/MessageList/__tests__/useMessageList.test.tsx:35,43`. - `MessageResponse` → `LocalMessage` via small local `toLocalMessage` helper where needed; SDK's `formatMessage` isn't used because it requires a configured Channel. - `ComponentProps<typeof X>` for `renderComponent({ props })` args. - Numeric `id`s in mock-builder calls fixed to string. Pre-existing latent test bug noted: `MessageStatus.test.tsx` used `it.each('string', fn)` (malformed — string iterated as chars). Converted to `it.skip` to preserve pre-migration runtime behavior (the test body never executed) and filed as future work to fix the test properly. Takes test:typecheck 437 → 227 (−210). Full test suite: same pre-existing SQLite-isolation flake in offline-support; no regressions.
1 parent 0be246a commit f964523

21 files changed

Lines changed: 700 additions & 403 deletions

package/src/components/Channel/__tests__/Channel.test.tsx

Lines changed: 144 additions & 90 deletions
Large diffs are not rendered by default.

package/src/components/Channel/__tests__/isAttachmentEqualHandler.test.tsx

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React from 'react';
33
import { Text } from 'react-native';
44

55
import { act, cleanup, render, waitFor } from '@testing-library/react-native';
6+
import type { Attachment, Channel as ChannelType, StreamChat } from 'stream-chat';
67

78
import { WithComponents } from '../../../contexts/componentsContext/ComponentsContext';
89
import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
@@ -19,14 +20,16 @@ import { Channel } from '../../Channel/Channel';
1920
import { Chat } from '../../Chat/Chat';
2021
import { MessageList } from '../../MessageList/MessageList';
2122

23+
type AttachmentWithCustomField = Attachment & { customField?: string };
24+
2225
describe('isAttachmentEqualHandler', () => {
23-
let channel;
24-
let chatClient;
26+
let channel: ChannelType;
27+
let chatClient: StreamChat;
2528

2629
const user = generateUser({ id: 'id', name: 'name' });
2730
const messages = [
2831
generateMessage({
29-
attachments: [{ customField: 'custom-field', type: 'test' }],
32+
attachments: [{ customField: 'custom-field', type: 'test' } as AttachmentWithCustomField],
3033
user,
3134
}),
3235
];
@@ -40,7 +43,7 @@ describe('isAttachmentEqualHandler', () => {
4043

4144
chatClient = await getTestClientWithUser(user);
4245
useMockedApis(chatClient, [getOrCreateChannelApi(mockedChannel)]);
43-
channel = chatClient.channel('messaging', mockedChannel.id);
46+
channel = chatClient.channel('messaging', mockedChannel.channel.id);
4447
await channel.watch();
4548
});
4649

@@ -50,7 +53,10 @@ describe('isAttachmentEqualHandler', () => {
5053
});
5154

5255
const getMessageWithCustomFields = () => {
53-
const isAttachmentEqualHandler = (prevProps, nextProps) => {
56+
const isAttachmentEqualHandler = (
57+
prevProps: AttachmentWithCustomField,
58+
nextProps: AttachmentWithCustomField,
59+
) => {
5460
const propsEqual =
5561
prevProps.customField === nextProps.customField && prevProps.type === nextProps.type;
5662
if (!propsEqual) {
@@ -64,14 +70,23 @@ describe('isAttachmentEqualHandler', () => {
6470
<Chat client={chatClient}>
6571
<WithComponents
6672
overrides={{
67-
UnsupportedAttachment: ({ attachment: { customField, type } }) => {
73+
UnsupportedAttachment: ({ attachment }) => {
74+
const { customField, type } = attachment as AttachmentWithCustomField;
6875
if (type === 'test') {
6976
return <Text testID='attachment-custom-field'>{customField}</Text>;
7077
}
78+
return null;
7179
},
7280
}}
7381
>
74-
<Channel channel={channel} isAttachmentEqual={isAttachmentEqualHandler}>
82+
<Channel
83+
channel={channel}
84+
isAttachmentEqual={
85+
isAttachmentEqualHandler as unknown as React.ComponentProps<
86+
typeof Channel
87+
>['isAttachmentEqual']
88+
}
89+
>
7590
<MessageList />
7691
</Channel>
7792
</WithComponents>
@@ -92,8 +107,10 @@ describe('isAttachmentEqualHandler', () => {
92107
chatClient,
93108
{
94109
...messages[0],
95-
attachments: [{ customField: 'custom-field-2', type: 'test' }],
96-
updated_at: new Date(),
110+
attachments: [
111+
{ customField: 'custom-field-2', type: 'test' } as AttachmentWithCustomField,
112+
],
113+
updated_at: new Date() as unknown as string,
97114
},
98115
channel,
99116
);

package/src/components/Channel/__tests__/ownCapabilities.test.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { FlatList } from 'react-native';
44
import { SafeAreaProvider } from 'react-native-safe-area-context';
55

66
import { act, fireEvent, render, waitFor } from '@testing-library/react-native';
7+
import type { Channel as ChannelType, MessageResponse, StreamChat } from 'stream-chat';
78

89
import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
910
import { allOwnCapabilities } from '../../../contexts/ownCapabilitiesContext/OwnCapabilitiesContext';
@@ -31,10 +32,10 @@ describe('Own capabilities', () => {
3132
user: otherUser,
3233
});
3334

34-
let chatClient;
35-
let channel;
35+
let chatClient: StreamChat;
36+
let channel: ChannelType;
3637

37-
const initializeChannel = async (c) => {
38+
const initializeChannel = async (c: ReturnType<typeof generateChannelResponse>) => {
3839
useMockedApis(chatClient, [getOrCreateChannelApi(c)]);
3940
channel = chatClient.channel('messaging');
4041

@@ -48,7 +49,7 @@ describe('Own capabilities', () => {
4849
});
4950
});
5051

51-
const getComponent = (props = {}) => (
52+
const getComponent = (props: Partial<React.ComponentProps<typeof Channel>> = {}) => (
5253
<SafeAreaProvider>
5354
<OverlayProvider>
5455
<Chat client={chatClient}>
@@ -61,7 +62,7 @@ describe('Own capabilities', () => {
6162
</SafeAreaProvider>
6263
);
6364

64-
const generateChannelWithCapabilities = async (capabilities = []) => {
65+
const generateChannelWithCapabilities = async (capabilities: string[] = []) => {
6566
const c = generateChannelResponse({
6667
channel: {
6768
own_capabilities: capabilities,
@@ -71,12 +72,15 @@ describe('Own capabilities', () => {
7172
await initializeChannel(c);
7273
};
7374

74-
const renderChannelAndOpenMessageActionsList = async (targetMessage, props = {}) => {
75+
const renderChannelAndOpenMessageActionsList = async (
76+
targetMessage: MessageResponse,
77+
props: Partial<React.ComponentProps<typeof Channel>> = {},
78+
) => {
7579
const { findByTestId, queryByLabelText, queryByText, unmount } = render(getComponent(props));
76-
await waitFor(() => queryByText(targetMessage.text));
80+
await waitFor(() => queryByText(targetMessage.text as string));
7781

7882
act(() => {
79-
fireEvent(queryByText(targetMessage.text), 'onLongPress');
83+
fireEvent(queryByText(targetMessage.text as string)!, 'onLongPress');
8084
});
8185

8286
await waitFor(() => expect(!!queryByLabelText('Message action list')).toBeTruthy());
@@ -363,7 +367,7 @@ describe('Own capabilities', () => {
363367
const sendMessage = jest.fn();
364368
channel.sendMessage = sendMessage;
365369
act(() => {
366-
fireEvent(queryByTestId('send-button'), 'onPress');
370+
fireEvent(queryByTestId('send-button')!, 'onPress');
367371
});
368372

369373
await waitFor(() => expect(sendMessage).toHaveBeenCalledTimes(0));
@@ -378,10 +382,10 @@ describe('Own capabilities', () => {
378382
const mockFn = jest.fn();
379383
const { queryByTestId } = render(
380384
getComponent({
381-
doSendMessageRequest: () => {
385+
doSendMessageRequest: (() => {
382386
mockFn();
383387
return sendMessageApi();
384-
},
388+
}) as unknown as React.ComponentProps<typeof Channel>['doSendMessageRequest'],
385389
}),
386390
);
387391

@@ -397,7 +401,7 @@ describe('Own capabilities', () => {
397401
});
398402

399403
act(() => {
400-
fireEvent(queryByTestId('send-button'), 'onPress');
404+
fireEvent(queryByTestId('send-button')!, 'onPress');
401405
});
402406

403407
await waitFor(() => expect(mockFn).toHaveBeenCalledTimes(1));

0 commit comments

Comments
 (0)