ep_webrtc 2.5.35 → 2.5.36
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 +1 -1
- package/static/tests/frontend-new/helper/utils.ts +96 -0
- package/static/tests/frontend-new/specs/audio_video_on_start.spec.ts +37 -0
- package/static/tests/frontend-new/specs/checkbox.spec.ts +165 -0
- package/static/tests/frontend-new/specs/enable_disable.spec.ts +69 -0
- package/static/tests/frontend-new/specs/errors.spec.ts +92 -0
- package/static/tests/frontend-new/specs/interface_buttons.spec.ts +271 -0
- package/static/tests/frontend-new/specs/race_conditions.spec.ts +271 -0
- package/static/tests/frontend-new/specs/setStream.spec.ts +185 -0
- package/static/tests/frontend/specs/audio_video_on_start.js +0 -35
- package/static/tests/frontend/specs/checkbox.js +0 -107
- package/static/tests/frontend/specs/enable_disable.js +0 -50
- package/static/tests/frontend/specs/errors.js +0 -58
- package/static/tests/frontend/specs/interface_buttons.js +0 -251
- package/static/tests/frontend/specs/race_conditions.js +0 -206
- package/static/tests/frontend/specs/setStream.js +0 -138
- package/static/tests/frontend/utils.js +0 -44
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {expect, test} from '@playwright/test';
|
|
2
|
+
import {cartesian, goToNewPadWithParams, installFakeGetUserMedia} from '../helper/utils';
|
|
3
|
+
|
|
4
|
+
const otherUserId = 'other_user_id';
|
|
5
|
+
const otherVideoId = `video_${otherUserId.replace(/\./g, '_')}`;
|
|
6
|
+
const otherInterfaceId = `interface_${otherVideoId}`;
|
|
7
|
+
|
|
8
|
+
test.describe('setStream()', () => {
|
|
9
|
+
test.describe('Audio and video enabled', () => {
|
|
10
|
+
const testCases = [...cartesian(...Array(4).fill([false, true]) as boolean[][])].map(
|
|
11
|
+
([webrtcaudioenabled, webrtcvideoenabled, peerAudio, peerVideo]: boolean[]) => ({
|
|
12
|
+
params: {webrtcaudioenabled, webrtcvideoenabled},
|
|
13
|
+
peer: {audio: peerAudio, video: peerVideo},
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
for (const tc of testCases) {
|
|
17
|
+
test.describe(JSON.stringify(tc), () => {
|
|
18
|
+
test.describe.configure({mode: 'serial'});
|
|
19
|
+
let sharedPage: import('@playwright/test').Page;
|
|
20
|
+
let ownVideoId: string;
|
|
21
|
+
let ownInterfaceId: string;
|
|
22
|
+
|
|
23
|
+
test.beforeAll(async ({browser}) => {
|
|
24
|
+
sharedPage = await browser.newPage();
|
|
25
|
+
test.setTimeout(60_000);
|
|
26
|
+
await goToNewPadWithParams(sharedPage, {av: false, ...tc.params});
|
|
27
|
+
await installFakeGetUserMedia(sharedPage);
|
|
28
|
+
await sharedPage.evaluate(() => (window as any).ep_webrtc.activate());
|
|
29
|
+
const ids = await sharedPage.evaluate(() => {
|
|
30
|
+
const w = window as any;
|
|
31
|
+
const ownUserId = w.ep_webrtc.getUserId();
|
|
32
|
+
const ownVideoId = `video_${ownUserId.replace(/\./g, '_')}`;
|
|
33
|
+
return {ownVideoId, ownInterfaceId: `interface_${ownVideoId}`};
|
|
34
|
+
});
|
|
35
|
+
ownVideoId = ids.ownVideoId;
|
|
36
|
+
ownInterfaceId = ids.ownInterfaceId;
|
|
37
|
+
await sharedPage.evaluate(async ({peer, otherUserId}) => {
|
|
38
|
+
const w = window as any;
|
|
39
|
+
const peerStream = (peer.audio || peer.video)
|
|
40
|
+
? await w.__fakeGetUserMedia(peer)
|
|
41
|
+
: new MediaStream();
|
|
42
|
+
await w.ep_webrtc.setStream(otherUserId, peerStream);
|
|
43
|
+
}, {peer: tc.peer, otherUserId});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test.afterAll(async () => {
|
|
47
|
+
await sharedPage.close();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('self and peer elements exist', async () => {
|
|
51
|
+
const count = await sharedPage.locator('.interface-container').count();
|
|
52
|
+
expect(count).toBe(2);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('self interface', async () => {
|
|
56
|
+
// Self view is always muted (no audio feedback).
|
|
57
|
+
const muted = await sharedPage.locator(`#${ownVideoId}`)
|
|
58
|
+
.evaluate((el) => (el as HTMLVideoElement).muted);
|
|
59
|
+
expect(muted).toBe(true);
|
|
60
|
+
|
|
61
|
+
const audioBtn = sharedPage.locator(`#${ownInterfaceId} .audio-btn`);
|
|
62
|
+
expect(await audioBtn.count()).toBe(1);
|
|
63
|
+
expect(await audioBtn.evaluate((el) => el.classList.contains('muted')))
|
|
64
|
+
.toBe(!tc.params.webrtcaudioenabled);
|
|
65
|
+
expect(await audioBtn.evaluate((el) => el.classList.contains('disallowed')))
|
|
66
|
+
.toBe(false);
|
|
67
|
+
|
|
68
|
+
const videoBtn = sharedPage.locator(`#${ownInterfaceId} .video-btn`);
|
|
69
|
+
expect(await videoBtn.count()).toBe(1);
|
|
70
|
+
expect(await videoBtn.evaluate((el) => el.classList.contains('off')))
|
|
71
|
+
.toBe(!tc.params.webrtcvideoenabled);
|
|
72
|
+
expect(await videoBtn.evaluate((el) => el.classList.contains('disallowed')))
|
|
73
|
+
.toBe(false);
|
|
74
|
+
|
|
75
|
+
const enlargeBtn = sharedPage.locator(`#${ownInterfaceId} .enlarge-btn`);
|
|
76
|
+
expect(await enlargeBtn.count()).toBe(1);
|
|
77
|
+
expect(await enlargeBtn.evaluate((el) => el.classList.contains('large')))
|
|
78
|
+
.toBe(false);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('peer interface', async () => {
|
|
82
|
+
const audioBtn = sharedPage.locator(`#${otherInterfaceId} .audio-btn`);
|
|
83
|
+
expect(await audioBtn.count()).toBe(1);
|
|
84
|
+
// Only initially muted if browser doesn't permit autoplay unless muted.
|
|
85
|
+
const peerVideoMuted = await sharedPage.locator(`#${otherVideoId}`)
|
|
86
|
+
.evaluate((el) => (el as HTMLVideoElement).muted);
|
|
87
|
+
expect(await audioBtn.evaluate((el) => el.classList.contains('muted')))
|
|
88
|
+
.toBe(peerVideoMuted);
|
|
89
|
+
|
|
90
|
+
const videoBtn = sharedPage.locator(`#${otherInterfaceId} .video-btn`);
|
|
91
|
+
expect(await videoBtn.count()).toBe(0);
|
|
92
|
+
|
|
93
|
+
const enlargeBtn = sharedPage.locator(`#${otherInterfaceId} .enlarge-btn`);
|
|
94
|
+
expect(await enlargeBtn.count()).toBe(1);
|
|
95
|
+
expect(await enlargeBtn.evaluate((el) => el.classList.contains('large')))
|
|
96
|
+
.toBe(false);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test.describe('Audio and video hard disabled', () => {
|
|
103
|
+
test.describe.configure({mode: 'serial'});
|
|
104
|
+
let sharedPage: import('@playwright/test').Page;
|
|
105
|
+
let ownVideoId: string;
|
|
106
|
+
let ownInterfaceId: string;
|
|
107
|
+
|
|
108
|
+
test.beforeAll(async ({browser}) => {
|
|
109
|
+
sharedPage = await browser.newPage();
|
|
110
|
+
test.setTimeout(60_000);
|
|
111
|
+
await goToNewPadWithParams(sharedPage, {
|
|
112
|
+
av: false,
|
|
113
|
+
webrtcaudioenabled: true,
|
|
114
|
+
webrtcvideoenabled: true,
|
|
115
|
+
});
|
|
116
|
+
await installFakeGetUserMedia(sharedPage);
|
|
117
|
+
await sharedPage.waitForFunction(
|
|
118
|
+
() => (window as any).$('#rtcbox').data('initialized'));
|
|
119
|
+
await sharedPage.evaluate(() => {
|
|
120
|
+
const w = window as any;
|
|
121
|
+
w.ep_webrtc._settings.audio.disabled = 'hard';
|
|
122
|
+
w.ep_webrtc._settings.video.disabled = 'hard';
|
|
123
|
+
});
|
|
124
|
+
await sharedPage.evaluate(() => (window as any).ep_webrtc.activate());
|
|
125
|
+
const ids = await sharedPage.evaluate(() => {
|
|
126
|
+
const w = window as any;
|
|
127
|
+
const ownUserId = w.ep_webrtc.getUserId();
|
|
128
|
+
const ownVideoId = `video_${ownUserId.replace(/\./g, '_')}`;
|
|
129
|
+
return {ownVideoId, ownInterfaceId: `interface_${ownVideoId}`};
|
|
130
|
+
});
|
|
131
|
+
ownVideoId = ids.ownVideoId;
|
|
132
|
+
ownInterfaceId = ids.ownInterfaceId;
|
|
133
|
+
await sharedPage.evaluate(async (otherUserId) => {
|
|
134
|
+
const w = window as any;
|
|
135
|
+
await w.ep_webrtc.setStream(otherUserId, new MediaStream());
|
|
136
|
+
}, otherUserId);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test.afterAll(async () => {
|
|
140
|
+
await sharedPage.close();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test('self and peer elements exist', async () => {
|
|
144
|
+
const count = await sharedPage.locator('.interface-container').count();
|
|
145
|
+
expect(count).toBe(2);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test('self interface', async () => {
|
|
149
|
+
const muted = await sharedPage.locator(`#${ownVideoId}`)
|
|
150
|
+
.evaluate((el) => (el as HTMLVideoElement).muted);
|
|
151
|
+
expect(muted).toBe(true);
|
|
152
|
+
|
|
153
|
+
const audioBtn = sharedPage.locator(`#${ownInterfaceId} .audio-btn`);
|
|
154
|
+
expect(await audioBtn.count()).toBe(1);
|
|
155
|
+
expect(await audioBtn.evaluate((el) => el.classList.contains('muted'))).toBe(true);
|
|
156
|
+
expect(await audioBtn.evaluate((el) => el.classList.contains('disallowed'))).toBe(true);
|
|
157
|
+
|
|
158
|
+
const videoBtn = sharedPage.locator(`#${ownInterfaceId} .video-btn`);
|
|
159
|
+
expect(await videoBtn.count()).toBe(1);
|
|
160
|
+
expect(await videoBtn.evaluate((el) => el.classList.contains('off'))).toBe(true);
|
|
161
|
+
expect(await videoBtn.evaluate((el) => el.classList.contains('disallowed'))).toBe(true);
|
|
162
|
+
|
|
163
|
+
const enlargeBtn = sharedPage.locator(`#${ownInterfaceId} .enlarge-btn`);
|
|
164
|
+
expect(await enlargeBtn.count()).toBe(1);
|
|
165
|
+
expect(await enlargeBtn.evaluate((el) => el.classList.contains('large'))).toBe(false);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test('peer interface', async () => {
|
|
169
|
+
const audioBtn = sharedPage.locator(`#${otherInterfaceId} .audio-btn`);
|
|
170
|
+
expect(await audioBtn.count()).toBe(1);
|
|
171
|
+
// Mute state only depends on browser autoplay-when-unmuted permission.
|
|
172
|
+
const peerVideoMuted = await sharedPage.locator(`#${otherVideoId}`)
|
|
173
|
+
.evaluate((el) => (el as HTMLVideoElement).muted);
|
|
174
|
+
expect(await audioBtn.evaluate((el) => el.classList.contains('muted')))
|
|
175
|
+
.toBe(peerVideoMuted);
|
|
176
|
+
|
|
177
|
+
const videoBtn = sharedPage.locator(`#${otherInterfaceId} .video-btn`);
|
|
178
|
+
expect(await videoBtn.count()).toBe(0);
|
|
179
|
+
|
|
180
|
+
const enlargeBtn = sharedPage.locator(`#${otherInterfaceId} .enlarge-btn`);
|
|
181
|
+
expect(await enlargeBtn.count()).toBe(1);
|
|
182
|
+
expect(await enlargeBtn.evaluate((el) => el.classList.contains('large'))).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const {cartesian, fakeGetUserMedia} = require('ep_webrtc/static/tests/frontend/utils');
|
|
4
|
-
|
|
5
|
-
describe('audio/video on/off according to query parameters/cookies', function () {
|
|
6
|
-
const testCases = cartesian(['audio', 'video'], [null, false, true], [null, false, true]);
|
|
7
|
-
|
|
8
|
-
for (const [avType, cookieVal, queryVal] of testCases) {
|
|
9
|
-
it(`${avType} cookie=${cookieVal} query=${queryVal}`, async function () {
|
|
10
|
-
this.timeout(60000);
|
|
11
|
-
await helper.aNewPad({
|
|
12
|
-
padPrefs: cookieVal == null ? {} : {[`${avType}EnabledOnStart`]: cookieVal},
|
|
13
|
-
params: Object.assign({
|
|
14
|
-
// Disable WebRTC so we can install a fake getUserMedia() before WebRTC stuff is
|
|
15
|
-
// initialized.
|
|
16
|
-
av: false,
|
|
17
|
-
}, queryVal == null ? {} : {[`webrtc${avType}enabled`]: queryVal}),
|
|
18
|
-
});
|
|
19
|
-
const chrome$ = helper.padChrome$;
|
|
20
|
-
chrome$.window.navigator.mediaDevices.getUserMedia = fakeGetUserMedia;
|
|
21
|
-
// Clicking $(#options-enablertc) also activates, but calling activate() directly blocks until
|
|
22
|
-
// activation is complete.
|
|
23
|
-
await chrome$.window.ep_webrtc.activate();
|
|
24
|
-
const {disabled} = chrome$.window.ep_webrtc._settings[avType];
|
|
25
|
-
const checkbox = chrome$(`#options-${avType}enabledonstart`);
|
|
26
|
-
if (disabled === 'hard') {
|
|
27
|
-
expect(checkbox.length).to.equal(0); // There shouldn't even be a checkbox.
|
|
28
|
-
} else {
|
|
29
|
-
const wantChecked = (queryVal || (queryVal == null && cookieVal) ||
|
|
30
|
-
(queryVal == null && cookieVal == null && disabled === 'none'));
|
|
31
|
-
expect(checkbox.prop('checked')).to.equal(wantChecked);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
});
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const {cartesian} = require('ep_webrtc/static/tests/frontend/utils');
|
|
4
|
-
|
|
5
|
-
describe('settingToCheckbox', function () {
|
|
6
|
-
const testCases = [
|
|
7
|
-
...cartesian([false, true], [null, false, true], [null, false, true]),
|
|
8
|
-
].map(([defaultVal, cookieVal, queryVal], i) => ({
|
|
9
|
-
name: `default=${defaultVal} cookie=${cookieVal} query=${queryVal}`,
|
|
10
|
-
defaultVal,
|
|
11
|
-
cookieVal,
|
|
12
|
-
queryVal,
|
|
13
|
-
i,
|
|
14
|
-
id: `checkboxId${i}`,
|
|
15
|
-
want: queryVal ||
|
|
16
|
-
(queryVal == null && cookieVal) ||
|
|
17
|
-
(queryVal == null && cookieVal == null && defaultVal),
|
|
18
|
-
}));
|
|
19
|
-
let chrome$;
|
|
20
|
-
let padcookie;
|
|
21
|
-
|
|
22
|
-
before(async function () {
|
|
23
|
-
this.timeout(60000);
|
|
24
|
-
await helper.aNewPad({
|
|
25
|
-
padPrefs: Object.assign({}, ...testCases
|
|
26
|
-
.filter(({cookieVal}) => cookieVal != null)
|
|
27
|
-
.map(({cookieVal, i}) => ({[`cookie${i}`]: cookieVal}))),
|
|
28
|
-
params: Object.assign({av: false}, ...testCases
|
|
29
|
-
.filter(({queryVal}) => queryVal != null)
|
|
30
|
-
.map(({queryVal, i}) => ({[`urlVar${i}`]: queryVal}))),
|
|
31
|
-
});
|
|
32
|
-
chrome$ = helper.padChrome$;
|
|
33
|
-
padcookie = chrome$.window.require('ep_etherpad-lite/static/js/pad_cookie').padcookie;
|
|
34
|
-
for (const {id} of testCases) {
|
|
35
|
-
chrome$('#settings').append(chrome$('<input>').attr('type', 'checkbox').attr('id', id));
|
|
36
|
-
}
|
|
37
|
-
await helper.waitForPromise(() => {
|
|
38
|
-
for (const {id} of testCases) {
|
|
39
|
-
if (chrome$(`#${id}`).length !== 1) return false;
|
|
40
|
-
}
|
|
41
|
-
return true;
|
|
42
|
-
});
|
|
43
|
-
for (const {defaultVal, i, id} of testCases) {
|
|
44
|
-
chrome$.window.ep_webrtc.settingToCheckbox({
|
|
45
|
-
urlVar: `urlVar${i}`,
|
|
46
|
-
cookie: `cookie${i}`,
|
|
47
|
-
defaultVal,
|
|
48
|
-
checkboxId: `#${id}`,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe('initially checked/unchecked', function () {
|
|
54
|
-
for (const {name, want, id} of testCases) {
|
|
55
|
-
it(name, async function () {
|
|
56
|
-
expect(chrome$(`#${id}`).prop('checked')).to.equal(want);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('query parameter sets cookie', function () {
|
|
62
|
-
for (const {name, queryVal, i} of testCases.filter(({queryVal}) => queryVal != null)) {
|
|
63
|
-
it(name, async function () {
|
|
64
|
-
expect(padcookie.getPref(`cookie${i}`)).to.equal(queryVal);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe('no query parameter, no cookie -> cookie not set', function () {
|
|
70
|
-
for (const {name, queryVal, cookieVal, i} of testCases) {
|
|
71
|
-
if (queryVal != null || cookieVal != null) continue;
|
|
72
|
-
it(name, async function () {
|
|
73
|
-
expect(padcookie.getPref(`cookie${i}`) == null).to.be(true);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('clicking sets cookie', function () {
|
|
79
|
-
for (const {name, i, id, want} of testCases) {
|
|
80
|
-
it(name, async function () {
|
|
81
|
-
const cb = chrome$(`#${id}`);
|
|
82
|
-
cb.click();
|
|
83
|
-
await helper.waitForPromise(() => cb.prop('checked') === !want);
|
|
84
|
-
expect(padcookie.getPref(`cookie${i}`)).to.equal(!want);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe('throws errors for missing params', function () {
|
|
90
|
-
const params = {
|
|
91
|
-
urlVar: 'urlVar',
|
|
92
|
-
cookie: 'cookie',
|
|
93
|
-
defaultVal: true,
|
|
94
|
-
checkboxId: '#checkboxId',
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
for (const k of Object.keys(params)) {
|
|
98
|
-
const badParams = Object.assign({}, params);
|
|
99
|
-
delete badParams[k];
|
|
100
|
-
|
|
101
|
-
it(k, async function () {
|
|
102
|
-
expect(() => chrome$.window.ep_webrtc.settingToCheckbox(badParams))
|
|
103
|
-
.to.throwError(new RegExp(k));
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
});
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const {cartesian} = require('ep_webrtc/static/tests/frontend/utils');
|
|
4
|
-
|
|
5
|
-
describe('enable/disable', function () {
|
|
6
|
-
const testCases = cartesian([null, false, true], [null, false, true, 'NO', 'YES', 'ignored']);
|
|
7
|
-
|
|
8
|
-
for (const [cookieVal, queryVal] of testCases) {
|
|
9
|
-
describe(`cookie=${cookieVal} query=${queryVal}`, function () {
|
|
10
|
-
let chrome$;
|
|
11
|
-
let wantChecked;
|
|
12
|
-
let checkbox;
|
|
13
|
-
|
|
14
|
-
before(async function () {
|
|
15
|
-
this.timeout(60000);
|
|
16
|
-
await helper.aNewPad({
|
|
17
|
-
padPrefs: cookieVal == null ? {} : {rtcEnabled: cookieVal},
|
|
18
|
-
params: queryVal == null ? {} : {av: queryVal},
|
|
19
|
-
});
|
|
20
|
-
chrome$ = helper.padChrome$;
|
|
21
|
-
// Normalize queryVal to null/false/true.
|
|
22
|
-
const queryNorm =
|
|
23
|
-
!!queryVal === queryVal ? queryVal // Already boolean.
|
|
24
|
-
: queryVal === 'NO' ? false
|
|
25
|
-
: queryVal === 'YES' ? true
|
|
26
|
-
: null;
|
|
27
|
-
await helper.waitForPromise(() => chrome$('#rtcbox').data('initialized'), 5000);
|
|
28
|
-
const defaultChecked = !!chrome$.window.ep_webrtc._settings.enabled;
|
|
29
|
-
wantChecked = (queryNorm || (queryNorm == null && cookieVal) ||
|
|
30
|
-
(queryNorm == null && cookieVal == null && defaultChecked));
|
|
31
|
-
checkbox = chrome$('#options-enablertc');
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('checkbox is checked/unchecked', async function () {
|
|
35
|
-
expect(checkbox.prop('checked')).to.equal(wantChecked);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('self video element', async function () {
|
|
39
|
-
expect(chrome$('#rtcbox video').length).to.equal(wantChecked ? 1 : 0);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('clicking checkbox toggles state', async function () {
|
|
43
|
-
checkbox.click();
|
|
44
|
-
expect(checkbox.prop('checked')).to.equal(!wantChecked);
|
|
45
|
-
await helper.waitForPromise(
|
|
46
|
-
() => chrome$('#rtcbox video').length === (wantChecked ? 0 : 1));
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
describe('error handling', function () {
|
|
4
|
-
let chrome$;
|
|
5
|
-
let $videoBtn;
|
|
6
|
-
let getUserMediaBackup;
|
|
7
|
-
|
|
8
|
-
const testCases = [
|
|
9
|
-
// Hard to test the version of NotAllowedError that is the SSL error
|
|
10
|
-
// because it requires changing window.location
|
|
11
|
-
['NotAllowedError', 'Failed to get permission to access'],
|
|
12
|
-
['NotFoundError', 'Failed to access'],
|
|
13
|
-
['NotReadableError', 'hardware error occurred'],
|
|
14
|
-
['AbortError', 'not a hardware error'],
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
before(async function () {
|
|
18
|
-
this.timeout(60000);
|
|
19
|
-
await helper.aNewPad({params: {
|
|
20
|
-
av: true,
|
|
21
|
-
webrtcaudioenabled: false,
|
|
22
|
-
webrtcvideoenabled: false,
|
|
23
|
-
}});
|
|
24
|
-
chrome$ = helper.padChrome$;
|
|
25
|
-
await helper.waitForPromise(() => chrome$('#rtcbox').data('initialized'));
|
|
26
|
-
const ownUserId = chrome$.window.ep_webrtc.getUserId();
|
|
27
|
-
const ownVideoId = `video_${ownUserId.replace(/\./g, '_')}`;
|
|
28
|
-
const ownInterfaceId = `interface_${ownVideoId}`;
|
|
29
|
-
$videoBtn = chrome$(`#${ownInterfaceId} .video-btn`);
|
|
30
|
-
getUserMediaBackup = chrome$.window.navigator.mediaDevices.getUserMedia;
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
after(async function () {
|
|
34
|
-
chrome$.window.navigator.mediaDevices.getUserMedia = getUserMediaBackup;
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
beforeEach(async function () {
|
|
38
|
-
// No idea why but this needs to be called twice to actually make #gritter-container hidden
|
|
39
|
-
chrome$.gritter.removeAll({fade: false});
|
|
40
|
-
chrome$.gritter.removeAll({fade: false});
|
|
41
|
-
expect($videoBtn.hasClass('off')).to.equal(true);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
for (const [errName, checkString] of testCases) {
|
|
45
|
-
it(errName, async function () {
|
|
46
|
-
chrome$.window.navigator.mediaDevices.getUserMedia = async () => {
|
|
47
|
-
const err = new Error();
|
|
48
|
-
err.name = errName;
|
|
49
|
-
throw err;
|
|
50
|
-
};
|
|
51
|
-
await helper.waitForPromise(() => chrome$('#gritter-container:visible').length === 0, 1000);
|
|
52
|
-
$videoBtn.click();
|
|
53
|
-
await helper.waitForPromise(() => chrome$('#gritter-container:visible').length === 1, 1000);
|
|
54
|
-
expect(chrome$('.gritter-title').html()).to.be('Error');
|
|
55
|
-
expect(chrome$('.gritter-content p').html()).to.contain(checkString);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
});
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const {fakeGetUserMedia} = require('ep_webrtc/static/tests/frontend/utils');
|
|
4
|
-
|
|
5
|
-
describe('Test the behavior of the interface buttons: Mute, Video Disable, Enlarge', function () {
|
|
6
|
-
let audioTrack;
|
|
7
|
-
let videoTrack;
|
|
8
|
-
|
|
9
|
-
const installFakeGetUserMedia = () => {
|
|
10
|
-
const chrome$ = helper.padChrome$;
|
|
11
|
-
chrome$.window.navigator.mediaDevices.getUserMedia = async (constraints) => {
|
|
12
|
-
const stream = await fakeGetUserMedia(constraints);
|
|
13
|
-
audioTrack = stream.getAudioTracks()[0];
|
|
14
|
-
videoTrack = stream.getVideoTracks()[0];
|
|
15
|
-
return stream;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
describe('audio and video on by default', function () {
|
|
20
|
-
beforeEach(async function () {
|
|
21
|
-
this.timeout(60000);
|
|
22
|
-
audioTrack = null;
|
|
23
|
-
videoTrack = null;
|
|
24
|
-
|
|
25
|
-
// Make sure webrtc starts disabled so we have time to wrap getUserMedia
|
|
26
|
-
await helper.aNewPad({
|
|
27
|
-
padPrefs: {
|
|
28
|
-
rtcEnabled: false,
|
|
29
|
-
audioEnabledOnStart: true,
|
|
30
|
-
videoEnabledOnStart: true,
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
const chrome$ = helper.padChrome$;
|
|
34
|
-
installFakeGetUserMedia();
|
|
35
|
-
// Clicking $('#options-enablertc') also activates, but calling activate() directly blocks
|
|
36
|
-
// until activation is complete.
|
|
37
|
-
await chrome$.window.ep_webrtc.activate();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('enlarges then shrinks', async function () {
|
|
41
|
-
const chrome$ = helper.padChrome$;
|
|
42
|
-
|
|
43
|
-
this.timeout(60000);
|
|
44
|
-
|
|
45
|
-
// i.e., "160.25px" -> 160.25 the number
|
|
46
|
-
const numFromCssSize = (size) => {
|
|
47
|
-
expect(size.slice(-2)).to.be('px');
|
|
48
|
-
return Number(size.slice(0, -2));
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// All of these sizes have to allow for tolerances.
|
|
52
|
-
// I.e. it has come back a quarter pixel off before.
|
|
53
|
-
const $video = chrome$('video');
|
|
54
|
-
await helper.waitForPromise(() => {
|
|
55
|
-
const w = numFromCssSize($video.css('width'));
|
|
56
|
-
const h = numFromCssSize($video.css('height'));
|
|
57
|
-
return 159 < w && w < 161 && 119 < h && h < 121;
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const $enlargeBtn = chrome$('.enlarge-btn');
|
|
61
|
-
$enlargeBtn.click();
|
|
62
|
-
|
|
63
|
-
// Expect it to grow to 260, 190
|
|
64
|
-
await helper.waitForPromise(
|
|
65
|
-
() => (numFromCssSize($video.css('width')) > 259 &&
|
|
66
|
-
numFromCssSize($video.css('height')) > 194),
|
|
67
|
-
1000);
|
|
68
|
-
$enlargeBtn.click();
|
|
69
|
-
// Expect it to shrink to 160, 116
|
|
70
|
-
await helper.waitForPromise(
|
|
71
|
-
() => (numFromCssSize($video.css('width')) < 161 &&
|
|
72
|
-
numFromCssSize($video.css('height')) < 121),
|
|
73
|
-
1000);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('mutes then unmutes', async function () {
|
|
77
|
-
this.timeout(60000);
|
|
78
|
-
|
|
79
|
-
const chrome$ = helper.padChrome$;
|
|
80
|
-
|
|
81
|
-
expect(audioTrack.enabled).to.be(true);
|
|
82
|
-
expect(chrome$('.audio-btn.muted').length).to.be(0);
|
|
83
|
-
expect(chrome$('.audio-btn').attr('title')).to.be('Mute');
|
|
84
|
-
|
|
85
|
-
const $audioBtn = chrome$('.audio-btn');
|
|
86
|
-
$audioBtn.click();
|
|
87
|
-
|
|
88
|
-
await helper.waitForPromise(
|
|
89
|
-
() => chrome$('.audio-btn.muted').length === 1 && audioTrack.enabled === false, 3000);
|
|
90
|
-
expect(chrome$('.audio-btn').attr('title')).to.be('Unmute');
|
|
91
|
-
$audioBtn.click();
|
|
92
|
-
await helper.waitForPromise(
|
|
93
|
-
() => chrome$('.audio-btn.muted').length === 0 && audioTrack.enabled === true, 3000);
|
|
94
|
-
expect(chrome$('.audio-btn').attr('title')).to.be('Mute');
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('disables then enables video', async function () {
|
|
98
|
-
this.timeout(60000);
|
|
99
|
-
|
|
100
|
-
const chrome$ = helper.padChrome$;
|
|
101
|
-
|
|
102
|
-
expect(videoTrack.enabled).to.be(true);
|
|
103
|
-
expect(chrome$('.video-btn.off').length).to.be(0);
|
|
104
|
-
expect(chrome$('.video-btn').attr('title')).to.contain('Disable');
|
|
105
|
-
|
|
106
|
-
const $videoBtn = chrome$('.video-btn');
|
|
107
|
-
$videoBtn.click();
|
|
108
|
-
|
|
109
|
-
await helper.waitForPromise(
|
|
110
|
-
() => chrome$('.video-btn.off').length === 1 && videoTrack.enabled === false, 3000);
|
|
111
|
-
expect(chrome$('.video-btn').attr('title')).to.contain('Enable');
|
|
112
|
-
$videoBtn.click();
|
|
113
|
-
await helper.waitForPromise(
|
|
114
|
-
() => chrome$('.video-btn.off').length === 0 && videoTrack.enabled === true, 3000);
|
|
115
|
-
expect(chrome$('.video-btn').attr('title')).to.contain('Disable');
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
context('audio and video off by default', function () {
|
|
120
|
-
beforeEach(async function () {
|
|
121
|
-
this.timeout(60000);
|
|
122
|
-
audioTrack = null;
|
|
123
|
-
videoTrack = null;
|
|
124
|
-
|
|
125
|
-
// Make sure webrtc starts disabled so we have time to wrap getUserMedia
|
|
126
|
-
await helper.aNewPad({
|
|
127
|
-
padPrefs: {
|
|
128
|
-
rtcEnabled: false,
|
|
129
|
-
audioEnabledOnStart: false,
|
|
130
|
-
videoEnabledOnStart: false,
|
|
131
|
-
},
|
|
132
|
-
});
|
|
133
|
-
const chrome$ = helper.padChrome$;
|
|
134
|
-
installFakeGetUserMedia();
|
|
135
|
-
// Clicking $('#options-enablertc') also activates, but calling activate() directly blocks
|
|
136
|
-
// until activation is complete.
|
|
137
|
-
await chrome$.window.ep_webrtc.activate();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('unmutes then mutes', async function () {
|
|
141
|
-
this.timeout(60000);
|
|
142
|
-
|
|
143
|
-
const chrome$ = helper.padChrome$;
|
|
144
|
-
|
|
145
|
-
expect(audioTrack).to.be(null);
|
|
146
|
-
expect(chrome$('.audio-btn.muted').length).to.be(1);
|
|
147
|
-
expect(chrome$('.audio-btn').attr('title')).to.be('Unmute');
|
|
148
|
-
|
|
149
|
-
const $audioBtn = chrome$('.audio-btn');
|
|
150
|
-
$audioBtn.click();
|
|
151
|
-
|
|
152
|
-
await helper.waitForPromise(
|
|
153
|
-
() => (chrome$('.audio-btn.muted').length === 0 &&
|
|
154
|
-
audioTrack != null && audioTrack.enabled),
|
|
155
|
-
3000);
|
|
156
|
-
expect(chrome$('.audio-btn').attr('title')).to.be('Mute');
|
|
157
|
-
$audioBtn.click();
|
|
158
|
-
await helper.waitForPromise(
|
|
159
|
-
() => chrome$('.audio-btn.muted').length === 1 && audioTrack.enabled === false, 3000);
|
|
160
|
-
expect(chrome$('.audio-btn').attr('title')).to.be('Unmute');
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('enables then disables video', async function () {
|
|
164
|
-
this.timeout(60000);
|
|
165
|
-
|
|
166
|
-
const chrome$ = helper.padChrome$;
|
|
167
|
-
|
|
168
|
-
expect(videoTrack).to.be(null);
|
|
169
|
-
expect(chrome$('.video-btn.off').length).to.be(1);
|
|
170
|
-
expect(chrome$('.video-btn').attr('title')).to.contain('Enable');
|
|
171
|
-
|
|
172
|
-
const $videoBtn = chrome$('.video-btn');
|
|
173
|
-
$videoBtn.click();
|
|
174
|
-
|
|
175
|
-
await helper.waitForPromise(
|
|
176
|
-
() => (chrome$('.video-btn.off').length === 0 &&
|
|
177
|
-
videoTrack != null && videoTrack.enabled),
|
|
178
|
-
3000);
|
|
179
|
-
expect(chrome$('.video-btn').attr('title')).to.contain('Disable');
|
|
180
|
-
$videoBtn.click();
|
|
181
|
-
await helper.waitForPromise(
|
|
182
|
-
() => chrome$('.video-btn.off').length === 1 && videoTrack.enabled === false, 3000);
|
|
183
|
-
expect(chrome$('.video-btn').attr('title')).to.contain('Enable');
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
context('audio and video hard-disabled', function () {
|
|
188
|
-
beforeEach(async function () {
|
|
189
|
-
this.timeout(60000);
|
|
190
|
-
audioTrack = null;
|
|
191
|
-
videoTrack = null;
|
|
192
|
-
// Make sure webrtc starts disabled so we have time to wrap getUserMedia and change settings
|
|
193
|
-
// before activation.
|
|
194
|
-
await helper.aNewPad({params: {av: false}});
|
|
195
|
-
const chrome$ = helper.padChrome$;
|
|
196
|
-
await helper.waitForPromise(() => chrome$('#rtcbox').data('initialized'));
|
|
197
|
-
chrome$.window.ep_webrtc._settings.audio.disabled = 'hard';
|
|
198
|
-
chrome$.window.ep_webrtc._settings.video.disabled = 'hard';
|
|
199
|
-
installFakeGetUserMedia();
|
|
200
|
-
// Clicking $(#options-enablertc) also activates, but calling activate() directly blocks until
|
|
201
|
-
// activation is complete.
|
|
202
|
-
await chrome$.window.ep_webrtc.activate();
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('cannot mute or unmute', async function () {
|
|
206
|
-
this.timeout(60000);
|
|
207
|
-
|
|
208
|
-
const chrome$ = helper.padChrome$;
|
|
209
|
-
|
|
210
|
-
expect(chrome$('.audio-btn.disallowed').length).to.be(1);
|
|
211
|
-
expect(chrome$('.audio-btn.muted').length).to.be(1);
|
|
212
|
-
expect(chrome$('.audio-btn').attr('title')).to.be('Audio disallowed by admin');
|
|
213
|
-
expect(audioTrack).to.be(null);
|
|
214
|
-
expect(videoTrack).to.be(null);
|
|
215
|
-
|
|
216
|
-
const $audioBtn = chrome$('.audio-btn');
|
|
217
|
-
$audioBtn.click();
|
|
218
|
-
|
|
219
|
-
// Wait a sec to make sure there's no change
|
|
220
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
221
|
-
expect(chrome$('.audio-btn.disallowed').length).to.be(1);
|
|
222
|
-
expect(chrome$('.audio-btn.muted').length).to.be(1);
|
|
223
|
-
expect(chrome$('.audio-btn').attr('title')).to.be('Audio disallowed by admin');
|
|
224
|
-
expect(audioTrack).to.be(null);
|
|
225
|
-
expect(videoTrack).to.be(null);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('cannot enable or disable video', async function () {
|
|
229
|
-
this.timeout(60000);
|
|
230
|
-
|
|
231
|
-
const chrome$ = helper.padChrome$;
|
|
232
|
-
|
|
233
|
-
expect(chrome$('.video-btn.disallowed').length).to.be(1);
|
|
234
|
-
expect(chrome$('.video-btn.off').length).to.be(1);
|
|
235
|
-
expect(chrome$('.video-btn').attr('title')).to.be('Video disallowed by admin');
|
|
236
|
-
expect(audioTrack).to.be(null);
|
|
237
|
-
expect(videoTrack).to.be(null);
|
|
238
|
-
|
|
239
|
-
const $videoBtn = chrome$('.video-btn');
|
|
240
|
-
$videoBtn.click();
|
|
241
|
-
|
|
242
|
-
// Wait a sec to make sure there's no change
|
|
243
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
244
|
-
expect(chrome$('.video-btn.disallowed').length).to.be(1);
|
|
245
|
-
expect(chrome$('.video-btn.off').length).to.be(1);
|
|
246
|
-
expect(chrome$('.video-btn').attr('title')).to.be('Video disallowed by admin');
|
|
247
|
-
expect(audioTrack).to.be(null);
|
|
248
|
-
expect(videoTrack).to.be(null);
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
});
|