瀏覽代碼

feat(tests): Adds follow-me and invite dialog test. (#15476)

* feat(tests): Adds follow-me test.

* feat(tests): Adds invite dialog test.

* squash: fix lint.
factor2
Дамян Минков 9 月之前
父節點
當前提交
c21f84c15a
沒有連結到貢獻者的電子郵件帳戶。

+ 3
- 0
tests/env.example 查看文件

30
 #WEBHOOKS_PROXY_URL=
30
 #WEBHOOKS_PROXY_URL=
31
 # A shared secret to authenticate the webhook proxy connection
31
 # A shared secret to authenticate the webhook proxy connection
32
 #WEBHOOKS_PROXY_SHARED_SECRET=
32
 #WEBHOOKS_PROXY_SHARED_SECRET=
33
+
34
+# A rest URL to be used by dial-in tests to invite jigasi to the conference
35
+#DIAL_IN_REST_URL=

+ 25
- 6
tests/helpers/Participant.ts 查看文件

238
             async () => await this.driver.execute(() => document.readyState === 'complete'),
238
             async () => await this.driver.execute(() => document.readyState === 'complete'),
239
             {
239
             {
240
                 timeout: 30_000, // 30 seconds
240
                 timeout: 30_000, // 30 seconds
241
-                timeoutMsg: 'Timeout waiting for Page Load Request to complete.'
241
+                timeoutMsg: `Timeout waiting for Page Load Request to complete for ${this.name}.`
242
             }
242
             }
243
         );
243
         );
244
     }
244
     }
245
 
245
 
246
+    /**
247
+     * Waits for the tile view to display.
248
+     */
249
+    async waitForTileViewDisplay(reverse = false) {
250
+        await this.driver.$('//div[@id="videoconference_page" and contains(@class, "tile-view")]').waitForDisplayed({
251
+            reverse,
252
+            timeout: 10_000,
253
+            timeoutMsg: `Tile view did not display in 10s for ${this.name}`
254
+        });
255
+    }
256
+
246
     /**
257
     /**
247
      * Checks if the participant is in the meeting.
258
      * Checks if the participant is in the meeting.
248
      */
259
      */
284
             () => this.isInMuc(),
295
             () => this.isInMuc(),
285
             {
296
             {
286
                 timeout: 10_000, // 10 seconds
297
                 timeout: 10_000, // 10 seconds
287
-                timeoutMsg: 'Timeout waiting to join muc.'
298
+                timeoutMsg: `Timeout waiting to join muc for ${this.name}`
288
             }
299
             }
289
         );
300
         );
290
     }
301
     }
300
         return driver.waitUntil(async () =>
311
         return driver.waitUntil(async () =>
301
             await driver.execute(() => APP.conference.getConnectionState() === 'connected'), {
312
             await driver.execute(() => APP.conference.getConnectionState() === 'connected'), {
302
             timeout: 15_000,
313
             timeout: 15_000,
303
-            timeoutMsg: 'expected ICE to be connected for 15s'
314
+            timeoutMsg: `expected ICE to be connected for 15s for ${this.name}`
304
         });
315
         });
305
     }
316
     }
306
 
317
 
309
      *
320
      *
310
      * @returns {Promise<void>}
321
      * @returns {Promise<void>}
311
      */
322
      */
