@linktr.ee/messaging-react 1.36.0-rc-1777522205 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.36.0-rc-1777522205",
3
+ "version": "1.37.0",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@linktr.ee/component-library": "11.8.6",
37
- "@linktr.ee/messaging-core": "^1.7.1",
37
+ "@linktr.ee/messaging-core": "^1.8.0",
38
38
  "@phosphor-icons/react": "^2.1.10"
39
39
  },
40
40
  "devDependencies": {
@@ -0,0 +1,126 @@
1
+ import { StreamChatService } from '@linktr.ee/messaging-core'
2
+ import { render, waitFor, act } from '@testing-library/react'
3
+ import React from 'react'
4
+ import type { StreamChat } from 'stream-chat'
5
+ import { describe, it, expect, vi, beforeEach } from 'vitest'
6
+
7
+ import { MessagingProvider, useMessagingContext } from './MessagingProvider'
8
+
9
+ // Stub stream-chat-react's <Chat /> so we don't need a real, fully-wired
10
+ // StreamChat instance just to verify provider state.
11
+ vi.mock('stream-chat-react', () => ({
12
+ Chat: ({ children }: { children: React.ReactNode }) => <>{children}</>,
13
+ }))
14
+
15
+ const setupServiceMock = () => {
16
+ const connectUser = vi.fn(
17
+ async () => ({ userID: 'mock' }) as unknown as StreamChat
18
+ )
19
+ const disconnectUser = vi.fn(async () => undefined)
20
+
21
+ vi.spyOn(StreamChatService.prototype, 'connectUser').mockImplementation(
22
+ connectUser
23
+ )
24
+ vi.spyOn(StreamChatService.prototype, 'disconnectUser').mockImplementation(
25
+ disconnectUser
26
+ )
27
+
28
+ return { connectUser, disconnectUser }
29
+ }
30
+
31
+ const Probe: React.FC<{ onState: (state: unknown) => void }> = ({
32
+ onState,
33
+ }) => {
34
+ const ctx = useMessagingContext()
35
+ React.useEffect(() => {
36
+ onState({
37
+ isConnected: ctx.isConnected,
38
+ isLoading: ctx.isLoading,
39
+ error: ctx.error,
40
+ hasClient: !!ctx.client,
41
+ })
42
+ }, [ctx, onState])
43
+ return null
44
+ }
45
+
46
+ describe('MessagingProvider', () => {
47
+ beforeEach(() => {
48
+ vi.restoreAllMocks()
49
+ })
50
+
51
+ it('connects a guest user through the underlying service', async () => {
52
+ const { connectUser } = setupServiceMock()
53
+ const states: unknown[] = []
54
+
55
+ render(
56
+ <MessagingProvider
57
+ apiKey="mock-api-key"
58
+ user={{ type: 'guest', id: 'guest-1', name: 'Guest' }}
59
+ serviceConfig={{
60
+ createChannel: async () => ({ channelId: 'ch-1' }),
61
+ }}
62
+ >
63
+ <Probe onState={(s) => states.push(s)} />
64
+ </MessagingProvider>
65
+ )
66
+
67
+ await waitFor(() => expect(connectUser).toHaveBeenCalledTimes(1))
68
+ expect(connectUser).toHaveBeenCalledWith({
69
+ type: 'guest',
70
+ id: 'guest-1',
71
+ name: 'Guest',
72
+ })
73
+
74
+ await waitFor(() => {
75
+ const last = states[states.length - 1] as { isConnected: boolean }
76
+ expect(last.isConnected).toBe(true)
77
+ })
78
+ })
79
+
80
+ it('disconnects and reconnects when remounted with a new key', async () => {
81
+ const { connectUser, disconnectUser } = setupServiceMock()
82
+
83
+ const guestUser = {
84
+ type: 'guest' as const,
85
+ id: 'guest-1',
86
+ name: 'Guest',
87
+ }
88
+ const authedUser = { id: 'user-1', name: 'Authed User' }
89
+
90
+ const { rerender } = render(
91
+ <MessagingProvider
92
+ key="guest"
93
+ apiKey="mock-api-key"
94
+ user={guestUser}
95
+ serviceConfig={{
96
+ createChannel: async () => ({ channelId: 'ch-1' }),
97
+ }}
98
+ >
99
+ <div />
100
+ </MessagingProvider>
101
+ )
102
+
103
+ await waitFor(() => expect(connectUser).toHaveBeenCalledTimes(1))
104
+ expect(connectUser).toHaveBeenLastCalledWith(guestUser)
105
+
106
+ await act(async () => {
107
+ rerender(
108
+ <MessagingProvider
109
+ key="authed"
110
+ apiKey="mock-api-key"
111
+ user={authedUser}
112
+ serviceConfig={{
113
+ fetchToken: async () => 'token',
114
+ createChannel: async () => ({ channelId: 'ch-1' }),
115
+ }}
116
+ >
117
+ <div />
118
+ </MessagingProvider>
119
+ )
120
+ })
121
+
122
+ await waitFor(() => expect(disconnectUser).toHaveBeenCalled())
123
+ await waitFor(() => expect(connectUser).toHaveBeenCalledTimes(2))
124
+ expect(connectUser).toHaveBeenLastCalledWith(authedUser)
125
+ })
126
+ })