VulpesOS/gaia/apps/system/test/unit/sound_manager_test.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

475 lines
16 KiB
JavaScript
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
/* global MocksHelper, MockL10n, SoundManager, MockSettingsListener, MockLock,
MockNavigatorSettings, MockasyncStorage,
MockCustomDialog, MockLazyLoader, MockService */
requireApp('system/shared/test/unit/mocks/mock_service.js');
require('/shared/test/unit/mocks/mock_lazy_loader.js');
require('/shared/test/unit/load_body_html_helper.js');
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
require('/shared/test/unit/mocks/mock_settings_listener.js');
require('/shared/test/unit/mocks/mock_custom_dialog.js');
require('/shared/test/unit/mocks/mock_l10n.js');
require('/shared/js/async_semaphore.js');
requireApp('system/test/unit/mock_asyncStorage.js');
requireApp('system/test/unit/mock_navigator_moz_telephony.js');
requireApp('system/test/unit/mock_screen_manager.js');
requireApp('system/js/service.js');
requireApp('system/js/base_module.js');
requireApp('system/js/base_ui.js');
requireApp('system/js/base_icon.js');
requireApp('system/js/playing_icon.js');
requireApp('system/js/headphone_icon.js');
requireApp('system/js/mute_icon.js');
requireApp('system/js/sound_manager.js');
var mocksForSoundManager = new MocksHelper([
'asyncStorage',
'CustomDialog',
'SettingsListener',
'LazyLoader',
'Service'
]).init();
suite('system/sound manager', function() {
var realL10n;
var realMozSettings;
var soundManager;
mocksForSoundManager.attachTestHelpers();
function sendChromeEvent(detail) {
var evt = new CustomEvent('mozChromeEvent', { detail: detail });
window.dispatchEvent(evt);
}
function checkVolume(data) {
for (var name in data) {
assert.equal(data[name], soundManager.currentVolume[name]);
}
}
setup(function() {
MockService.mockQueryWith('screenEnabled', true);
this.sinon.stub(MockService, 'request', function(action) {
if (action === 'showCustomDialog') {
MockCustomDialog.show(arguments[1], arguments[2],
arguments[3], arguments[4]);
} else if (action === 'hideCustomDialog') {
MockCustomDialog.hide(arguments[1], arguments[2],
arguments[3], arguments[4]);
} else {
return Promise.resolve(document.createElement('div'));
}
});
MockLazyLoader.mLoadRightAway = true;
this.sinon.spy(MockLazyLoader, 'load');
soundManager = new SoundManager();
soundManager.start();
});
teardown(function() {
soundManager.stop();
});
test('Default channel', function() {
MockService.mockQueryWith('locked', false);
soundManager.homescreenVisible = false;
MockService.mockQueryWith('isFtuRunning', true);
assert.equal(soundManager.getChannel(), 'notification');
MockService.mockQueryWith('isFtuRunning', false);
assert.equal(soundManager.getChannel(), 'content');
});
test('Should lazy load icons', function() {
assert.isTrue(MockLazyLoader.load.calledWith([
'js/headphone_icon.js',
'js/mute_icon.js',
'js/playing_icon.js'
]));
});
suiteSetup(function() {
loadBodyHTML('/index.html');
realL10n = navigator.mozL10n;
realMozSettings = navigator.mozSettings;
navigator.mozL10n = MockL10n;
navigator.mozSettings = MockNavigatorSettings;
});
suiteTeardown(function() {
navigator.mozL10n = realL10n;
navigator.mozSettings = realMozSettings;
document.body.innerHTML = '';
});
suite('Headset', function() {
setup(function() {
this.sinon.stub(soundManager.headphoneIcon, 'update');
});
test('Headset is connected', function() {
sendChromeEvent({'type': 'headphones-status-changed',
'state': 'on' });
assert.isTrue(soundManager.headphoneIcon.update.called);
});
test('Headset is disconnected', function() {
sendChromeEvent({'type': 'headphones-status-changed',
'state': 'off' });
assert.isFalse(soundManager.headphoneIcon.update.called);
});
});
suite('stop test', function() {
test('stop listening event listener', function() {
sendChromeEvent({'type': 'default-volume-channel-changed',
'channel': 'normal'});
assert.equal('normal', soundManager.defaultVolumeControlChannel);
soundManager.stop();
sendChromeEvent({'type': 'default-volume-channel-changed',
'channel': 'none'});
assert.equal('normal', soundManager.defaultVolumeControlChannel);
});
});
suite('auto start/stop', function() {
suite('change channel', function() {
test('default volume channel changed', function() {
sendChromeEvent({'type': 'default-volume-channel-changed',
'channel': 'normal'});
assert.equal('normal', soundManager.defaultVolumeControlChannel);
});
test('audio channel changed', function() {
window.dispatchEvent(new CustomEvent('audiochannelchanged', {
detail: {
channel: 'alarm'
}
}));
assert.equal('alarm', soundManager.currentChannel);
});
});
suite('read volume from settings', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('audio.volume.alarm', 1);
MockSettingsListener.mTriggerCallback('audio.volume.bt_sco', 2);
MockSettingsListener.mTriggerCallback('audio.volume.content', 3);
MockSettingsListener.mTriggerCallback('audio.volume.notification', 4);
MockSettingsListener.mTriggerCallback('audio.volume.telephony', 5);
});
test('volume for each channel changed', function() {
assert.equal(1, soundManager.currentVolume.alarm);
assert.equal(2, soundManager.currentVolume.bt_sco);
assert.equal(3, soundManager.currentVolume.content);
assert.equal(4, soundManager.currentVolume.notification);
assert.equal(5, soundManager.currentVolume.telephony);
});
});
suite('settings changed', function() {
setup(function() {
this.sinon.stub(soundManager.muteIcon, 'update');
});
test('key: audio.volume.cemaxvol', function() {
MockSettingsListener.mTriggerCallback('audio.volume.cemaxvol', 6);
assert.equal(6, soundManager.CEWarningVol);
});
test('key: vibration.enabled', function() {
MockSettingsListener.mTriggerCallback('vibration.enabled', true);
assert.equal(true, soundManager.vibrationEnabled);
assert.isTrue(soundManager.muteIcon.update.called);
MockSettingsListener.mTriggerCallback('vibration.enabled', false);
assert.equal(false, soundManager.vibrationEnabled);
});
});
suite('mute icon update', function() {
setup(function() {
this.sinon.stub(soundManager.muteIcon, 'update');
});
test('notification volume settings change', function() {
MockSettingsListener.mTriggerCallback('audio.volume.notification', 0);
assert.isTrue(soundManager.muteIcon.update.called);
MockSettingsListener.mTriggerCallback('audio.volume.notification', 1);
assert.isTrue(soundManager.muteIcon.update.called);
});
});
suite('volume change', function() {
setup(function() {
// reset the all volume to 5
soundManager.currentVolume.alarm = 5;
soundManager.currentVolume.bt_sco = 5;
soundManager.currentVolume.content = 5;
soundManager.currentVolume.notification = 5;
soundManager.currentVolume.telephony = 5;
soundManager.currentChannel = 'normal';
});
test('volume up event', function() {
window.dispatchEvent(new CustomEvent('volumeup'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 6,
'notification': 5,
'telephony': 5
});
});
test('volume down event', function() {
window.dispatchEvent(new CustomEvent('volumedown'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 4,
'notification': 5,
'telephony': 5
});
});
test('volume up to vibrate', function() {
var spy = this.sinon.spy(soundManager, 'notifyByVibrating');
soundManager.currentChannel = 'notification';
soundManager.currentVolume.notification = -1;
soundManager.vibrationEnabled = false;
window.dispatchEvent(new CustomEvent('volumeup'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 5,
'notification': 0,
'telephony': 5
});
assert.equal('MUTE', soundManager.muteState);
assert.isTrue(soundManager.vibrationEnabled);
assert.isTrue(MockNavigatorSettings.mSettings['vibration.enabled']);
var vibrationClassList = soundManager.element.classList;
assert.isTrue(vibrationClassList.contains('vibration'));
assert.isTrue(spy.calledOnce);
});
test('volume down to vibrate', function() {
this.sinon.stub(soundManager.muteIcon, 'update');
var spy = this.sinon.spy(soundManager, 'notifyByVibrating');
soundManager.currentChannel = 'notification';
soundManager.currentVolume.notification = 1;
soundManager.vibrationEnabled = false;
window.dispatchEvent(new CustomEvent('volumedown'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 5,
'notification': 0,
'telephony': 5
});
assert.equal('MUTE', soundManager.muteState);
assert.isTrue(soundManager.vibrationEnabled);
assert.isTrue(MockNavigatorSettings.mSettings['vibration.enabled']);
var vibrationClassList = soundManager.element.classList;
assert.isTrue(vibrationClassList.contains('vibration'));
assert.isTrue(spy.calledOnce);
assert.isTrue(soundManager.muteIcon.update.called);
});
test('volume down to silent', function() {
this.sinon.stub(soundManager.muteIcon, 'update');
soundManager.currentChannel = 'notification';
soundManager.currentVolume.notification = 0;
window.dispatchEvent(new CustomEvent('volumedown'));
// we cannot check content channel here, because it is driven by
// SettingsListener's event.
checkVolume({
'alarm': 5,
'bt_sco': 5,
'notification': 0,
'telephony': 5
});
assert.equal('MUTE', soundManager.muteState);
assert.isFalse(soundManager.vibrationEnabled);
assert.isFalse(MockNavigatorSettings.mSettings['vibration.enabled']);
// The content channel should be mute too.
assert.equal(0,
MockNavigatorSettings.mSettings['audio.volume.content']);
var vibrationClassList = soundManager.element.classList;
assert.isFalse(vibrationClassList.contains('vibration'));
assert.isTrue(soundManager.muteIcon.update.called);
});
test('handleVolumeKey: screen-off and channel none', function() {
MockService.mockQueryWith('screenEnabled', false);
soundManager.currentChannel = 'none';
window.dispatchEvent(new CustomEvent('volumeup'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 5,
'notification': 5,
'telephony': 5
});
});
test('handleVolumeKey: headset connected and channel-normal', function() {
soundManager.isHeadsetConnected = true;
soundManager.homescreenVisible = true;
window.dispatchEvent(new CustomEvent('volumeup'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 6,
'notification': 5,
'telephony': 5
});
window.dispatchEvent(new CustomEvent('volumedown'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 5,
'notification': 5,
'telephony': 5
});
});
test('handleVolumeKey: headset connected and channel-none', function() {
soundManager.isHeadsetConnected = true;
soundManager.currentChannel = 'none';
soundManager.homescreenVisible = true;
window.dispatchEvent(new CustomEvent('volumeup'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 5,
'notification': 6,
'telephony': 5
});
});
test('handleVolumeKey: not at homescreen', function() {
soundManager.currentChannel = 'none';
soundManager.homescreenVisible = false;
window.dispatchEvent(new CustomEvent('volumeup'));
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 6,
'notification': 5,
'telephony': 5
});
});
test('over volume up', function() {
soundManager.changeVolume(20);
checkVolume({
'alarm': 5,
'bt_sco': 5,
'content': 15,
'notification': 5,
'telephony': 5
});
});
test('enter slient mode', function() {
soundManager.currentVolume.content = 15;
soundManager.enterSilentMode('content');
assert.equal(0,
MockNavigatorSettings.mSettings['audio.volume.content']);
MockLock.mCallbacks.onsuccess();
assert.equal(15, MockasyncStorage.mItems['content.volume']);
});
test('leave slient mode', function() {
soundManager.currentVolume.content = 15;
soundManager.enterSilentMode('content');
soundManager.leaveSilentMode('content');
assert.equal(15,
MockNavigatorSettings.mSettings['audio.volume.content']);
});
test('mute it', function() {
window.dispatchEvent(new CustomEvent('mute'));
assert.equal(0,
MockNavigatorSettings.mSettings['audio.volume.notification']);
});
test('umute it', function() {
window.dispatchEvent(new CustomEvent('mute'));
window.dispatchEvent(new CustomEvent('unmute'));
assert.equal(5,
MockNavigatorSettings.mSettings['audio.volume.notification']);
});
test('mute notification and unmute notification/content', function() {
soundManager.enterSilentMode('content');
assert.equal(0,
MockNavigatorSettings.mSettings['audio.volume.content']);
window.dispatchEvent(new CustomEvent('mute'));
window.dispatchEvent(new CustomEvent('unmute'));
assert.isTrue(
MockNavigatorSettings.mSettings['audio.volume.content'] > 0);
});
});
suite('homescreen showing', function() {
test('hide dialog when homescreen is opening', function() {
var event = new CustomEvent('homescreenopening');
window.dispatchEvent(event);
assert.isFalse(MockCustomDialog.mShown);
assert.isTrue(soundManager.homescreenVisible);
});
test('hide dialog when homescreen is opened', function() {
var event = new CustomEvent('homescreenopened');
window.dispatchEvent(event);
assert.isFalse(MockCustomDialog.mShown);
assert.isTrue(soundManager.homescreenVisible);
});
});
suite('CE accumulator', function() {
var fakeTimer;
setup(function() {
fakeTimer = sinon.useFakeTimers();
SoundManager.TIME_ONE_MINUTE = 10;
SoundManager.CE_RESET_TIME = 50;
soundManager.currentVolume.content = 15;
sendChromeEvent({'type': 'headphones-status-changed',
'state': 'on' });
window.dispatchEvent(new CustomEvent('audiochannelchanged',{
detail: {
channel: 'content'
}
}));
});
teardown(function() {
fakeTimer.restore();
});
test('CE check', function() {
MockLock.mCallbacks.onsuccess();
assert.isTrue(MockCustomDialog.mShown);
MockCustomDialog.mShowedCancel.callback();
assert.isTrue(soundManager.CEAccumulatorID > 0);
assert.isTrue(soundManager.CEAccumulatorTime > 0);
});
test('CE times out and reset to original state', function() {
// trigger timer
MockLock.mCallbacks.onsuccess();
fakeTimer.tick(55);
assert.equal(0, soundManager.CEAccumulatorTime);
assert.equal(0, soundManager.CETimestamp);
});
});
});
});