312
-    async waitForSendReceiveData(timeout = 15_000, msg = 'expected to receive/send data in 15s'): Promise<void> {
323
+    async waitForSendReceiveData(
324
+            timeout = 15_000, msg = `expected to receive/send data in 15s for ${this.name}`): Promise<void> {
313
         const driver = this.driver;
325
         const driver = this.driver;
314
 
326
 
315
         return driver.waitUntil(async () =>
327
         return driver.waitUntil(async () =>
340
         return driver.waitUntil(async () =>
352
         return driver.waitUntil(async () =>
341
             await driver.execute(count => APP.conference.getNumberOfParticipantsWithTracks() >= count, number), {
353
             await driver.execute(count => APP.conference.getNumberOfParticipantsWithTracks() >= count, number), {
342
             timeout: 15_000,
354
             timeout: 15_000,
343
-            timeoutMsg: 'expected remote streams in 15s'
355
+            timeoutMsg: `expected remote streams in 15s for ${this.name}`
344
         });
356
         });
345
     }
357
     }
346
 
358
 
357
         return driver.waitUntil(async () =>
369
         return driver.waitUntil(async () =>
358
             await driver.execute(count => APP.conference.listMembers().length === count, number), {
370
             await driver.execute(count => APP.conference.listMembers().length === count, number), {
359
             timeout: 15_000,
371
             timeout: 15_000,
360
-            timeoutMsg: msg || `not the expected participants ${number} in 15s`
372
+            timeoutMsg: msg || `not the expected participants ${number} in 15s for ${this.name}`
361
         });
373
         });
362
     }
374
     }
363
 
375
 
531
         return await this.driver.execute(() => APP.UI.getLargeVideoID());
543
         return await this.driver.execute(() => APP.UI.getLargeVideoID());
532
     }
544
     }
533
 
545
 
546
+    /**
547
+     * Returns the source of the large video currently shown.
548
+     */
549
+    async getLargeVideoId() {
550
+        return await this.driver.execute('return document.getElementById("largeVideo").srcObject.id');
551
+    }
552
+
534
     /**
553
     /**
535
      * Makes sure that the avatar is displayed in the local thumbnail and that the video is not displayed.
554
      * Makes sure that the avatar is displayed in the local thumbnail and that the video is not displayed.
536
      * There are 3 options for avatar:
555
      * There are 3 options for avatar:

+ 48
- 0
tests/pageobjects/Filmstrip.ts 查看文件

53
         return await remoteDisplayName.getText();
53
         return await remoteDisplayName.getText();
54
     }
54
     }
55
 
55
 
56
+    /**
57
+     * Returns the remote video id of a participant with endpointID.
58
+     * @param endpointId
59
+     */
60
+    async getRemoteVideoId(endpointId: string) {
61
+        const remoteDisplayName = this.participant.driver.$(`span[id="participant_${endpointId}"]`);
62
+
63
+        await remoteDisplayName.moveTo();
64
+
65
+        return await this.participant.driver.execute(eId =>
66
+            document.evaluate(`//span[@id="participant_${eId}"]//video`,
67
+                document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue?.srcObject?.id, endpointId);
68
+    }
69
+
70
+    /**
71
+     * Returns the local video id.
72
+     */
73
+    async getLocalVideoId() {
74
+        return await this.participant.driver.execute(
75
+            'return document.getElementById("localVideo_container").srcObject.id');
76
+    }
77
+
56
     /**
78
     /**
57
      * Pins a participant by clicking on their thumbnail.
79
      * Pins a participant by clicking on their thumbnail.
58
      * @param participant The participant.
80
      * @param participant The participant.
162
             timeoutMsg: `Local video thumbnail is${hidden ? '' : ' not'} displayed for ${this.participant.name}`
184
             timeoutMsg: `Local video thumbnail is${hidden ? '' : ' not'} displayed for ${this.participant.name}`
163
         });
185
         });
164
     }
186
     }
187
+
188
+    /**
189
+     * Toggles the filmstrip.
190
+     */
191
+    async toggle() {
192
+        const toggleButton = this.participant.driver.$('#toggleFilmstripButton');
193
+
194
+        await toggleButton.moveTo();
195
+        await toggleButton.waitForDisplayed();
196
+        await toggleButton.click();
197
+    }
198
+
199
+    /**
200
+     * Asserts that the remote videos are hidden or not.
201
+     * @param reverse
202
+     */
203
+    async assertRemoteVideosHidden(reverse = false) {
204
+        await this.participant.driver.waitUntil(
205
+            async () =>
206
+                await this.participant.driver.$$('//div[@id="remoteVideos" and contains(@class, "hidden")]').length > 0,
207
+            {
208
+                timeout: 10_000, // 10 seconds
209
+                timeoutMsg: `Timeout waiting fore remote videos to be hidden: ${!reverse}.`
210
+            }
211
+        );
212
+    }
165
 }
