Skip to content

Commit 6eb5887

Browse files
committed
fix: add tests
1 parent 6f282b1 commit 6eb5887

File tree

2 files changed

+190
-19
lines changed

2 files changed

+190
-19
lines changed

packages/client/src/__tests__/StreamVideoClient.api.test.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,20 @@ const secret = process.env.STREAM_SECRET!;
1010

1111
const serverClient = new StreamClient(apiKey, secret);
1212

13-
const tokenProvider = (userId: string) => {
14-
return async () => {
15-
return new Promise<string>((resolve) => {
16-
setTimeout(() => {
17-
const token = serverClient.createToken(
18-
userId,
19-
undefined,
20-
Math.round(Date.now() / 1000 - 10),
21-
);
22-
resolve(token);
23-
}, 100);
24-
});
25-
};
26-
};
27-
2813
describe('StreamVideoClient - coordinator API', () => {
2914
let client: StreamVideoClient;
30-
const user = {
31-
id: 'sara',
32-
};
3315

3416
beforeAll(() => {
17+
const user = { id: 'sara' };
3518
client = new StreamVideoClient(apiKey, {
3619
// tests run in node, so we have to fake being in browser env
3720
browser: true,
3821
timeout: 15000,
3922
});
40-
client.connectUser(user, tokenProvider(user.id));
23+
client.connectUser(
24+
user,
25+
serverClient.generateUserToken({ user_id: user.id }),
26+
);
4127
});
4228

4329
it('query calls', { retry: 3, timeout: 20000 }, async () => {
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import 'dotenv/config';
2+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
3+
import { StreamVideoClient } from '../StreamVideoClient';
4+
import { StreamClient } from '@stream-io/node-sdk';
5+
import { AllClientEvents } from '../coordinator/connection/types';
6+
import { RxUtils } from '../store';
7+
import { Call } from '../Call';
8+
9+
const apiKey = process.env.STREAM_API_KEY!;
10+
const secret = process.env.STREAM_SECRET!;
11+
12+
describe('StreamVideoClient Ringing', () => {
13+
const serverClient = new StreamClient(apiKey, secret);
14+
15+
let oliverClient: StreamVideoClient;
16+
let sachaClient: StreamVideoClient;
17+
let marceloClient: StreamVideoClient;
18+
19+
beforeAll(async () => {
20+
const makeClient = async (userId: string) => {
21+
const client = new StreamVideoClient(apiKey, {
22+
// tests run in node, so we have to fake being in browser env
23+
browser: true,
24+
timeout: 15000,
25+
});
26+
await client.connectUser(
27+
{ id: userId },
28+
serverClient.generateUserToken({ user_id: userId }),
29+
);
30+
return client;
31+
};
32+
[oliverClient, sachaClient, marceloClient] = await Promise.all([
33+
makeClient('oliver'),
34+
makeClient('sacha'),
35+
makeClient('marcelo'),
36+
]);
37+
});
38+
39+
afterAll(async () => {
40+
await Promise.all([
41+
oliverClient.disconnectUser(),
42+
sachaClient.disconnectUser(),
43+
marceloClient.disconnectUser(),
44+
]);
45+
});
46+
47+
describe('standard ringing', async () => {
48+
it.each(['oliver', 'sara'])(
49+
'server-side: %s should ring all members, call creator should get call.ring event if present in members',
50+
async (creatorId: string) => {
51+
const oliverRing = expectEvent(oliverClient, 'call.ring');
52+
const sachaRing = expectEvent(sachaClient, 'call.ring');
53+
const marceloRing = expectEvent(marceloClient, 'call.ring');
54+
55+
const call = serverClient.video.call('default', crypto.randomUUID());
56+
await call.create({
57+
ring: true,
58+
data: {
59+
created_by_id: creatorId,
60+
members: [
61+
{ user_id: 'oliver' },
62+
{ user_id: 'sacha' },
63+
{ user_id: 'marcelo' },
64+
],
65+
},
66+
});
67+
68+
const [oliverRingEvent, sachaRingEvent, marceloRingEvent] =
69+
await Promise.all([oliverRing, sachaRing, marceloRing]);
70+
71+
expect(oliverRingEvent.call.cid).toBe(call.cid);
72+
expect(sachaRingEvent.call.cid).toBe(call.cid);
73+
expect(marceloRingEvent.call.cid).toBe(call.cid);
74+
75+
const oliverCall = await expectCall(oliverClient, call.cid);
76+
const sachaCall = await expectCall(sachaClient, call.cid);
77+
const marceloCall = await expectCall(marceloClient, call.cid);
78+
expect(oliverCall).toBeDefined();
79+
expect(sachaCall).toBeDefined();
80+
expect(marceloCall).toBeDefined();
81+
expect(oliverCall.ringing).toBe(true);
82+
expect(sachaCall.ringing).toBe(true);
83+
expect(marceloCall.ringing).toBe(true);
84+
},
85+
);
86+
});
87+
88+
describe('ringing individual members', () => {
89+
it('should ring individual members', async () => {
90+
const oliverCall = oliverClient.call('default', crypto.randomUUID());
91+
await oliverCall.create({
92+
ring: false, // don't ring all members by default
93+
data: {
94+
members: [
95+
{ user_id: 'oliver' },
96+
{ user_id: 'sacha' },
97+
{ user_id: 'marcelo' },
98+
],
99+
},
100+
});
101+
102+
// no one should get a ring event yet
103+
const oliverRing = expectEvent(oliverClient, 'call.ring', 500);
104+
const sachaRing = expectEvent(sachaClient, 'call.ring', 500);
105+
const marceloRing = expectEvent(marceloClient, 'call.ring', 500);
106+
await expect(
107+
Promise.all([oliverRing, sachaRing, marceloRing]),
108+
).rejects.toThrow();
109+
110+
// oliver is calling sacha. only sacha should get a ring event
111+
const sachaIndividualRing = expectEvent(sachaClient, 'call.ring');
112+
const marceloIndividualRing = expectEvent(marceloClient, 'call.ring');
113+
await oliverCall.ring({ target_member_ids: ['sacha'] });
114+
await expect(sachaIndividualRing).resolves.toHaveProperty(
115+
'call.cid',
116+
oliverCall.cid,
117+
);
118+
await expect(marceloIndividualRing).rejects.toThrow();
119+
120+
const sachaCall = await expectCall(sachaClient, oliverCall.cid);
121+
expect(sachaCall).toBeDefined();
122+
123+
// sacha is calling marcelo. only marcelo should get a ring event
124+
const oliverIndividualRing = expectEvent(oliverClient, 'call.ring');
125+
const marceloIndividualRing2 = expectEvent(marceloClient, 'call.ring');
126+
await sachaCall.ring({ target_member_ids: ['marcelo'] });
127+
await expect(marceloIndividualRing2).resolves.toHaveProperty(
128+
'call.cid',
129+
sachaCall.cid,
130+
);
131+
await expect(oliverIndividualRing).rejects.toThrow();
132+
133+
const marceloCall = await expectCall(marceloClient, sachaCall.cid);
134+
expect(marceloCall).toBeDefined();
135+
});
136+
});
137+
});
138+
139+
const expectEvent = async <E extends keyof AllClientEvents>(
140+
client: StreamVideoClient,
141+
eventName: E,
142+
timeout: number = 2500,
143+
): Promise<AllClientEvents[E]> => {
144+
return new Promise<AllClientEvents[E]>((resolve, reject) => {
145+
let timeoutId: NodeJS.Timeout | undefined = undefined;
146+
const off = client.on(eventName, (e) => {
147+
off();
148+
clearTimeout(timeoutId);
149+
resolve(e);
150+
});
151+
timeoutId = setTimeout(() => {
152+
off();
153+
reject(
154+
new Error(
155+
`Timeout waiting for event: ${eventName}, user_id: ${client.state.connectedUser?.id}`,
156+
),
157+
);
158+
}, timeout);
159+
});
160+
};
161+
162+
const expectCall = async (
163+
client: StreamVideoClient,
164+
cid: string,
165+
timeout: number = 2500,
166+
) => {
167+
return new Promise<Call>((resolve, reject) => {
168+
let timeoutId: NodeJS.Timeout | undefined = undefined;
169+
const off = RxUtils.createSubscription(client.state.calls$, (calls) => {
170+
const call = calls.find((c) => c.cid === cid);
171+
if (call) {
172+
clearTimeout(timeoutId);
173+
resolve(call);
174+
}
175+
});
176+
timeoutId = setTimeout(() => {
177+
off();
178+
reject(
179+
new Error(
180+
`Timeout waiting for call: ${cid}, user_id: ${client.state.connectedUser?.id}`,
181+
),
182+
);
183+
}, timeout);
184+
});
185+
};

0 commit comments

Comments
 (0)