@stream-io/video-client 0.1.4 → 0.1.6

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.
@@ -164,7 +164,6 @@ export declare class Call {
164
164
  */
165
165
  join: (data?: JoinCallData) => Promise<void>;
166
166
  private waitForJoinResponse;
167
- private assertCallJoined;
168
167
  /**
169
168
  * Starts publishing the given video stream to the call.
170
169
  * The stream will be stopped if the user changes an input device, or if the user leaves the call.
@@ -276,6 +275,7 @@ export declare class Call {
276
275
  * @returns
277
276
  */
278
277
  updatePublishQuality: (enabledRids: string[]) => Promise<void | undefined>;
278
+ private assertCallJoined;
279
279
  /**
280
280
  * Sends a reaction to the other call participants.
281
281
  *
@@ -406,7 +406,7 @@ export declare class Call {
406
406
  * @param request
407
407
  * @returns
408
408
  */
409
- queryMembers: (request: Omit<QueryMembersRequest, 'type' | 'id'>) => Promise<QueryMembersResponse>;
409
+ queryMembers: (request?: Omit<QueryMembersRequest, 'type' | 'id'>) => Promise<QueryMembersResponse>;
410
410
  /**
411
411
  * Will update the call members.
412
412
  *
@@ -2,7 +2,7 @@ import { Call } from './Call';
2
2
  import { StreamClient } from './coordinator/connection/client';
3
3
  import { StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore } from './store';
4
4
  import type { ConnectedEvent, CreateDeviceRequest, CreateGuestRequest, CreateGuestResponse, GetEdgesResponse, ListDevicesResponse, QueryCallsRequest } from './gen/coordinator';
5
- import type { EventHandler, EventTypes, Logger, StreamClientOptions, TokenOrProvider, TokenProvider, User, UserWithId } from './coordinator/connection/types';
5
+ import type { EventHandler, EventTypes, Logger, LogLevel, StreamClientOptions, TokenOrProvider, TokenProvider, User, UserWithId } from './coordinator/connection/types';
6
6
  /**
7
7
  * A `StreamVideoClient` instance lets you communicate with our API, and authenticate users.
8
8
  */
@@ -11,8 +11,7 @@ export declare class StreamVideoClient {
11
11
  * A reactive store that exposes all the state variables in a reactive manner - you can subscribe to changes of the different state variables. Our library is built in a way that all state changes are exposed in this store, so all UI changes in your application should be handled by subscribing to these variables.
12
12
  */
13
13
  readonly readOnlyStateStore: StreamVideoReadOnlyStateStore;
14
- readonly user?: User;
15
- readonly token?: TokenOrProvider;
14
+ readonly logLevel: LogLevel;
16
15
  readonly logger: Logger;
17
16
  protected readonly writeableStateStore: StreamVideoWriteableStateStore;
18
17
  streamClient: StreamClient;
@@ -38,7 +37,7 @@ export declare class StreamVideoClient {
38
37
  * @param user the user to connect.
39
38
  * @param token a token or a function that returns a token.
40
39
  */
41
- connectUser(user?: User, token?: TokenOrProvider): Promise<void | ConnectedEvent>;
40
+ connectUser(user: User, token?: TokenOrProvider): Promise<void | ConnectedEvent>;
42
41
  /**
43
42
  * Disconnects the currently connected user from the client.
44
43
  *
@@ -83,7 +82,7 @@ export declare class StreamVideoClient {
83
82
  *
84
83
  * @param data the query data.
85
84
  */
86
- queryCalls: (data: QueryCallsRequest) => Promise<{
85
+ queryCalls: (data?: QueryCallsRequest) => Promise<{
87
86
  calls: Call[];
88
87
  duration: string;
89
88
  next?: string | undefined;
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -39,8 +39,6 @@ export declare class StreamClient {
39
39
  rejectConnectionId?: Function;
40
40
  connectionIdPromise?: Promise<string | undefined>;
41
41
  private nextRequestAbortController;
42
- private waitForConnectPromise?;
43
- private resolveConnectPromise?;
44
42
  /**
45
43
  * Initialize a client.
46
44
  *
@@ -60,10 +58,6 @@ export declare class StreamClient {
60
58
  getLocationHint: (hintUrl?: string, timeout?: number) => Promise<string>;
61
59
  _getConnectionID: () => string | undefined;
62
60
  _hasConnectionID: () => boolean;
63
- /**
64
- * This will start a promise to hold API calls until `connectUser` is called, useful when user is set in `StreamVideoClient constructor`
65
- */
66
- startWaitingForConnection: () => void;
67
61
  /**
68
62
  * connectUser - Set the current user and open a WebSocket connection
69
63
  *
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "0.1.4";
1
+ export declare const version = "0.1.6";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-client",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",
package/src/Call.ts CHANGED
@@ -72,6 +72,7 @@ import {
72
72
  import {
73
73
  BehaviorSubject,
74
74
  debounce,
75
+ filter,
75
76
  map,
76
77
  pairwise,
77
78
  Subject,
@@ -371,12 +372,15 @@ export class Call {
371
372
  * Leave the call and stop the media streams that were published by the call.
372
373
  */
373
374
  leave = async ({ reject = false }: CallLeaveOptions = {}) => {
374
- // TODO: handle case when leave is called during JOINING
375
375
  const callingState = this.state.callingState;
376
376
  if (callingState === CallingState.LEFT) {
377
377
  throw new Error('Cannot leave call that has already been left.');
378
378
  }
379
379
 
380
+ if (callingState === CallingState.JOINING) {
381
+ await this.assertCallJoined();
382
+ }
383
+
380
384
  if (this.ringing) {
381
385
  // I'm the one who started the call, so I should cancel it.
382
386
  const hasOtherParticipants = this.state.remoteParticipants.length > 0;
@@ -930,14 +934,6 @@ export class Call {
930
934
  });
931
935
  };
932
936
 
933
- private assertCallJoined = () => {
934
- return new Promise<void>((resolve) => {
935
- this.state.callingState$
936
- .pipe(takeWhile((state) => state !== CallingState.JOINED, true))
937
- .subscribe(() => resolve());
938
- });
939
- };
940
-
941
937
  /**
942
938
  * Starts publishing the given video stream to the call.
943
939
  * The stream will be stopped if the user changes an input device, or if the user leaves the call.
@@ -1223,6 +1219,17 @@ export class Call {
1223
1219
  return this.publisher?.updateVideoPublishQuality(enabledRids);
1224
1220
  };
1225
1221
 
1222
+ private assertCallJoined = () => {
1223
+ return new Promise<void>((resolve) => {
1224
+ this.state.callingState$
1225
+ .pipe(
1226
+ takeWhile((state) => state !== CallingState.JOINED, true),
1227
+ filter((s) => s === CallingState.JOINED),
1228
+ )
1229
+ .subscribe(() => resolve());
1230
+ });
1231
+ };
1232
+
1226
1233
  /**
1227
1234
  * Sends a reaction to the other call participants.
1228
1235
  *
@@ -1510,11 +1517,11 @@ export class Call {
1510
1517
  * @param request
1511
1518
  * @returns
1512
1519
  */
1513
- queryMembers = (request: Omit<QueryMembersRequest, 'type' | 'id'>) => {
1520
+ queryMembers = (request?: Omit<QueryMembersRequest, 'type' | 'id'>) => {
1514
1521
  return this.streamClient.post<QueryMembersResponse, QueryMembersRequest>(
1515
1522
  '/call/members',
1516
1523
  {
1517
- ...request,
1524
+ ...(request || {}),
1518
1525
  id: this.id,
1519
1526
  type: this.type,
1520
1527
  },
@@ -38,8 +38,7 @@ export class StreamVideoClient {
38
38
  * A reactive store that exposes all the state variables in a reactive manner - you can subscribe to changes of the different state variables. Our library is built in a way that all state changes are exposed in this store, so all UI changes in your application should be handled by subscribing to these variables.
39
39
  */
40
40
  readonly readOnlyStateStore: StreamVideoReadOnlyStateStore;
41
- readonly user?: User;
42
- readonly token?: TokenOrProvider;
41
+ readonly logLevel: LogLevel = 'warn';
43
42
  readonly logger: Logger;
44
43
 
45
44
  protected readonly writeableStateStore: StreamVideoWriteableStateStore;
@@ -109,17 +108,20 @@ export class StreamVideoClient {
109
108
  }.${sdkInfo.minor}.${sdkInfo.patch}`,
110
109
  );
111
110
  }
112
- this.user = apiKeyOrArgs.user;
113
- this.token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
114
- if (this.user) {
115
- this.streamClient.startWaitingForConnection();
116
- }
117
111
  }
118
112
 
119
113
  this.writeableStateStore = new StreamVideoWriteableStateStore();
120
114
  this.readOnlyStateStore = new StreamVideoReadOnlyStateStore(
121
115
  this.writeableStateStore,
122
116
  );
117
+
118
+ if (typeof apiKeyOrArgs !== 'string') {
119
+ const user = apiKeyOrArgs.user;
120
+ const token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
121
+ if (user) {
122
+ this.connectUser(user, token);
123
+ }
124
+ }
123
125
  }
124
126
 
125
127
  /**
@@ -131,30 +133,30 @@ export class StreamVideoClient {
131
133
  * @param token a token or a function that returns a token.
132
134
  */
133
135
  async connectUser(
134
- user?: User,
136
+ user: User,
135
137
  token?: TokenOrProvider,
136
138
  ): Promise<void | ConnectedEvent> {
137
- const userToConnect = user || this.user;
138
- const tokenToUse = token || this.token;
139
- if (!userToConnect) {
140
- throw new Error('Connect user is called without user');
141
- }
142
- if (userToConnect.type === 'anonymous') {
143
- userToConnect.id = '!anon';
144
- return this.connectAnonymousUser(userToConnect as UserWithId, tokenToUse);
139
+ if (user.type === 'anonymous') {
140
+ user.id = '!anon';
141
+ return this.connectAnonymousUser(user as UserWithId, token);
145
142
  }
146
- if (userToConnect.type === 'guest') {
147
- const response = await this.createGuestUser({
148
- user: {
149
- ...userToConnect,
150
- role: 'guest',
151
- },
152
- });
153
- return this.connectUser(response.user, response.access_token);
154
- }
155
- const connectUser = () => {
156
- return this.streamClient.connectUser(userToConnect, tokenToUse);
143
+ let connectUser = () => {
144
+ return this.streamClient.connectUser(user, token);
157
145
  };
146
+ if (user.type === 'guest') {
147
+ connectUser = async () => {
148
+ const response = await this.createGuestUser({
149
+ user: {
150
+ ...user,
151
+ role: 'guest',
152
+ },
153
+ });
154
+ return this.streamClient.connectUser(
155
+ response.user,
156
+ response.access_token,
157
+ );
158
+ };
159
+ }
158
160
  this.connectionPromise = this.disconnectionPromise
159
161
  ? this.disconnectionPromise.then(() => connectUser())
160
162
  : connectUser();
@@ -199,7 +201,7 @@ export class StreamVideoClient {
199
201
  this.on('call.created', (event) => {
200
202
  if (event.type !== 'call.created') return;
201
203
  const { call, members } = event;
202
- if (userToConnect.id === call.created_by.id) {
204
+ if (user.id === call.created_by.id) {
203
205
  this.logger(
204
206
  'warn',
205
207
  'Received `call.created` sent by the current user',
@@ -225,7 +227,7 @@ export class StreamVideoClient {
225
227
  this.on('call.ring', async (event) => {
226
228
  if (event.type !== 'call.ring') return;
227
229
  const { call, members } = event;
228
- if (userToConnect.id === call.created_by.id) {
230
+ if (user.id === call.created_by.id) {
229
231
  this.logger(
230
232
  'debug',
231
233
  'Received `call.ring` sent by the current user so ignoring the event',
@@ -267,7 +269,7 @@ export class StreamVideoClient {
267
269
  * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
268
270
  */
269
271
  disconnectUser = async (timeout?: number) => {
270
- if (!this.streamClient.user) {
272
+ if (!this.streamClient.user && !this.connectionPromise) {
271
273
  return;
272
274
  }
273
275
  const disconnectUser = () => this.streamClient.disconnectUser(timeout);
@@ -338,7 +340,7 @@ export class StreamVideoClient {
338
340
  *
339
341
  * @param data the query data.
340
342
  */
341
- queryCalls = async (data: QueryCallsRequest) => {
343
+ queryCalls = async (data: QueryCallsRequest = {}) => {
342
344
  const response = await this.streamClient.post<
343
345
  QueryCallsResponse,
344
346
  QueryCallsRequest
@@ -2,20 +2,20 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
2
  import { StreamVideoClient } from '../StreamVideoClient';
3
3
  import 'dotenv/config';
4
4
  import { generateUUIDv4 } from '../coordinator/connection/utils';
5
- import { WSConnectionFallback } from '../coordinator/connection/connection_fallback';
5
+ import { StreamVideoServerClient } from '../StreamVideoServerClient';
6
6
 
7
7
  const apiKey = process.env.STREAM_API_KEY!;
8
- const tokenUrl = process.env.TOKEN_PROVIDER_URL!;
8
+ const secret = process.env.STREAM_SECRET!;
9
9
 
10
10
  const tokenProvider = (userId: string) => {
11
+ const serverClient = new StreamVideoServerClient(apiKey, { secret });
11
12
  return async () => {
12
- const url = new URL(tokenUrl);
13
- url.searchParams.set('api_key', apiKey);
14
- url.searchParams.set('user_id', userId);
15
-
16
- const response = await fetch(url.toString());
17
- const data = await response.json();
18
- return data.token;
13
+ return new Promise<string>((resolve) => {
14
+ setTimeout(() => {
15
+ const token = serverClient.createToken(userId);
16
+ resolve(token);
17
+ }, 100);
18
+ });
19
19
  };
20
20
  };
21
21
 
@@ -0,0 +1,93 @@
1
+ import 'dotenv/config';
2
+ import { beforeAll, describe, expect, it, vi } from 'vitest';
3
+ import { StreamVideoServerClient } from '../../StreamVideoServerClient';
4
+ import { generateUUIDv4 } from '../../coordinator/connection/utils';
5
+ import { Call } from '../../Call';
6
+
7
+ const apiKey = process.env.STREAM_API_KEY!;
8
+ const secret = process.env.STREAM_SECRET!;
9
+
10
+ describe('call members API', () => {
11
+ let client: StreamVideoServerClient;
12
+ const callId = `call${generateUUIDv4()}`;
13
+ let call: Call;
14
+
15
+ beforeAll(() => {
16
+ client = new StreamVideoServerClient(apiKey, {
17
+ secret,
18
+ logLevel: 'error',
19
+ });
20
+
21
+ call = client.call('default', callId);
22
+ });
23
+
24
+ it('create with members', async () => {
25
+ const response = await call.getOrCreate({
26
+ data: {
27
+ created_by_id: 'john',
28
+ members: [{ user_id: 'john', role: 'admin' }, { user_id: 'jack' }],
29
+ },
30
+ });
31
+
32
+ expect(response.members[0].user_id).toBe('jack');
33
+ expect(response.members[1].user_id).toBe('john');
34
+ expect(response.members[1].role).toBe('admin');
35
+ });
36
+
37
+ it('add or update members', async () => {
38
+ const response = await call.updateCallMembers({
39
+ update_members: [
40
+ { user_id: 'sara' },
41
+ { user_id: 'jane', role: 'admin' },
42
+ { user_id: 'john', role: 'user' },
43
+ ],
44
+ });
45
+
46
+ expect(response.members[0].user_id).toBe('sara');
47
+ expect(response.members[1].user_id).toBe('jane');
48
+ expect(response.members[1].role).toBe('admin');
49
+ expect(response.members[2].user_id).toBe('john');
50
+ expect(response.members[2].role).toBe('user');
51
+ });
52
+
53
+ it('remove members', async () => {
54
+ const response = await call.updateCallMembers({
55
+ remove_members: ['sara'],
56
+ });
57
+
58
+ expect(response.duration).toBeDefined();
59
+ });
60
+
61
+ it('query members', async () => {
62
+ let response = await call.queryMembers();
63
+
64
+ let members = response.members;
65
+ expect(members.length).toBe(3);
66
+
67
+ const queryMembersReq = {
68
+ sort: [{ field: 'user_id', direction: 1 }],
69
+ limit: 2,
70
+ };
71
+ response = await call.queryMembers(queryMembersReq);
72
+
73
+ members = response.members;
74
+ expect(members.length).toBe(2);
75
+ expect(members[0].user_id).toBe('jack');
76
+ expect(members[1].user_id).toBe('jane');
77
+
78
+ response = await call.queryMembers({
79
+ ...queryMembersReq,
80
+ next: response.next,
81
+ });
82
+
83
+ expect(response.members.length).toBe(1);
84
+
85
+ response = await call.queryMembers({
86
+ filter_conditions: { role: { $eq: 'admin' } },
87
+ });
88
+ members = response.members;
89
+
90
+ expect(members.length).toBe(1);
91
+ members.forEach((m) => expect(m.role).toBe('admin'));
92
+ });
93
+ });
@@ -0,0 +1,78 @@
1
+ import 'dotenv/config';
2
+ import { beforeAll, describe, expect, it } from 'vitest';
3
+ import { StreamVideoServerClient } from '../../StreamVideoServerClient';
4
+ import { generateUUIDv4 } from '../../coordinator/connection/utils';
5
+ import { LogLevel } from '../../coordinator/connection/types';
6
+ import { OwnCapability, RecordSettingsModeEnum } from '../../gen/coordinator';
7
+
8
+ const apiKey = process.env.STREAM_API_KEY!;
9
+ const secret = process.env.STREAM_SECRET!;
10
+
11
+ describe('call types CRUD API', () => {
12
+ let client: StreamVideoServerClient;
13
+ const callTypeName = `calltype${generateUUIDv4()}`;
14
+
15
+ beforeAll(() => {
16
+ client = new StreamVideoServerClient(apiKey, {
17
+ secret,
18
+ logLevel: 'trace',
19
+ logger: (logLevel: LogLevel, message: string, ...args: unknown[]) => {
20
+ console.log(new Date().toISOString(), message, ...args);
21
+ },
22
+ });
23
+ });
24
+
25
+ it('create', async () => {
26
+ const createResponse = await client.createCallType({
27
+ name: callTypeName,
28
+ settings: {
29
+ audio: { mic_default_on: true, default_device: 'speaker' },
30
+ },
31
+ grants: {
32
+ admin: [
33
+ OwnCapability.SEND_AUDIO,
34
+ OwnCapability.SEND_VIDEO,
35
+ OwnCapability.MUTE_USERS,
36
+ ],
37
+ user: [OwnCapability.SEND_AUDIO, OwnCapability.SEND_VIDEO],
38
+ },
39
+ });
40
+
41
+ expect(createResponse.name).toBe(callTypeName);
42
+ expect(createResponse.settings.audio.mic_default_on).toBe(true);
43
+ expect(createResponse.settings.audio.default_device).toBe('speaker');
44
+ expect(createResponse.grants.admin).toBeDefined();
45
+ expect(createResponse.grants.user).toBeDefined();
46
+ });
47
+
48
+ it('read', async () => {
49
+ const readResponse = await client.getCallTypes();
50
+
51
+ expect(readResponse.call_types[callTypeName]).toContain({
52
+ name: callTypeName,
53
+ });
54
+ });
55
+
56
+ it('update', async () => {
57
+ const updateResponse = await client.updateCallType(callTypeName, {
58
+ settings: {
59
+ audio: { mic_default_on: false, default_device: 'earpiece' },
60
+ recording: {
61
+ mode: RecordSettingsModeEnum.DISABLED,
62
+ },
63
+ },
64
+ });
65
+
66
+ expect(updateResponse.settings.audio.mic_default_on).toBeFalsy();
67
+ expect(updateResponse.settings.audio.default_device).toBe('earpiece');
68
+ expect(updateResponse.settings.recording.mode).toBe(
69
+ RecordSettingsModeEnum.DISABLED,
70
+ );
71
+ });
72
+
73
+ it('delete', async () => {
74
+ await client.deleteCallType(callTypeName);
75
+
76
+ await expect(() => client.getCallType(callTypeName)).rejects.toThrowError();
77
+ });
78
+ });
@@ -0,0 +1,147 @@
1
+ import 'dotenv/config';
2
+ import { beforeAll, describe, expect, it, vi } from 'vitest';
3
+ import { StreamVideoServerClient } from '../../StreamVideoServerClient';
4
+ import { generateUUIDv4 } from '../../coordinator/connection/utils';
5
+ import { Call } from '../../Call';
6
+ import {
7
+ RecordSettingsRequestModeEnum,
8
+ RecordSettingsRequestQualityEnum,
9
+ } from '../../gen/coordinator';
10
+
11
+ const apiKey = process.env.STREAM_API_KEY!;
12
+ const secret = process.env.STREAM_SECRET!;
13
+
14
+ describe('call API', () => {
15
+ let client: StreamVideoServerClient;
16
+ const callId = `call${generateUUIDv4()}`;
17
+ let call: Call;
18
+
19
+ beforeAll(() => {
20
+ client = new StreamVideoServerClient(apiKey, {
21
+ secret,
22
+ logLevel: 'error',
23
+ });
24
+
25
+ call = client.call('default', callId);
26
+ });
27
+
28
+ it('create', async () => {
29
+ const response = await call.getOrCreate({
30
+ data: { created_by_id: 'john' },
31
+ });
32
+
33
+ expect(response.call.created_by.id).toBe('john');
34
+ });
35
+
36
+ it('update', async () => {
37
+ const response = await call.update({
38
+ settings_override: {
39
+ audio: { mic_default_on: true, default_device: 'speaker' },
40
+ },
41
+ custom: { color: 'red' },
42
+ });
43
+
44
+ expect(response.call.settings.audio.mic_default_on).toBe(true);
45
+ expect(response.call.custom.color).toBe('red');
46
+ });
47
+
48
+ it('RTMP address', async () => {
49
+ const resp = await call.getOrCreate();
50
+ const address = resp.call.ingress.rtmp.address;
51
+
52
+ expect(address).toBeDefined();
53
+ });
54
+
55
+ it('query calls', async () => {
56
+ let response = await client.queryCalls();
57
+
58
+ let calls = response.calls;
59
+ expect(calls.length).toBeGreaterThanOrEqual(1);
60
+
61
+ const queryCallsReq = {
62
+ sort: [{ field: 'starts_at', direction: -1 }],
63
+ limit: 2,
64
+ };
65
+ response = await client.queryCalls(queryCallsReq);
66
+
67
+ calls = response.calls;
68
+ expect(calls.length).toBe(2);
69
+
70
+ response = await client.queryCalls({
71
+ ...queryCallsReq,
72
+ next: response.next,
73
+ });
74
+
75
+ expect(response.calls.length).toBeLessThanOrEqual(2);
76
+
77
+ response = await client.queryCalls({
78
+ filter_conditions: { backstage: { $eq: false } },
79
+ });
80
+
81
+ expect(response.calls.length).toBeGreaterThanOrEqual(1);
82
+ });
83
+
84
+ describe('recording', () => {
85
+ it('enable call recording', async () => {
86
+ let response = await call.update({
87
+ settings_override: {
88
+ recording: {
89
+ mode: RecordSettingsRequestModeEnum.DISABLED,
90
+ },
91
+ },
92
+ });
93
+ let settings = response.call.settings.recording;
94
+
95
+ expect(settings.mode).toBe(RecordSettingsRequestModeEnum.DISABLED);
96
+
97
+ response = await call.update({
98
+ settings_override: {
99
+ recording: {
100
+ mode: RecordSettingsRequestModeEnum.AVAILABLE,
101
+ },
102
+ },
103
+ });
104
+
105
+ settings = response.call.settings.recording;
106
+ expect(settings.mode).toBe(RecordSettingsRequestModeEnum.AVAILABLE);
107
+
108
+ response = await call.update({
109
+ settings_override: {
110
+ recording: {
111
+ audio_only: false,
112
+ quality: RecordSettingsRequestQualityEnum._1080P,
113
+ },
114
+ },
115
+ });
116
+
117
+ settings = response.call.settings.recording;
118
+ expect(settings.audio_only).toBe(false);
119
+ expect(settings.quality).toBe(RecordSettingsRequestQualityEnum._1080P);
120
+ });
121
+
122
+ it('start recording', async () => {
123
+ // somewhat dummy test, we should do a proper test in the future where we join a call and start recording
124
+ await expect(() => call.startRecording()).rejects.toThrowError(
125
+ 'Stream error code 4: StartRecording failed with error: "cannot record inactive call"',
126
+ );
127
+ });
128
+
129
+ it('stop recording', async () => {
130
+ // somewhat dummy test, we should do a proper test in the future
131
+ await expect(() => call.stopRecording()).rejects.toThrowError(
132
+ 'Stream error code 4: StopRecording failed with error: "call is not being recorded"',
133
+ );
134
+ });
135
+
136
+ it('query recordings', async () => {
137
+ // somewhat dummy test, we should do a proper test in the future
138
+ let response = await call.queryRecordings();
139
+
140
+ expect(response.recordings).toBeDefined();
141
+
142
+ response = await call.queryRecordings('session123');
143
+
144
+ expect(response.recordings).toBeDefined();
145
+ });
146
+ });
147
+ });