213
 }

+ 60
- 2
tests/pageobjects/InviteDialog.ts 查看文件

1
 import BaseDialog from './BaseDialog';
1
 import BaseDialog from './BaseDialog';
2
 
2
 
3
 const CONFERENCE_ID = 'conference-id';
3
 const CONFERENCE_ID = 'conference-id';
4
+const CONFERENCE_URL = 'invite-more-dialog-conference-url';
4
 const DIALOG_CONTAINER = 'invite-more-dialog';
5
 const DIALOG_CONTAINER = 'invite-more-dialog';
6
+const MORE_NUMBERS = 'more-numbers';
7
+const PHONE_NUMBER = 'phone-number';
5
 
8
 
6
 /**
9
 /**
7
  * Represents the invite dialog in a particular participant.
10
  * Represents the invite dialog in a particular participant.
31
     async getPinNumber() {
34
     async getPinNumber() {
32
         await this.open();
35
         await this.open();
33
 
36
 
34
-        const elem = this.participant.driver.$(`.${CONFERENCE_ID}`);
37
+        return (await this.getValueAfterColon(CONFERENCE_ID)).replace(/[# ]/g, '');
38
+    }
39
+
40
+    /**
41
+     * Private helper to get values after colons. The invite dialog lists conference specific information
42
+     * after a label, followed by a colon.
43
+     *
44
+     * @param className
45
+     * @private
46
+     */
47
+    private async getValueAfterColon(className: string) {
48
+        const elem = this.participant.driver.$(`.${className}`);
35
 
49
 
36
         await elem.waitForExist({ timeout: 5000 });
50
         await elem.waitForExist({ timeout: 5000 });
37
 
51
 
39
 
53
 
40
         this.participant.log(`Extracted text in invite dialog: ${fullText}`);
54
         this.participant.log(`Extracted text in invite dialog: ${fullText}`);
41
 
55
 
42
-        return fullText.split(':')[1].trim().replace(/[# ]/g, '');
56
+        return fullText.split(':')[1].trim();
57
+    }
58
+
59
+    /**
60
+     * Returns the meeting url displayed in the dialog.
61
+     */
62
+    async getMeetingURL() {
63
+        const elem = this.participant.driver.$(`.${CONFERENCE_URL}`);
64
+
65
+        await elem.waitForExist();
66
+
67
+        return (await elem.getText())?.trim();
68
+    }
69
+
70
+    /**
71
+     * Waits for the dialog to be open or closed.
72
+     * @param reverse
73
+     */
74
+    async waitTillOpen(reverse = false) {
75
+        await this.participant.driver.waitUntil(
76
+            /* eslint-disable no-extra-parens */
77
+            async () => (reverse ? !await this.isOpen() : await this.isOpen()),
78
+            {
79
+                timeout: 2_000,
80
+                timeoutMsg: `invite dialog did not ${reverse ? 'close' : 'open'}`
81
+            }
82
+        );
83
+    }
84
+
85
+    /**
86
+     * Gets the string that contains the dial in number for the current conference.
87
+     */
88
+    async getDialInNumber() {
89
+        return await this.getValueAfterColon(PHONE_NUMBER);
90
+    }
91
+
92
+    /**
93
+     * Clicks the link to open a page to show all available dial in numbers.
94
+     */
95
+    async openDialInNumbersPage() {
96
+        const moreNumbers = this.participant.driver.$(`.${MORE_NUMBERS}`);
97
+
98
+        await moreNumbers.waitForExist();
99
+        await moreNumbers.waitForClickable();
100
+        await moreNumbers.click();
43
     }
101
     }
44
 }
