mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 02:08:57 +00:00
Add regression test for mute consistency
This commit is contained in:
@@ -56,6 +56,8 @@ export type CIType = {
|
|||||||
resetReleaseNoteAndMegaphoneFetcher(): void;
|
resetReleaseNoteAndMegaphoneFetcher(): void;
|
||||||
forceUnprocessed: boolean;
|
forceUnprocessed: boolean;
|
||||||
setMediaPermissions(): Promise<void>;
|
setMediaPermissions(): Promise<void>;
|
||||||
|
maybeUpdateMaxAudioLevel: (level: number) => void;
|
||||||
|
getAndResetMaxAudioLevel: () => number | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GetCIOptionsType = Readonly<{
|
export type GetCIOptionsType = Readonly<{
|
||||||
@@ -251,6 +253,21 @@ export function getCI({
|
|||||||
await window.IPC.setMediaPermissions(true);
|
await window.IPC.setMediaPermissions(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let maxAudioLevel: number | undefined;
|
||||||
|
|
||||||
|
function maybeUpdateMaxAudioLevel(level: number) {
|
||||||
|
if (maxAudioLevel === undefined || maxAudioLevel < level) {
|
||||||
|
maxAudioLevel = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tracker for maximum received audio level in a 1:1 call
|
||||||
|
function getAndResetMaxAudioLevel(): number | undefined {
|
||||||
|
const level = maxAudioLevel;
|
||||||
|
maxAudioLevel = undefined;
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
deviceName,
|
deviceName,
|
||||||
getConversationId,
|
getConversationId,
|
||||||
@@ -273,5 +290,7 @@ export function getCI({
|
|||||||
resetReleaseNoteAndMegaphoneFetcher,
|
resetReleaseNoteAndMegaphoneFetcher,
|
||||||
forceUnprocessed,
|
forceUnprocessed,
|
||||||
setMediaPermissions,
|
setMediaPermissions,
|
||||||
|
maybeUpdateMaxAudioLevel,
|
||||||
|
getAndResetMaxAudioLevel,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3666,6 +3666,7 @@ export class CallingClass {
|
|||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
call.handleAudioLevels = () => {
|
call.handleAudioLevels = () => {
|
||||||
|
window.SignalCI?.maybeUpdateMaxAudioLevel(call.remoteAudioLevel);
|
||||||
reduxInterface.directCallAudioLevelsChange({
|
reduxInterface.directCallAudioLevelsChange({
|
||||||
conversationId,
|
conversationId,
|
||||||
localAudioLevel: call.outgoingAudioLevel,
|
localAudioLevel: call.outgoingAudioLevel,
|
||||||
|
|||||||
@@ -225,6 +225,13 @@ describe('callMessages', function callMessages(this: Mocha.Suite) {
|
|||||||
'.module-ongoing-call__direct-call-speaking-indicator > .CallingAudioIndicator--with-content'
|
'.module-ongoing-call__direct-call-speaking-indicator > .CallingAudioIndicator--with-content'
|
||||||
)
|
)
|
||||||
).toBeVisible({ timeout: 15000 });
|
).toBeVisible({ timeout: 15000 });
|
||||||
|
|
||||||
|
// Wait a second to let the audio play
|
||||||
|
await new Promise(f => setTimeout(f, 2000));
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await window2.evaluate('window.SignalCI?.getAndResetMaxAudioLevel()')
|
||||||
|
).toBeGreaterThanOrEqual(0.25);
|
||||||
} finally {
|
} finally {
|
||||||
await bootstrap2.screenshotWindow(window2, 'callee');
|
await bootstrap2.screenshotWindow(window2, 'callee');
|
||||||
// hang up after we detect audio (or fail to)
|
// hang up after we detect audio (or fail to)
|
||||||
@@ -246,4 +253,99 @@ describe('callMessages', function callMessages(this: Mocha.Suite) {
|
|||||||
await bootstrap2.screenshotWindow(window2, 'callee');
|
await bootstrap2.screenshotWindow(window2, 'callee');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('mute consistency regression', async () => {
|
||||||
|
const theRaven = join(FIXTURES, 'the_raven.wav');
|
||||||
|
|
||||||
|
const window1 = await app1.getWindow();
|
||||||
|
|
||||||
|
const window2 = await app2.getWindow();
|
||||||
|
|
||||||
|
// First call: Neither muted, window2 ends call
|
||||||
|
|
||||||
|
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
await setInputAndOutput(window1, 'input_source_a', 'output_sink_a');
|
||||||
|
|
||||||
|
await setInputAndOutput(window2, 'input_source_b', 'output_sink_b');
|
||||||
|
} finally {
|
||||||
|
// hang up
|
||||||
|
await window2.locator('.CallControls__JoinLeaveButton--hangup').click();
|
||||||
|
|
||||||
|
await awaitNoCall(window1);
|
||||||
|
await awaitNoCall(window2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second call
|
||||||
|
await startAudioCallWith(window1, bootstrap2.phone.device.aci);
|
||||||
|
|
||||||
|
// window1 mutes after placing call but before window 2 answers
|
||||||
|
await window1.getByLabel('Mute mic').click();
|
||||||
|
|
||||||
|
// 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 });
|
||||||
|
|
||||||
|
// Wait a few hundred ms for initial comfort noise to subside
|
||||||
|
await new Promise(f => setTimeout(f, 600));
|
||||||
|
// 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
|
||||||
|
await window2.evaluate('window.SignalCI?.getAndResetMaxAudioLevel()');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await setInputAndOutput(window1, 'input_source_a', 'output_sink_a');
|
||||||
|
|
||||||
|
await setInputAndOutput(window2, 'input_source_b', 'output_sink_b');
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
// Make sure we got no audio
|
||||||
|
expect(
|
||||||
|
await window2.evaluate('window.SignalCI?.getAndResetMaxAudioLevel()')
|
||||||
|
).toBeCloseTo(0);
|
||||||
|
} finally {
|
||||||
|
await window2.locator('.CallControls__JoinLeaveButton--hangup').click();
|
||||||
|
|
||||||
|
await execFilePromise(VIRTUAL_AUDIO, [
|
||||||
|
'--stop',
|
||||||
|
'--input-source',
|
||||||
|
'input_source_a',
|
||||||
|
'--output-sink',
|
||||||
|
'output_source_a',
|
||||||
|
]);
|
||||||
|
|
||||||
|
await awaitNoCall(window1);
|
||||||
|
await awaitNoCall(window2);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user