@webex/plugin-meetings 2.60.1-next.14 → 2.60.1-next.15
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/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/index.d.ts +0 -1
- package/dist/meeting/index.js +3 -13
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/voicea-meeting.d.ts +0 -4
- package/dist/meeting/voicea-meeting.js +26 -58
- package/dist/meeting/voicea-meeting.js.map +1 -1
- package/dist/webinar/index.js +1 -1
- package/package.json +3 -3
- package/src/meeting/index.ts +3 -18
- package/src/meeting/voicea-meeting.ts +26 -65
- package/test/unit/spec/meeting/index.js +149 -4
- package/test/unit/spec/meeting/voicea-meeting.ts +266 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getSpeakerFromProxyOrStore,
|
|
3
|
+
processNewCaptions,
|
|
4
|
+
} from '@webex/plugin-meetings/src/meeting/voicea-meeting';
|
|
5
|
+
import {assert} from '@webex/test-helper-chai';
|
|
6
|
+
import { expect } from 'chai';
|
|
7
|
+
|
|
8
|
+
describe('plugin-meetings', () => {
|
|
9
|
+
let fakeMeeting, fakeVoiceaPayload;
|
|
10
|
+
const fakeMemberId = "4f35a5ab-f750-3ba7-b309-dea62a512257";
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
const fakeMemberList = {
|
|
13
|
+
[fakeMemberId]: {
|
|
14
|
+
participant: {
|
|
15
|
+
person: {
|
|
16
|
+
id: "8093d335-9b96-4f9d-a6b2-7293423be88a",
|
|
17
|
+
name: "John Doe",
|
|
18
|
+
isExternal: false,
|
|
19
|
+
orgId: "1eb65fdf-9643-417f-9974-ad72cae0e10f",
|
|
20
|
+
incomingCallProtocols: []
|
|
21
|
+
},
|
|
22
|
+
status: {
|
|
23
|
+
audioStatus: "SENDRECV",
|
|
24
|
+
videoStatus: "INACTIVE",
|
|
25
|
+
videoSlidesStatus: "RECVONLY",
|
|
26
|
+
audioSlidesStatus: "INACTIVE",
|
|
27
|
+
csis: [
|
|
28
|
+
3060099329,
|
|
29
|
+
3060099328,
|
|
30
|
+
1234867712,
|
|
31
|
+
1234867713
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
id: fakeMemberId
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const fakeCaptions = {
|
|
40
|
+
captions: [
|
|
41
|
+
{
|
|
42
|
+
id: "6bece1b9-4e50-fafe-fb63-d27d5fb27280",
|
|
43
|
+
isFinal: true,
|
|
44
|
+
text: "Oh it's not update.",
|
|
45
|
+
currentSpokenLanguage: "en",
|
|
46
|
+
timestamp: "1:34",
|
|
47
|
+
speaker: {
|
|
48
|
+
speakerId: "8093d335-9b96-4f9d-a6b2-7293423be88a",
|
|
49
|
+
name: "John Doe"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: "c34400a9-cb2b-20c3-d20c-bd7981cc62a9",
|
|
54
|
+
isFinal: true,
|
|
55
|
+
text: "Nice.",
|
|
56
|
+
currentSpokenLanguage: "en",
|
|
57
|
+
timestamp: "1:60",
|
|
58
|
+
speaker: {
|
|
59
|
+
speakerId: "8093d335-9b96-4f9d-a6b2-7293423be88a",
|
|
60
|
+
name: "John Doe"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "311cc182-e657-c077-c078-795f866c4e9b_8093d335-9b96-4f9d-a6b2-7293423be88a",
|
|
65
|
+
isFinal: false,
|
|
66
|
+
text: " Don't bother me talking I'm just going to get the transcript data that is interim and I",
|
|
67
|
+
currentCaptionLanguage: "en",
|
|
68
|
+
speaker: {
|
|
69
|
+
speakerId: "8093d335-9b96-4f9d-a6b2-7293423be88a",
|
|
70
|
+
name: "John Doe"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
interimCaptions: {
|
|
75
|
+
"6bece1b9-4e50-fafe-fb63-d27d5fb27280": [],
|
|
76
|
+
"c34400a9-cb2b-20c3-d20c-bd7981cc62a9": [],
|
|
77
|
+
"311cc182-e657-c077-c078-795f866c4e9b": [
|
|
78
|
+
"311cc182-e657-c077-c078-795f866c4e9b_8093d335-9b96-4f9d-a6b2-7293423be88a"
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
speakerProxy: {},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
fakeMeeting = {
|
|
85
|
+
members: {
|
|
86
|
+
membersCollection: {
|
|
87
|
+
members: fakeMemberList
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
transcription: fakeCaptions
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fakeVoiceaPayload = {
|
|
94
|
+
isFinal: true,
|
|
95
|
+
transcriptId: "311cc182-e657-c077-c078-795f866c4e9b",
|
|
96
|
+
transcripts: [
|
|
97
|
+
{
|
|
98
|
+
text: "Don't bother me talking I'm just going to get the transcript data that is interim and I needed if I keep talking, I get the interim data",
|
|
99
|
+
csis: [
|
|
100
|
+
1234867712
|
|
101
|
+
],
|
|
102
|
+
transcript_language_code: "en"
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
transcript: {
|
|
106
|
+
text: "Don't bother me talking I'm just going to get the transcript data that is interim and I needed if I keep talking, I get the interim data",
|
|
107
|
+
csis: [
|
|
108
|
+
1234867712
|
|
109
|
+
],
|
|
110
|
+
transcript_language_code: "en"
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('voicea-meeting', () => {
|
|
116
|
+
it('should export the correct members', () => {
|
|
117
|
+
assert.isFunction(getSpeakerFromProxyOrStore);
|
|
118
|
+
assert.isFunction(processNewCaptions);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('getSpeakerFromProxyOrStore', () => {
|
|
122
|
+
it('should return a cached speaker if csisKey is in speakerProxy', () => {
|
|
123
|
+
// Add a speaker to the speakerProxy
|
|
124
|
+
const csisKey = 1234867712;
|
|
125
|
+
const cachedSpeaker = {
|
|
126
|
+
speakerId: 'cached-speaker-id',
|
|
127
|
+
name: 'Cached Speaker'
|
|
128
|
+
};
|
|
129
|
+
fakeMeeting.transcription.speakerProxy[csisKey] = cachedSpeaker;
|
|
130
|
+
|
|
131
|
+
const { speaker, needsCaching } = getSpeakerFromProxyOrStore({
|
|
132
|
+
csisKey,
|
|
133
|
+
meetingMembers: fakeMeeting.members.membersCollection.members,
|
|
134
|
+
transcriptData: fakeMeeting.transcription
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
expect(speaker).to.deep.equal(cachedSpeaker);
|
|
138
|
+
expect(needsCaching).to.be.false;
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should find and cache a speaker if not already in speakerProxy', () => {
|
|
142
|
+
const csisKey = 1234867712; // This csis exists in the fakeMemberList
|
|
143
|
+
|
|
144
|
+
// Ensure speakerProxy is empty
|
|
145
|
+
fakeMeeting.transcription.speakerProxy = {};
|
|
146
|
+
|
|
147
|
+
const { speaker, needsCaching } = getSpeakerFromProxyOrStore({
|
|
148
|
+
csisKey,
|
|
149
|
+
meetingMembers: fakeMeeting.members.membersCollection.members,
|
|
150
|
+
transcriptData: fakeMeeting.transcription
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
expect(speaker.speakerId).to.equal(fakeMeeting.members.membersCollection.members[fakeMemberId].participant.person.id);
|
|
154
|
+
expect(speaker.name).to.equal(fakeMeeting.members.membersCollection.members[fakeMemberId].participant.person.name);
|
|
155
|
+
expect(needsCaching).to.be.true;
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('processNewCaptions', () => {
|
|
160
|
+
it('should process new final captions correctly', () => {
|
|
161
|
+
let transcriptData = fakeMeeting.transcription;
|
|
162
|
+
let transcriptId = fakeVoiceaPayload.transcriptId;
|
|
163
|
+
delete fakeVoiceaPayload.transcripts;
|
|
164
|
+
|
|
165
|
+
// Assuming that processNewCaptions is a pure function that doesn't mutate the input but returns a new state
|
|
166
|
+
processNewCaptions({
|
|
167
|
+
data: fakeVoiceaPayload,
|
|
168
|
+
meeting: fakeMeeting
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Check if speaker details are cached if needed
|
|
172
|
+
const csisKey = fakeVoiceaPayload.transcript.csis[0];
|
|
173
|
+
const speaker = transcriptData.speakerProxy[csisKey];
|
|
174
|
+
expect(speaker).to.exist;
|
|
175
|
+
|
|
176
|
+
// Check if interim captions are removed
|
|
177
|
+
expect(transcriptData.interimCaptions[transcriptId]).to.deep.equal([]);
|
|
178
|
+
|
|
179
|
+
//check if the interim caption is removed
|
|
180
|
+
const oldInterimCaption = transcriptData.captions.find(caption => caption.id === `${transcriptId}_${speaker.speakerId}`);
|
|
181
|
+
expect(oldInterimCaption).to.not.exist;
|
|
182
|
+
|
|
183
|
+
// Check the final caption data
|
|
184
|
+
const newCaption = transcriptData.captions.find(caption => caption.id === transcriptId);
|
|
185
|
+
expect(newCaption).to.exist;
|
|
186
|
+
expect(newCaption).to.include({
|
|
187
|
+
id: transcriptId,
|
|
188
|
+
isFinal: fakeVoiceaPayload.isFinal,
|
|
189
|
+
text: fakeVoiceaPayload.transcript.text,
|
|
190
|
+
currentSpokenLanguage: fakeVoiceaPayload.transcript.transcript_language_code,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Check the speaker data in the new caption
|
|
194
|
+
expect(newCaption.speaker).to.deep.equal(speaker);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should process new interim captions correctly', () => {
|
|
198
|
+
let transcriptData = fakeMeeting.transcription;
|
|
199
|
+
let transcriptId = fakeVoiceaPayload.transcriptId;
|
|
200
|
+
delete fakeVoiceaPayload.transcript;
|
|
201
|
+
|
|
202
|
+
transcriptData.captions.splice(transcriptData.length - 1, 1);
|
|
203
|
+
fakeVoiceaPayload.isFinal = false;
|
|
204
|
+
|
|
205
|
+
processNewCaptions({
|
|
206
|
+
data: fakeVoiceaPayload,
|
|
207
|
+
meeting: fakeMeeting
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Check if speaker details are cached if needed
|
|
211
|
+
const csisKey = fakeVoiceaPayload.transcripts[0].csis[0];
|
|
212
|
+
const speaker = transcriptData.speakerProxy[csisKey];
|
|
213
|
+
expect(speaker).to.exist;
|
|
214
|
+
|
|
215
|
+
// Check the final caption data
|
|
216
|
+
const newCaption = transcriptData.captions.find(caption => caption.id === `${transcriptId}_${speaker.speakerId}`);
|
|
217
|
+
expect(newCaption).to.exist;
|
|
218
|
+
expect(newCaption).to.include({
|
|
219
|
+
id: `${transcriptId}_${speaker.speakerId}`,
|
|
220
|
+
isFinal: fakeVoiceaPayload.isFinal,
|
|
221
|
+
text: fakeVoiceaPayload.transcripts[0].text,
|
|
222
|
+
currentCaptionLanguage: fakeVoiceaPayload.transcripts[0].transcript_language_code,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Check if interim captions has the right caption id
|
|
226
|
+
expect(transcriptData.interimCaptions[transcriptId]).to.deep.equal([newCaption.id]);
|
|
227
|
+
|
|
228
|
+
// Check the speaker data in the new caption
|
|
229
|
+
expect(newCaption.speaker).to.deep.equal(speaker);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should process interim captions with an existing one correctly', () => {
|
|
233
|
+
let transcriptData = fakeMeeting.transcription;
|
|
234
|
+
let transcriptId = fakeVoiceaPayload.transcriptId;
|
|
235
|
+
delete fakeVoiceaPayload.transcript;
|
|
236
|
+
fakeVoiceaPayload.isFinal = false;
|
|
237
|
+
|
|
238
|
+
processNewCaptions({
|
|
239
|
+
data: fakeVoiceaPayload,
|
|
240
|
+
meeting: fakeMeeting
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Check if speaker details are cached if needed
|
|
244
|
+
const csisKey = fakeVoiceaPayload.transcripts[0].csis[0];
|
|
245
|
+
const speaker = transcriptData.speakerProxy[csisKey];
|
|
246
|
+
expect(speaker).to.exist;
|
|
247
|
+
|
|
248
|
+
// Check the final caption data
|
|
249
|
+
const newCaption = transcriptData.captions.find(caption => caption.id === `${transcriptId}_${speaker.speakerId}`);
|
|
250
|
+
expect(newCaption).to.exist;
|
|
251
|
+
expect(newCaption).to.include({
|
|
252
|
+
id: `${transcriptId}_${speaker.speakerId}`,
|
|
253
|
+
isFinal: fakeVoiceaPayload.isFinal,
|
|
254
|
+
text: fakeVoiceaPayload.transcripts[0].text,
|
|
255
|
+
currentCaptionLanguage: fakeVoiceaPayload.transcripts[0].transcript_language_code,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Check if interim captions has the right caption id
|
|
259
|
+
expect(transcriptData.interimCaptions[transcriptId]).to.deep.equal([newCaption.id]);
|
|
260
|
+
|
|
261
|
+
// Check the speaker data in the new caption
|
|
262
|
+
expect(newCaption.speaker).to.deep.equal(speaker);
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
});
|