102
 }

+ 48
- 4
tests/pageobjects/SettingsDialog.ts 查看文件

1
 import BaseDialog from './BaseDialog';
1
 import BaseDialog from './BaseDialog';
2
 
2
 
3
 const EMAIL_FIELD = '#setEmail';
3
 const EMAIL_FIELD = '#setEmail';
4
+const FOLLOW_ME_CHECKBOX = '//input[@name="follow-me"]';
4
 const HIDE_SELF_VIEW_CHECKBOX = '//input[@name="hide-self-view"]';
5
 const HIDE_SELF_VIEW_CHECKBOX = '//input[@name="hide-self-view"]';
5
 const SETTINGS_DIALOG_CONTENT = '.settings-pane';
6
 const SETTINGS_DIALOG_CONTENT = '.settings-pane';
7
+const X_PATH_MODERATOR_TAB = '//div[contains(@class, "settings-dialog")]//*[text()="Moderator"]';
6
 const X_PATH_MORE_TAB = '//div[contains(@class, "settings-dialog")]//*[text()="General"]';
8
 const X_PATH_MORE_TAB = '//div[contains(@class, "settings-dialog")]//*[text()="General"]';
7
 const X_PATH_PROFILE_TAB = '//div[contains(@class, "settings-dialog")]//*[text()="Profile"]';
9
 const X_PATH_PROFILE_TAB = '//div[contains(@class, "settings-dialog")]//*[text()="Profile"]';
8
 
10
 
37
     }
39
     }
38
 
40
 
39
     /**
41
     /**
40
-     * Selects the Profile tab to be displayed.
42
+     * Selects the More tab to be displayed.
41
      */
43
      */
42
     async openMoreTab() {
44
     async openMoreTab() {
43
         await this.openTab(X_PATH_MORE_TAB);
45
         await this.openTab(X_PATH_MORE_TAB);
44
     }
46
     }
45
 
47
 
48
+    /**
49
+     * Selects the moderator tab to be displayed.
50
+     */
51
+    async openModeratorTab() {
52
+        await this.openTab(X_PATH_MODERATOR_TAB);
53
+    }
54
+
46
     /**
55
     /**
47
      * Enters the passed in email into the email field.
56
      * Enters the passed in email into the email field.
48
      * @param email
57
      * @param email
75
     async setHideSelfView(hideSelfView: boolean) {
84
     async setHideSelfView(hideSelfView: boolean) {
76
         await this.openMoreTab();
85
         await this.openMoreTab();
77
 
86
 
78
-        const checkbox = this.participant.driver.$(HIDE_SELF_VIEW_CHECKBOX);
87
+        await this.setCheckbox(HIDE_SELF_VIEW_CHECKBOX, hideSelfView);
88
+    }
89
+
90
+    /**
91
+     * Sets the follow me feature to enabled/disabled.
92
+     * @param enable
93
+     */
94
+    async setFollowMe(enable: boolean) {
95
+        await this.openModeratorTab();
96
+
97
+        await this.setCheckbox(FOLLOW_ME_CHECKBOX, enable);
98
+    }
99
+
100
+    /**
101
+     * Returns true if the follow me checkbox is displayed in the settings dialog.
102
+     */
103
+    async isFollowMeDisplayed() {
104
+        const elem = this.participant.driver.$(X_PATH_MODERATOR_TAB);
105
+
106
+        if (!await elem.isExisting()) {
107
+            return false;
108
+        }
109
+
110
+        await this.openModeratorTab();
111
+
112
+        return await this.participant.driver.$$(FOLLOW_ME_CHECKBOX).length > 0;
113
+    }
114
+
115
+    /**
116
+     * Sets the state of a checkbox.
117
+     * @param selector
118
+     * @param enable
119
+     * @private
120
+     */
121
+    private async setCheckbox(selector: string, enable: boolean) {
122
+        const checkbox = this.participant.driver.$(selector);
79
 
123
 
80
         await checkbox.waitForExist();
124
         await checkbox.waitForExist();
81
 
125
 
82
-        if (hideSelfView !== await checkbox.isSelected()) {
126
+        if (enable !== await checkbox.isSelected()) {
83
             // we show a div with svg and text after the input and those elements grab the click
127
             // we show a div with svg and text after the input and those elements grab the click
84
             // so we need to click on the parent element
128
             // so we need to click on the parent element
85
-            await this.participant.driver.$(`${HIDE_SELF_VIEW_CHECKBOX}//ancestor::div[1]`).click();
129
+            await this.participant.driver.$(`${selector}//ancestor::div[1]`).click();
86
         }
130
         }
87
     }
