mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 02:08:57 +00:00
Clean up callMessages_test
Co-authored-by: Miriam Zimmerman <mutexlox@signal.org>
This commit is contained in:
@@ -35,6 +35,11 @@ describe('callMessages', function callMessages(this: Mocha.Suite) {
|
|||||||
let app1: App;
|
let app1: App;
|
||||||
let app2: App;
|
let app2: App;
|
||||||
|
|
||||||
|
const INPUT1 = 'input_source_a';
|
||||||
|
const OUTPUT1 = 'output_sink_a';
|
||||||
|
const INPUT2 = 'input_source_b';
|
||||||
|
const OUTPUT2 = 'output_sink_b';
|
||||||
|
|
||||||
async function setUpAudio(source: string, sink: string) {
|
async function setUpAudio(source: string, sink: string) {
|
||||||
debug(`setup source: ${source}, sink: ${sink}`);
|
debug(`setup source: ${source}, sink: ${sink}`);
|
||||||
const args = ['--setup', '--input-source', source, '--output-sink', sink];
|
const args = ['--setup', '--input-source', source, '--output-sink', sink];
|
||||||
@@ -62,18 +67,50 @@ describe('callMessages', function callMessages(this: Mocha.Suite) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function playAudio(source: string, sink: string, inputFile: string) {
|
||||||
|
execFile(
|
||||||
|
VIRTUAL_AUDIO,
|
||||||
|
[
|
||||||
|
'--play',
|
||||||
|
'--input-source',
|
||||||
|
source,
|
||||||
|
'--output-sink',
|
||||||
|
sink,
|
||||||
|
'--input-file',
|
||||||
|
inputFile,
|
||||||
|
],
|
||||||
|
(error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
debug(stdout);
|
||||||
|
debug(stderr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function stopAudio(source: string, sink: string) {
|
||||||
|
await execFilePromise(VIRTUAL_AUDIO, [
|
||||||
|
'--stop',
|
||||||
|
'--input-source',
|
||||||
|
source,
|
||||||
|
'--output-sink',
|
||||||
|
sink,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
runTurnInContainer();
|
runTurnInContainer();
|
||||||
// Set up two virtual sources and sinks.
|
// Set up two virtual sources and sinks.
|
||||||
await setUpAudio('input_source_a', 'output_sink_a');
|
await setUpAudio(INPUT1, OUTPUT1);
|
||||||
await setUpAudio('input_source_b', 'output_sink_b');
|
await setUpAudio(INPUT2, OUTPUT2);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
tearDownTurnContainer();
|
tearDownTurnContainer();
|
||||||
|
|
||||||
await tearDownAudio('input_source_a', 'output_sink_a');
|
await tearDownAudio(INPUT1, OUTPUT1);
|
||||||
await tearDownAudio('input_source_b', 'output_sink_b');
|
await tearDownAudio(INPUT2, OUTPUT2);
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@@ -164,6 +201,22 @@ describe('callMessages', function callMessages(this: Mocha.Suite) {
|
|||||||
await win.locator('.module-calling-device-selection__close-button').click();
|
await win.locator('.module-calling-device-selection__close-button').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function acceptAudioCall(win: Page) {
|
||||||
|
// Only wait for 3 seconds to make sure that this succeeded properly rather
|
||||||
|
// than timing out after ~10 seconds and using a direct connection
|
||||||
|
await win
|
||||||
|
.locator('.IncomingCallBar__button--accept-audio')
|
||||||
|
.click({ timeout: 3000 });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function hangupCall(win: Page) {
|
||||||
|
await win.locator('.CallControls__JoinLeaveButton--hangup').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAndResetMaxAudioLevel(win: Page) {
|
||||||
|
return win.evaluate('window.SignalCI?.getAndResetMaxAudioLevel()');
|
||||||
|
}
|
||||||
|
|
||||||
it('can call and decline a call', async () => {
|
it('can call and decline a call', async () => {
|
||||||
const window1 = await app1.getWindow();
|
const window1 = await app1.getWindow();
|
||||||
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
||||||
@@ -187,37 +240,13 @@ describe('callMessages', function callMessages(this: Mocha.Suite) {
|
|||||||
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
||||||
|
|
||||||
const window2 = await app2.getWindow();
|
const window2 = await app2.getWindow();
|
||||||
|
await acceptAudioCall(window2);
|
||||||
// Only wait for 3 seconds to make sure that this succeeded properly rather
|
|
||||||
// than timing out after ~10 seconds and using a direct connection
|
|
||||||
await window2
|
|
||||||
.locator('.IncomingCallBar__button--accept-audio')
|
|
||||||
.click({ timeout: 3000 });
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setInputAndOutput(window1, 'input_source_a', 'output_sink_a');
|
await setInputAndOutput(window1, INPUT1, OUTPUT1);
|
||||||
|
await setInputAndOutput(window2, INPUT2, OUTPUT2);
|
||||||
|
|
||||||
await setInputAndOutput(window2, 'input_source_b', 'output_sink_b');
|
playAudio(INPUT1, OUTPUT1, theRaven);
|
||||||
|
|
||||||
execFile(
|
|
||||||
VIRTUAL_AUDIO,
|
|
||||||
[
|
|
||||||
'--play',
|
|
||||||
'--input-source',
|
|
||||||
'input_source_a',
|
|
||||||
'--output-sink',
|
|
||||||
'output_sink_a',
|
|
||||||
'--input-file',
|
|
||||||
theRaven,
|
|
||||||
],
|
|
||||||
(error, stdout, stderr) => {
|
|
||||||
if (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
debug(stdout);
|
|
||||||
debug(stderr);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Wait for audio levels indicator to be visible.
|
// Wait for audio levels indicator to be visible.
|
||||||
await expect(
|
await expect(
|
||||||
@@ -226,31 +255,20 @@ describe('callMessages', function callMessages(this: Mocha.Suite) {
|
|||||||
)
|
)
|
||||||
).toBeVisible({ timeout: 15000 });
|
).toBeVisible({ timeout: 15000 });
|
||||||
|
|
||||||
// Wait a second to let the audio play
|
// Wait 2 seconds to let the audio play
|
||||||
await new Promise(f => setTimeout(f, 2000));
|
await new Promise(f => setTimeout(f, 2000));
|
||||||
|
|
||||||
expect(
|
expect(await getAndResetMaxAudioLevel(window2)).toBeGreaterThanOrEqual(
|
||||||
await window2.evaluate('window.SignalCI?.getAndResetMaxAudioLevel()')
|
0.25
|
||||||
).toBeGreaterThanOrEqual(0.25);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
await bootstrap2.screenshotWindow(window2, 'callee');
|
|
||||||
// hang up after we detect audio (or fail to)
|
// hang up after we detect audio (or fail to)
|
||||||
await window2.locator('.CallControls__JoinLeaveButton--hangup').click();
|
await hangupCall(window2);
|
||||||
|
|
||||||
await execFilePromise(VIRTUAL_AUDIO, [
|
await stopAudio(INPUT1, OUTPUT1);
|
||||||
'--stop',
|
|
||||||
'--input-source',
|
|
||||||
'input_source_a',
|
|
||||||
'--output-sink',
|
|
||||||
'output_source_a',
|
|
||||||
]);
|
|
||||||
|
|
||||||
await awaitNoCall(window1);
|
await awaitNoCall(window1);
|
||||||
await awaitNoCall(window2);
|
await awaitNoCall(window2);
|
||||||
|
|
||||||
await window2.locator('.NavTabs__Item--Settings').click();
|
|
||||||
await window2.locator('.Preferences__button--calls').click();
|
|
||||||
await bootstrap2.screenshotWindow(window2, 'callee');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -258,91 +276,48 @@ describe('callMessages', function callMessages(this: Mocha.Suite) {
|
|||||||
const theRaven = join(FIXTURES, 'the_raven.wav');
|
const theRaven = join(FIXTURES, 'the_raven.wav');
|
||||||
|
|
||||||
const window1 = await app1.getWindow();
|
const window1 = await app1.getWindow();
|
||||||
|
|
||||||
const window2 = await app2.getWindow();
|
const window2 = await app2.getWindow();
|
||||||
|
|
||||||
// First call: Neither muted, window2 ends call
|
// First call: Neither muted, window2 ends call
|
||||||
|
|
||||||
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
||||||
|
await acceptAudioCall(window2);
|
||||||
// Only wait for 3 seconds to make sure that this succeeded properly rather
|
|
||||||
// than timing out after ~10 seconds and using a direct connection
|
|
||||||
await window2
|
|
||||||
.locator('.IncomingCallBar__button--accept-audio')
|
|
||||||
.click({ timeout: 3000 });
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setInputAndOutput(window1, 'input_source_a', 'output_sink_a');
|
await setInputAndOutput(window1, INPUT1, OUTPUT1);
|
||||||
|
await setInputAndOutput(window2, INPUT2, OUTPUT2);
|
||||||
await setInputAndOutput(window2, 'input_source_b', 'output_sink_b');
|
|
||||||
} finally {
|
} finally {
|
||||||
// hang up
|
await hangupCall(window2);
|
||||||
await window2.locator('.CallControls__JoinLeaveButton--hangup').click();
|
|
||||||
|
|
||||||
await awaitNoCall(window1);
|
await awaitNoCall(window1);
|
||||||
await awaitNoCall(window2);
|
await awaitNoCall(window2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second call
|
// Second call: window1 mutes after placing call but before window 2 answers
|
||||||
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
||||||
|
|
||||||
// window1 mutes after placing call but before window 2 answers
|
|
||||||
await window1.getByLabel('Mute mic').click();
|
await window1.getByLabel('Mute mic').click();
|
||||||
|
|
||||||
// Only wait for 3 seconds to make sure that this succeeded properly rather
|
await acceptAudioCall(window2);
|
||||||
// than timing out after ~10 seconds and using a direct connection
|
|
||||||
await window2
|
|
||||||
.locator('.IncomingCallBar__button--accept-audio')
|
|
||||||
.click({ timeout: 3000 });
|
|
||||||
|
|
||||||
// Wait a few hundred ms for initial comfort noise to subside
|
// Wait a few hundred ms for initial comfort noise to subside
|
||||||
await new Promise(f => setTimeout(f, 600));
|
await new Promise(f => setTimeout(f, 600));
|
||||||
|
|
||||||
// We haven't played any audio into the virtual mic yet, so it's safe to
|
// We haven't played any audio into the virtual mic yet, so it's safe to
|
||||||
// ignore anything this early / to assume it's comfort noise
|
// ignore anything this early / to assume it's comfort noise
|
||||||
await window2.evaluate('window.SignalCI?.getAndResetMaxAudioLevel()');
|
await getAndResetMaxAudioLevel(window2);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setInputAndOutput(window1, 'input_source_a', 'output_sink_a');
|
await setInputAndOutput(window1, INPUT1, OUTPUT1);
|
||||||
|
await setInputAndOutput(window2, INPUT2, OUTPUT2);
|
||||||
|
playAudio(INPUT1, OUTPUT1, theRaven);
|
||||||
|
|
||||||
await setInputAndOutput(window2, 'input_source_b', 'output_sink_b');
|
// Wait 2 seconds to let the audio play.
|
||||||
|
|
||||||
execFile(
|
|
||||||
VIRTUAL_AUDIO,
|
|
||||||
[
|
|
||||||
'--play',
|
|
||||||
'--input-source',
|
|
||||||
'input_source_a',
|
|
||||||
'--output-sink',
|
|
||||||
'output_sink_a',
|
|
||||||
'--input-file',
|
|
||||||
theRaven,
|
|
||||||
],
|
|
||||||
(error, stdout, stderr) => {
|
|
||||||
if (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
debug(stdout);
|
|
||||||
debug(stderr);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Wait a second
|
|
||||||
await new Promise(f => setTimeout(f, 2000));
|
await new Promise(f => setTimeout(f, 2000));
|
||||||
|
|
||||||
// Make sure we got no audio
|
// Make sure we got no audio
|
||||||
expect(
|
expect(await getAndResetMaxAudioLevel(window2)).toBeCloseTo(0);
|
||||||
await window2.evaluate('window.SignalCI?.getAndResetMaxAudioLevel()')
|
|
||||||
).toBeCloseTo(0);
|
|
||||||
} finally {
|
} finally {
|
||||||
await window2.locator('.CallControls__JoinLeaveButton--hangup').click();
|
await hangupCall(window2);
|
||||||
|
|
||||||
await execFilePromise(VIRTUAL_AUDIO, [
|
await stopAudio(INPUT1, OUTPUT1);
|
||||||
'--stop',
|
|
||||||
'--input-source',
|
|
||||||
'input_source_a',
|
|
||||||
'--output-sink',
|
|
||||||
'output_source_a',
|
|
||||||
]);
|
|
||||||
|
|
||||||
await awaitNoCall(window1);
|
await awaitNoCall(window1);
|
||||||
await awaitNoCall(window2);
|
await awaitNoCall(window2);
|
||||||
|
|||||||
Reference in New Issue
Block a user