Skip to content

Commit 5c4254a

Browse files
dmceachernmsftcarocao-msft
authored andcommitted
Chat adapter error update (#2471)
* add error emitter to typing indicator * add proxy in stateful client for typingIndicator * add test * Change files * fix name * Update @internal-react-composites-7cc319fa-75a7-4732-b1fb-a9425738de8d.json * update composite test script to build first * add test to stateful suite * fix spelling... * remove auto build
1 parent a3ad7bf commit 5c4254a

6 files changed

Lines changed: 54 additions & 1 deletion
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fix issue where typingIndicator errors were not being caught by the ChatAdapter.",
4+
"packageName": "@internal/chat-stateful-client",
5+
"email": "94866715+dmceachernmsft@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fix issue where typingIndicator errors were not being caught by the ChatAdapter",
4+
"packageName": "@internal/react-composites",
5+
"email": "94866715+dmceachernmsft@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}

packages/chat-stateful-client/src/StatefulChatThreadClient.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,17 @@ describe('stateful chatThreadClient correctly wraps errors', () => {
317317
);
318318
});
319319

320+
test('when sendTypingNotification fails', async () => {
321+
const chatThreadClient = createMockChatThreadClient('threadId');
322+
chatThreadClient.sendTypingNotification = async (): Promise<boolean> => {
323+
throw new Error('injected error');
324+
};
325+
const client = createMockChatClientWithChatThreadClient(chatThreadClient);
326+
await expect(client.getChatThreadClient('threadId').sendTypingNotification()).rejects.toThrow(
327+
new ChatError('ChatThreadClient.sendTypingNotification', new Error('injected error'))
328+
);
329+
});
330+
320331
test('when sendMessage fails', async () => {
321332
const chatThreadClient = createMockChatThreadClient('threadId');
322333
chatThreadClient.sendMessage = async (): Promise<any> => {

packages/chat-stateful-client/src/StatefulChatThreadClient.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ class ProxyChatThreadClient implements ProxyHandler<ChatThreadClient> {
109109
case 'listReadReceipts': {
110110
return createDecoratedListReadReceipts(chatThreadClient, this._context);
111111
}
112+
case 'sendTypingNotification': {
113+
return this._context.withAsyncErrorTeedToState(
114+
async (...args: Parameters<ChatThreadClient['sendTypingNotification']>) => {
115+
return await chatThreadClient.sendTypingNotification(...args);
116+
},
117+
'ChatThreadClient.sendTypingNotification'
118+
);
119+
}
112120
case 'removeParticipant': {
113121
return this._context.withAsyncErrorTeedToState(
114122
async (...args: Parameters<ChatThreadClient['removeParticipant']>) => {

packages/react-composites/src/composites/ChatComposite/adapter/AzureCommunicationChatAdapter.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,24 @@ describe('Error is reflected in state and events', () => {
111111
const allLoaded = await adapter.loadPreviousChatMessages(1);
112112
expect(allLoaded).toBe(true);
113113
});
114+
115+
it('when sendTypingNotification fails', async () => {
116+
const threadClient = new StubChatThreadClient();
117+
threadClient.sendTypingNotification = (): Promise<boolean> => {
118+
throw new Error('injected error');
119+
};
120+
const adapter = await createChatAdapterWithStubs(new StubChatClient(threadClient));
121+
const stateListener = new StateChangeListener(adapter);
122+
const errorListener = new ErrorListener(adapter);
123+
124+
await expect(adapter.sendTypingIndicator()).rejects.toThrow();
125+
126+
expect(stateListener.onChangeCalledCount).toBe(1);
127+
const latestError = stateListener.state.latestErrors['ChatThreadClient.sendTypingNotification'];
128+
expect(latestError).toBeDefined();
129+
expect(errorListener.errors.length).toBe(1);
130+
expect(errorListener.errors[0].target).toBe('ChatThreadClient.sendTypingNotification');
131+
});
114132
});
115133

116134
const createChatAdapterWithStubs = async (chatClient: StubChatClient): Promise<ChatAdapter> => {

packages/react-composites/src/composites/ChatComposite/adapter/AzureCommunicationChatAdapter.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,9 @@ export class AzureCommunicationChatAdapter implements ChatAdapter {
228228
}
229229

230230
async sendTypingIndicator(): Promise<void> {
231-
await this.handlers.onTyping();
231+
await this.asyncTeeErrorToEventEmitter(async () => {
232+
await this.handlers.onTyping();
233+
});
232234
}
233235

234236
async removeParticipant(userId: string): Promise<void> {

0 commit comments

Comments
 (0)