131
     }
88
 }
132
 }

+ 0
- 1
tests/pageobjects/Toolbar.ts 查看文件

113
         await this.getButton(CLOSE_PARTICIPANTS_PANE).click();
113
         await this.getButton(CLOSE_PARTICIPANTS_PANE).click();
114
     }
114
     }
115
 
115
 
116
-
117
     /**
116
     /**
118
      * Clicks Participants pane button.
117
      * Clicks Participants pane button.
119
      *
118
      *

+ 2
- 3
tests/specs/2way/fakeDialInAudio.spec.ts 查看文件

1
 import process from 'node:process';
1
 import process from 'node:process';
2
 
2
 
3
 import { ensureOneParticipant, ensureTwoParticipants } from '../../helpers/participants';
3
 import { ensureOneParticipant, ensureTwoParticipants } from '../../helpers/participants';
4
-import { cleanup, waitForAudioFromDialInParticipant } from '../helpers/DialIn';
4
+import { cleanup, isDialInEnabled, waitForAudioFromDialInParticipant } from '../helpers/DialIn';
5
 
5
 
6
 describe('Fake Dial-In - ', () => {
6
 describe('Fake Dial-In - ', () => {
7
     it('join participant', async () => {
7
     it('join participant', async () => {
17
         await ensureOneParticipant(ctx);
17
         await ensureOneParticipant(ctx);
18
 
18
 
19
         // check dial-in is enabled, so skip
19
         // check dial-in is enabled, so skip
20
-        if (await ctx.p1.driver.execute(() => Boolean(
21
-            config.dialInConfCodeUrl && config.dialInNumbersUrl && config.hosts?.muc))) {
20
+        if (await isDialInEnabled(ctx.p1)) {
22
             ctx.skipSuiteTests = true;
21
             ctx.skipSuiteTests = true;
23
         }
22
         }
24
     });
23
     });

+ 93
- 0
tests/specs/3way/followMe.spec.ts 查看文件

1
+import { ensureThreeParticipants, ensureTwoParticipants } from '../../helpers/participants';
2
+
3
+describe('Follow Me - ', () => {
4
+    it('joining the meeting', async () => {
5
+        await ensureTwoParticipants(ctx);
6
+
7
+        const { p1 } = ctx;
8
+
9
+        await p1.getToolbar().clickSettingsButton();
10
+
11
+        const settings = p1.getSettingsDialog();
12
+
13
+        await settings.waitForDisplay();
14
+        await settings.setFollowMe(true);
15
+        await settings.submit();
16
+    });
17
+
18
+    it('follow me checkbox visible only for moderators', async () => {
19
+        const { p2 } = ctx;
20
+
21
+        if (!await p2.isModerator()) {
22
+            await p2.getToolbar().clickSettingsButton();
23
+
24
+            const settings = p2.getSettingsDialog();
25
+
26
+            await settings.waitForDisplay();
27
+            expect(await settings.isFollowMeDisplayed()).toBe(false);
28
+
29
+            await settings.clickCloseButton();
30
+        }
31
+    });
32
+
33
+    it('filmstrip commands', async () => {
34
+        const { p1, p2 } = ctx;
35
+
36
+        const p1Filmstrip = p1.getFilmstrip();
37
+        const p2Filmstrip = p2.getFilmstrip();
38
+
39
+        await p1Filmstrip.toggle();
40
+
41
+        await p1Filmstrip.assertRemoteVideosHidden();
42
+        await p2Filmstrip.assertRemoteVideosHidden();
43
+    });
44
+
45
+    it('tile view', async () => {
46
+        await ensureThreeParticipants(ctx);
47
+
48
+        const { p1, p2, p3 } = ctx;
49
+
50
+        await p1.waitForTileViewDisplay();
51
+
52
+        await p1.getToolbar().clickExitTileViewButton();
53
+
54
+        await Promise.all([
55
+            p1.waitForTileViewDisplay(true),
56
+            p2.waitForTileViewDisplay(true),
57
+            p3.waitForTileViewDisplay(true)
58
+        ]);
59
+
60
+        await p1.getToolbar().clickEnterTileViewButton();
61
+
62
+        await Promise.all([
63
+            p1.waitForTileViewDisplay(),
64
+            p2.waitForTileViewDisplay(),
65
+            p3.waitForTileViewDisplay()
66
+        ]);
67
+    });
68
+
69
+    it('next on stage', async () => {
70
+        const { p1, p2, p3 } = ctx;
71
+
72
+        await p1.getFilmstrip().pinParticipant(p2);
73
+
74
+        const p2Filmstrip = p2.getFilmstrip();
75
+        const localVideoId = await p2Filmstrip.getLocalVideoId();
76
+
77
+        await p2.driver.waitUntil(
78
+            async () => await localVideoId === await p2.getLargeVideoId(),
79
+            {
80
+                timeout: 5_000,
81
+                timeoutMsg: 'The pinned participant is not displayed on stage for p2'
82
+            });
83
+
84
+        const p2VideoIdOnp3 = await p3.getFilmstrip().getRemoteVideoId(await p2.getEndpointId());
85
+
86
+        await p3.driver.waitUntil(
87
+            async () => p2VideoIdOnp3 === await p3.getLargeVideoId(),
88
+            {
89
+                timeout: 5_000,
90
+                timeoutMsg: 'The pinned participant is not displayed on stage for p3'
91
+            });
92
+    });
93
+});

+ 2
- 3
tests/specs/alone/dialInAudio.spec.ts 查看文件

2
 import process from 'node:process';
2
 import process from 'node:process';
3
 
3
 
4
 import { ensureOneParticipant } from '../../helpers/participants';
4
 import { ensureOneParticipant } from '../../helpers/participants';
5
-import { cleanup, waitForAudioFromDialInParticipant } from '../helpers/DialIn';
5
+import { cleanup, isDialInEnabled, waitForAudioFromDialInParticipant } from '../helpers/DialIn';
6
 
6
 
7
 describe('Dial-In - ', () => {
7
 describe('Dial-In - ', () => {
8
     it('join participant', async () => {
8
     it('join participant', async () => {
16
         await ensureOneParticipant(ctx);
16
         await ensureOneParticipant(ctx);
17
 
17
 
18
         // check dial-in is enabled
18
         // check dial-in is enabled
19
-        if (!await ctx.p1.driver.execute(() => Boolean(
20
-            config.dialInConfCodeUrl && config.dialInNumbersUrl && config.hosts?.muc))) {
19
+        if (!await isDialInEnabled(ctx.p1)) {
21
             ctx.skipSuiteTests = true;
20
             ctx.skipSuiteTests = true;
22
         }
21
         }
23
     });
22
     });

+ 87
- 0
tests/specs/alone/invite.spec.ts 查看文件

1
+import { ensureOneParticipant } from '../../helpers/participants';
2
+import { isDialInEnabled } from '../helpers/DialIn';
3
+
4
+describe('Invite - ', () => {
5
+    it('join participant', async () => {
6
+        await ensureOneParticipant(ctx);
7
+    });
8
+
9
+    it('url displayed', async () => {
10
+        const { p1 } = ctx;
11
+        const inviteDialog = p1.getInviteDialog();
12
+
13
+        await inviteDialog.open();
14
+        await inviteDialog.waitTillOpen();
15
+
16
+        const driverUrl = await p1.driver.getUrl();
17
+
18
+        expect(driverUrl.includes(await inviteDialog.getMeetingURL())).toBe(true);
19
+
20
+        await inviteDialog.clickCloseButton();
21
+
22
+        await inviteDialog.waitTillOpen(true);
23
+    });
24
+
25
+    it('dial-in displayed', async () => {
26
+        const { p1 } = ctx;
27
+
28
+        if (!await isDialInEnabled(p1)) {
29
+            return;
30
+        }
31
+
32
+        const inviteDialog = p1.getInviteDialog();
33
+
34
+        await inviteDialog.open();
35
+        await inviteDialog.waitTillOpen();
36
+
37
+        expect((await inviteDialog.getDialInNumber()).length > 0).toBe(true);
38
+        expect((await inviteDialog.getPinNumber()).length > 0).toBe(true);
39
+    });
40
+
41
+    it('view more numbers', async () => {
42
+        const { p1 } = ctx;
43
+
44
+        if (!await isDialInEnabled(p1)) {
45
+            return;
46
+        }
47
+
48
+        const inviteDialog = p1.getInviteDialog();
49
+
50
+        await inviteDialog.open();
51
+        await inviteDialog.waitTillOpen();
52
+
53
+        const windows = await p1.driver.getWindowHandles();
54
+
55
+        expect(windows.length).toBe(1);
56
+
57
+        const meetingWindow = windows[0];
58
+
59
+        const displayedNumber = await inviteDialog.getDialInNumber();
60
+        const displayedPin = await inviteDialog.getPinNumber();
61
+
62
+        await inviteDialog.openDialInNumbersPage();
63
+
64
+        const newWindow = (await p1.driver.getWindowHandles()).filter(w => w !== meetingWindow);
65
+
66
+        expect(newWindow.length).toBe(1);
67
+
68
+        const moreNumbersWindow = newWindow[0];
69
+
70
+        await p1.driver.switchWindow(moreNumbersWindow);
71
+
72
+        await browser.pause(5000);
73
+
74
+        await p1.driver.$('.dial-in-numbers-list').waitForExist();
75
+
76
+        const conferenceIdMessage = p1.driver.$('//div[contains(@class, "pinLabel")]');
77
+
78
+        expect((await conferenceIdMessage.getText()).replace(/ /g, '').includes(displayedPin)).toBe(true);
79
+
80
+        const numbers = p1.driver.$$('.dial-in-number');
81
+
82
+        const nums = await numbers.filter(
83
+            async el => (await el.getText()).trim() === displayedNumber);
84
+
85
+        expect(nums.length).toBe(1);
86
+    });
87
+});

+ 9
- 0
tests/specs/helpers/DialIn.ts 查看文件

37
         await participant.getFilmstrip().kickParticipant(jigasiEndpointId);
37
         await participant.getFilmstrip().kickParticipant(jigasiEndpointId);
38
     }
38
     }
39
 }
39
 }
40
+
41
+/**
42
+ * Checks if the dial-in is enabled.
43
+ * @param participant
44
+ */
45
+export async function isDialInEnabled(participant: Participant) {
46
+    return await participant.driver.execute(() => Boolean(
47
+        config.dialInConfCodeUrl && config.dialInNumbersUrl && config.hosts?.muc));
48
+}

Loading…
取消
儲存